| accumulator.hxx | | accumulator.hxx | |
| | | | |
| skipping to change at line 55 | | skipping to change at line 55 | |
| #include "metaprogramming.hxx" | | #include "metaprogramming.hxx" | |
| #include "bit_array.hxx" | | #include "bit_array.hxx" | |
| #include "static_assert.hxx" | | #include "static_assert.hxx" | |
| #include "mathutil.hxx" | | #include "mathutil.hxx" | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "multi_iterator_coupled.hxx" | | #include "multi_iterator_coupled.hxx" | |
| #include "matrix.hxx" | | #include "matrix.hxx" | |
| #include "multi_math.hxx" | | #include "multi_math.hxx" | |
| #include "eigensystem.hxx" | | #include "eigensystem.hxx" | |
| #include "histogram.hxx" | | #include "histogram.hxx" | |
|
| | | #include "polygon.hxx" | |
| | | #include "functorexpression.hxx" | |
| | | #include "labelimage.hxx" | |
| #include <algorithm> | | #include <algorithm> | |
| #include <iostream> | | #include <iostream> | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \defgroup FeatureAccumulators Feature Accumulators | | /** \defgroup FeatureAccumulators Feature Accumulators | |
| | | | |
| The namespace <tt>vigra::acc</tt> provides the function \ref vigra::acc::ex
tractFeatures() along with associated statistics functors and accumulator c
lasses. Together, they provide a framework for efficient compution of a wid
e variety of statistical features, both globally for an entire image, and l
ocally for each region defined by a label array. Many different statistics
can be composed out of a small number of fundamental statistics and suitabl
e modifiers. The user simply selects the desired statistics by means of the
ir <i>tags</i> (see below), and a template meta-program automatically gener
ates an efficient functor that computes exactly those statistics. | | The namespace <tt>vigra::acc</tt> provides the function \ref vigra::acc::ex
tractFeatures() along with associated statistics functors and accumulator c
lasses. Together, they provide a framework for efficient compution of a wid
e variety of statistical features, both globally for an entire image, and l
ocally for each region defined by a label array. Many different statistics
can be composed out of a small number of fundamental statistics and suitabl
e modifiers. The user simply selects the desired statistics by means of the
ir <i>tags</i> (see below), and a template meta-program automatically gener
ates an efficient functor that computes exactly those statistics. | |
| | | | |
| The function \ref acc::extractFeatures() "extractFeatures()" scans the data
in as few passes as the selected statstics permit (usually one or two pass
es are sufficient). Statistics are computed by accurate incremental algorit
hms, whose internal state is maintained by accumulator objects. The state i
s updated by passing data to the accumulator one sample at a time. Accumula
tors are grouped within an accumulator chain. Dependencies between accumula
tors in the accumulator chain are automatically resolved and missing depend
encies are inserted. For example, to compute the mean, you also need to cou
nt the number of samples. This allows accumulators to offload some of their
computations on other accumulators, making the algorithms more efficient.
Each accumulator only sees data in the appropriate pass through the data, c
alled its "working pass". | | The function \ref acc::extractFeatures() "extractFeatures()" scans the data
in as few passes as the selected statstics permit (usually one or two pass
es are sufficient). Statistics are computed by accurate incremental algorit
hms, whose internal state is maintained by accumulator objects. The state i
s updated by passing data to the accumulator one sample at a time. Accumula
tors are grouped within an accumulator chain. Dependencies between accumula
tors in the accumulator chain are automatically resolved and missing depend
encies are inserted. For example, to compute the mean, you also need to cou
nt the number of samples. This allows accumulators to offload some of their
computations on other accumulators, making the algorithms more efficient.
Each accumulator only sees data in the appropriate pass through the data, c
alled its "working pass". | |
| | | | |
| <b>\#include</b> \<vigra/accumulator.hxx\> | | <b>\#include</b> \<vigra/accumulator.hxx\> | |
| | | | |
|
| <b>Basic statistics:</b> | | <b>Basic statistics:</b> | |
| - PowerSum<N> (@f$ \sum_i x_i^N @f$) | | - PowerSum<N> (computes @f$ \sum_i x_i^N @f$) | |
| - AbsPowerSum<N> (@f$ \sum_i |x_i|^N @f$) | | - AbsPowerSum<N> (computes @f$ \sum_i |x_i|^N @f$) | |
| - Skewness, UnbiasedSkewness | | - Skewness, UnbiasedSkewness | |
| - Kurtosis, UnbiasedKurtosis | | - Kurtosis, UnbiasedKurtosis | |
| - Minimum, Maximum | | - Minimum, Maximum | |
| - FlatScatterMatrix (flattened upper-triangular part of scatter matrix) | | - FlatScatterMatrix (flattened upper-triangular part of scatter matrix) | |
| - 4 histogram classes (see \ref histogram "below") | | - 4 histogram classes (see \ref histogram "below") | |
| - StandardQuantiles (0%, 10%, 25%, 50%, 75%, 90%, 100%) | | - StandardQuantiles (0%, 10%, 25%, 50%, 75%, 90%, 100%) | |
| - ArgMinWeight, ArgMaxWeight (store data or coordinate where weight ass
umes its minimal or maximal value) | | - ArgMinWeight, ArgMaxWeight (store data or coordinate where weight ass
umes its minimal or maximal value) | |
| - CoordinateSystem (identity matrix of appropriate size) | | - CoordinateSystem (identity matrix of appropriate size) | |
| | | | |
| <b>Modifiers:</b> (S is the statistc to be modified) | | <b>Modifiers:</b> (S is the statistc to be modified) | |
| | | | |
| skipping to change at line 98 | | skipping to change at line 101 | |
| - Data preparation: | | - Data preparation: | |
| <table border="0"> | | <table border="0"> | |
| <tr><td> Central<S> </td><td> substract mean before computing S </
td></tr> | | <tr><td> Central<S> </td><td> substract mean before computing S </
td></tr> | |
| <tr><td> Principal<S> </td><td> project onto PCA eigenvectors </td
></tr> | | <tr><td> Principal<S> </td><td> project onto PCA eigenvectors </td
></tr> | |
| <tr><td> Whitened<S> </td><td> scale to unit variance
after PCA </td></tr> | | <tr><td> Whitened<S> </td><td> scale to unit variance
after PCA </td></tr> | |
| <tr><td> Coord<S> </td><td> compute S from pixel coordinates
rather than from pixel values </td></tr> | | <tr><td> Coord<S> </td><td> compute S from pixel coordinates
rather than from pixel values </td></tr> | |
| <tr><td> Weighted<S> </td><td> compute weighted version of S <
/td></tr> | | <tr><td> Weighted<S> </td><td> compute weighted version of S <
/td></tr> | |
| <tr><td> Global<S> </td><td> compute S globally rather than pe
r region (per region is default if labels are given) </td></tr> | | <tr><td> Global<S> </td><td> compute S globally rather than pe
r region (per region is default if labels are given) </td></tr> | |
| </table> | | </table> | |
| | | | |
|
| Aliases for a couple of important features are implemented (mainly as < | | Aliases for many important features are implemented (mainly as <tt>type | |
| tt>typedef FullName Alias</tt>). The alias names are equivalent to full nam | | def FullName Alias</tt>). The alias names are equivalent to full names. Bel | |
| es. | | ow are some examples for supported alias names. A full list of all availabl | |
| Here are some examples for supported alias names (these examples also s | | e statistics and alias names can be found in the namespace reference <tt>vi | |
| how how to compose statistics from the fundamental statistics and modifiers | | gra::acc</tt>. These examples also show how to compose statistics from the | |
| ): | | fundamental statistics and modifiers: | |
| | | | |
| <table border="0"> | | <table border="0"> | |
| <tr><th> Alias </th><th> Full Name </th></t
r> | | <tr><th> Alias </th><th> Full Name </th></t
r> | |
| <tr><td> Count </td><td> PowerSum<0> </td></t
r> | | <tr><td> Count </td><td> PowerSum<0> </td></t
r> | |
| <tr><td> Sum </td><td> PowerSum<1> </td></t
r> | | <tr><td> Sum </td><td> PowerSum<1> </td></t
r> | |
| <tr><td> SumOfSquares </td><td> PowerSum<2> </td></t
r> | | <tr><td> SumOfSquares </td><td> PowerSum<2> </td></t
r> | |
| <tr><td> Mean </td><td> DivideByCount<PowerSum<1>> </td></t
r> | | <tr><td> Mean </td><td> DivideByCount<PowerSum<1>> </td></t
r> | |
| <tr><td> RootMeanSquares </td><td> RootDivideByCount<PowerSum<2
>> </td></tr> | | <tr><td> RootMeanSquares </td><td> RootDivideByCount<PowerSum<2
>> </td></tr> | |
| <tr><td> Moment<N> </td><td> DivideByCount<PowerSum<N>> </td></
tr> | | <tr><td> Moment<N> </td><td> DivideByCount<PowerSum<N>> </td></
tr> | |
| <tr><td> Variance </td><td> DivideByCount<Central<PowerSum<2>>>
</td></tr> | | <tr><td> Variance </td><td> DivideByCount<Central<PowerSum<2>>>
</td></tr> | |
| | | | |
| skipping to change at line 136 | | skipping to change at line 138 | |
| #include <vigra/multi_array.hxx> | | #include <vigra/multi_array.hxx> | |
| #include <vigra/impex.hxx> | | #include <vigra/impex.hxx> | |
| #include <vigra/accumulator.hxx> | | #include <vigra/accumulator.hxx> | |
| using namespace vigra::acc; | | using namespace vigra::acc; | |
| typedef double DataType; | | typedef double DataType; | |
| int size = 1000; | | int size = 1000; | |
| vigra::MultiArray<2, DataType> data(vigra::Shape2(size, size)); | | vigra::MultiArray<2, DataType> data(vigra::Shape2(size, size)); | |
| | | | |
| AccumulatorChain<DataType, | | AccumulatorChain<DataType, | |
| Select<Variance, Mean, StdDev, Minimum, Maximum, RootMeanSquares, S
kewness, Covariance> > | | Select<Variance, Mean, StdDev, Minimum, Maximum, RootMeanSquares, S
kewness, Covariance> > | |
|
| a; | | a; | |
| | | | |
| std::cout << "passes required: " << a.passesRequired() << std::endl; | | std::cout << "passes required: " << a.passesRequired() << std::endl; | |
| extractFeatures(data.begin(), data.end(), a); | | extractFeatures(data.begin(), data.end(), a); | |
| | | | |
| std::cout << "Mean: " << get<Mean>(a) << std::endl; | | std::cout << "Mean: " << get<Mean>(a) << std::endl; | |
| std::cout << "Variance: " << get<Variance>(a) << std::endl; | | std::cout << "Variance: " << get<Variance>(a) << std::endl; | |
| \endcode | | \endcode | |
| | | | |
| The \ref acc::AccumulatorChain object contains the selected statistics
and their dependencies. Statistics have to be wrapped with \ref acc::Select
. The statistics are computed with the acc::extractFeatures function and th
e statistics can be accessed with acc::get . | | The \ref acc::AccumulatorChain object contains the selected statistics
and their dependencies. Statistics have to be wrapped with \ref acc::Select
. The statistics are computed with the acc::extractFeatures function and th
e statistics can be accessed with acc::get . | |
| | | | |
| | | | |
| skipping to change at line 163 | | skipping to change at line 165 | |
| - each accumulator only sees data in the appropriate pass (its "working
pass") | | - each accumulator only sees data in the appropriate pass (its "working
pass") | |
| | | | |
| The Accumulators can also be used with vector-valued data (vigra::RGBVa
lue, vigra::TinyVector, vigra::MultiArray or vigra::MultiArrayView): | | The Accumulators can also be used with vector-valued data (vigra::RGBVa
lue, vigra::TinyVector, vigra::MultiArray or vigra::MultiArrayView): | |
| | | | |
| \code | | \code | |
| typedef vigra::RGBValue<double> DataType; | | typedef vigra::RGBValue<double> DataType; | |
| AccumulatorChain<DataType, Select<...> > a; | | AccumulatorChain<DataType, Select<...> > a; | |
| ... | | ... | |
| \endcode | | \endcode | |
| | | | |
|
| To compute <b>weighted statistics</b> (Weighted<>) or <b>statistics ove
r coordinates</b> (Coord<>), the accumulator chain can be used with \ref Co
upledScanOrderIterator. The coupled iterator provides simultaneous access t
o several images (e.g. weight and data) and pixel coordinates. The first pa
rameter in the accumulator chain is the type of the CoupledHandle. The inde
ces at which the CoupledHandle holds the data, weights etc. can be specifie
d inside the Select wrapper. | | To compute <b>weighted statistics</b> (Weighted<>) or <b>statistics ove
r coordinates</b> (Coord<>), the accumulator chain can be used with several
coupled arrays, one for the data and another for the weights and/or the la
bels. "Coupled" means that statistics are computed over the corresponding e
lements of the involved arrays. This is internally done by means of \ref Co
upledScanOrderIterator and \ref vigra::CoupledHandle which provide simultan
eous access to several arrays (e.g. weight and data) and corresponding coor
dinates. The types of the coupled arrays are best specified by means of the
helper class \ref vigra::CoupledArrays : | |
| | | | |
|
| These <b>index specifiers</b> are: (INDEX is of type int) | | \code | |
| | | vigra::MultiArray<3, RGBValue<unsigned char> > data(...); | |
| | | vigra::MultiArray<3, double> weights(...); | |
| | | | |
|
| - DataArg<INDEX>: CoupledHandle holds data at index 'INDEX' (default IN | | AccumulatorChain<CoupledArrays<3, RGBValue<unsigned char>, double>, | |
| DEX=1) | | Select<...> > a; | |
| - LabelArg<INDEX>: CoupledHandle holds labels at index 'INDEX' (default | | \endcode | |
| INDEX=2) | | | |
| - WeightArg<INDEX>: CoupledHandle holds weights at index 'INDEX' (defau | | | |
| lt INDEX=outermost index) | | | |
| | | | |
|
| Pixel coordinates are always at index 0. | | This works likewise for label images which are needed for region statistics | |
| | | (see below). The indxx of the array holding data, weights, or labels respe | |
| | | ctively can be specified inside the Select wrapper. These <b>index specifie | |
| | | rs</b> are: (INDEX is of type int) | |
| | | - DataArg<INDEX>: data are in array 'INDEX' (default INDEX=1) | |
| | | - LabelArg<INDEX>: labels are in array 'INDEX' (default INDEX=2) | |
| | | - WeightArg<INDEX>: weights are in array 'INDEX' (default INDEX=rightmo | |
| | | st index) | |
| | | | |
|
| | | Pixel coordinates are always at index 0. To collect statistics, you simply
pass all arrays to the <tt>extractFeatures()</tt> function: | |
| \code | | \code | |
| using namespace vigra::acc; | | using namespace vigra::acc; | |
| vigra::MultiArray<3, double> data(...), weights(...); | | vigra::MultiArray<3, double> data(...), weights(...); | |
|
| typedef vigra::CoupledIteratorType<3, double, double>::type Iterator; / | | | |
| /type of the CoupledScanOrderIterator | | | |
| typedef Iterator::value_type Handle; //type of the corresponding Couple | | | |
| dHandle | | | |
| | | | |
|
| AccumulatorChain<Handle, | | AccumulatorChain<CoupledArrays<3, double, double>, // two 3D arrays for | |
| Select<DataArg<1>, WeightArg<2>, //where to look in the Handl | | data and weights | |
| e (coordinates are always arg 0) | | Select<DataArg<1>, WeightArg<2>, // in which array to loo | |
| Mean, Variance, //statistics over values | | k (coordinates are always arg 0) | |
| Coord<Mean>, Coord<Variance>, //statistics over coordin | | Mean, Variance, //statistics over values | |
| ates, | | Coord<Mean>, Coord<Variance>, //statistics over coordi | |
| Weighted<Mean>, Weighted<Variance>, //weighted values, | | nates, | |
| Weighted<Coord<Mean> > > > //weighted coordinates. | | Weighted<Mean>, Weighted<Variance>, //weighted values, | |
| a; | | Weighted<Coord<Mean> > > > //weighted coordinates. | |
| | | a; | |
| | | | |
|
| Iterator start = createCoupledIterator(data, weights); //coord->index 0 | | extractFeatures(data, weights, a); | |
| , data->index 1, weights->index 2 | | \endcode | |
| Iterator end = start.getEndIterator(); | | | |
| | | | |
|
| extractFeatures(start,end,a); | | This even works for a single array, which is useful if you want to comb | |
| | | ine values with coordinates. For example, to find the location of the minim | |
| | | um element in an array, you interpret the data as weights and select the <t | |
| | | t>Coord<ArgMinWeight></tt> statistic (note that the version of <tt>extractF | |
| | | eatures()</tt> below only works in conjunction with <tt>CoupledArrays</tt>, | |
| | | despite the fact that there is only one array involved): | |
| | | \code | |
| | | using namespace vigra::acc; | |
| | | vigra::MultiArray<3, double> data(...); | |
| | | | |
| | | AccumulatorChain<CoupledArrays<3, double>, | |
| | | Select<WeightArg<1>, // we interprete the da | |
| | | ta as weights | |
| | | Coord<ArgMinWeight> > > // and look for the coo | |
| | | rdinate with minimal weight | |
| | | a; | |
| | | | |
| | | extractFeatures(data, a); | |
| | | std::cout << "minimum is at " << get<Coord<ArgMinWeight> >(a) << std::e | |
| | | ndl; | |
| \endcode | | \endcode | |
| | | | |
|
| To compute <b>region statistics</b>, use \ref acc::AccumulatorChainArra
y : | | To compute <b>region statistics</b>, you use \ref acc::AccumulatorChain
Array. Regions are defined by means of a label array whose elements specify
the region ID of the corresponding point. Therefore, you will always need
at least two arrays here, which are again best specified using the <tt>Coup
ledArrays</tt> helper: | |
| | | | |
| \code | | \code | |
| using namespace vigra::acc; | | using namespace vigra::acc; | |
| vigra::MultiArray<3, double> data(...); | | vigra::MultiArray<3, double> data(...); | |
| vigra::MultiArray<3, int> labels(...); | | vigra::MultiArray<3, int> labels(...); | |
|
| typedef vigra::CoupledIteratorType<3, double, int>::type Iterator; | | | |
| typedef Iterator::value_type Handle; | | | |
| | | | |
|
| AccumulatorChainArray<Handle, | | AccumulatorChainArray<CoupledArrays<3, double, int>, | |
| Select<DataArg<1>, LabelArg<2>, //where to look in the Handle | | Select<DataArg<1>, LabelArg<2>, // in which array to look (co | |
| (coordinates are always arg 0) | | ordinates are always arg 0) | |
| Mean, Variance, //per-region statistics ov | | Mean, Variance, //per-region statistics o | |
| er values | | ver values | |
| Coord<Mean>, Coord<Variance>, //per-region statistics ov | | Coord<Mean>, Coord<Variance>, //per-region statistics o | |
| er coordinates | | ver coordinates | |
| Global<Mean>, Global<Variance> > > //global statistics | | Global<Mean>, Global<Variance> > > //global statistics | |
| a; | | a; | |
| | | | |
|
| Iterator start = createCoupledIterator(data, labels); | | | |
| Iterator end = start.getEndIterator(); | | | |
| | | | |
| a.ignoreLabel(0); //statistics will not be computed for region 0 (e.g.
background) | | a.ignoreLabel(0); //statistics will not be computed for region 0 (e.g.
background) | |
| | | | |
|
| extractFeatures(start,end,a); | | extractFeatures(data, labels, a); | |
| | | | |
| int regionlabel = ...; | | int regionlabel = ...; | |
| std::cout << get<Mean>(a, regionlabel) << std::endl; //get Mean of regi
on with label 'regionlabel' | | std::cout << get<Mean>(a, regionlabel) << std::endl; //get Mean of regi
on with label 'regionlabel' | |
| \endcode | | \endcode | |
| | | | |
| In some application it will be known only at run-time which statistics
have to be computed. An Accumulator with <b>run-time activation</b> is prov
ided by the \ref acc::DynamicAccumulatorChain class. One specifies a set of
statistics at compile-time and from this set one can activate the needed s
tatistics at run-time: | | In some application it will be known only at run-time which statistics
have to be computed. An Accumulator with <b>run-time activation</b> is prov
ided by the \ref acc::DynamicAccumulatorChain class. One specifies a set of
statistics at compile-time and from this set one can activate the needed s
tatistics at run-time: | |
| | | | |
| \code | | \code | |
| using namespace vigra::acc; | | using namespace vigra::acc; | |
| vigra::MultiArray<2, double> data(...); | | vigra::MultiArray<2, double> data(...); | |
| | | | |
| skipping to change at line 247 | | skipping to change at line 259 | |
| <b>Accumulator merging</b> (e.g. for parallelization or hierarchical se
gmentation) is possible for many accumulators: | | <b>Accumulator merging</b> (e.g. for parallelization or hierarchical se
gmentation) is possible for many accumulators: | |
| | | | |
| \code | | \code | |
| using namespace vigra::acc; | | using namespace vigra::acc; | |
| vigra::MultiArray<2, double> data(...); | | vigra::MultiArray<2, double> data(...); | |
| AccumulatorChain<double, Select<Mean, Variance, Skewness> > a, a1, a2; | | AccumulatorChain<double, Select<Mean, Variance, Skewness> > a, a1, a2; | |
| | | | |
| extractFeatures(data.begin(), data.end(), a); //process entire data set
at once | | extractFeatures(data.begin(), data.end(), a); //process entire data set
at once | |
| extractFeatures(data.begin(), data.begin()+data.size()/2, a1); //proces
s first half | | extractFeatures(data.begin(), data.begin()+data.size()/2, a1); //proces
s first half | |
| extractFeatures(data.begin()+data.size()/2, data.end(), a2); //process
second half | | extractFeatures(data.begin()+data.size()/2, data.end(), a2); //process
second half | |
|
| a1 += a2; // merge: a1 now equals a0 (with numerical tolerances) | | a1 += a2; // merge: a1 now equals a0 (within numerical tolerances) | |
| \endcode | | \endcode | |
| | | | |
| Not all statistics can be merged (e.g. Principal<A> usually cannot, exc
ept for some important specializations). A statistic can be merged if the "
+=" operator is supported (see the documentation of that particular statist
ic). If the accumulator chain only requires one pass to collect the data, i
t is also possible to just apply the extractFeatures() function repeatedly: | | Not all statistics can be merged (e.g. Principal<A> usually cannot, exc
ept for some important specializations). A statistic can be merged if the "
+=" operator is supported (see the documentation of that particular statist
ic). If the accumulator chain only requires one pass to collect the data, i
t is also possible to just apply the extractFeatures() function repeatedly: | |
| | | | |
| \code | | \code | |
| using namespace vigra::acc; | | using namespace vigra::acc; | |
| vigra::MultiArray<2, double> data(...); | | vigra::MultiArray<2, double> data(...); | |
| AccumulatorChain<double, Select<Mean, Variance> > a; | | AccumulatorChain<double, Select<Mean, Variance> > a; | |
| | | | |
| extractFeatures(data.begin(), data.begin()+data.size()/2, a); // this w
orks because | | extractFeatures(data.begin(), data.begin()+data.size()/2, a); // this w
orks because | |
|
| extractFeatures(data.begin()+data.size()/2, data.end(), a); // all st | | extractFeatures(data.begin()+data.size()/2, data.end(), a); // all st | |
| atistics only work in pass 1 | | atistics only need pass 1 | |
| | | \endcode | |
| | | | |
| | | More care is needed to merge coordinate-based statistics. By default, a | |
| | | ll coordinate statistics are computed in the local coordinate system of the | |
| | | current region of interest. That is, the upper left corner of the ROI has | |
| | | the coordinate (0, 0) by default. This behavior is not desirable when you w | |
| | | ant to merge coordinate statistics from different ROIs: then, all accumulat | |
| | | ors should use the same coordinate system, usually the global system of the | |
| | | entire dataset. This can be achieved by the <tt>setCoordinateOffset()</tt> | |
| | | function. The following code demonstrates this for the <tt>RegionCenter</t | |
| | | t> statistic: | |
| | | | |
| | | \code | |
| | | using namespace vigra; | |
| | | using namespace vigra::acc; | |
| | | | |
| | | MultiArray<2, double> data(width, height); | |
| | | MultiArray<2, int> labels(width, height); | |
| | | | |
| | | AccumulatorChainArray<CoupledArrays<2, double, int>, | |
| | | Select<DataArg<1>, LabelArg<2>, | |
| | | RegionCenter> > | |
| | | a1, a2; | |
| | | | |
| | | // a1 is responsible for the left half of the image. The local coordina | |
| | | te system of this ROI | |
| | | // happens to be identical to the global coordinate system, so the offs | |
| | | et is zero. | |
| | | Shape2 origin(0,0); | |
| | | a1.setCoordinateOffset(origin); | |
| | | extractFeatures(data.subarray(origin, Shape2(width/2, height)), | |
| | | labels.subarray(origin, Shape2(width/2, height)), | |
| | | a1); | |
| | | | |
| | | // a2 is responsible for the right half, so the offset of the local coo | |
| | | rdinate system is (width/2, 0) | |
| | | origin = Shape2(width/2, 0); | |
| | | a2.setCoordinateOffset(origin); | |
| | | extractFeatures(data.subarray(origin, Shape2(width, height)), | |
| | | labels.subarray(origin, Shape2(width, height)), | |
| | | a2); | |
| | | | |
| | | // since both accumulators worked in the same global coordinate system, | |
| | | we can safely merge them | |
| | | a1.merge(a2); | |
| | | \endcode | |
| | | | |
| | | When you compute region statistics in ROIs, it is sometimes desirable t | |
| | | o use a local region labeling in each ROI. In this way, the labels of each | |
| | | ROI cover a consecutive range of numbers starting with 0. This can save a l | |
| | | ot of memory, because <tt>AccumulatorChainArray</tt> internally uses dense | |
| | | arrays -- accumulators will be allocated for all labels from 0 to the maxmi | |
| | | mum label, even when many of them are unused. This is avoided by a local la | |
| | | beling. However, this means that label 1 (say) may refer to two different r | |
| | | egions in different ROIs. To adjust for this mismatch, you can pass a label | |
| | | mapping to <tt>merge()</tt> that provides a global label for each label of | |
| | | the accumulator to be merged. Thus, each region on the right hand side wil | |
| | | l be merged into the left-hand-side accumulator with the given <i>global</i | |
| | | > label. For example, let us assume that the left and right half of the ima | |
| | | ge contain just one region and background. Then, the accumulators of both R | |
| | | OIs have the label 0 (background) and 1 (the region). Upon merging, the reg | |
| | | ion from the right ROI should be given the global label 2, whereas the back | |
| | | ground should keep its label 0. This is achieved like this: | |
| | | | |
| | | \code | |
| | | std::vector<int> labelMapping(2); | |
| | | labelMapping[0] = 0; // background keeps label 0 | |
| | | labelMapping[1] = 2; // local region 1 becomes global region 2 | |
| | | | |
|
| | | a1.merge(a2, labelMapping); | |
| \endcode | | \endcode | |
| | | | |
| \anchor histogram | | \anchor histogram | |
| Four kinds of <b>histograms</b> are currently implemented: | | Four kinds of <b>histograms</b> are currently implemented: | |
| | | | |
| <table border="0"> | | <table border="0"> | |
| <tr><td> IntegerHistogram </td><td> Data values are equal to b
in indices </td></tr> | | <tr><td> IntegerHistogram </td><td> Data values are equal to b
in indices </td></tr> | |
| <tr><td> UserRangeHistogram </td><td> User provides lower and upp
er bounds for linear range mapping from values to indices. </td></tr> | | <tr><td> UserRangeHistogram </td><td> User provides lower and upp
er bounds for linear range mapping from values to indices. </td></tr> | |
| <tr><td> AutoRangeHistogram </td><td> Range mapping bounds are de
fiend by minimum and maximum of the data (2 passes needed!) </td></tr> | | <tr><td> AutoRangeHistogram </td><td> Range mapping bounds are de
fiend by minimum and maximum of the data (2 passes needed!) </td></tr> | |
| <tr><td> GlobalRangeHistogram </td><td> Likewise, but use gl
obal min/max rather than region min/max as AutoRangeHistogram will </td></t
r> | | <tr><td> GlobalRangeHistogram </td><td> Likewise, but use gl
obal min/max rather than region min/max as AutoRangeHistogram will </td></t
r> | |
| | | | |
| skipping to change at line 366 | | skipping to change at line 420 | |
| typedef typename Select<T01, T02, T03, T04, T05, | | typedef typename Select<T01, T02, T03, T04, T05, | |
| T06, T07, T08, T09, T10, | | T06, T07, T08, T09, T10, | |
| T11, T12, T13, T14, T15, | | T11, T12, T13, T14, T15, | |
| T16, T17, T18, T19, T20>::type type; | | T16, T17, T18, T19, T20>::type type; | |
| }; | | }; | |
| | | | |
| struct AccumulatorBegin | | struct AccumulatorBegin | |
| { | | { | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("AccumulatorBegin (internal)"); | | return "AccumulatorBegin (internal)"; | |
| return n; | | // static const std::string n("AccumulatorBegin (internal)"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class T, class BASE> | | template <class T, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| {}; | | {}; | |
| }; | | }; | |
| | | | |
| struct AccumulatorEnd; | | struct AccumulatorEnd; | |
| struct DataArgTag; | | struct DataArgTag; | |
| struct WeightArgTag; | | struct WeightArgTag; | |
| struct LabelArgTag; | | struct LabelArgTag; | |
| struct CoordArgTag; | | struct CoordArgTag; | |
| struct LabelDispatchTag; | | struct LabelDispatchTag; | |
| | | | |
|
| | | template <class T, class TAG, class CHAIN> | |
| | | struct HandleArgSelector; // find the correct handle in a CoupledHandle | |
| | | | |
| struct Error__Global_statistics_are_only_defined_for_AccumulatorChainArray; | | struct Error__Global_statistics_are_only_defined_for_AccumulatorChainArray; | |
| | | | |
| /** \brief Specifies index of labels in CoupledHandle. | | /** \brief Specifies index of labels in CoupledHandle. | |
| | | | |
| LabelArg<INDEX> tells the acc::AccumulatorChainArray which index of the
Handle contains the labels. (Note that coordinates are always index 0) | | LabelArg<INDEX> tells the acc::AccumulatorChainArray which index of the
Handle contains the labels. (Note that coordinates are always index 0) | |
| */ | | */ | |
| template <int INDEX> | | template <int INDEX> | |
| class LabelArg | | class LabelArg | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("LabelArg<") + asString(IN | | return std::string("LabelArg<") + asString(INDEX) + "> (internal)"; | |
| DEX) + "> (internal)"; | | // static const std::string n = std::string("LabelArg<") + asString | |
| return n; | | (INDEX) + "> (internal)"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class T, class BASE> | | template <class T, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef LabelArgTag Tag; | | typedef LabelArgTag Tag; | |
| typedef void value_type; | | typedef void value_type; | |
| typedef void result_type; | | typedef void result_type; | |
| | | | |
| | | | |
| skipping to change at line 422 | | skipping to change at line 481 | |
| static const unsigned int workInPass = 0; | | static const unsigned int workInPass = 0; | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| template <int INDEX> | | template <int INDEX> | |
| class CoordArg | | class CoordArg | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("CoordArg<") + asString(IN | | return std::string("CoordArg<") + asString(INDEX) + "> (internal)"; | |
| DEX) + "> (internal)"; | | // static const std::string n = std::string("CoordArg<") + asString | |
| return n; | | (INDEX) + "> (internal)"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class T, class BASE> | | template <class T, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef CoordArgTag Tag; | | typedef CoordArgTag Tag; | |
| typedef void value_type; | | typedef void value_type; | |
| typedef void result_type; | | typedef void result_type; | |
| | | | |
| | | | |
| skipping to change at line 462 | | skipping to change at line 522 | |
| template <class TAG, class A> | | template <class TAG, class A> | |
| typename LookupTag<TAG, A>::reference | | typename LookupTag<TAG, A>::reference | |
| getAccumulator(A & a); | | getAccumulator(A & a); | |
| | | | |
| template <class TAG, class A> | | template <class TAG, class A> | |
| typename LookupDependency<TAG, A>::result_type | | typename LookupDependency<TAG, A>::result_type | |
| getDependency(A const & a); | | getDependency(A const & a); | |
| | | | |
| #endif | | #endif | |
| | | | |
|
| namespace detail { | | namespace acc_detail { | |
| | | | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| /*
*/ | | /*
*/ | |
| /* internal tag handling meta-functions
*/ | | /* internal tag handling meta-functions
*/ | |
| /*
*/ | | /*
*/ | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| | | | |
| // we must make sure that Arg<INDEX> tags are at the end of the chain b
ecause | | // we must make sure that Arg<INDEX> tags are at the end of the chain b
ecause | |
| // all other tags potentially depend on them | | // all other tags potentially depend on them | |
| template <class T> | | template <class T> | |
| | | | |
| skipping to change at line 592 | | skipping to change at line 652 | |
| { | | { | |
| typedef SeparateGlobalAndRegionTags<TAIL> Inner; | | typedef SeparateGlobalAndRegionTags<TAIL> Inner; | |
| typedef TypeList<DataArg<INDEX>, typename Inner::RegionTags> RegionTag
s; | | typedef TypeList<DataArg<INDEX>, typename Inner::RegionTags> RegionTag
s; | |
| typedef TypeList<DataArg<INDEX>, typename Inner::GlobalTags> GlobalTag
s; | | typedef TypeList<DataArg<INDEX>, typename Inner::GlobalTags> GlobalTag
s; | |
| }; | | }; | |
| | | | |
| template <int INDEX, class TAIL> | | template <int INDEX, class TAIL> | |
| struct SeparateGlobalAndRegionTags<TypeList<LabelArg<INDEX>, TAIL> > | | struct SeparateGlobalAndRegionTags<TypeList<LabelArg<INDEX>, TAIL> > | |
| { | | { | |
| typedef SeparateGlobalAndRegionTags<TAIL> Inner; | | typedef SeparateGlobalAndRegionTags<TAIL> Inner; | |
|
| typedef typename Inner::RegionTags RegionTags; | | typedef TypeList<LabelArg<INDEX>, typename Inner::RegionTags> RegionTa
gs; | |
| typedef TypeList<LabelArg<INDEX>, typename Inner::GlobalTags> GlobalTa
gs; | | typedef TypeList<LabelArg<INDEX>, typename Inner::GlobalTags> GlobalTa
gs; | |
| }; | | }; | |
| | | | |
| template <int INDEX, class TAIL> | | template <int INDEX, class TAIL> | |
| struct SeparateGlobalAndRegionTags<TypeList<WeightArg<INDEX>, TAIL> > | | struct SeparateGlobalAndRegionTags<TypeList<WeightArg<INDEX>, TAIL> > | |
| { | | { | |
| typedef SeparateGlobalAndRegionTags<TAIL> Inner; | | typedef SeparateGlobalAndRegionTags<TAIL> Inner; | |
| typedef TypeList<WeightArg<INDEX>, typename Inner::RegionTags> RegionT
ags; | | typedef TypeList<WeightArg<INDEX>, typename Inner::RegionTags> RegionT
ags; | |
| typedef TypeList<WeightArg<INDEX>, typename Inner::GlobalTags> GlobalT
ags; | | typedef TypeList<WeightArg<INDEX>, typename Inner::GlobalTags> GlobalT
ags; | |
| }; | | }; | |
| | | | |
| skipping to change at line 657 | | skipping to change at line 717 | |
| | | | |
| template <class T> | | template <class T> | |
| struct ApplyVisitorToTag; | | struct ApplyVisitorToTag; | |
| | | | |
| template <class HEAD, class TAIL> | | template <class HEAD, class TAIL> | |
| struct ApplyVisitorToTag<TypeList<HEAD, TAIL> > | | struct ApplyVisitorToTag<TypeList<HEAD, TAIL> > | |
| { | | { | |
| template <class Accu, class Visitor> | | template <class Accu, class Visitor> | |
| static bool exec(Accu & a, std::string const & tag, Visitor const & v) | | static bool exec(Accu & a, std::string const & tag, Visitor const & v) | |
| { | | { | |
|
| static const std::string name = normalizeString(HEAD::name()); | | static std::string * name = VIGRA_SAFE_STATIC(name, new std::string | |
| if(name == tag) | | (normalizeString(HEAD::name()))); | |
| | | if(*name == tag) | |
| { | | { | |
| v.template exec<HEAD>(a); | | v.template exec<HEAD>(a); | |
| return true; | | return true; | |
| } | | } | |
| else | | else | |
| { | | { | |
| return ApplyVisitorToTag<TAIL>::exec(a, tag, v); | | return ApplyVisitorToTag<TAIL>::exec(a, tag, v); | |
| } | | } | |
| } | | } | |
| }; | | }; | |
| | | | |
| skipping to change at line 849 | | skipping to change at line 909 | |
| | | | |
| template <unsigned, class U> | | template <unsigned, class U> | |
| void pass(U const &) | | void pass(U const &) | |
| {} | | {} | |
| | | | |
| template <unsigned, class U> | | template <unsigned, class U> | |
| void pass(U const &, double) | | void pass(U const &, double) | |
| {} | | {} | |
| | | | |
| template <class U> | | template <class U> | |
|
| void merge(U const &) | | void mergeImpl(U const &) | |
| {} | | {} | |
| | | | |
| template <class U> | | template <class U> | |
| void resize(U const &) | | void resize(U const &) | |
| {} | | {} | |
| | | | |
|
| | | template <class U> | |
| | | void setCoordinateOffsetImpl(U const &) | |
| | | {} | |
| | | | |
| void activate() | | void activate() | |
| {} | | {} | |
| | | | |
| bool isActive() const | | bool isActive() const | |
| { | | { | |
| return false; | | return false; | |
| } | | } | |
| | | | |
| template <class Flags> | | template <class Flags> | |
| static void activateImpl(Flags &) | | static void activateImpl(Flags &) | |
| | | | |
| skipping to change at line 949 | | skipping to change at line 1013 | |
| static void exec(A & a, T const & t, double weight) | | static void exec(A & a, T const & t, double weight) | |
| { | | { | |
| a.update(t, weight); | | a.update(t, weight); | |
| } | | } | |
| | | | |
| static typename A::result_type get(A const & a) | | static typename A::result_type get(A const & a) | |
| { | | { | |
| return a(); | | return a(); | |
| } | | } | |
| | | | |
|
| static void merge(A & a, A const & o) | | static void mergeImpl(A & a, A const & o) | |
| { | | { | |
| a += o; | | a += o; | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static void resize(A & a, T const & t) | | static void resize(A & a, T const & t) | |
| { | | { | |
| a.reshape(t); | | a.reshape(t); | |
| } | | } | |
| | | | |
| static void applyHistogramOptions(A & a, HistogramOptions const & optio
ns) | | static void applyHistogramOptions(A & a, HistogramOptions const & optio
ns) | |
| { | | { | |
| ApplyHistogramOptions<typename A::Tag>::exec(a, options); | | ApplyHistogramOptions<typename A::Tag>::exec(a, options); | |
| } | | } | |
| | | | |
| static unsigned int passesRequired() | | static unsigned int passesRequired() | |
| { | | { | |
| static const unsigned int A_workInPass = A::workInPass; | | static const unsigned int A_workInPass = A::workInPass; | |
|
| return std::max(A_workInPass, A::InternalBaseType::passesRequired())
; | | return std::max(A_workInPass, A::InternalBaseType::passesRequired()
); | |
| } | | } | |
| }; | | }; | |
| | | | |
| template <class A, unsigned CurrentPass> | | template <class A, unsigned CurrentPass> | |
| struct DecoratorImpl<A, CurrentPass, true, CurrentPass> | | struct DecoratorImpl<A, CurrentPass, true, CurrentPass> | |
| { | | { | |
| static bool isActive(A const & a) | | static bool isActive(A const & a) | |
| { | | { | |
| return A::isActiveImpl(getAccumulator<AccumulatorEnd>(a).active_acc
umulators_); | | return A::isActiveImpl(getAccumulator<AccumulatorEnd>(a).active_acc
umulators_); | |
| } | | } | |
| | | | |
| skipping to change at line 996 | | skipping to change at line 1060 | |
| | | | |
| template <class T> | | template <class T> | |
| static void exec(A & a, T const & t, double weight) | | static void exec(A & a, T const & t, double weight) | |
| { | | { | |
| if(isActive(a)) | | if(isActive(a)) | |
| a.update(t, weight); | | a.update(t, weight); | |
| } | | } | |
| | | | |
| static typename A::result_type get(A const & a) | | static typename A::result_type get(A const & a) | |
| { | | { | |
|
| static const std::string message = std::string("get(accumulator): a | | if(!isActive(a)) | |
| ttempt to access inactive statistic '") + | | { | |
| | | std::string message = std::string("get(accumulator): attempt to | |
| typeid(typename A::Tag).name() + "'."; | | access inactive statistic '") + | |
| vigra_precondition(isActive(a), message); | | A::Tag::name() + "'."; | |
| | | vigra_precondition(false, message); | |
| | | } | |
| return a(); | | return a(); | |
| } | | } | |
| | | | |
|
| static void merge(A & a, A const & o) | | static void mergeImpl(A & a, A const & o) | |
| { | | { | |
| if(isActive(a)) | | if(isActive(a)) | |
| a += o; | | a += o; | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static void resize(A & a, T const & t) | | static void resize(A & a, T const & t) | |
| { | | { | |
| if(isActive(a)) | | if(isActive(a)) | |
| a.reshape(t); | | a.reshape(t); | |
| | | | |
| skipping to change at line 1053 | | skipping to change at line 1120 | |
| { | | { | |
| MultiArray<N, T, Alloc>(s, initial).swap(a); | | MultiArray<N, T, Alloc>(s, initial).swap(a); | |
| } | | } | |
| | | | |
| template <class T, class Alloc, class Shape> | | template <class T, class Alloc, class Shape> | |
| void reshapeImpl(Matrix<T, Alloc> & a, Shape const & s, T const & initial =
T()) | | void reshapeImpl(Matrix<T, Alloc> & a, Shape const & s, T const & initial =
T()) | |
| { | | { | |
| Matrix<T, Alloc>(s, initial).swap(a); | | Matrix<T, Alloc>(s, initial).swap(a); | |
| } | | } | |
| | | | |
|
| | | template <class T, class U> | |
| | | void copyShapeImpl(T const &, U const &) // to be used for scalars and st | |
| | | atic arrays | |
| | | {} | |
| | | | |
| | | template <unsigned int N, class T, class Alloc, class U> | |
| | | void copyShapeImpl(MultiArray<N, T, Alloc> const & from, U & to) | |
| | | { | |
| | | to.reshape(from.shape()); | |
| | | } | |
| | | | |
| | | template <class T, class Alloc, class U> | |
| | | void copyShapeImpl(Matrix<T, Alloc> const & from, U & to) | |
| | | { | |
| | | to.reshape(from.shape()); | |
| | | } | |
| | | | |
| | | template <class T, class U> | |
| | | bool hasDataImpl(T const &) // to be used for scalars and static arrays | |
| | | { | |
| | | return true; | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T, class Stride> | |
| | | bool hasDataImpl(MultiArrayView<N, T, Stride> const & a) | |
| | | { | |
| | | return a.hasData(); | |
| | | } | |
| | | | |
| // generic functions to create suitable shape objects from various inpu
t data types | | // generic functions to create suitable shape objects from various inpu
t data types | |
| template <unsigned int N, class T, class Stride> | | template <unsigned int N, class T, class Stride> | |
| inline typename MultiArrayShape<N>::type | | inline typename MultiArrayShape<N>::type | |
| shapeOf(MultiArrayView<N, T, Stride> const & a) | | shapeOf(MultiArrayView<N, T, Stride> const & a) | |
| { | | { | |
| return a.shape(); | | return a.shape(); | |
| } | | } | |
| | | | |
| template <class T, int N> | | template <class T, int N> | |
| inline Shape1 | | inline Shape1 | |
| | | | |
| skipping to change at line 1126 | | skipping to change at line 1221 | |
| typedef LabelDispatch const & const_reference; | | typedef LabelDispatch const & const_reference; | |
| typedef GlobalAccumulatorChain InternalBaseType; | | typedef GlobalAccumulatorChain InternalBaseType; | |
| | | | |
| typedef T const & argument_type; | | typedef T const & argument_type; | |
| typedef argument_type first_argument_type; | | typedef argument_type first_argument_type; | |
| typedef double second_argument_type; | | typedef double second_argument_type; | |
| typedef RegionAccumulatorChain & result_type; | | typedef RegionAccumulatorChain & result_type; | |
| | | | |
| static const int index = GlobalAccumulatorChain::index + 1; | | static const int index = GlobalAccumulatorChain::index + 1; | |
| | | | |
|
| GlobalAccumulatorChain next_; | | | |
| RegionAccumulatorArray regions_; | | | |
| HistogramOptions region_histogram_options_; | | | |
| MultiArrayIndex ignore_label_; | | | |
| ActiveFlagsType active_region_accumulators_; | | | |
| | | | |
| template <class IndexDefinition, class TagFound=typename IndexDefinitio
n::Tag> | | template <class IndexDefinition, class TagFound=typename IndexDefinitio
n::Tag> | |
|
| struct LabelIndexSelector | | struct CoordIndexSelector | |
| { | | { | |
|
| static const int value = 2; // default: CoupledHandle holds labels | | static const int value = 0; // default: CoupledHandle holds coordin | |
| at index 2 | | ates at index 0 | |
| | | | |
| template <class U, class NEXT> | | | |
| static MultiArrayIndex exec(CoupledHandle<U, NEXT> const & t) | | | |
| { | | | |
| return (MultiArrayIndex)get<value>(t); | | | |
| } | | | |
| }; | | }; | |
| | | | |
| template <class IndexDefinition> | | template <class IndexDefinition> | |
|
| struct LabelIndexSelector<IndexDefinition, LabelArgTag> | | struct CoordIndexSelector<IndexDefinition, CoordArgTag> | |
| { | | { | |
| static const int value = IndexDefinition::value; | | static const int value = IndexDefinition::value; | |
|
| | | | |
| template <class U, class NEXT> | | | |
| static MultiArrayIndex exec(CoupledHandle<U, NEXT> const & t) | | | |
| { | | | |
| return (MultiArrayIndex)get<value>(t); | | | |
| } | | | |
| }; | | }; | |
| | | | |
|
| | | static const int coordIndex = CoordIndexSelector<typename LookupTag<Coo | |
| | | rdArgTag, GlobalAccumulatorChain>::type>::value; | |
| | | static const int coordSize = CoupledHandleCast<coordIndex, T>::type::v | |
| | | alue_type::static_size; | |
| | | typedef TinyVector<double, coordSize> CoordinateType; | |
| | | | |
| | | GlobalAccumulatorChain next_; | |
| | | RegionAccumulatorArray regions_; | |
| | | HistogramOptions region_histogram_options_; | |
| | | MultiArrayIndex ignore_label_; | |
| | | ActiveFlagsType active_region_accumulators_; | |
| | | CoordinateType coordinateOffset_; | |
| | | | |
| template <class TAG> | | template <class TAG> | |
| struct ActivateImpl | | struct ActivateImpl | |
| { | | { | |
| typedef typename LookupTag<TAG, type>::type TargetAccumulator; | | typedef typename LookupTag<TAG, type>::type TargetAccumulator; | |
| | | | |
| static void activate(GlobalAccumulatorChain & globals, RegionAccumu
latorArray & regions, | | static void activate(GlobalAccumulatorChain & globals, RegionAccumu
latorArray & regions, | |
| ActiveFlagsType & flags) | | ActiveFlagsType & flags) | |
| { | | { | |
| TargetAccumulator::template activateImpl<LabelDispatch>( | | TargetAccumulator::template activateImpl<LabelDispatch>( | |
| flags, getAccumulator<AccumulatorEnd>(globals).active
_accumulators_); | | flags, getAccumulator<AccumulatorEnd>(globals).active
_accumulators_); | |
| | | | |
| skipping to change at line 1202 | | skipping to change at line 1290 | |
| { | | { | |
| static void activate(GlobalAccumulatorChain &, RegionAccumulatorArr
ay &, ActiveFlagsType &) | | static void activate(GlobalAccumulatorChain &, RegionAccumulatorArr
ay &, ActiveFlagsType &) | |
| {} | | {} | |
| | | | |
| static bool isActive(GlobalAccumulatorChain const & globals, Active
FlagsType const &) | | static bool isActive(GlobalAccumulatorChain const & globals, Active
FlagsType const &) | |
| { | | { | |
| return getAccumulator<LabelArg<INDEX> >(globals).isActive(); | | return getAccumulator<LabelArg<INDEX> >(globals).isActive(); | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| typedef typename LookupTag<LabelArgTag, GlobalAccumulatorChain>::type F | | | |
| indLabelIndex; | | | |
| | | | |
| LabelDispatch() | | LabelDispatch() | |
| : next_(), | | : next_(), | |
| regions_(), | | regions_(), | |
| region_histogram_options_(), | | region_histogram_options_(), | |
| ignore_label_(-1), | | ignore_label_(-1), | |
| active_region_accumulators_() | | active_region_accumulators_() | |
| {} | | {} | |
| | | | |
| LabelDispatch(LabelDispatch const & o) | | LabelDispatch(LabelDispatch const & o) | |
| : next_(o.next_), | | : next_(o.next_), | |
| | | | |
| skipping to change at line 1241 | | skipping to change at line 1327 | |
| { | | { | |
| if(maxRegionLabel() == (MultiArrayIndex)maxlabel) | | if(maxRegionLabel() == (MultiArrayIndex)maxlabel) | |
| return; | | return; | |
| unsigned int oldSize = regions_.size(); | | unsigned int oldSize = regions_.size(); | |
| regions_.resize(maxlabel + 1); | | regions_.resize(maxlabel + 1); | |
| for(unsigned int k=oldSize; k<regions_.size(); ++k) | | for(unsigned int k=oldSize; k<regions_.size(); ++k) | |
| { | | { | |
| getAccumulator<AccumulatorEnd>(regions_[k]).setGlobalAccumulato
r(&next_); | | getAccumulator<AccumulatorEnd>(regions_[k]).setGlobalAccumulato
r(&next_); | |
| getAccumulator<AccumulatorEnd>(regions_[k]).active_accumulators
_ = active_region_accumulators_; | | getAccumulator<AccumulatorEnd>(regions_[k]).active_accumulators
_ = active_region_accumulators_; | |
| regions_[k].applyHistogramOptions(region_histogram_options_); | | regions_[k].applyHistogramOptions(region_histogram_options_); | |
|
| | | regions_[k].setCoordinateOffsetImpl(coordinateOffset_); | |
| } | | } | |
| } | | } | |
| | | | |
| void ignoreLabel(MultiArrayIndex l) | | void ignoreLabel(MultiArrayIndex l) | |
| { | | { | |
| ignore_label_ = l; | | ignore_label_ = l; | |
| } | | } | |
| | | | |
|
| | | MultiArrayIndex ignoredLabel() const | |
| | | { | |
| | | return ignore_label_; | |
| | | } | |
| | | | |
| void applyHistogramOptions(HistogramOptions const & options) | | void applyHistogramOptions(HistogramOptions const & options) | |
| { | | { | |
| applyHistogramOptions(options, options); | | applyHistogramOptions(options, options); | |
| } | | } | |
| | | | |
|
| void applyHistogramOptions(HistogramOptions const & regionoptions, Hist | | void applyHistogramOptions(HistogramOptions const & regionoptions, | |
| ogramOptions const & globaloptions) | | HistogramOptions const & globaloptions) | |
| { | | { | |
| region_histogram_options_ = regionoptions; | | region_histogram_options_ = regionoptions; | |
|
| | | for(unsigned int k=0; k<regions_.size(); ++k) | |
| | | { | |
| | | regions_[k].applyHistogramOptions(region_histogram_options_); | |
| | | } | |
| next_.applyHistogramOptions(globaloptions); | | next_.applyHistogramOptions(globaloptions); | |
| } | | } | |
| | | | |
|
| | | void setCoordinateOffsetImpl(CoordinateType const & offset) | |
| | | { | |
| | | coordinateOffset_ = offset; | |
| | | for(unsigned int k=0; k<regions_.size(); ++k) | |
| | | { | |
| | | regions_[k].setCoordinateOffsetImpl(coordinateOffset_); | |
| | | } | |
| | | next_.setCoordinateOffsetImpl(coordinateOffset_); | |
| | | } | |
| | | | |
| | | void setCoordinateOffsetImpl(MultiArrayIndex k, CoordinateType const & | |
| | | offset) | |
| | | { | |
| | | vigra_precondition(0 <= k && k < (MultiArrayIndex)regions_.size(), | |
| | | "Accumulator::setCoordinateOffset(k, offset): region k does no | |
| | | t exist."); | |
| | | regions_[k].setCoordinateOffsetImpl(offset); | |
| | | } | |
| | | | |
| template <class U> | | template <class U> | |
| void resize(U const & t) | | void resize(U const & t) | |
| { | | { | |
| if(regions_.size() == 0) | | if(regions_.size() == 0) | |
| { | | { | |
|
| static const int labelIndex = LabelIndexSelector<FindLabelIndex | | typedef HandleArgSelector<U, LabelArgTag, GlobalAccumulatorChai | |
| >::value; | | n> LabelHandle; | |
| typedef typename CoupledHandleCast<labelIndex, T>::type LabelHa | | | |
| ndle; | | | |
| typedef typename LabelHandle::value_type LabelType; | | typedef typename LabelHandle::value_type LabelType; | |
|
| typedef MultiArrayView<LabelHandle::dimensions, LabelType, Stri | | typedef MultiArrayView<LabelHandle::size, LabelType, StridedArr | |
| dedArrayTag> LabelArray; | | ayTag> LabelArray; | |
| LabelArray labelArray(t.shape(), cast<labelIndex>(t).strides(), | | LabelArray labelArray(t.shape(), LabelHandle::getHandle(t).stri | |
| const_cast<LabelType *>(cast<labelIndex>(t).ptr())); | | des(), | |
| | | const_cast<LabelType *>(LabelHandle::getH | |
| | | andle(t).ptr())); | |
| | | | |
| LabelType minimum, maximum; | | LabelType minimum, maximum; | |
| labelArray.minmax(&minimum, &maximum); | | labelArray.minmax(&minimum, &maximum); | |
| setMaxRegionLabel(maximum); | | setMaxRegionLabel(maximum); | |
| } | | } | |
| next_.resize(t); | | next_.resize(t); | |
| // FIXME: only call resize when label k actually exists? | | // FIXME: only call resize when label k actually exists? | |
| for(unsigned int k=0; k<regions_.size(); ++k) | | for(unsigned int k=0; k<regions_.size(); ++k) | |
| regions_[k].resize(t); | | regions_[k].resize(t); | |
| } | | } | |
| | | | |
| template <unsigned N> | | template <unsigned N> | |
| void pass(T const & t) | | void pass(T const & t) | |
| { | | { | |
|
| if(LabelIndexSelector<FindLabelIndex>::exec(t) != ignore_label_) | | typedef HandleArgSelector<T, LabelArgTag, GlobalAccumulatorChain> L | |
| | | abelHandle; | |
| | | if(LabelHandle::getValue(t) != ignore_label_) | |
| { | | { | |
| next_.template pass<N>(t); | | next_.template pass<N>(t); | |
|
| regions_[LabelIndexSelector<FindLabelIndex>::exec(t)].template
pass<N>(t); | | regions_[LabelHandle::getValue(t)].template pass<N>(t); | |
| } | | } | |
| } | | } | |
| | | | |
| template <unsigned N> | | template <unsigned N> | |
| void pass(T const & t, double weight) | | void pass(T const & t, double weight) | |
| { | | { | |
|
| if(LabelIndexSelector<FindLabelIndex>::exec(t) != ignore_label_) | | typedef HandleArgSelector<T, LabelArgTag, GlobalAccumulatorChain> L | |
| | | abelHandle; | |
| | | if(LabelHandle::getValue(t) != ignore_label_) | |
| { | | { | |
| next_.template pass<N>(t, weight); | | next_.template pass<N>(t, weight); | |
|
| regions_[LabelIndexSelector<FindLabelIndex>::exec(t)].template
pass<N>(t, weight); | | regions_[LabelHandle::getValue(t)].template pass<N>(t, weight); | |
| } | | } | |
| } | | } | |
| | | | |
| static unsigned int passesRequired() | | static unsigned int passesRequired() | |
| { | | { | |
| return std::max(GlobalAccumulatorChain::passesRequired(), RegionAcc
umulatorChain::passesRequired()); | | return std::max(GlobalAccumulatorChain::passesRequired(), RegionAcc
umulatorChain::passesRequired()); | |
| } | | } | |
| | | | |
| unsigned int passesRequiredDynamic() const | | unsigned int passesRequiredDynamic() const | |
| { | | { | |
| | | | |
| skipping to change at line 1343 | | skipping to change at line 1459 | |
| for(unsigned int k=0; k<regions_.size(); ++k) | | for(unsigned int k=0; k<regions_.size(); ++k) | |
| getAccumulator<AccumulatorEnd>(regions_[k]).active_accumulators
_.set(); | | getAccumulator<AccumulatorEnd>(regions_[k]).active_accumulators
_.set(); | |
| } | | } | |
| | | | |
| template <class TAG> | | template <class TAG> | |
| bool isActive() const | | bool isActive() const | |
| { | | { | |
| return ActivateImpl<TAG>::isActive(next_, active_region_accumulator
s_); | | return ActivateImpl<TAG>::isActive(next_, active_region_accumulator
s_); | |
| } | | } | |
| | | | |
|
| void merge(LabelDispatch const & o) | | void mergeImpl(LabelDispatch const & o) | |
| { | | { | |
| for(unsigned int k=0; k<regions_.size(); ++k) | | for(unsigned int k=0; k<regions_.size(); ++k) | |
|
| regions_[k].merge(o.regions_[k]); | | regions_[k].mergeImpl(o.regions_[k]); | |
| next_.merge(o.next_); | | next_.mergeImpl(o.next_); | |
| } | | } | |
| | | | |
|
| void merge(unsigned i, unsigned j) | | void mergeImpl(unsigned i, unsigned j) | |
| { | | { | |
|
| regions_[i].merge(regions_[j]); | | regions_[i].mergeImpl(regions_[j]); | |
| regions_[j].reset(); | | regions_[j].reset(); | |
| getAccumulator<AccumulatorEnd>(regions_[j]).active_accumulators_ =
active_region_accumulators_; | | getAccumulator<AccumulatorEnd>(regions_[j]).active_accumulators_ =
active_region_accumulators_; | |
| } | | } | |
| | | | |
| template <class ArrayLike> | | template <class ArrayLike> | |
|
| void merge(LabelDispatch const & o, ArrayLike const & labelMapping) | | void mergeImpl(LabelDispatch const & o, ArrayLike const & labelMapping) | |
| { | | { | |
| MultiArrayIndex newMaxLabel = std::max<MultiArrayIndex>(maxRegionLa
bel(), *argMax(labelMapping.begin(), labelMapping.end())); | | MultiArrayIndex newMaxLabel = std::max<MultiArrayIndex>(maxRegionLa
bel(), *argMax(labelMapping.begin(), labelMapping.end())); | |
| setMaxRegionLabel(newMaxLabel); | | setMaxRegionLabel(newMaxLabel); | |
| for(unsigned int k=0; k<labelMapping.size(); ++k) | | for(unsigned int k=0; k<labelMapping.size(); ++k) | |
|
| regions_[labelMapping[k]].merge(o.regions_[k]); | | regions_[labelMapping[k]].mergeImpl(o.regions_[k]); | |
| next_.merge(o.next_); | | next_.mergeImpl(o.next_); | |
| } | | } | |
| }; | | }; | |
| | | | |
| template <class TargetTag, class TagList> | | template <class TargetTag, class TagList> | |
| struct FindNextTag; | | struct FindNextTag; | |
| | | | |
| template <class TargetTag, class HEAD, class TAIL> | | template <class TargetTag, class HEAD, class TAIL> | |
| struct FindNextTag<TargetTag, TypeList<HEAD, TAIL> > | | struct FindNextTag<TargetTag, TypeList<HEAD, TAIL> > | |
| { | | { | |
| typedef typename FindNextTag<TargetTag, TAIL>::type type; | | typedef typename FindNextTag<TargetTag, TAIL>::type type; | |
| | | | |
| skipping to change at line 1450 | | skipping to change at line 1566 | |
| static std::string name() | | static std::string name() | |
| { | | { | |
| return TAG::name(); | | return TAG::name(); | |
| } | | } | |
| | | | |
| template <class ActiveFlags> | | template <class ActiveFlags> | |
| static void activateImpl(ActiveFlags & flags) | | static void activateImpl(ActiveFlags & flags) | |
| { | | { | |
| flags.template set<index>(); | | flags.template set<index>(); | |
| typedef typename StandardizeDependencies<Tag>::type StdDeps; | | typedef typename StandardizeDependencies<Tag>::type StdDeps; | |
|
| detail::ActivateDependencies<StdDeps>::template exec<ThisType>(
flags); | | acc_detail::ActivateDependencies<StdDeps>::template exec<ThisTy
pe>(flags); | |
| } | | } | |
| | | | |
| template <class Accu, class ActiveFlags, class GlobalFlags> | | template <class Accu, class ActiveFlags, class GlobalFlags> | |
| static void activateImpl(ActiveFlags & flags, GlobalFlags & gflags) | | static void activateImpl(ActiveFlags & flags, GlobalFlags & gflags) | |
| { | | { | |
| flags.template set<index>(); | | flags.template set<index>(); | |
| typedef typename StandardizeDependencies<Tag>::type StdDeps; | | typedef typename StandardizeDependencies<Tag>::type StdDeps; | |
|
| detail::ActivateDependencies<StdDeps>::template exec<Accu>(flag
s, gflags); | | acc_detail::ActivateDependencies<StdDeps>::template exec<Accu>(
flags, gflags); | |
| } | | } | |
| | | | |
| template <class ActiveFlags> | | template <class ActiveFlags> | |
| static bool isActiveImpl(ActiveFlags & flags) | | static bool isActiveImpl(ActiveFlags & flags) | |
| { | | { | |
| return flags.template test<index>(); | | return flags.template test<index>(); | |
| } | | } | |
| | | | |
| void setDirty() const | | void setDirty() const | |
| { | | { | |
| | | | |
| skipping to change at line 1504 | | skipping to change at line 1620 | |
| template <int INDEX> | | template <int INDEX> | |
| bool isDirtyImpl() const | | bool isDirtyImpl() const | |
| { | | { | |
| return next_.template isDirtyImpl<INDEX>(); | | return next_.template isDirtyImpl<INDEX>(); | |
| } | | } | |
| | | | |
| void reset() | | void reset() | |
| {} | | {} | |
| | | | |
| template <class Shape> | | template <class Shape> | |
|
| | | void setCoordinateOffset(Shape const &) | |
| | | {} | |
| | | | |
| | | template <class Shape> | |
| void reshape(Shape const &) | | void reshape(Shape const &) | |
| {} | | {} | |
| | | | |
| void operator+=(AccumulatorBase const &) | | void operator+=(AccumulatorBase const &) | |
| {} | | {} | |
| | | | |
| template <class U> | | template <class U> | |
| void update(U const &) | | void update(U const &) | |
| {} | | {} | |
| | | | |
| | | | |
| skipping to change at line 1541 | | skipping to change at line 1661 | |
| // * ensure that each accumulator is only called in its desired pa
ss as defined in A::workInPass | | // * ensure that each accumulator is only called in its desired pa
ss as defined in A::workInPass | |
| // * determine how many passes through the data are required | | // * determine how many passes through the data are required | |
| struct Accumulator | | struct Accumulator | |
| : public AccumulatorImpl | | : public AccumulatorImpl | |
| { | | { | |
| typedef Accumulator type; | | typedef Accumulator type; | |
| typedef Accumulator & reference; | | typedef Accumulator & reference; | |
| typedef Accumulator const & const_reference; | | typedef Accumulator const & const_reference; | |
| typedef AccumulatorImpl A; | | typedef AccumulatorImpl A; | |
| | | | |
|
| static const unsigned int workInPass = A::workInPass; | | static const unsigned int workInPass = A::workInPass; | |
| static const bool allowRuntimeActivation = CONFIG::allowRuntimeActi
vation; | | static const bool allowRuntimeActivation = CONFIG::allowRuntimeActi
vation; | |
| | | | |
| template <class T> | | template <class T> | |
| void resize(T const & t) | | void resize(T const & t) | |
| { | | { | |
| this->next_.resize(t); | | this->next_.resize(t); | |
| DecoratorImpl<Accumulator, workInPass, allowRuntimeActivation>:
:resize(*this, t); | | DecoratorImpl<Accumulator, workInPass, allowRuntimeActivation>:
:resize(*this, t); | |
| } | | } | |
| | | | |
| void reset() | | void reset() | |
| | | | |
| skipping to change at line 1576 | | skipping to change at line 1696 | |
| DecoratorImpl<Accumulator, N, allowRuntimeActivation>::exec(*th
is, t); | | DecoratorImpl<Accumulator, N, allowRuntimeActivation>::exec(*th
is, t); | |
| } | | } | |
| | | | |
| template <unsigned N, class T> | | template <unsigned N, class T> | |
| void pass(T const & t, double weight) | | void pass(T const & t, double weight) | |
| { | | { | |
| this->next_.template pass<N>(t, weight); | | this->next_.template pass<N>(t, weight); | |
| DecoratorImpl<Accumulator, N, allowRuntimeActivation>::exec(*th
is, t, weight); | | DecoratorImpl<Accumulator, N, allowRuntimeActivation>::exec(*th
is, t, weight); | |
| } | | } | |
| | | | |
|
| void merge(Accumulator const & o) | | void mergeImpl(Accumulator const & o) | |
| { | | { | |
|
| DecoratorImpl<Accumulator, Accumulator::workInPass, allowRuntim | | DecoratorImpl<Accumulator, Accumulator::workInPass, allowRuntim | |
| eActivation>::merge(*this, o); | | eActivation>::mergeImpl(*this, o); | |
| this->next_.merge(o.next_); | | this->next_.mergeImpl(o.next_); | |
| } | | } | |
| | | | |
| void applyHistogramOptions(HistogramOptions const & options) | | void applyHistogramOptions(HistogramOptions const & options) | |
| { | | { | |
| DecoratorImpl<Accumulator, workInPass, allowRuntimeActivation>:
:applyHistogramOptions(*this, options); | | DecoratorImpl<Accumulator, workInPass, allowRuntimeActivation>:
:applyHistogramOptions(*this, options); | |
| this->next_.applyHistogramOptions(options); | | this->next_.applyHistogramOptions(options); | |
| } | | } | |
| | | | |
|
| | | template <class SHAPE> | |
| | | void setCoordinateOffsetImpl(SHAPE const & offset) | |
| | | { | |
| | | this->setCoordinateOffset(offset); | |
| | | this->next_.setCoordinateOffsetImpl(offset); | |
| | | } | |
| | | | |
| static unsigned int passesRequired() | | static unsigned int passesRequired() | |
| { | | { | |
| return DecoratorImpl<Accumulator, workInPass, allowRuntimeActiv
ation>::passesRequired(); | | return DecoratorImpl<Accumulator, workInPass, allowRuntimeActiv
ation>::passesRequired(); | |
| } | | } | |
| | | | |
| template <class ActiveFlags> | | template <class ActiveFlags> | |
| static unsigned int passesRequired(ActiveFlags const & flags) | | static unsigned int passesRequired(ActiveFlags const & flags) | |
| { | | { | |
| return DecoratorImpl<Accumulator, workInPass, allowRuntimeActiv
ation>::passesRequired(flags); | | return DecoratorImpl<Accumulator, workInPass, allowRuntimeActiv
ation>::passesRequired(flags); | |
| } | | } | |
| | | | |
| skipping to change at line 1673 | | skipping to change at line 1800 | |
| {} | | {} | |
| | | | |
| type const * pointer_; | | type const * pointer_; | |
| }; | | }; | |
| | | | |
| typedef typename ConfigureAccumulatorChain<T, RegionTags, dynamic, Glob
alAccumulatorHandle>::type RegionAccumulatorChain; | | typedef typename ConfigureAccumulatorChain<T, RegionTags, dynamic, Glob
alAccumulatorHandle>::type RegionAccumulatorChain; | |
| | | | |
| typedef LabelDispatch<T, GlobalAccumulatorChain, RegionAccumulatorChain
> type; | | typedef LabelDispatch<T, GlobalAccumulatorChain, RegionAccumulatorChain
> type; | |
| }; | | }; | |
| | | | |
|
| } // namespace detail | | } // namespace acc_detail | |
| | | | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| /*
*/ | | /*
*/ | |
| /* accumulator chain
*/ | | /* accumulator chain
*/ | |
| /*
*/ | | /*
*/ | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| | | | |
| // Implement the high-level interface of an accumulator chain | | // Implement the high-level interface of an accumulator chain | |
| template <class T, class NEXT> | | template <class T, class NEXT> | |
| class AccumulatorChainImpl | | class AccumulatorChainImpl | |
| | | | |
| skipping to change at line 1720 | | skipping to change at line 1847 | |
| next_.applyHistogramOptions(options); | | next_.applyHistogramOptions(options); | |
| } | | } | |
| | | | |
| /** Set regional and global options for all histograms in the accumulat
or chain. | | /** Set regional and global options for all histograms in the accumulat
or chain. | |
| */ | | */ | |
| void setHistogramOptions(HistogramOptions const & regionoptions, Histog
ramOptions const & globaloptions) | | void setHistogramOptions(HistogramOptions const & regionoptions, Histog
ramOptions const & globaloptions) | |
| { | | { | |
| next_.applyHistogramOptions(regionoptions, globaloptions); | | next_.applyHistogramOptions(regionoptions, globaloptions); | |
| } | | } | |
| | | | |
|
| | | /** Set an offset for <tt>Coord<...></tt> statistics. | |
| | | | |
| | | If the offset is non-zero, coordinate statistics such as <tt>Region | |
| | | Center</tt> are computed | |
| | | in the global coordinate system defined by the \a offset. Without a | |
| | | n offset, these statistics | |
| | | are computed in the local coordinate system of the current region o | |
| | | f interest. | |
| | | */ | |
| | | template <class SHAPE> | |
| | | void setCoordinateOffset(SHAPE const & offset) | |
| | | { | |
| | | next_.setCoordinateOffsetImpl(offset); | |
| | | } | |
| | | | |
| /** Reset current_pass_ of the accumulator chain to 'reset_to_pass'. | | /** Reset current_pass_ of the accumulator chain to 'reset_to_pass'. | |
| */ | | */ | |
| void reset(unsigned int reset_to_pass = 0) | | void reset(unsigned int reset_to_pass = 0) | |
| { | | { | |
| current_pass_ = reset_to_pass; | | current_pass_ = reset_to_pass; | |
| if(reset_to_pass == 0) | | if(reset_to_pass == 0) | |
| next_.reset(); | | next_.reset(); | |
| } | | } | |
| | | | |
| template <unsigned N> | | template <unsigned N> | |
| void update(T const & t) | | void update(T const & t) | |
| { | | { | |
| if(current_pass_ == N) | | if(current_pass_ == N) | |
| { | | { | |
| next_.template pass<N>(t); | | next_.template pass<N>(t); | |
| } | | } | |
| else if(current_pass_ < N) | | else if(current_pass_ < N) | |
| { | | { | |
| current_pass_ = N; | | current_pass_ = N; | |
| if(N == 1) | | if(N == 1) | |
|
| next_.resize(detail::shapeOf(t)); | | next_.resize(acc_detail::shapeOf(t)); | |
| next_.template pass<N>(t); | | next_.template pass<N>(t); | |
| } | | } | |
| else | | else | |
| { | | { | |
| std::string message("AccumulatorChain::update(): cannot return
to pass "); | | std::string message("AccumulatorChain::update(): cannot return
to pass "); | |
| message << N << " after working on pass " << current_pass_ << "
."; | | message << N << " after working on pass " << current_pass_ << "
."; | |
| vigra_precondition(false, message); | | vigra_precondition(false, message); | |
| } | | } | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 1762 | | skipping to change at line 1901 | |
| void update(T const & t, double weight) | | void update(T const & t, double weight) | |
| { | | { | |
| if(current_pass_ == N) | | if(current_pass_ == N) | |
| { | | { | |
| next_.template pass<N>(t, weight); | | next_.template pass<N>(t, weight); | |
| } | | } | |
| else if(current_pass_ < N) | | else if(current_pass_ < N) | |
| { | | { | |
| current_pass_ = N; | | current_pass_ = N; | |
| if(N == 1) | | if(N == 1) | |
|
| next_.resize(detail::shapeOf(t)); | | next_.resize(acc_detail::shapeOf(t)); | |
| next_.template pass<N>(t, weight); | | next_.template pass<N>(t, weight); | |
| } | | } | |
| else | | else | |
| { | | { | |
| std::string message("AccumulatorChain::update(): cannot return
to pass "); | | std::string message("AccumulatorChain::update(): cannot return
to pass "); | |
| message << N << " after working on pass " << current_pass_ << "
."; | | message << N << " after working on pass " << current_pass_ << "
."; | |
| vigra_precondition(false, message); | | vigra_precondition(false, message); | |
| } | | } | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 1784 | | skipping to change at line 1923 | |
| */ | | */ | |
| void operator+=(AccumulatorChainImpl const & o) | | void operator+=(AccumulatorChainImpl const & o) | |
| { | | { | |
| merge(o); | | merge(o); | |
| } | | } | |
| | | | |
| /** Merge the accumulator chain with accumulator chain 'o'. This only w
orks if all selected statistics in the accumulator chain support the '+=' o
perator. See the documentations of the particular statistics for support in
formation. | | /** Merge the accumulator chain with accumulator chain 'o'. This only w
orks if all selected statistics in the accumulator chain support the '+=' o
perator. See the documentations of the particular statistics for support in
formation. | |
| */ | | */ | |
| void merge(AccumulatorChainImpl const & o) | | void merge(AccumulatorChainImpl const & o) | |
| { | | { | |
|
| next_.merge(o.next_); | | next_.mergeImpl(o.next_); | |
| } | | } | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| return next_.get(); | | return next_.get(); | |
| } | | } | |
| | | | |
| void operator()(T const & t) | | void operator()(T const & t) | |
| { | | { | |
| update<1>(t); | | update<1>(t); | |
| | | | |
| skipping to change at line 1886 | | skipping to change at line 2025 | |
| typedef double WeightType; | | typedef double WeightType; | |
| typedef vigra::CoupledIteratorType<dim, DataType, WeightType>::HandleTy
pe Handle; | | typedef vigra::CoupledIteratorType<dim, DataType, WeightType>::HandleTy
pe Handle; | |
| AccumulatorChain<Handle, Select<DataArg<1>, WeightArg<2>, Mean,...> > a
; | | AccumulatorChain<Handle, Select<DataArg<1>, WeightArg<2>, Mean,...> > a
; | |
| \endcode | | \endcode | |
| | | | |
| See \ref FeatureAccumulators for more information and examples of use. | | See \ref FeatureAccumulators for more information and examples of use. | |
| */ | | */ | |
| template <class T, class Selected, bool dynamic=false> | | template <class T, class Selected, bool dynamic=false> | |
| class AccumulatorChain | | class AccumulatorChain | |
| #ifndef DOXYGEN // hide AccumulatorChainImpl from documentation | | #ifndef DOXYGEN // hide AccumulatorChainImpl from documentation | |
|
| : public AccumulatorChainImpl<T, typename detail::ConfigureAccumulatorChain
<T, Selected, dynamic>::type> | | : public AccumulatorChainImpl<T, typename acc_detail::ConfigureAccumulatorC
hain<T, Selected, dynamic>::type> | |
| #endif | | #endif | |
| { | | { | |
| public: | | public: | |
| // \brief TypeList of Tags in the accumulator chain (?). | | // \brief TypeList of Tags in the accumulator chain (?). | |
|
| typedef typename detail::ConfigureAccumulatorChain<T, Selected, dynamic
>::TagList AccumulatorTags; | | typedef typename acc_detail::ConfigureAccumulatorChain<T, Selected, dyn
amic>::TagList AccumulatorTags; | |
| | | | |
| /** Before having seen data (current_pass_==0), the shape of the data c
an be changed... (?) | | /** Before having seen data (current_pass_==0), the shape of the data c
an be changed... (?) | |
| */ | | */ | |
| template <class U, int N> | | template <class U, int N> | |
| void reshape(TinyVector<U, N> const & s) | | void reshape(TinyVector<U, N> const & s) | |
| { | | { | |
| vigra_precondition(this->current_pass_ == 0, | | vigra_precondition(this->current_pass_ == 0, | |
| "AccumulatorChain::reshape(): cannot reshape after seeing data
. Call AccumulatorChain::reset() first."); | | "AccumulatorChain::reshape(): cannot reshape after seeing data
. Call AccumulatorChain::reset() first."); | |
| this->next_.resize(s); | | this->next_.resize(s); | |
| this->current_pass_ = 1; | | this->current_pass_ = 1; | |
| } | | } | |
| | | | |
| /** Return the names of all tags in the accumulator chain (selected sta
tistics and their dependencies). | | /** Return the names of all tags in the accumulator chain (selected sta
tistics and their dependencies). | |
| */ | | */ | |
| static ArrayVector<std::string> const & tagNames() | | static ArrayVector<std::string> const & tagNames() | |
| { | | { | |
|
| static const ArrayVector<std::string> n = collectTagNames(); | | static ArrayVector<std::string> * n = VIGRA_SAFE_STATIC(n, new Arra | |
| return n; | | yVector<std::string>(collectTagNames())); | |
| | | return *n; | |
| } | | } | |
| | | | |
| #ifdef DOXYGEN // hide AccumulatorChainImpl from documentation | | #ifdef DOXYGEN // hide AccumulatorChainImpl from documentation | |
| | | | |
| /** Set options for all histograms in the accumulator chain. See histogra
m accumulators for possible options. The function is ignored if there is no
histogram in the accumulator chain. | | /** Set options for all histograms in the accumulator chain. See histogra
m accumulators for possible options. The function is ignored if there is no
histogram in the accumulator chain. | |
| */ | | */ | |
| void setHistogramOptions(HistogramOptions const & options); | | void setHistogramOptions(HistogramOptions const & options); | |
| | | | |
|
| | | /** Set an offset for <tt>Coord<...></tt> statistics. | |
| | | | |
| | | If the offset is non-zero, coordinate statistics such as <tt>RegionCe | |
| | | nter</tt> are computed | |
| | | in the global coordinate system defined by the \a offset. Without an | |
| | | offset, these statistics | |
| | | are computed in the local coordinate system of the current region of | |
| | | interest. | |
| | | */ | |
| | | template <class SHAPE> | |
| | | void setCoordinateOffset(SHAPE const & offset); | |
| | | | |
| /** Reset current_pass_ of the accumulator chain to 'reset_to_pass'. */ | | /** Reset current_pass_ of the accumulator chain to 'reset_to_pass'. */ | |
| void reset(unsigned int reset_to_pass = 0); | | void reset(unsigned int reset_to_pass = 0); | |
| | | | |
| /** Equivalent to merge(o) . */ | | /** Equivalent to merge(o) . */ | |
| void operator+=(AccumulatorChainImpl const & o); | | void operator+=(AccumulatorChainImpl const & o); | |
| | | | |
| /** Merge the accumulator chain with accumulator chain 'o'. This only wor
ks if all selected statistics in the accumulator chain support the '+=' ope
rator. See the documentations of the particular statistics for support info
rmation. | | /** Merge the accumulator chain with accumulator chain 'o'. This only wor
ks if all selected statistics in the accumulator chain support the '+=' ope
rator. See the documentations of the particular statistics for support info
rmation. | |
| */ | | */ | |
| void merge(AccumulatorChainImpl const & o); | | void merge(AccumulatorChainImpl const & o); | |
| | | | |
| | | | |
| skipping to change at line 1946 | | skipping to change at line 2094 | |
| /** Return the number of passes required to compute all statistics in the
accumulator chain. | | /** Return the number of passes required to compute all statistics in the
accumulator chain. | |
| */ | | */ | |
| unsigned int passesRequired() const; | | unsigned int passesRequired() const; | |
| | | | |
| #endif | | #endif | |
| | | | |
| private: | | private: | |
| static ArrayVector<std::string> collectTagNames() | | static ArrayVector<std::string> collectTagNames() | |
| { | | { | |
| ArrayVector<std::string> n; | | ArrayVector<std::string> n; | |
|
| detail::CollectAccumulatorNames<AccumulatorTags>::exec(n); | | acc_detail::CollectAccumulatorNames<AccumulatorTags>::exec(n); | |
| std::sort(n.begin(), n.end()); | | std::sort(n.begin(), n.end()); | |
| return n; | | return n; | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| | | template <unsigned int N, class T1, class T2, class T3, class T4, class T5, | |
| | | class Selected, bool dynamic> | |
| | | class AccumulatorChain<CoupledArrays<N, T1, T2, T3, T4, T5>, Selected, dyna | |
| | | mic> | |
| | | : public AccumulatorChain<typename CoupledArrays<N, T1, T2, T3, T4, T5>::Ha | |
| | | ndleType, Selected, dynamic> | |
| | | {}; | |
| | | | |
| // Create a dynamic accumulator chain containing the Selected statistic
s and their dependencies. | | // Create a dynamic accumulator chain containing the Selected statistic
s and their dependencies. | |
| // Statistics will only be computed if activate<Tag>() is called at run
time. | | // Statistics will only be computed if activate<Tag>() is called at run
time. | |
| /** \brief Create a dynamic accumulator chain containing the selected stati
stics and their dependencies. | | /** \brief Create a dynamic accumulator chain containing the selected stati
stics and their dependencies. | |
| | | | |
| DynamicAccumulatorChain is used to compute global statistics with run-t
ime activation. A set of statistics is selected at run-time and from this s
et statistics can be activated at run-time by calling activate<stat>() or a
ctivate(std::string stat). | | DynamicAccumulatorChain is used to compute global statistics with run-t
ime activation. A set of statistics is selected at run-time and from this s
et statistics can be activated at run-time by calling activate<stat>() or a
ctivate(std::string stat). | |
| | | | |
| The template parameters are as follows: | | The template parameters are as follows: | |
| - T: The input type | | - T: The input type | |
| - either element type of the data(e.g. double, int, RGBValue, ...) | | - either element type of the data(e.g. double, int, RGBValue, ...) | |
| - or type of CoupledHandle (for access to coordinates and/or weight
s) | | - or type of CoupledHandle (for access to coordinates and/or weight
s) | |
| | | | |
| skipping to change at line 2015 | | skipping to change at line 2168 | |
| /** Activate all statistics in the accumulator chain. | | /** Activate all statistics in the accumulator chain. | |
| */ | | */ | |
| void activateAll() | | void activateAll() | |
| { | | { | |
| getAccumulator<AccumulatorEnd>(*this).active_accumulators_.set(); | | getAccumulator<AccumulatorEnd>(*this).active_accumulators_.set(); | |
| } | | } | |
| /** Return true if the statistic 'tag' is active, i.e. activate(std::st
ring tag) or activate<TAG>() has been called. If the statistic is not in th
e accumulator chain a PreconditionViolation is thrown. (Note that alias nam
es are not recognized.) | | /** Return true if the statistic 'tag' is active, i.e. activate(std::st
ring tag) or activate<TAG>() has been called. If the statistic is not in th
e accumulator chain a PreconditionViolation is thrown. (Note that alias nam
es are not recognized.) | |
| */ | | */ | |
| bool isActive(std::string tag) const | | bool isActive(std::string tag) const | |
| { | | { | |
|
| detail::TagIsActive_Visitor v; | | acc_detail::TagIsActive_Visitor v; | |
| vigra_precondition(isActiveImpl(tag, v), | | vigra_precondition(isActiveImpl(tag, v), | |
| std::string("DynamicAccumulatorChain::isActive(): Tag '") + tag
+ "' not found."); | | std::string("DynamicAccumulatorChain::isActive(): Tag '") + tag
+ "' not found."); | |
| return v.result; | | return v.result; | |
| } | | } | |
| | | | |
| /** %isActive\<TAG\>() returns true if statistic 'TAG' is active, i.e.
activate(std::string tag) or activate<TAG>() has been called. If the statis
tic is not in the accumulator chain, true is returned. (?) | | /** %isActive\<TAG\>() returns true if statistic 'TAG' is active, i.e.
activate(std::string tag) or activate<TAG>() has been called. If the statis
tic is not in the accumulator chain, true is returned. (?) | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| bool isActive() const | | bool isActive() const | |
| { | | { | |
| | | | |
| skipping to change at line 2051 | | skipping to change at line 2204 | |
| */ | | */ | |
| unsigned int passesRequired() const | | unsigned int passesRequired() const | |
| { | | { | |
| return InternalBaseType::passesRequired(getAccumulator<AccumulatorE
nd>(*this).active_accumulators_); | | return InternalBaseType::passesRequired(getAccumulator<AccumulatorE
nd>(*this).active_accumulators_); | |
| } | | } | |
| | | | |
| protected: | | protected: | |
| | | | |
| bool activateImpl(std::string tag) | | bool activateImpl(std::string tag) | |
| { | | { | |
|
| return detail::ApplyVisitorToTag<AccumulatorTags>::exec(*this, | | return acc_detail::ApplyVisitorToTag<AccumulatorTags>::exec(*this, | |
| normalizeString(tag), detail::Acti | | normalizeString(tag), acc_detail:: | |
| vateTag_Visitor()); | | ActivateTag_Visitor()); | |
| } | | } | |
| | | | |
|
| bool isActiveImpl(std::string tag, detail::TagIsActive_Visitor & v) con
st | | bool isActiveImpl(std::string tag, acc_detail::TagIsActive_Visitor & v)
const | |
| { | | { | |
|
| return detail::ApplyVisitorToTag<AccumulatorTags>::exec(*this, norm
alizeString(tag), v); | | return acc_detail::ApplyVisitorToTag<AccumulatorTags>::exec(*this,
normalizeString(tag), v); | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| | | template <unsigned int N, class T1, class T2, class T3, class T4, class T5, | |
| | | class Selected> | |
| | | class DynamicAccumulatorChain<CoupledArrays<N, T1, T2, T3, T4, T5>, Selecte | |
| | | d> | |
| | | : public DynamicAccumulatorChain<typename CoupledArrays<N, T1, T2, T3, T4, | |
| | | T5>::HandleType, Selected> | |
| | | {}; | |
| | | | |
| /** \brief Create an array of accumulator chains containing the selected pe
r-region and global statistics and their dependencies. | | /** \brief Create an array of accumulator chains containing the selected pe
r-region and global statistics and their dependencies. | |
| | | | |
| AccumulatorChainArray is used to compute per-region statistics (as well
as global statistics). The statistics are selected at compile-time. An arr
ay of accumulator chains (one per region) for region statistics is created
and one accumulator chain for global statistics. The region labels always s
tart at 0. Use the Global modifier to compute global statistics (by default
per-region statistics are computed). | | AccumulatorChainArray is used to compute per-region statistics (as well
as global statistics). The statistics are selected at compile-time. An arr
ay of accumulator chains (one per region) for region statistics is created
and one accumulator chain for global statistics. The region labels always s
tart at 0. Use the Global modifier to compute global statistics (by default
per-region statistics are computed). | |
| | | | |
| The template parameters are as follows: | | The template parameters are as follows: | |
| - T: The input type, type of CoupledHandle (for access to coordinates,
labels and weights) | | - T: The input type, type of CoupledHandle (for access to coordinates,
labels and weights) | |
| - Selected: statistics to be computed and index specifier for the Coupl
edHandle, wrapped with Select | | - Selected: statistics to be computed and index specifier for the Coupl
edHandle, wrapped with Select | |
| | | | |
| Usage: | | Usage: | |
| \code | | \code | |
| | | | |
| skipping to change at line 2084 | | skipping to change at line 2242 | |
| typedef unsigned int LabelType; | | typedef unsigned int LabelType; | |
| typedef vigra::CoupledIteratorType<dim, DataType, WeightType, LabelType
>::HandleType Handle; | | typedef vigra::CoupledIteratorType<dim, DataType, WeightType, LabelType
>::HandleType Handle; | |
| AccumulatorChainArray<Handle, Select<DataArg<1>, WeightArg<2>, LabelArg
<3>, Mean, Variance, ...> > a; | | AccumulatorChainArray<Handle, Select<DataArg<1>, WeightArg<2>, LabelArg
<3>, Mean, Variance, ...> > a; | |
| \endcode | | \endcode | |
| | | | |
| See \ref FeatureAccumulators for more information and examples of use. | | See \ref FeatureAccumulators for more information and examples of use. | |
| */ | | */ | |
| template <class T, class Selected, bool dynamic=false> | | template <class T, class Selected, bool dynamic=false> | |
| class AccumulatorChainArray | | class AccumulatorChainArray | |
| #ifndef DOXYGEN //hide AccumulatorChainImpl vom documentation | | #ifndef DOXYGEN //hide AccumulatorChainImpl vom documentation | |
|
| : public AccumulatorChainImpl<T, typename detail::ConfigureAccumulatorChain
Array<T, Selected, dynamic>::type> | | : public AccumulatorChainImpl<T, typename acc_detail::ConfigureAccumulatorC
hainArray<T, Selected, dynamic>::type> | |
| #endif | | #endif | |
| { | | { | |
| public: | | public: | |
|
| typedef typename detail::ConfigureAccumulatorChainArray<T, Selected, dy | | typedef AccumulatorChainImpl<T, typename acc_detail::ConfigureAccumulat | |
| namic> Creator; | | orChainArray<T, Selected, dynamic>::type> base_type; | |
| | | typedef typename acc_detail::ConfigureAccumulatorChainArray<T, Selected | |
| | | , dynamic> Creator; | |
| typedef typename Creator::TagList AccumulatorTags; | | typedef typename Creator::TagList AccumulatorTags; | |
| typedef typename Creator::GlobalTags GlobalTags; | | typedef typename Creator::GlobalTags GlobalTags; | |
| typedef typename Creator::RegionTags RegionTags; | | typedef typename Creator::RegionTags RegionTags; | |
| | | | |
| /** Statistics will not be computed for label l. Note that only one lab
el can be ignored. | | /** Statistics will not be computed for label l. Note that only one lab
el can be ignored. | |
| */ | | */ | |
| void ignoreLabel(MultiArrayIndex l) | | void ignoreLabel(MultiArrayIndex l) | |
| { | | { | |
| this->next_.ignoreLabel(l); | | this->next_.ignoreLabel(l); | |
| } | | } | |
| | | | |
|
| | | /** Ask for a label to be ignored. Default: -1 (meaning that no label i | |
| | | s ignored). | |
| | | */ | |
| | | MultiArrayIndex ignoredLabel() const | |
| | | { | |
| | | return this->next_.ignoredLabel(); | |
| | | } | |
| | | | |
| /** Set the maximum region label (e.g. for merging two accumulator chai
ns). | | /** Set the maximum region label (e.g. for merging two accumulator chai
ns). | |
| */ | | */ | |
| void setMaxRegionLabel(unsigned label) | | void setMaxRegionLabel(unsigned label) | |
| { | | { | |
| this->next_.setMaxRegionLabel(label); | | this->next_.setMaxRegionLabel(label); | |
| } | | } | |
| | | | |
|
| /** %Maximum region label. (equal to regionCount() - 1) | | /** Maximum region label. (equal to regionCount() - 1) | |
| */ | | */ | |
| MultiArrayIndex maxRegionLabel() const | | MultiArrayIndex maxRegionLabel() const | |
| { | | { | |
| return this->next_.maxRegionLabel(); | | return this->next_.maxRegionLabel(); | |
| } | | } | |
| | | | |
| /** Number of Regions. (equal to maxRegionLabel() + 1) | | /** Number of Regions. (equal to maxRegionLabel() + 1) | |
| */ | | */ | |
| unsigned int regionCount() const | | unsigned int regionCount() const | |
| { | | { | |
| return this->next_.regions_.size(); | | return this->next_.regions_.size(); | |
| } | | } | |
| | | | |
|
| | | /** Equivalent to <tt>merge(o)</tt>. | |
| | | */ | |
| | | void operator+=(AccumulatorChainArray const & o) | |
| | | { | |
| | | merge(o); | |
| | | } | |
| | | | |
| /** Merge region i with region j. | | /** Merge region i with region j. | |
| */ | | */ | |
| void merge(unsigned i, unsigned j) | | void merge(unsigned i, unsigned j) | |
| { | | { | |
| vigra_precondition(i <= maxRegionLabel() && j <= maxRegionLabel(), | | vigra_precondition(i <= maxRegionLabel() && j <= maxRegionLabel(), | |
| "AccumulatorChainArray::merge(): region labels out of range."); | | "AccumulatorChainArray::merge(): region labels out of range."); | |
|
| this->next_.merge(i, j); | | this->next_.mergeImpl(i, j); | |
| } | | } | |
| | | | |
| /** Merge with accumulator chain o. maxRegionLabel() of the two accumul
ators must be equal. | | /** Merge with accumulator chain o. maxRegionLabel() of the two accumul
ators must be equal. | |
| */ | | */ | |
| void merge(AccumulatorChainArray const & o) | | void merge(AccumulatorChainArray const & o) | |
| { | | { | |
| if(maxRegionLabel() == -1) | | if(maxRegionLabel() == -1) | |
| setMaxRegionLabel(o.maxRegionLabel()); | | setMaxRegionLabel(o.maxRegionLabel()); | |
| vigra_precondition(maxRegionLabel() == o.maxRegionLabel(), | | vigra_precondition(maxRegionLabel() == o.maxRegionLabel(), | |
| "AccumulatorChainArray::merge(): maxRegionLabel must be equal."
); | | "AccumulatorChainArray::merge(): maxRegionLabel must be equal."
); | |
|
| this->next_.merge(o.next_); | | this->next_.mergeImpl(o.next_); | |
| } | | } | |
| | | | |
| /** Merge with accumulator chain o using a mapping between labels of th
e two accumulators. Label l of accumulator chain o is mapped to labelMappin
g[l]. Hence, all elements of labelMapping must be <= maxRegionLabel() and s
ize of labelMapping must match o.regionCount(). | | /** Merge with accumulator chain o using a mapping between labels of th
e two accumulators. Label l of accumulator chain o is mapped to labelMappin
g[l]. Hence, all elements of labelMapping must be <= maxRegionLabel() and s
ize of labelMapping must match o.regionCount(). | |
| */ | | */ | |
| template <class ArrayLike> | | template <class ArrayLike> | |
| void merge(AccumulatorChainArray const & o, ArrayLike const & labelMapp
ing) | | void merge(AccumulatorChainArray const & o, ArrayLike const & labelMapp
ing) | |
| { | | { | |
| vigra_precondition(labelMapping.size() == o.regionCount(), | | vigra_precondition(labelMapping.size() == o.regionCount(), | |
| "AccumulatorChainArray::merge(): labelMapping.size() must match
regionCount() of RHS."); | | "AccumulatorChainArray::merge(): labelMapping.size() must match
regionCount() of RHS."); | |
|
| this->next_.merge(o.next_, labelMapping); | | this->next_.mergeImpl(o.next_, labelMapping); | |
| } | | } | |
| | | | |
| /** Return names of all tags in the accumulator chain (selected statist
ics and their dependencies). | | /** Return names of all tags in the accumulator chain (selected statist
ics and their dependencies). | |
| */ | | */ | |
| static ArrayVector<std::string> const & tagNames() | | static ArrayVector<std::string> const & tagNames() | |
| { | | { | |
| static const ArrayVector<std::string> n = collectTagNames(); | | static const ArrayVector<std::string> n = collectTagNames(); | |
| return n; | | return n; | |
| } | | } | |
| | | | |
|
| | | using base_type::setCoordinateOffset; | |
| | | | |
| | | /** Set an offset for <tt>Coord<...></tt> statistics for region \a k. | |
| | | | |
| | | If the offset is non-zero, coordinate statistics such as <tt>Region | |
| | | Center</tt> are computed | |
| | | in the global coordinate system defined by the \a offset. Without a | |
| | | n offset, these statistics | |
| | | are computed in the local coordinate system of the current region o | |
| | | f interest. | |
| | | */ | |
| | | template <class SHAPE> | |
| | | void setCoordinateOffset(MultiArrayIndex k, SHAPE const & offset) | |
| | | { | |
| | | this->next_.setCoordinateOffsetImpl(k, offset); | |
| | | } | |
| | | | |
| #ifdef DOXYGEN // hide AccumulatorChainImpl from documentation | | #ifdef DOXYGEN // hide AccumulatorChainImpl from documentation | |
| | | | |
|
| /** \copydoc AccumulatorChain::setHistogramOptions(HistogramOptions const
&) */ | | /** \copydoc vigra::acc::AccumulatorChain::setHistogramOptions(HistogramO
ptions const &) */ | |
| void setHistogramOptions(HistogramOptions const & options); | | void setHistogramOptions(HistogramOptions const & options); | |
| | | | |
| /** Set regional and global options for all histograms in the accumulator
chain. | | /** Set regional and global options for all histograms in the accumulator
chain. | |
| */ | | */ | |
| void setHistogramOptions(HistogramOptions const & regionoptions, Histogra
mOptions const & globaloptions); | | void setHistogramOptions(HistogramOptions const & regionoptions, Histogra
mOptions const & globaloptions); | |
| | | | |
|
| /** \copydoc AccumulatorChain::reset() */ | | /** \copydoc vigra::acc::AccumulatorChain::setCoordinateOffset(SHAPE cons | |
| | | t &) | |
| | | */ | |
| | | template <class SHAPE> | |
| | | void setCoordinateOffset(SHAPE const & offset) | |
| | | | |
| | | /** \copydoc vigra::acc::AccumulatorChain::reset() */ | |
| void reset(unsigned int reset_to_pass = 0); | | void reset(unsigned int reset_to_pass = 0); | |
| | | | |
|
| /** \copydoc AccumulatorChain::operator+=() */ | | /** \copydoc vigra::acc::AccumulatorChain::operator+=() */ | |
| void operator+=(AccumulatorChainImpl const & o); | | void operator+=(AccumulatorChainImpl const & o); | |
| | | | |
|
| /** \copydoc AccumulatorChain::updatePassN(T const &,unsigned int) */ | | /** \copydoc vigra::acc::AccumulatorChain::updatePassN(T const &,unsigned
int) */ | |
| void updatePassN(T const & t, unsigned int N); | | void updatePassN(T const & t, unsigned int N); | |
| | | | |
|
| /** \copydoc AccumulatorChain::updatePassN(T const &,double,unsigned int)
*/ | | /** \copydoc vigra::acc::AccumulatorChain::updatePassN(T const &,double,u
nsigned int) */ | |
| void updatePassN(T const & t, double weight, unsigned int N); | | void updatePassN(T const & t, double weight, unsigned int N); | |
| | | | |
| #endif | | #endif | |
| | | | |
| private: | | private: | |
| static ArrayVector<std::string> collectTagNames() | | static ArrayVector<std::string> collectTagNames() | |
| { | | { | |
| ArrayVector<std::string> n; | | ArrayVector<std::string> n; | |
|
| detail::CollectAccumulatorNames<AccumulatorTags>::exec(n); | | acc_detail::CollectAccumulatorNames<AccumulatorTags>::exec(n); | |
| std::sort(n.begin(), n.end()); | | std::sort(n.begin(), n.end()); | |
| return n; | | return n; | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| | | template <unsigned int N, class T1, class T2, class T3, class T4, class T5, | |
| | | class Selected, bool dynamic> | |
| | | class AccumulatorChainArray<CoupledArrays<N, T1, T2, T3, T4, T5>, Selected, | |
| | | dynamic> | |
| | | : public AccumulatorChainArray<typename CoupledArrays<N, T1, T2, T3, T4, T5 | |
| | | >::HandleType, Selected, dynamic> | |
| | | {}; | |
| | | | |
| /** \brief Create an array of dynamic accumulator chains containing the sel
ected per-region and global statistics and their dependencies. | | /** \brief Create an array of dynamic accumulator chains containing the sel
ected per-region and global statistics and their dependencies. | |
| | | | |
| DynamicAccumulatorChainArray is used to compute per-region statistics (
as well as global statistics) with run-time activation. A set of statistics
is selected at run-time and from this set statistics can be activated at r
un-time by calling activate<stat>() or activate(std::string stat). | | DynamicAccumulatorChainArray is used to compute per-region statistics (
as well as global statistics) with run-time activation. A set of statistics
is selected at run-time and from this set statistics can be activated at r
un-time by calling activate<stat>() or activate(std::string stat). | |
| | | | |
| The template parameters are as follows: | | The template parameters are as follows: | |
| - T: The input type, type of CoupledHandle (for access to coordinates,
labels and weights) | | - T: The input type, type of CoupledHandle (for access to coordinates,
labels and weights) | |
| - Selected: statistics to be computed and index specifier for the Coupl
edHandle, wrapped with Select | | - Selected: statistics to be computed and index specifier for the Coupl
edHandle, wrapped with Select | |
| | | | |
| Usage: | | Usage: | |
| \code | | \code | |
| | | | |
| skipping to change at line 2243 | | skipping to change at line 2440 | |
| /** \copydoc DynamicAccumulatorChain::activateAll() */ | | /** \copydoc DynamicAccumulatorChain::activateAll() */ | |
| void activateAll() | | void activateAll() | |
| { | | { | |
| this->next_.activateAll(); | | this->next_.activateAll(); | |
| } | | } | |
| | | | |
| /** Return true if the statistic 'tag' is active, i.e. activate(std::st
ring tag) or activate<TAG>() has been called. If the statistic is not in th
e accumulator chain a PreconditionViolation is thrown. (Note that alias nam
es are not recognized.) | | /** Return true if the statistic 'tag' is active, i.e. activate(std::st
ring tag) or activate<TAG>() has been called. If the statistic is not in th
e accumulator chain a PreconditionViolation is thrown. (Note that alias nam
es are not recognized.) | |
| */ | | */ | |
| bool isActive(std::string tag) const | | bool isActive(std::string tag) const | |
| { | | { | |
|
| detail::TagIsActive_Visitor v; | | acc_detail::TagIsActive_Visitor v; | |
| vigra_precondition(isActiveImpl(tag, v), | | vigra_precondition(isActiveImpl(tag, v), | |
| std::string("DynamicAccumulatorChainArray::isActive(): Tag '")
+ tag + "' not found."); | | std::string("DynamicAccumulatorChainArray::isActive(): Tag '")
+ tag + "' not found."); | |
| return v.result; | | return v.result; | |
| } | | } | |
| | | | |
| /** %isActive\<TAG\>() returns true if statistic 'TAG' is active, i.e.
activate(std::string tag) or activate<TAG>() has been called. If the statis
tic is not in the accumulator chain, true is returned. (?) | | /** %isActive\<TAG\>() returns true if statistic 'TAG' is active, i.e.
activate(std::string tag) or activate<TAG>() has been called. If the statis
tic is not in the accumulator chain, true is returned. (?) | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| bool isActive() const | | bool isActive() const | |
| { | | { | |
| | | | |
| skipping to change at line 2277 | | skipping to change at line 2474 | |
| /** \copydoc DynamicAccumulatorChain::passesRequired() */ | | /** \copydoc DynamicAccumulatorChain::passesRequired() */ | |
| unsigned int passesRequired() const | | unsigned int passesRequired() const | |
| { | | { | |
| return this->next_.passesRequiredDynamic(); | | return this->next_.passesRequiredDynamic(); | |
| } | | } | |
| | | | |
| protected: | | protected: | |
| | | | |
| bool activateImpl(std::string tag) | | bool activateImpl(std::string tag) | |
| { | | { | |
|
| return detail::ApplyVisitorToTag<AccumulatorTags>::exec(this->next_ | | return acc_detail::ApplyVisitorToTag<AccumulatorTags>::exec(this->n | |
| , | | ext_, | |
| normalizeString(tag), detail::Acti | | normalizeString(tag), acc_detail:: | |
| vateTag_Visitor()); | | ActivateTag_Visitor()); | |
| } | | } | |
| | | | |
|
| bool isActiveImpl(std::string tag, detail::TagIsActive_Visitor & v) con
st | | bool isActiveImpl(std::string tag, acc_detail::TagIsActive_Visitor & v)
const | |
| { | | { | |
|
| return detail::ApplyVisitorToTag<AccumulatorTags>::exec(this->next_
, normalizeString(tag), v); | | return acc_detail::ApplyVisitorToTag<AccumulatorTags>::exec(this->n
ext_, normalizeString(tag), v); | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| | | template <unsigned int N, class T1, class T2, class T3, class T4, class T5, | |
| | | class Selected> | |
| | | class DynamicAccumulatorChainArray<CoupledArrays<N, T1, T2, T3, T4, T5>, Se | |
| | | lected> | |
| | | : public DynamicAccumulatorChainArray<typename CoupledArrays<N, T1, T2, T3, | |
| | | T4, T5>::HandleType, Selected> | |
| | | {}; | |
| | | | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| /*
*/ | | /*
*/ | |
| /* generic access functions
*/ | | /* generic access functions
*/ | |
| /*
*/ | | /*
*/ | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| | | | |
| template <class TAG> | | template <class TAG> | |
| struct Error__Attempt_to_access_inactive_statistic; | | struct Error__Attempt_to_access_inactive_statistic; | |
| | | | |
|
| namespace detail { | | namespace acc_detail { | |
| | | | |
| // accumulator lookup rules: find the accumulator that implements TAG | | // accumulator lookup rules: find the accumulator that implements TAG | |
| | | | |
| // When A does not implement TAG, continue search in A::InternalBaseTyp
e. | | // When A does not implement TAG, continue search in A::InternalBaseTyp
e. | |
| template <class TAG, class A, class FromTag=typename A::Tag> | | template <class TAG, class A, class FromTag=typename A::Tag> | |
| struct LookupTagImpl | | struct LookupTagImpl | |
| #ifndef DOXYGEN | | #ifndef DOXYGEN | |
| : public LookupTagImpl<TAG, typename A::InternalBaseType> | | : public LookupTagImpl<TAG, typename A::InternalBaseType> | |
| #endif | | #endif | |
| {}; | | {}; | |
| | | | |
| skipping to change at line 2402 | | skipping to change at line 2604 | |
| struct LookupTagImpl<LabelDispatchTag, A, LabelDispatchTag> | | struct LookupTagImpl<LabelDispatchTag, A, LabelDispatchTag> | |
| { | | { | |
| typedef LabelDispatchTag Tag; | | typedef LabelDispatchTag Tag; | |
| typedef A type; | | typedef A type; | |
| typedef A & reference; | | typedef A & reference; | |
| typedef A * pointer; | | typedef A * pointer; | |
| typedef void value_type; | | typedef void value_type; | |
| typedef void result_type; | | typedef void result_type; | |
| }; | | }; | |
| | | | |
|
| } // namespace detail | | } // namespace acc_detail | |
| | | | |
| // Lookup the accumulator in the chain A that implements the given TAG. | | // Lookup the accumulator in the chain A that implements the given TAG. | |
| template <class Tag, class A> | | template <class Tag, class A> | |
| struct LookupTag | | struct LookupTag | |
|
| : public detail::LookupTagImpl<typename StandardizeTag<Tag>::type, A> | | : public acc_detail::LookupTagImpl<typename StandardizeTag<Tag>::type, A> | |
| {}; | | {}; | |
| | | | |
| // Lookup the dependency TAG of the accumulator A. | | // Lookup the dependency TAG of the accumulator A. | |
| // This template ensures that dependencies are used with matching modif
iers. | | // This template ensures that dependencies are used with matching modif
iers. | |
| // Specifically, if you search for Count as a dependency of Weighted<Me
an>, the search | | // Specifically, if you search for Count as a dependency of Weighted<Me
an>, the search | |
| // actually returns Weighted<Count>, wheras Count will be returned for
plain Mean. | | // actually returns Weighted<Count>, wheras Count will be returned for
plain Mean. | |
| template <class Tag, class A, class TargetTag> | | template <class Tag, class A, class TargetTag> | |
| struct LookupDependency | | struct LookupDependency | |
|
| : public detail::LookupTagImpl< | | : public acc_detail::LookupTagImpl< | |
| typename TransferModifiers<TargetTag, typename StandardizeTag<Tag>::
type>::type, A> | | typename TransferModifiers<TargetTag, typename StandardizeTag<Tag>::
type>::type, A> | |
| {}; | | {}; | |
| | | | |
|
| namespace detail { | | namespace acc_detail { | |
| | | | |
| // CastImpl applies the same rules as LookupTagImpl, but returns a refe
rence to an | | // CastImpl applies the same rules as LookupTagImpl, but returns a refe
rence to an | |
| // accumulator instance rather than an accumulator type | | // accumulator instance rather than an accumulator type | |
| template <class Tag, class FromTag, class reference> | | template <class Tag, class FromTag, class reference> | |
| struct CastImpl | | struct CastImpl | |
| { | | { | |
| template <class A> | | template <class A> | |
| static reference exec(A & a) | | static reference exec(A & a) | |
| { | | { | |
| return CastImpl<Tag, typename A::InternalBaseType::Tag, reference>:
:exec(a.next_); | | return CastImpl<Tag, typename A::InternalBaseType::Tag, reference>:
:exec(a.next_); | |
| | | | |
| skipping to change at line 2538 | | skipping to change at line 2740 | |
| template <class reference> | | template <class reference> | |
| struct CastImpl<LabelDispatchTag, LabelDispatchTag, reference> | | struct CastImpl<LabelDispatchTag, LabelDispatchTag, reference> | |
| { | | { | |
| template <class A> | | template <class A> | |
| static reference exec(A & a) | | static reference exec(A & a) | |
| { | | { | |
| return a; | | return a; | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| } // namespace detail | | } // namespace acc_detail | |
| | | | |
| // Get a reference to the accumulator TAG in the accumulator chain A | | // Get a reference to the accumulator TAG in the accumulator chain A | |
| /** Get a reference to the accumulator 'TAG' in the accumulator chain 'a'.
This can be useful for example to update a certain accumulator with data, s
et individual options or get information about a certain accumulator.\n | | /** Get a reference to the accumulator 'TAG' in the accumulator chain 'a'.
This can be useful for example to update a certain accumulator with data, s
et individual options or get information about a certain accumulator.\n | |
| Example of use (set options): | | Example of use (set options): | |
| \code | | \code | |
| vigra::MultiArray<2, double> data(...); | | vigra::MultiArray<2, double> data(...); | |
| typedef UserRangeHistogram<40> SomeHistogram; //binCount set at compi
le time | | typedef UserRangeHistogram<40> SomeHistogram; //binCount set at compi
le time | |
| typedef UserRangeHistogram<0> SomeHistogram2; // binCount must be set a
t run-time | | typedef UserRangeHistogram<0> SomeHistogram2; // binCount must be set a
t run-time | |
| AccumulatorChain<DataType, Select<SomeHistogram, SomeHistogram2> > a; | | AccumulatorChain<DataType, Select<SomeHistogram, SomeHistogram2> > a; | |
| | | | |
| | | | |
| skipping to change at line 2571 | | skipping to change at line 2773 | |
| std::cout << "passes required by Mean: " << getAccumulator<Mean>(a).passe
sRequired() << std::endl; | | std::cout << "passes required by Mean: " << getAccumulator<Mean>(a).passe
sRequired() << std::endl; | |
| \endcode | | \endcode | |
| See \ref FeatureAccumulators for more information about feature computation
via accumulators. | | See \ref FeatureAccumulators for more information about feature computation
via accumulators. | |
| */ | | */ | |
| template <class TAG, class A> | | template <class TAG, class A> | |
| inline typename LookupTag<TAG, A>::reference | | inline typename LookupTag<TAG, A>::reference | |
| getAccumulator(A & a) | | getAccumulator(A & a) | |
| { | | { | |
| typedef typename LookupTag<TAG, A>::Tag StandardizedTag; | | typedef typename LookupTag<TAG, A>::Tag StandardizedTag; | |
| typedef typename LookupTag<TAG, A>::reference reference; | | typedef typename LookupTag<TAG, A>::reference reference; | |
|
| return detail::CastImpl<StandardizedTag, typename A::Tag, reference>::e
xec(a); | | return acc_detail::CastImpl<StandardizedTag, typename A::Tag, reference
>::exec(a); | |
| } | | } | |
| | | | |
| // Get a reference to the accumulator TAG for region 'label' in the acc
umulator chain A | | // Get a reference to the accumulator TAG for region 'label' in the acc
umulator chain A | |
| /** Get a reference to the accumulator 'TAG' for region 'label' in the accu
mulator chain 'a'. | | /** Get a reference to the accumulator 'TAG' for region 'label' in the accu
mulator chain 'a'. | |
| */ | | */ | |
| template <class TAG, class A> | | template <class TAG, class A> | |
| inline typename LookupTag<TAG, A>::reference | | inline typename LookupTag<TAG, A>::reference | |
| getAccumulator(A & a, MultiArrayIndex label) | | getAccumulator(A & a, MultiArrayIndex label) | |
| { | | { | |
| typedef typename LookupTag<TAG, A>::Tag StandardizedTag; | | typedef typename LookupTag<TAG, A>::Tag StandardizedTag; | |
| typedef typename LookupTag<TAG, A>::reference reference; | | typedef typename LookupTag<TAG, A>::reference reference; | |
|
| return detail::CastImpl<StandardizedTag, typename A::Tag, reference>::e
xec(a, label); | | return acc_detail::CastImpl<StandardizedTag, typename A::Tag, reference
>::exec(a, label); | |
| } | | } | |
| | | | |
| // get the result of the accumulator specified by TAG | | // get the result of the accumulator specified by TAG | |
| /** Get the result of the accumulator 'TAG' in the accumulator chain 'a'.\n | | /** Get the result of the accumulator 'TAG' in the accumulator chain 'a'.\n | |
| Example of use: | | Example of use: | |
| \code | | \code | |
| vigra::MultiArray<2, double> data(...); | | vigra::MultiArray<2, double> data(...); | |
| AccumulatorChain<DataType, Select<Variance, Mean, StdDev> > a; | | AccumulatorChain<DataType, Select<Variance, Mean, StdDev> > a; | |
| extractFeatures(data.begin(), data.end(), a); | | extractFeatures(data.begin(), data.end(), a); | |
| double mean = get<Mean>(a); | | double mean = get<Mean>(a); | |
| | | | |
| skipping to change at line 2642 | | skipping to change at line 2844 | |
| // Get the result of the accumulator specified by TAG without checking
if the accumulator is active. | | // Get the result of the accumulator specified by TAG without checking
if the accumulator is active. | |
| // This must be used within an accumulator implementation to access dep
endencies because | | // This must be used within an accumulator implementation to access dep
endencies because | |
| // it applies the approprate modifiers to the given TAG. It must not be
used in other situations. | | // it applies the approprate modifiers to the given TAG. It must not be
used in other situations. | |
| // FIXME: is there a shorter name? | | // FIXME: is there a shorter name? | |
| template <class TAG, class A> | | template <class TAG, class A> | |
| inline typename LookupDependency<TAG, A>::result_type | | inline typename LookupDependency<TAG, A>::result_type | |
| getDependency(A const & a) | | getDependency(A const & a) | |
| { | | { | |
| typedef typename LookupDependency<TAG, A>::Tag StandardizedTag; | | typedef typename LookupDependency<TAG, A>::Tag StandardizedTag; | |
| typedef typename LookupDependency<TAG, A>::reference reference; | | typedef typename LookupDependency<TAG, A>::reference reference; | |
|
| return detail::CastImpl<StandardizedTag, typename A::Tag, reference>::e
xec(a)(); | | return acc_detail::CastImpl<StandardizedTag, typename A::Tag, reference
>::exec(a)(); | |
| } | | } | |
| | | | |
| // activate the dynamic accumulator specified by Tag | | // activate the dynamic accumulator specified by Tag | |
| /** Activate the dynamic accumulator 'Tag' in the dynamic accumulator chain
'a'. Same as a.activate<Tag>() (see DynamicAccumulatorChain::activate<Tag>
() or DynamicAccumulatorChainArray::activate<Tag>()). For run-time activati
on use DynamicAccumulatorChain::activate(std::string tag) or DynamicAccumul
atorChainArray::activate(std::string tag) instead.\n | | /** Activate the dynamic accumulator 'Tag' in the dynamic accumulator chain
'a'. Same as a.activate<Tag>() (see DynamicAccumulatorChain::activate<Tag>
() or DynamicAccumulatorChainArray::activate<Tag>()). For run-time activati
on use DynamicAccumulatorChain::activate(std::string tag) or DynamicAccumul
atorChainArray::activate(std::string tag) instead.\n | |
| See \ref FeatureAccumulators for more information about feature computation
via accumulators. | | See \ref FeatureAccumulators for more information about feature computation
via accumulators. | |
| */ | | */ | |
| template <class Tag, class A> | | template <class Tag, class A> | |
| inline void | | inline void | |
| activate(A & a) | | activate(A & a) | |
| { | | { | |
| | | | |
| skipping to change at line 2673 | | skipping to change at line 2875 | |
| { | | { | |
| return a.template isActive<Tag>(); | | return a.template isActive<Tag>(); | |
| } | | } | |
| | | | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| /*
*/ | | /*
*/ | |
| /* generic loops
*/ | | /* generic loops
*/ | |
| /*
*/ | | /*
*/ | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| | | | |
|
| /** Generic loop to collect the statistics of the accumulator chain 'a' in
as many passes over the data as necessary.\n | | /** Generic loop to collect statistics from one or several arrays. | |
| | | | |
|
| Example of use: | | This function automatically performs as many passes over the data as necess
ary for the selected statistics. The basic version of <tt>extractFeatures()
</tt> takes an iterator pair and a reference to an accumulator chain: | |
| \code | | \code | |
|
| vigra::MultiArray<3, double> data(...); | | namespace vigra { namespace acc { | |
| vigra::MultiArray<3, int> labels(...); | | | |
| typedef vigra::CoupledIteratorType<3, double, int>::type Iterator; | | | |
| typedef Iterator::value_type Handle; | | | |
| | | | |
|
| AccumulatorChainArray<Handle, | | template <class ITERATOR, class ACCUMULATOR> | |
| Select<DataArg<1>, LabelArg<2>, Mean, Variance> > a; | | void extractFeatures(ITERATOR start, ITERATOR end, ACCUMULATOR & a); | |
| | | }} | |
| | | \endcode | |
| | | The <tt>ITERATOR</tt> can be any STL-conforming <i>forward iterator</i> (in | |
| | | cluding raw pointers and \ref vigra::CoupledScanOrderIterator). The <tt>ACC | |
| | | UMULATOR</tt> must be instantiated with the <tt>ITERATOR</tt>'s <tt>value_t | |
| | | ype</tt> as its first template argument. For example, to use a raw pointer | |
| | | you write: | |
| | | \code | |
| | | AccumulatorChain<double, Select<Mean, Variance> > a; | |
| | | | |
|
| Iterator start = createCoupledIterator(data, labels); | | double * start = ..., | |
| Iterator end = start.getEndIterator(); | | * end = ...; | |
| | | extractFeatures(start, end, a); | |
| | | \endcode | |
| | | Similarly, you can use MultiArray's scan-order iterator: | |
| | | \code | |
| | | AccumulatorChain<TinyVector<float, 2>, Select<Mean, Variance> > a; | |
| | | | |
|
| extractFeatures(start,end,a); | | MultiArray<3, TinyVector<float, 2> > data(...); | |
| | | extractFeatures(data.begin(), data.end(), a); | |
| | | \endcode | |
| | | An alternative syntax is used when you want to compute weighted or region s | |
| | | tatistics (or both). Then it is necessary to iterate over several arrays si | |
| | | multaneously. This fact is best conveyed to the accumulator via the helper | |
| | | class \ref vigra::CoupledArrays that is used as the accumulator's first tem | |
| | | plate argument and holds the dimension and value types of the arrays involv | |
| | | ed. To actually compute the features, you then pass appropriate arrays to t | |
| | | he <tt>extractfeatures()</tt> function directly. For example, region statis | |
| | | tics can be obtained like this: | |
| | | \code | |
| | | MultiArray<3, double> data(...); | |
| | | MultiArray<3, int> labels(...); | |
| | | | |
| | | AccumulatorChainArray<CoupledArrays<3, double, int>, | |
| | | Select<DataArg<1>, LabelArg<2>, // where to look | |
| | | for data and region labels | |
| | | Mean, Variance> > // what statistic | |
| | | s to compute | |
| | | a; | |
| | | | |
| | | extractFeatures(data, labels, a); | |
| | | \endcode | |
| | | This form of <tt>extractFeatures()</tt> is supported for up to five arrays | |
| | | (although at most three are currently making sense in practice): | |
| | | \code | |
| | | namespace vigra { namespace acc { | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class ACCUMULATOR> | |
| | | void extractFeatures(MultiArrayView<N, T1, S1> const & a1, | |
| | | ACCUMULATOR & a); | |
| | | | |
| | | ... | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3, class S3, | |
| | | class T4, class S4, | |
| | | class T5, class S5, | |
| | | class ACCUMULATOR> | |
| | | void extractFeatures(MultiArrayView<N, T1, S1> const & a1, | |
| | | MultiArrayView<N, T2, S2> const & a2, | |
| | | MultiArrayView<N, T3, S3> const & a3, | |
| | | MultiArrayView<N, T4, S4> const & a4, | |
| | | MultiArrayView<N, T5, S5> const & a5, | |
| | | ACCUMULATOR & a); | |
| | | }} | |
| \endcode | | \endcode | |
|
| | | Of course, the number and types of the arrays specified in <tt>CoupledArray | |
| | | s</tt> must conform to the number and types of the arrays passed to <tt>ext | |
| | | ractFeatures()</tt>. | |
| | | | |
| See \ref FeatureAccumulators for more information about feature computation
via accumulators. | | See \ref FeatureAccumulators for more information about feature computation
via accumulators. | |
| */ | | */ | |
|
| | | doxygen_overloaded_function(template <...> void extractFeatures) | |
| | | | |
| template <class ITERATOR, class ACCUMULATOR> | | template <class ITERATOR, class ACCUMULATOR> | |
| void extractFeatures(ITERATOR start, ITERATOR end, ACCUMULATOR & a) | | void extractFeatures(ITERATOR start, ITERATOR end, ACCUMULATOR & a) | |
| { | | { | |
| for(unsigned int k=1; k <= a.passesRequired(); ++k) | | for(unsigned int k=1; k <= a.passesRequired(); ++k) | |
| for(ITERATOR i=start; i < end; ++i) | | for(ITERATOR i=start; i < end; ++i) | |
| a.updatePassN(*i, k); | | a.updatePassN(*i, k); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class ACCUMULATOR> | |
| | | void extractFeatures(MultiArrayView<N, T1, S1> const & a1, | |
| | | ACCUMULATOR & a) | |
| | | { | |
| | | typedef typename CoupledIteratorType<N, T1>::type Iterator; | |
| | | Iterator start = createCoupledIterator(a1), | |
| | | end = start.getEndIterator(); | |
| | | extractFeatures(start, end, a); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class ACCUMULATOR> | |
| | | void extractFeatures(MultiArrayView<N, T1, S1> const & a1, | |
| | | MultiArrayView<N, T2, S2> const & a2, | |
| | | ACCUMULATOR & a) | |
| | | { | |
| | | typedef typename CoupledIteratorType<N, T1, T2>::type Iterator; | |
| | | Iterator start = createCoupledIterator(a1, a2), | |
| | | end = start.getEndIterator(); | |
| | | extractFeatures(start, end, a); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3, class S3, | |
| | | class ACCUMULATOR> | |
| | | void extractFeatures(MultiArrayView<N, T1, S1> const & a1, | |
| | | MultiArrayView<N, T2, S2> const & a2, | |
| | | MultiArrayView<N, T3, S3> const & a3, | |
| | | ACCUMULATOR & a) | |
| | | { | |
| | | typedef typename CoupledIteratorType<N, T1, T2, T3>::type Iterator; | |
| | | Iterator start = createCoupledIterator(a1, a2, a3), | |
| | | end = start.getEndIterator(); | |
| | | extractFeatures(start, end, a); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3, class S3, | |
| | | class T4, class S4, | |
| | | class ACCUMULATOR> | |
| | | void extractFeatures(MultiArrayView<N, T1, S1> const & a1, | |
| | | MultiArrayView<N, T2, S2> const & a2, | |
| | | MultiArrayView<N, T3, S3> const & a3, | |
| | | MultiArrayView<N, T4, S4> const & a4, | |
| | | ACCUMULATOR & a) | |
| | | { | |
| | | typedef typename CoupledIteratorType<N, T1, T2, T3, T4>::type Iterator; | |
| | | Iterator start = createCoupledIterator(a1, a2, a3, a4), | |
| | | end = start.getEndIterator(); | |
| | | extractFeatures(start, end, a); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3, class S3, | |
| | | class T4, class S4, | |
| | | class T5, class S5, | |
| | | class ACCUMULATOR> | |
| | | void extractFeatures(MultiArrayView<N, T1, S1> const & a1, | |
| | | MultiArrayView<N, T2, S2> const & a2, | |
| | | MultiArrayView<N, T3, S3> const & a3, | |
| | | MultiArrayView<N, T4, S4> const & a4, | |
| | | MultiArrayView<N, T5, S5> const & a5, | |
| | | ACCUMULATOR & a) | |
| | | { | |
| | | typedef typename CoupledIteratorType<N, T1, T2, T3, T4, T5>::type Itera | |
| | | tor; | |
| | | Iterator start = createCoupledIterator(a1, a2, a3, a4, a5), | |
| | | end = start.getEndIterator(); | |
| | | extractFeatures(start, end, a); | |
| | | } | |
| | | | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| /*
*/ | | /*
*/ | |
| /* AccumulatorResultTraits
*/ | | /* AccumulatorResultTraits
*/ | |
| /*
*/ | | /*
*/ | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| | | | |
| template <class T> | | template <class T> | |
| struct AccumulatorResultTraits | | struct AccumulatorResultTraits | |
| { | | { | |
| typedef T type; | | typedef T type; | |
| | | | |
| skipping to change at line 2785 | | skipping to change at line 3111 | |
| | | | |
| This modifier only works when labels are given (with (Dynamic)AccumulatorCh
ainArray), in which case statistics are computed per-region by default. | | This modifier only works when labels are given (with (Dynamic)AccumulatorCh
ainArray), in which case statistics are computed per-region by default. | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| class Global | | class Global | |
| { | | { | |
| public: | | public: | |
| typedef typename StandardizeTag<TAG>::type TargetTag; | | typedef typename StandardizeTag<TAG>::type TargetTag; | |
| typedef typename TargetTag::Dependencies Dependencies; | | typedef typename TargetTag::Dependencies Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("Global<") + TargetTag::na | | return std::string("Global<") + TargetTag::name() + " >"; | |
| me() + " >"; | | // static const std::string n = std::string("Global<") + TargetTag: | |
| return n; | | :name() + " >"; | |
| | | // return n; | |
| } | | } | |
| }; | | }; | |
| | | | |
| /** \brief Specifies index of data in CoupledHandle. | | /** \brief Specifies index of data in CoupledHandle. | |
| | | | |
| If AccumulatorChain is used with CoupledIterator, DataArg<INDEX> tells
the accumulator chain which index of the Handle contains the data. (Coordin
ates are always index 0) | | If AccumulatorChain is used with CoupledIterator, DataArg<INDEX> tells
the accumulator chain which index of the Handle contains the data. (Coordin
ates are always index 0) | |
| */ | | */ | |
| template <int INDEX> | | template <int INDEX> | |
| class DataArg | | class DataArg | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("DataArg<") + asString(IND | | return std::string("DataArg<") + asString(INDEX) + "> (internal)"; | |
| EX) + "> (internal)"; | | // static const std::string n = std::string("DataArg<") + asString( | |
| return n; | | INDEX) + "> (internal)"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class T, class BASE> | | template <class T, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef DataArgTag Tag; | | typedef DataArgTag Tag; | |
| typedef void value_type; | | typedef void value_type; | |
| typedef void result_type; | | typedef void result_type; | |
| | | | |
| static const int value = INDEX; | | static const int value = INDEX; | |
| static const unsigned int workInPass = 0; | | static const unsigned int workInPass = 0; | |
| }; | | }; | |
| }; | | }; | |
| | | | |
|
| // Tags are automatically wrapped with DataFromHandle if CoupledHandle used | | namespace acc_detail { | |
| template <class TAG> | | | |
| class DataFromHandle | | template <class T, int DEFAULT, class TAG, class IndexDefinition, | |
| | | class TagFound=typename IndexDefinition::Tag> | |
| | | struct HandleArgSelectorImpl | |
| { | | { | |
|
| public: | | static const int value = DEFAULT; | |
| typedef typename StandardizeTag<TAG>::type TargetTag; | | typedef typename CoupledHandleCast<value, T>::type type; | |
| typedef typename TargetTag::Dependencies Dependencies; | | typedef typename CoupledHandleCast<value, T>::value_type value_type; | |
| | | static const int size = type::dimensions; | |
| | | | |
|
| static std::string const & name() | | template <class U, class NEXT> | |
| | | static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >::type | |
| | | const & | |
| | | getHandle(CoupledHandle<U, NEXT> const & t) | |
| { | | { | |
|
| static const std::string n = std::string("DataFromHandle<") + Targe | | return vigra::cast<value>(t); | |
| tTag::name() + " > (internal)"; | | | |
| return n; | | | |
| } | | } | |
| | | | |
|
| template <class IndexDefinition, class TagFound=typename IndexDefinitio | | template <class U, class NEXT> | |
| n::Tag> | | static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >::type | |
| struct DataIndexSelector | | ::const_reference | |
| | | getValue(CoupledHandle<U, NEXT> const & t) | |
| { | | { | |
|
| static const int value = 1; // default: CoupledHandle holds data at | | return vigra::get<value>(t); | |
| index 1 | | } | |
| | | }; | |
| | | | |
|
| template <class U, class NEXT> | | template <class T, int DEFAULT, class TAG, class IndexDefinition> | |
| static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >:: | | struct HandleArgSelectorImpl<T, DEFAULT, TAG, IndexDefinition, TAG> | |
| type::const_reference | | { | |
| exec(CoupledHandle<U, NEXT> const & t) | | static const int value = IndexDefinition::value; | |
| { | | typedef typename CoupledHandleCast<value, T>::type type; | |
| return get<value>(t); | | typedef typename CoupledHandleCast<value, T>::value_type value_type; | |
| } | | static const int size = type::dimensions; | |
| }; | | | |
| | | | |
|
| template <class IndexDefinition> | | template <class U, class NEXT> | |
| struct DataIndexSelector<IndexDefinition, DataArgTag> | | static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >::type | |
| | | const & | |
| | | getHandle(CoupledHandle<U, NEXT> const & t) | |
| { | | { | |
|
| static const int value = IndexDefinition::value; | | return vigra::cast<value>(t); | |
| | | } | |
| | | | |
|
| template <class U, class NEXT> | | template <class U, class NEXT> | |
| static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >:: | | static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >::type | |
| type::const_reference | | ::const_reference | |
| exec(CoupledHandle<U, NEXT> const & t) | | getValue(CoupledHandle<U, NEXT> const & t) | |
| { | | { | |
| return get<value>(t); | | return vigra::get<value>(t); | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| template <class T, class BASE> | | } // namespace acc_detail | |
| struct SelectInputType | | | |
| | | template <class T, class CHAIN> | |
| | | struct HandleArgSelector<T, LabelArgTag, CHAIN> | |
| | | : public acc_detail::HandleArgSelectorImpl<T, 2, LabelArgTag, | |
| | | typename LookupTag<LabelArgTag, | |
| | | CHAIN>::type> | |
| | | {}; | |
| | | | |
| | | template <class T, class CHAIN> | |
| | | struct HandleArgSelector<T, DataArgTag, CHAIN> | |
| | | : public acc_detail::HandleArgSelectorImpl<T, 1, DataArgTag, | |
| | | typename LookupTag<DataArgTag, C | |
| | | HAIN>::type> | |
| | | {}; | |
| | | | |
| | | template <class T, class CHAIN> | |
| | | struct HandleArgSelector<T, CoordArgTag, CHAIN> | |
| | | : public acc_detail::HandleArgSelectorImpl<T, 0, CoordArgTag, | |
| | | typename LookupTag<CoordArgTag, | |
| | | CHAIN>::type> | |
| | | { | |
| | | typedef acc_detail::HandleArgSelectorImpl<T, 0, CoordArgTag, | |
| | | typename LookupTag<CoordArgTag, CHAIN>::type> base | |
| | | _type; | |
| | | typedef TinyVector<double, base_type::size> value_type; | |
| | | }; | |
| | | | |
| | | // Tags are automatically wrapped with DataFromHandle if CoupledHandle used | |
| | | template <class TAG> | |
| | | class DataFromHandle | |
| | | { | |
| | | public: | |
| | | typedef typename StandardizeTag<TAG>::type TargetTag; | |
| | | typedef typename TargetTag::Dependencies Dependencies; | |
| | | | |
| | | static std::string name() | |
| { | | { | |
|
| typedef typename LookupTag<DataArgTag, BASE>::type FindDataIndex; | | return std::string("DataFromHandle<") + TargetTag::name() + " > (in | |
| typedef DataIndexSelector<FindDataIndex> DataIndex; | | ternal)"; | |
| typedef typename CoupledHandleCast<DataIndex::value, T>::type::valu | | // static const std::string n = std::string("DataFromHandle<") + Ta | |
| e_type type; | | rgetTag::name() + " > (internal)"; | |
| }; | | // return n; | |
| | | } | |
| | | | |
| template <class T, class BASE> | | template <class T, class BASE> | |
| struct Impl | | struct Impl | |
|
| : public TargetTag::template Impl<typename SelectInputType<T, BASE>::ty
pe, BASE> | | : public TargetTag::template Impl<typename HandleArgSelector<T, DataArg
Tag, BASE>::value_type, BASE> | |
| { | | { | |
|
| typedef SelectInputType<T, BASE> InputTypeSelector; | | typedef HandleArgSelector<T, DataArgTag, BASE> DataHandle; | |
| typedef typename InputTypeSelector::DataIndex DataIndex; | | typedef typename DataHandle::value_type input_type; | |
| typedef typename InputTypeSelector::type input_type; | | typedef input_type const & argument_type; | |
| typedef input_type const & argument_type; | | typedef argument_type first_argument_typ | |
| typedef argument_type first_argument_type | | e; | |
| ; | | | |
| | | | |
| typedef typename TargetTag::template Impl<input_type, BASE> ImplTyp
e; | | typedef typename TargetTag::template Impl<input_type, BASE> ImplTyp
e; | |
| | | | |
| using ImplType::reshape; | | using ImplType::reshape; | |
| | | | |
| template <class U, class NEXT> | | template <class U, class NEXT> | |
| void reshape(CoupledHandle<U, NEXT> const & t) | | void reshape(CoupledHandle<U, NEXT> const & t) | |
| { | | { | |
|
| ImplType::reshape(detail::shapeOf(DataIndex::exec(t))); | | ImplType::reshape(acc_detail::shapeOf(DataHandle::getValue(t)))
; | |
| } | | } | |
| | | | |
| template <class U, class NEXT> | | template <class U, class NEXT> | |
| void update(CoupledHandle<U, NEXT> const & t) | | void update(CoupledHandle<U, NEXT> const & t) | |
| { | | { | |
|
| ImplType::update(DataIndex::exec(t)); | | ImplType::update(DataHandle::getValue(t)); | |
| } | | } | |
| | | | |
| template <class U, class NEXT> | | template <class U, class NEXT> | |
| void update(CoupledHandle<U, NEXT> const & t, double weight) | | void update(CoupledHandle<U, NEXT> const & t, double weight) | |
| { | | { | |
|
| ImplType::update(DataIndex::exec(t), weight); | | ImplType::update(DataHandle::getValue(t), weight); | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| /** \brief Modifier. Compute statistic from pixel coordinates rather than f
rom pixel values. | | /** \brief Modifier. Compute statistic from pixel coordinates rather than f
rom pixel values. | |
| | | | |
| AccumulatorChain must be used with CoupledIterator in order to have acc
ess to pixel coordinates. | | AccumulatorChain must be used with CoupledIterator in order to have acc
ess to pixel coordinates. | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| class Coord | | class Coord | |
| { | | { | |
| public: | | public: | |
| typedef typename StandardizeTag<TAG>::type TargetTag; | | typedef typename StandardizeTag<TAG>::type TargetTag; | |
| typedef typename TargetTag::Dependencies Dependencies; | | typedef typename TargetTag::Dependencies Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("Coord<") + TargetTag::nam | | return std::string("Coord<") + TargetTag::name() + " >"; | |
| e() + " >"; | | // static const std::string n = std::string("Coord<") + TargetTag:: | |
| return n; | | name() + " >"; | |
| | | // return n; | |
| } | | } | |
| | | | |
|
| template <class IndexDefinition, class TagFound=typename IndexDefinitio | | template <class T, class BASE> | |
| n::Tag> | | struct Impl | |
| struct CoordIndexSelector | | : public TargetTag::template Impl<typename HandleArgSelector<T, CoordAr | |
| | | gTag, BASE>::value_type, BASE> | |
| { | | { | |
|
| static const int value = 0; // default: CoupledHandle holds coordin | | typedef HandleArgSelector<T, CoordArgTag, BASE> CoordHandle; | |
| ates at index 0 | | typedef typename CoordHandle::value_type input_type; | |
| | | typedef input_type const & argument_type; | |
| | | typedef argument_type first_argument_ty | |
| | | pe; | |
| | | | |
|
| template <class U, class NEXT> | | typedef typename TargetTag::template Impl<input_type, BASE> ImplTyp | |
| static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >:: | | e; | |
| type::const_reference | | | |
| exec(CoupledHandle<U, NEXT> const & t) | | | |
| { | | | |
| return get<value>(t); | | | |
| } | | | |
| }; | | | |
| | | | |
|
| template <class IndexDefinition> | | input_type offset_; | |
| struct CoordIndexSelector<IndexDefinition, CoordArgTag> | | | |
| { | | | |
| static const int value = IndexDefinition::value; | | | |
| | | | |
|
| template <class U, class NEXT> | | Impl() | |
| static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >:: | | : offset_() | |
| type::const_reference | | {} | |
| exec(CoupledHandle<U, NEXT> const & t) | | | |
| | | void setCoordinateOffset(input_type const & offset) | |
| { | | { | |
|
| return get<value>(t); | | offset_ = offset; | |
| } | | } | |
|
| }; | | | |
| | | | |
| template <class T, class BASE> | | | |
| struct SelectInputType | | | |
| { | | | |
| typedef typename LookupTag<CoordArgTag, BASE>::type FindDataIndex; | | | |
| typedef CoordIndexSelector<FindDataIndex> CoordIndex; | | | |
| typedef typename CoupledHandleCast<CoordIndex::value, T>::type::val | | | |
| ue_type type; | | | |
| }; | | | |
| | | | |
| template <class T, class BASE> | | | |
| struct Impl | | | |
| : public TargetTag::template Impl<typename SelectInputType<T, BASE>::ty | | | |
| pe, BASE> | | | |
| { | | | |
| typedef SelectInputType<T, BASE> InputTypeSelector; | | | |
| typedef typename InputTypeSelector::CoordIndex CoordIndex; | | | |
| typedef typename InputTypeSelector::type input_type; | | | |
| typedef input_type const & argument_type; | | | |
| typedef argument_type first_argument_type | | | |
| ; | | | |
| | | | |
| typedef typename TargetTag::template Impl<input_type, BASE> ImplTyp | | | |
| e; | | | |
| | | | |
| using ImplType::reshape; | | using ImplType::reshape; | |
| | | | |
| template <class U, class NEXT> | | template <class U, class NEXT> | |
| void reshape(CoupledHandle<U, NEXT> const & t) | | void reshape(CoupledHandle<U, NEXT> const & t) | |
| { | | { | |
|
| ImplType::reshape(detail::shapeOf(CoordIndex::exec(t))); | | ImplType::reshape(acc_detail::shapeOf(CoordHandle::getValue(t))
); | |
| } | | } | |
| | | | |
| template <class U, class NEXT> | | template <class U, class NEXT> | |
| void update(CoupledHandle<U, NEXT> const & t) | | void update(CoupledHandle<U, NEXT> const & t) | |
| { | | { | |
|
| ImplType::update(CoordIndex::exec(t)); | | ImplType::update(CoordHandle::getValue(t)+offset_); | |
| } | | } | |
| | | | |
| template <class U, class NEXT> | | template <class U, class NEXT> | |
| void update(CoupledHandle<U, NEXT> const & t, double weight) | | void update(CoupledHandle<U, NEXT> const & t, double weight) | |
| { | | { | |
|
| ImplType::update(CoordIndex::exec(t), weight); | | ImplType::update(CoordHandle::getValue(t)+offset_, weight); | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| /** \brief Specifies index of data in CoupledHandle. | | /** \brief Specifies index of data in CoupledHandle. | |
| | | | |
| If AccumulatorChain is used with CoupledIterator, WeightArg<INDEX> tell
s the accumulator chain which index of the Handle contains the weights. (No
te that coordinates are always index 0.) | | If AccumulatorChain is used with CoupledIterator, WeightArg<INDEX> tell
s the accumulator chain which index of the Handle contains the weights. (No
te that coordinates are always index 0.) | |
| */ | | */ | |
| template <int INDEX> | | template <int INDEX> | |
| class WeightArg | | class WeightArg | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("WeightArg<") + asString(I | | return std::string("WeightArg<") + asString(INDEX) + "> (internal)" | |
| NDEX) + "> (internal)"; | | ; | |
| return n; | | // static const std::string n = std::string("WeightArg<") + asStrin | |
| | | g(INDEX) + "> (internal)"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class T, class BASE> | | template <class T, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef WeightArgTag Tag; | | typedef WeightArgTag Tag; | |
| typedef void value_type; | | typedef void value_type; | |
| typedef void result_type; | | typedef void result_type; | |
| | | | |
| | | | |
| skipping to change at line 3026 | | skipping to change at line 3371 | |
| | | | |
| /** \brief Compute weighted version of the statistic. | | /** \brief Compute weighted version of the statistic. | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| class Weighted | | class Weighted | |
| { | | { | |
| public: | | public: | |
| typedef typename StandardizeTag<TAG>::type TargetTag; | | typedef typename StandardizeTag<TAG>::type TargetTag; | |
| typedef typename TargetTag::Dependencies Dependencies; | | typedef typename TargetTag::Dependencies Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("Weighted<") + TargetTag:: | | return std::string("Weighted<") + TargetTag::name() + " >"; | |
| name() + " >"; | | // static const std::string n = std::string("Weighted<") + TargetTa | |
| return n; | | g::name() + " >"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class IndexDefinition, class TagFound=typename IndexDefinitio
n::Tag> | | template <class IndexDefinition, class TagFound=typename IndexDefinitio
n::Tag> | |
| struct WeightIndexSelector | | struct WeightIndexSelector | |
| { | | { | |
| template <class U, class NEXT> | | template <class U, class NEXT> | |
| static double exec(CoupledHandle<U, NEXT> const & t) | | static double exec(CoupledHandle<U, NEXT> const & t) | |
| { | | { | |
| return (double)*t; // default: CoupledHandle holds weights at t
he last (outermost) index | | return (double)*t; // default: CoupledHandle holds weights at t
he last (outermost) index | |
| } | | } | |
| | | | |
| skipping to change at line 3074 | | skipping to change at line 3420 | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| // Centralize by subtracting the mean and cache the result | | // Centralize by subtracting the mean and cache the result | |
| class Centralize | | class Centralize | |
| { | | { | |
| public: | | public: | |
| typedef Select<Mean> Dependencies; | | typedef Select<Mean> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Centralize (internal)"); | | return "Centralize (internal)"; | |
| return n; | | // static const std::string n("Centralize (internal)"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
| typedef typename AccumulatorResultTraits<U>::element_promote_type e
lement_type; | | typedef typename AccumulatorResultTraits<U>::element_promote_type e
lement_type; | |
| typedef typename AccumulatorResultTraits<U>::SumType v
alue_type; | | typedef typename AccumulatorResultTraits<U>::SumType v
alue_type; | |
| | | | |
| skipping to change at line 3104 | | skipping to change at line 3451 | |
| {} | | {} | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| value_ = element_type(); | | value_ = element_type(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
|
| detail::reshapeImpl(value_, s); | | acc_detail::reshapeImpl(value_, s); | |
| } | | } | |
| | | | |
| void update(U const & t) const | | void update(U const & t) const | |
| { | | { | |
| using namespace vigra::multi_math; | | using namespace vigra::multi_math; | |
| value_ = t - getDependency<Mean>(*this); | | value_ = t - getDependency<Mean>(*this); | |
| } | | } | |
| | | | |
| void update(U const & t, double) const | | void update(U const & t, double) const | |
| { | | { | |
| | | | |
| skipping to change at line 3142 | | skipping to change at line 3489 | |
| | | | |
| Works in pass 2, %operator+=() not supported (merging not supported). | | Works in pass 2, %operator+=() not supported (merging not supported). | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| class Central | | class Central | |
| { | | { | |
| public: | | public: | |
| typedef typename StandardizeTag<TAG>::type TargetTag
; | | typedef typename StandardizeTag<TAG>::type TargetTag
; | |
| typedef Select<Centralize, typename TargetTag::Dependencies> Dependenc
ies; | | typedef Select<Centralize, typename TargetTag::Dependencies> Dependenc
ies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("Central<") + TargetTag::n | | return std::string("Central<") + TargetTag::name() + " >"; | |
| ame() + " >"; | | // static const std::string n = std::string("Central<") + TargetTag | |
| return n; | | ::name() + " >"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public TargetTag::template Impl<typename AccumulatorResultTraits<U>::
SumType, BASE> | | : public TargetTag::template Impl<typename AccumulatorResultTraits<U>::
SumType, BASE> | |
| { | | { | |
| typedef typename TargetTag::template Impl<typename AccumulatorResul
tTraits<U>::SumType, BASE> ImplType; | | typedef typename TargetTag::template Impl<typename AccumulatorResul
tTraits<U>::SumType, BASE> ImplType; | |
| | | | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
| | | | |
| skipping to change at line 3218 | | skipping to change at line 3566 | |
| // ImplType::update(t - getDependency<Mean>(*this), weight); | | // ImplType::update(t - getDependency<Mean>(*this), weight); | |
| // } | | // } | |
| // }; | | // }; | |
| // }; | | // }; | |
| | | | |
| class PrincipalProjection | | class PrincipalProjection | |
| { | | { | |
| public: | | public: | |
| typedef Select<Centralize, Principal<CoordinateSystem> > Dependencies; | | typedef Select<Centralize, Principal<CoordinateSystem> > Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("PrincipalProjection (internal)"); | | return "PrincipalProjection (internal)"; | |
| return n; | | // static const std::string n("PrincipalProjection (internal)"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
| typedef typename AccumulatorResultTraits<U>::element_promote_type e
lement_type; | | typedef typename AccumulatorResultTraits<U>::element_promote_type e
lement_type; | |
| typedef typename AccumulatorResultTraits<U>::SumType v
alue_type; | | typedef typename AccumulatorResultTraits<U>::SumType v
alue_type; | |
| | | | |
| skipping to change at line 3248 | | skipping to change at line 3597 | |
| {} | | {} | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| value_ = element_type(); | | value_ = element_type(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
|
| detail::reshapeImpl(value_, s); | | acc_detail::reshapeImpl(value_, s); | |
| } | | } | |
| | | | |
| void update(U const & t) const | | void update(U const & t) const | |
| { | | { | |
| for(unsigned int k=0; k<t.size(); ++k) | | for(unsigned int k=0; k<t.size(); ++k) | |
| { | | { | |
| value_[k] = getDependency<Principal<CoordinateSystem> >(*th
is)(0, k)*getDependency<Centralize>(*this)[0]; | | value_[k] = getDependency<Principal<CoordinateSystem> >(*th
is)(0, k)*getDependency<Centralize>(*this)[0]; | |
| for(unsigned int d=1; d<t.size(); ++d) | | for(unsigned int d=1; d<t.size(); ++d) | |
| value_[k] += getDependency<Principal<CoordinateSystem>
>(*this)(d, k)*getDependency<Centralize>(*this)[d]; | | value_[k] += getDependency<Principal<CoordinateSystem>
>(*this)(d, k)*getDependency<Centralize>(*this)[d]; | |
| } | | } | |
| | | | |
| skipping to change at line 3291 | | skipping to change at line 3640 | |
| | | | |
| Works in pass 2, %operator+=() not supported (merging not supported). | | Works in pass 2, %operator+=() not supported (merging not supported). | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| class Principal | | class Principal | |
| { | | { | |
| public: | | public: | |
| typedef typename StandardizeTag<TAG>::type
TargetTag; | | typedef typename StandardizeTag<TAG>::type
TargetTag; | |
| typedef Select<PrincipalProjection, typename TargetTag::Dependencies>
Dependencies; | | typedef Select<PrincipalProjection, typename TargetTag::Dependencies>
Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("Principal<") + TargetTag: | | return std::string("Principal<") + TargetTag::name() + " >"; | |
| :name() + " >"; | | // static const std::string n = std::string("Principal<") + TargetT | |
| return n; | | ag::name() + " >"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public TargetTag::template Impl<typename AccumulatorResultTraits<U>::
SumType, BASE> | | : public TargetTag::template Impl<typename AccumulatorResultTraits<U>::
SumType, BASE> | |
| { | | { | |
| typedef typename TargetTag::template Impl<typename AccumulatorResul
tTraits<U>::SumType, BASE> ImplType; | | typedef typename TargetTag::template Impl<typename AccumulatorResul
tTraits<U>::SumType, BASE> ImplType; | |
| | | | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
| | | | |
| skipping to change at line 3357 | | skipping to change at line 3707 | |
| /*
*/ | | /*
*/ | |
| /**************************************************************************
**/ | | /**************************************************************************
**/ | |
| | | | |
| /** \brief Basic statistic. Identity matrix of appropriate size. | | /** \brief Basic statistic. Identity matrix of appropriate size. | |
| */ | | */ | |
| class CoordinateSystem | | class CoordinateSystem | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("CoordinateSystem"); | | return "CoordinateSystem"; | |
| return n; | | // static const std::string n("CoordinateSystem"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef double element_type; | | typedef double element_type; | |
| typedef Matrix<double> value_type; | | typedef Matrix<double> value_type; | |
| typedef value_type const & result_type; | | typedef value_type const & result_type; | |
| | | | |
| | | | |
| skipping to change at line 3385 | | skipping to change at line 3736 | |
| {} | | {} | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| value_ = element_type(); | | value_ = element_type(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
|
| detail::reshapeImpl(value_, s); | | acc_detail::reshapeImpl(value_, s); | |
| } | | } | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| return value_; | | return value_; | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| template <class BASE, class T, | | template <class BASE, class T, | |
| | | | |
| skipping to change at line 3419 | | skipping to change at line 3770 | |
| {} | | {} | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| value_ = element_type(); | | value_ = element_type(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
|
| detail::reshapeImpl(value_, s); | | acc_detail::reshapeImpl(value_, s); | |
| } | | } | |
| | | | |
| void operator+=(SumBaseImpl const & o) | | void operator+=(SumBaseImpl const & o) | |
| { | | { | |
| value_ += o.value_; | | value_ += o.value_; | |
| } | | } | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| return value_; | | return value_; | |
| } | | } | |
| }; | | }; | |
| | | | |
| // Count | | // Count | |
| template <> | | template <> | |
| class PowerSum<0> | | class PowerSum<0> | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("PowerSum<0>"); | | return "PowerSum<0>"; | |
| return n; | | // static const std::string n("PowerSum<0>"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class T, class BASE> | | template <class T, class BASE> | |
| struct Impl | | struct Impl | |
| : public SumBaseImpl<BASE, T, double, double> | | : public SumBaseImpl<BASE, T, double, double> | |
| { | | { | |
| void update(T const & t) | | void update(T const & t) | |
| { | | { | |
| ++this->value_; | | ++this->value_; | |
| } | | } | |
| | | | |
| skipping to change at line 3469 | | skipping to change at line 3821 | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| // Sum | | // Sum | |
| template <> | | template <> | |
| class PowerSum<1> | | class PowerSum<1> | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("PowerSum<1>"); | | return "PowerSum<1>"; | |
| return n; | | // static const std::string n("PowerSum<1>"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public SumBaseImpl<BASE, U> | | : public SumBaseImpl<BASE, U> | |
| { | | { | |
| void update(U const & t) | | void update(U const & t) | |
| { | | { | |
| this->value_ += t; | | this->value_ += t; | |
| } | | } | |
| | | | |
| void update(U const & t, double weight) | | void update(U const & t, double weight) | |
| { | | { | |
|
| | | using namespace multi_math; | |
| | | | |
| this->value_ += weight*t; | | this->value_ += weight*t; | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| /** \brief Basic statistic. PowerSum<N> =@f$ \sum_i x_i^N @f$ | | /** \brief Basic statistic. PowerSum<N> =@f$ \sum_i x_i^N @f$ | |
| | | | |
| Works in pass 1, %operator+=() supported (merging supported). | | Works in pass 1, %operator+=() supported (merging supported). | |
| */ | | */ | |
| template <unsigned N> | | template <unsigned N> | |
| class PowerSum | | class PowerSum | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("PowerSum<") + asString(N) | | return std::string("PowerSum<") + asString(N) + ">"; | |
| + ">"; | | // static const std::string n = std::string("PowerSum<") + asString | |
| return n; | | (N) + ">"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public SumBaseImpl<BASE, U> | | : public SumBaseImpl<BASE, U> | |
| { | | { | |
| void update(U const & t) | | void update(U const & t) | |
| { | | { | |
| using namespace vigra::multi_math; | | using namespace vigra::multi_math; | |
| this->value_ += pow(t, (int)N); | | this->value_ += pow(t, (int)N); | |
| | | | |
| skipping to change at line 3531 | | skipping to change at line 3887 | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| template <> | | template <> | |
| class AbsPowerSum<1> | | class AbsPowerSum<1> | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("AbsPowerSum<1>"); | | return "AbsPowerSum<1>"; | |
| return n; | | // static const std::string n("AbsPowerSum<1>"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public SumBaseImpl<BASE, U> | | : public SumBaseImpl<BASE, U> | |
| { | | { | |
| void update(U const & t) | | void update(U const & t) | |
| { | | { | |
| using namespace vigra::multi_math; | | using namespace vigra::multi_math; | |
| this->value_ += abs(t); | | this->value_ += abs(t); | |
| | | | |
| skipping to change at line 3565 | | skipping to change at line 3922 | |
| /** \brief Basic statistic. AbsPowerSum<N> =@f$ \sum_i |x_i|^N @f$ | | /** \brief Basic statistic. AbsPowerSum<N> =@f$ \sum_i |x_i|^N @f$ | |
| | | | |
| Works in pass 1, %operator+=() supported (merging supported). | | Works in pass 1, %operator+=() supported (merging supported). | |
| */ | | */ | |
| template <unsigned N> | | template <unsigned N> | |
| class AbsPowerSum | | class AbsPowerSum | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("AbsPowerSum<") + asString | | return std::string("AbsPowerSum<") + asString(N) + ">"; | |
| (N) + ">"; | | // static const std::string n = std::string("AbsPowerSum<") + asStr | |
| return n; | | ing(N) + ">"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public SumBaseImpl<BASE, U> | | : public SumBaseImpl<BASE, U> | |
| { | | { | |
| void update(U const & t) | | void update(U const & t) | |
| { | | { | |
| using namespace vigra::multi_math; | | using namespace vigra::multi_math; | |
| this->value_ += pow(abs(t), (int)N); | | this->value_ += pow(abs(t), (int)N); | |
| | | | |
| skipping to change at line 3612 | | skipping to change at line 3970 | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| value_ = element_type(); | | value_ = element_type(); | |
| this->setClean(); | | this->setClean(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
|
| detail::reshapeImpl(value_, s); | | acc_detail::reshapeImpl(value_, s); | |
| } | | } | |
| | | | |
| void operator+=(CachedResultBase const &) | | void operator+=(CachedResultBase const &) | |
| { | | { | |
| this->setDirty(); | | this->setDirty(); | |
| } | | } | |
| | | | |
| void update(U const &) | | void update(U const &) | |
| { | | { | |
| this->setDirty(); | | this->setDirty(); | |
| | | | |
| skipping to change at line 3641 | | skipping to change at line 3999 | |
| // cached Mean and Variance | | // cached Mean and Variance | |
| /** \brief Modifier. Divide statistic by Count: DivideByCount<TAG> = TAG /
Count . | | /** \brief Modifier. Divide statistic by Count: DivideByCount<TAG> = TAG /
Count . | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| class DivideByCount | | class DivideByCount | |
| { | | { | |
| public: | | public: | |
| typedef typename StandardizeTag<TAG>::type TargetTag; | | typedef typename StandardizeTag<TAG>::type TargetTag; | |
| typedef Select<TargetTag, Count> Dependencies; | | typedef Select<TargetTag, Count> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("DivideByCount<") + Target | | return std::string("DivideByCount<") + TargetTag::name() + " >"; | |
| Tag::name() + " >"; | | // static const std::string n = std::string("DivideByCount<") + Tar | |
| return n; | | getTag::name() + " >"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public CachedResultBase<BASE, typename LookupDependency<TargetTag, BA
SE>::value_type, U> | | : public CachedResultBase<BASE, typename LookupDependency<TargetTag, BA
SE>::value_type, U> | |
| { | | { | |
| typedef typename CachedResultBase<BASE, typename LookupDependency<T
argetTag, BASE>::value_type, U>::result_type result_type; | | typedef typename CachedResultBase<BASE, typename LookupDependency<T
argetTag, BASE>::value_type, U>::result_type result_type; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| | | | |
| skipping to change at line 3676 | | skipping to change at line 4035 | |
| // UnbiasedVariance | | // UnbiasedVariance | |
| /** \brief Modifier. Divide statistics by Count-1: DivideUnbiased<TAG> = T
AG / (Count-1) | | /** \brief Modifier. Divide statistics by Count-1: DivideUnbiased<TAG> = T
AG / (Count-1) | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| class DivideUnbiased | | class DivideUnbiased | |
| { | | { | |
| public: | | public: | |
| typedef typename StandardizeTag<TAG>::type TargetTag; | | typedef typename StandardizeTag<TAG>::type TargetTag; | |
| typedef Select<TargetTag, Count> Dependencies; | | typedef Select<TargetTag, Count> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("DivideUnbiased<") + Targe | | return std::string("DivideUnbiased<") + TargetTag::name() + " >"; | |
| tTag::name() + " >"; | | // static const std::string n = std::string("DivideUnbiased<") + Ta | |
| return n; | | rgetTag::name() + " >"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename LookupDependency<TargetTag, BASE>::value_type val
ue_type; | | typedef typename LookupDependency<TargetTag, BASE>::value_type val
ue_type; | |
| typedef value_type result_typ
e; | | typedef value_type result_typ
e; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| | | | |
| skipping to change at line 3707 | | skipping to change at line 4067 | |
| // RootMeanSquares and StdDev | | // RootMeanSquares and StdDev | |
| /** \brief Modifier. RootDivideByCount<TAG> = sqrt( TAG/Count ) | | /** \brief Modifier. RootDivideByCount<TAG> = sqrt( TAG/Count ) | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| class RootDivideByCount | | class RootDivideByCount | |
| { | | { | |
| public: | | public: | |
| typedef typename StandardizeTag<DivideByCount<TAG> >::type TargetTag; | | typedef typename StandardizeTag<DivideByCount<TAG> >::type TargetTag; | |
| typedef Select<TargetTag> Dependencies; | | typedef Select<TargetTag> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
| typedef typename StandardizeTag<TAG>::type InnerTag; | | typedef typename StandardizeTag<TAG>::type InnerTag; | |
|
| static const std::string n = std::string("RootDivideByCount<") + In | | return std::string("RootDivideByCount<") + InnerTag::name() + " >"; | |
| nerTag::name() + " >"; | | // static const std::string n = std::string("RootDivideByCount<") + | |
| return n; | | InnerTag::name() + " >"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename LookupDependency<TargetTag, BASE>::value_type val
ue_type; | | typedef typename LookupDependency<TargetTag, BASE>::value_type val
ue_type; | |
| typedef value_type result_typ
e; | | typedef value_type result_typ
e; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| | | | |
| skipping to change at line 3739 | | skipping to change at line 4100 | |
| // UnbiasedStdDev | | // UnbiasedStdDev | |
| /** \brief Modifier. RootDivideUnbiased<TAG> = sqrt( TAG / (Count-1) ) | | /** \brief Modifier. RootDivideUnbiased<TAG> = sqrt( TAG / (Count-1) ) | |
| */ | | */ | |
| template <class TAG> | | template <class TAG> | |
| class RootDivideUnbiased | | class RootDivideUnbiased | |
| { | | { | |
| public: | | public: | |
| typedef typename StandardizeTag<DivideUnbiased<TAG> >::type TargetTag; | | typedef typename StandardizeTag<DivideUnbiased<TAG> >::type TargetTag; | |
| typedef Select<TargetTag> Dependencies; | | typedef Select<TargetTag> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
| typedef typename StandardizeTag<TAG>::type InnerTag; | | typedef typename StandardizeTag<TAG>::type InnerTag; | |
|
| static const std::string n = std::string("RootDivideUnbiased<") + I | | return std::string("RootDivideUnbiased<") + InnerTag::name() + " >" | |
| nnerTag::name() + " >"; | | ; | |
| return n; | | // static const std::string n = std::string("RootDivideUnbiased<") | |
| | | + InnerTag::name() + " >"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename LookupDependency<TargetTag, BASE>::value_type val
ue_type; | | typedef typename LookupDependency<TargetTag, BASE>::value_type val
ue_type; | |
| typedef value_type result_typ
e; | | typedef value_type result_typ
e; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| | | | |
| skipping to change at line 3769 | | skipping to change at line 4131 | |
| }; | | }; | |
| | | | |
| /** \brief Spezialization: works in pass 1, %operator+=() supported (mergin
g supported). | | /** \brief Spezialization: works in pass 1, %operator+=() supported (mergin
g supported). | |
| */ | | */ | |
| template <> | | template <> | |
| class Central<PowerSum<2> > | | class Central<PowerSum<2> > | |
| { | | { | |
| public: | | public: | |
| typedef Select<Mean, Count> Dependencies; | | typedef Select<Mean, Count> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Central<PowerSum<2> >"); | | return "Central<PowerSum<2> >"; | |
| return n; | | // static const std::string n("Central<PowerSum<2> >"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public SumBaseImpl<BASE, U> | | : public SumBaseImpl<BASE, U> | |
| { | | { | |
| void operator+=(Impl const & o) | | void operator+=(Impl const & o) | |
| { | | { | |
| using namespace vigra::multi_math; | | using namespace vigra::multi_math; | |
| double n1 = getDependency<Count>(*this), n2 = getDependency<Cou
nt>(o); | | double n1 = getDependency<Count>(*this), n2 = getDependency<Cou
nt>(o); | |
| | | | |
| skipping to change at line 3823 | | skipping to change at line 4186 | |
| }; | | }; | |
| | | | |
| /** \brief Specialization: works in pass 2, %operator+=() supported (mergin
g supported). | | /** \brief Specialization: works in pass 2, %operator+=() supported (mergin
g supported). | |
| */ | | */ | |
| template <> | | template <> | |
| class Central<PowerSum<3> > | | class Central<PowerSum<3> > | |
| { | | { | |
| public: | | public: | |
| typedef Select<Centralize, Count, Mean, Central<PowerSum<2> > > Depende
ncies; | | typedef Select<Centralize, Count, Mean, Central<PowerSum<2> > > Depende
ncies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Central<PowerSum<3> >"); | | return "Central<PowerSum<3> >"; | |
| return n; | | // static const std::string n("Central<PowerSum<3> >"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public SumBaseImpl<BASE, U> | | : public SumBaseImpl<BASE, U> | |
| { | | { | |
| typedef typename SumBaseImpl<BASE, U>::value_type value_type; | | typedef typename SumBaseImpl<BASE, U>::value_type value_type; | |
| | | | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
| | | | |
| skipping to change at line 3878 | | skipping to change at line 4242 | |
| }; | | }; | |
| }; | | }; | |
| /** \brief Specialization: works in pass 2, %operator+=() supported (mergin
g supported). | | /** \brief Specialization: works in pass 2, %operator+=() supported (mergin
g supported). | |
| */ | | */ | |
| template <> | | template <> | |
| class Central<PowerSum<4> > | | class Central<PowerSum<4> > | |
| { | | { | |
| public: | | public: | |
| typedef Select<Centralize, Central<PowerSum<3> > > Dependencies; | | typedef Select<Centralize, Central<PowerSum<3> > > Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Central<PowerSum<4> >"); | | return "Central<PowerSum<4> >"; | |
| return n; | | // static const std::string n("Central<PowerSum<4> >"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public SumBaseImpl<BASE, U> | | : public SumBaseImpl<BASE, U> | |
| { | | { | |
| typedef typename SumBaseImpl<BASE, U>::value_type value_type; | | typedef typename SumBaseImpl<BASE, U>::value_type value_type; | |
| | | | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
| | | | |
| skipping to change at line 3941 | | skipping to change at line 4306 | |
| /** \brief Basic statistic. Skewness. | | /** \brief Basic statistic. Skewness. | |
| | | | |
| %Skewness =@f$ \frac{ \frac{1}{n}\sum_i (x_i-\hat{x})^3 }{ (\frac{1}{n}
\sum_i (x_i-\hat{x})^2)^{3/2} } @f$ . | | %Skewness =@f$ \frac{ \frac{1}{n}\sum_i (x_i-\hat{x})^3 }{ (\frac{1}{n}
\sum_i (x_i-\hat{x})^2)^{3/2} } @f$ . | |
| Works in pass 2, %operator+=() supported (merging supported). | | Works in pass 2, %operator+=() supported (merging supported). | |
| */ | | */ | |
| class Skewness | | class Skewness | |
| { | | { | |
| public: | | public: | |
| typedef Select<Central<PowerSum<2> >, Central<PowerSum<3> > > Dependenc
ies; | | typedef Select<Central<PowerSum<2> >, Central<PowerSum<3> > > Dependenc
ies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Skewness"); | | return "Skewness"; | |
| return n; | | // static const std::string n("Skewness"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
| typedef typename LookupDependency<Central<PowerSum<3> >, BASE>::val
ue_type value_type; | | typedef typename LookupDependency<Central<PowerSum<3> >, BASE>::val
ue_type value_type; | |
| typedef value_type
result_type; | | typedef value_type
result_type; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| typedef Central<PowerSum<3> > Sum3; | | typedef Central<PowerSum<3> > Sum3; | |
| typedef Central<PowerSum<2> > Sum2; | | typedef Central<PowerSum<2> > Sum2; | |
| | | | |
|
| using namespace multi_math; | | using namespace multi_math; | |
| return sqrt(getDependency<Count>(*this)) * getDependency<Sum3>(
*this) / pow(getDependency<Sum2>(*this), 1.5); | | return sqrt(getDependency<Count>(*this)) * getDependency<Sum3>(
*this) / pow(getDependency<Sum2>(*this), 1.5); | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| /** \brief Basic statistic. Unbiased Skewness. | | /** \brief Basic statistic. Unbiased Skewness. | |
| | | | |
| Works in pass 2, %operator+=() supported (merging supported). | | Works in pass 2, %operator+=() supported (merging supported). | |
| */ | | */ | |
| class UnbiasedSkewness | | class UnbiasedSkewness | |
| { | | { | |
| public: | | public: | |
| typedef Select<Skewness> Dependencies; | | typedef Select<Skewness> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("UnbiasedSkewness"); | | return "UnbiasedSkewness"; | |
| return n; | | // static const std::string n("UnbiasedSkewness"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
| typedef typename LookupDependency<Central<PowerSum<3> >, BASE>::val
ue_type value_type; | | typedef typename LookupDependency<Central<PowerSum<3> >, BASE>::val
ue_type value_type; | |
| typedef value_type
result_type; | | typedef value_type
result_type; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
|
| using namespace multi_math; | | using namespace multi_math; | |
| double n = getDependency<Count>(*this); | | double n = getDependency<Count>(*this); | |
| return sqrt(n*(n-1.0)) / (n - 2.0) * getDependency<Skewness>(*t
his); | | return sqrt(n*(n-1.0)) / (n - 2.0) * getDependency<Skewness>(*t
his); | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| /** \brief Basic statistic. Kurtosis. | | /** \brief Basic statistic. Kurtosis. | |
| | | | |
| %Kurtosis = @f$ \frac{ \frac{1}{n}\sum_i (x_i-\bar{x})^4 }{ | | %Kurtosis = @f$ \frac{ \frac{1}{n}\sum_i (x_i-\bar{x})^4 }{ | |
| (\frac{1}{n} \sum_i(x_i-\bar{x})^2)^2 } - 3 @f$ . | | (\frac{1}{n} \sum_i(x_i-\bar{x})^2)^2 } - 3 @f$ . | |
| Works in pass 2, %operator+=() supported (merging supported). | | Works in pass 2, %operator+=() supported (merging supported). | |
| */ | | */ | |
| class Kurtosis | | class Kurtosis | |
| { | | { | |
| public: | | public: | |
| typedef Select<Central<PowerSum<2> >, Central<PowerSum<4> > > Dependenc
ies; | | typedef Select<Central<PowerSum<2> >, Central<PowerSum<4> > > Dependenc
ies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Kurtosis"); | | return "Kurtosis"; | |
| return n; | | // static const std::string n("Kurtosis"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
|
| typedef typename LookupDependency<Central<PowerSum<4> >, BASE>::val | | typedef typename LookupDependency<Central<PowerSum<4> >, BASE>::val | |
| ue_type value_type; | | ue_type value_type; | |
| typedef value_type | | typedef value_type | |
| result_type; | | result_type; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| typedef Central<PowerSum<4> > Sum4; | | typedef Central<PowerSum<4> > Sum4; | |
| typedef Central<PowerSum<2> > Sum2; | | typedef Central<PowerSum<2> > Sum2; | |
| | | | |
|
| using namespace multi_math; | | using namespace multi_math; | |
| return getDependency<Count>(*this) * getDependency<Sum4>(*this) | | return getDependency<Count>(*this) * getDependency<Sum4>(*this) | |
| / sq(getDependency<Sum2>(*this)) - value_type(3.0); | | / sq(getDependency<Sum2>(*this)) - 3.0; | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| /** \brief Basic statistic. Unbiased Kurtosis. | | /** \brief Basic statistic. Unbiased Kurtosis. | |
| | | | |
| Works in pass 2, %operator+=() supported (merging supported). | | Works in pass 2, %operator+=() supported (merging supported). | |
| */ | | */ | |
| class UnbiasedKurtosis | | class UnbiasedKurtosis | |
| { | | { | |
| public: | | public: | |
| typedef Select<Kurtosis> Dependencies; | | typedef Select<Kurtosis> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("UnbiasedKurtosis"); | | return "UnbiasedKurtosis"; | |
| return n; | | // static const std::string n("UnbiasedKurtosis"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| static const unsigned int workInPass = 2; | | static const unsigned int workInPass = 2; | |
| | | | |
| typedef typename LookupDependency<Central<PowerSum<4> >, BASE>::val
ue_type value_type; | | typedef typename LookupDependency<Central<PowerSum<4> >, BASE>::val
ue_type value_type; | |
|
| typedef value_type
result_type; | | typedef value_type
result_type; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
|
| using namespace multi_math; | | using namespace multi_math; | |
| double n = getDependency<Count>(*this); | | double n = getDependency<Count>(*this); | |
| return (n-1.0)/((n-2.0)*(n-3.0))*((n+1.0)*getDependency<Kurtosi
s>(*this) + value_type(6.0)); | | return (n-1.0)/((n-2.0)*(n-3.0))*((n+1.0)*getDependency<Kurtosi
s>(*this) + value_type(6.0)); | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
|
| namespace detail { | | namespace acc_detail { | |
| | | | |
| template <class Scatter, class Sum> | | template <class Scatter, class Sum> | |
| void updateFlatScatterMatrix(Scatter & sc, Sum const & s, double w) | | void updateFlatScatterMatrix(Scatter & sc, Sum const & s, double w) | |
| { | | { | |
| int size = s.size(); | | int size = s.size(); | |
| for(MultiArrayIndex j=0, k=0; j<size; ++j) | | for(MultiArrayIndex j=0, k=0; j<size; ++j) | |
| for(MultiArrayIndex i=j; i<size; ++i, ++k) | | for(MultiArrayIndex i=j; i<size; ++i, ++k) | |
| sc[k] += w*s[i]*s[j]; | | sc[k] += w*s[i]*s[j]; | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 4129 | | skipping to change at line 4498 | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class Scatter> | | template <class Scatter> | |
| void flatScatterMatrixToCovariance(double & cov, Scatter const & sc, double
n) | | void flatScatterMatrixToCovariance(double & cov, Scatter const & sc, double
n) | |
| { | | { | |
| cov = sc / n; | | cov = sc / n; | |
| } | | } | |
| | | | |
|
| } // namespace detail | | } // namespace acc_detail | |
| | | | |
| // we only store the flattened upper triangular part of the scatter matrix | | // we only store the flattened upper triangular part of the scatter matrix | |
| /** \brief Basic statistic. Flattened uppter-triangular part of scatter mat
rix. | | /** \brief Basic statistic. Flattened uppter-triangular part of scatter mat
rix. | |
| | | | |
| Works in pass 1, %operator+=() supported (merging supported). | | Works in pass 1, %operator+=() supported (merging supported). | |
| */ | | */ | |
| class FlatScatterMatrix | | class FlatScatterMatrix | |
| { | | { | |
| public: | | public: | |
| typedef Select<Mean, Count> Dependencies; | | typedef Select<Mean, Count> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("FlatScatterMatrix"); | | return "FlatScatterMatrix"; | |
| return n; | | // static const std::string n("FlatScatterMatrix"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename AccumulatorResultTraits<U>::element_promote_type
element_type; | | typedef typename AccumulatorResultTraits<U>::element_promote_type
element_type; | |
| typedef typename AccumulatorResultTraits<U>::FlatCovarianceType
value_type; | | typedef typename AccumulatorResultTraits<U>::FlatCovarianceType
value_type; | |
| typedef value_type const & result
_type; | | typedef value_type const & result
_type; | |
| | | | |
| | | | |
| skipping to change at line 4174 | | skipping to change at line 4544 | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| value_ = element_type(); | | value_ = element_type(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
| int size = prod(s); | | int size = prod(s); | |
|
| detail::reshapeImpl(value_, Shape1(size*(size+1)/2)); | | acc_detail::reshapeImpl(value_, Shape1(size*(size+1)/2)); | |
| detail::reshapeImpl(diff_, s); | | acc_detail::reshapeImpl(diff_, s); | |
| } | | } | |
| | | | |
| void operator+=(Impl const & o) | | void operator+=(Impl const & o) | |
| { | | { | |
| double n1 = getDependency<Count>(*this), n2 = getDependency<Cou
nt>(o); | | double n1 = getDependency<Count>(*this), n2 = getDependency<Cou
nt>(o); | |
| if(n1 == 0.0) | | if(n1 == 0.0) | |
| { | | { | |
| value_ = o.value_; | | value_ = o.value_; | |
| } | | } | |
| else if(n2 != 0.0) | | else if(n2 != 0.0) | |
| { | | { | |
| using namespace vigra::multi_math; | | using namespace vigra::multi_math; | |
| diff_ = getDependency<Mean>(*this) - getDependency<Mean>(o)
; | | diff_ = getDependency<Mean>(*this) - getDependency<Mean>(o)
; | |
|
| detail::updateFlatScatterMatrix(value_, diff_, n1 * n2 / (n
1 + n2)); | | acc_detail::updateFlatScatterMatrix(value_, diff_, n1 * n2
/ (n1 + n2)); | |
| value_ += o.value_; | | value_ += o.value_; | |
| } | | } | |
| } | | } | |
| | | | |
| void update(U const & t) | | void update(U const & t) | |
| { | | { | |
| compute(t); | | compute(t); | |
| } | | } | |
| | | | |
| void update(U const & t, double weight) | | void update(U const & t, double weight) | |
| | | | |
| skipping to change at line 4217 | | skipping to change at line 4587 | |
| } | | } | |
| | | | |
| private: | | private: | |
| void compute(U const & t, double weight = 1.0) | | void compute(U const & t, double weight = 1.0) | |
| { | | { | |
| double n = getDependency<Count>(*this); | | double n = getDependency<Count>(*this); | |
| if(n > weight) | | if(n > weight) | |
| { | | { | |
| using namespace vigra::multi_math; | | using namespace vigra::multi_math; | |
| diff_ = getDependency<Mean>(*this) - t; | | diff_ = getDependency<Mean>(*this) - t; | |
|
| detail::updateFlatScatterMatrix(value_, diff_, n * weight /
(n - weight)); | | acc_detail::updateFlatScatterMatrix(value_, diff_, n * weig
ht / (n - weight)); | |
| } | | } | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| // Covariance | | // Covariance | |
| template <> | | template <> | |
| class DivideByCount<FlatScatterMatrix> | | class DivideByCount<FlatScatterMatrix> | |
| { | | { | |
| public: | | public: | |
| typedef Select<FlatScatterMatrix, Count> Dependencies; | | typedef Select<FlatScatterMatrix, Count> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("DivideByCount<FlatScatterMatrix>"); | | return "DivideByCount<FlatScatterMatrix>"; | |
| return n; | | // static const std::string n("DivideByCount<FlatScatterMatrix>"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public CachedResultBase<BASE, typename AccumulatorResultTraits<U>::Co
varianceType, U> | | : public CachedResultBase<BASE, typename AccumulatorResultTraits<U>::Co
varianceType, U> | |
| { | | { | |
| typedef CachedResultBase<BASE, typename AccumulatorResultTraits<U>:
:CovarianceType, U> BaseType; | | typedef CachedResultBase<BASE, typename AccumulatorResultTraits<U>:
:CovarianceType, U> BaseType; | |
| typedef typename BaseType::result_type result_type; | | typedef typename BaseType::result_type result_type; | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
| int size = prod(s); | | int size = prod(s); | |
|
| detail::reshapeImpl(this->value_, Shape2(size,size)); | | acc_detail::reshapeImpl(this->value_, Shape2(size,size)); | |
| } | | } | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| if(this->isDirty()) | | if(this->isDirty()) | |
| { | | { | |
|
| detail::flatScatterMatrixToCovariance(this->value_, getDepe
ndency<FlatScatterMatrix>(*this), getDependency<Count>(*this)); | | acc_detail::flatScatterMatrixToCovariance(this->value_, get
Dependency<FlatScatterMatrix>(*this), getDependency<Count>(*this)); | |
| this->setClean(); | | this->setClean(); | |
| } | | } | |
| return this->value_; | | return this->value_; | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| // UnbiasedCovariance | | // UnbiasedCovariance | |
| template <> | | template <> | |
| class DivideUnbiased<FlatScatterMatrix> | | class DivideUnbiased<FlatScatterMatrix> | |
| { | | { | |
| public: | | public: | |
| typedef Select<FlatScatterMatrix, Count> Dependencies; | | typedef Select<FlatScatterMatrix, Count> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("DivideUnbiased<FlatScatterMatrix>"); | | return "DivideUnbiased<FlatScatterMatrix>"; | |
| return n; | | // static const std::string n("DivideUnbiased<FlatScatterMatrix>"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public CachedResultBase<BASE, typename AccumulatorResultTraits<U>::Co
varianceType, U> | | : public CachedResultBase<BASE, typename AccumulatorResultTraits<U>::Co
varianceType, U> | |
| { | | { | |
| typedef CachedResultBase<BASE, typename AccumulatorResultTraits<U>:
:CovarianceType, U> BaseType; | | typedef CachedResultBase<BASE, typename AccumulatorResultTraits<U>:
:CovarianceType, U> BaseType; | |
| typedef typename BaseType::result_type result_type; | | typedef typename BaseType::result_type result_type; | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
| int size = prod(s); | | int size = prod(s); | |
|
| detail::reshapeImpl(this->value_, Shape2(size,size)); | | acc_detail::reshapeImpl(this->value_, Shape2(size,size)); | |
| } | | } | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| if(this->isDirty()) | | if(this->isDirty()) | |
| { | | { | |
|
| detail::flatScatterMatrixToCovariance(this->value_, getDepe
ndency<FlatScatterMatrix>(*this), getDependency<Count>(*this) - 1.0); | | acc_detail::flatScatterMatrixToCovariance(this->value_, get
Dependency<FlatScatterMatrix>(*this), getDependency<Count>(*this) - 1.0); | |
| this->setClean(); | | this->setClean(); | |
| } | | } | |
| return this->value_; | | return this->value_; | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| /** Basic statistic. ScatterMatrixEigensystem (?) | | /** Basic statistic. ScatterMatrixEigensystem (?) | |
| */ | | */ | |
| class ScatterMatrixEigensystem | | class ScatterMatrixEigensystem | |
| { | | { | |
| public: | | public: | |
| typedef Select<FlatScatterMatrix> Dependencies; | | typedef Select<FlatScatterMatrix> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("ScatterMatrixEigensystem"); | | return "ScatterMatrixEigensystem"; | |
| return n; | | // static const std::string n("ScatterMatrixEigensystem"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename AccumulatorResultTraits<U>::element_promote_type
element_type; | | typedef typename AccumulatorResultTraits<U>::element_promote_type
element_type; | |
| typedef typename AccumulatorResultTraits<U>::SumType
EigenvalueType; | | typedef typename AccumulatorResultTraits<U>::SumType
EigenvalueType; | |
| typedef typename AccumulatorResultTraits<U>::CovarianceType
EigenvectorType; | | typedef typename AccumulatorResultTraits<U>::CovarianceType
EigenvectorType; | |
| typedef std::pair<EigenvalueType, EigenvectorType>
value_type; | | typedef std::pair<EigenvalueType, EigenvectorType>
value_type; | |
| typedef value_type const &
result_type; | | typedef value_type const &
result_type; | |
| | | | |
| mutable value_type value_; | | mutable value_type value_; | |
| | | | |
| Impl() | | Impl() | |
| : value_() | | : value_() | |
| {} | | {} | |
| | | | |
|
| void operator+=(Impl const &) | | void operator+=(Impl const & o) | |
| { | | { | |
|
| | | if(!acc_detail::hasDataImpl(value_.second)) | |
| | | { | |
| | | acc_detail::copyShapeImpl(o.value_.first, value_.first); | |
| | | acc_detail::copyShapeImpl(o.value_.second, value_.second); | |
| | | } | |
| this->setDirty(); | | this->setDirty(); | |
| } | | } | |
| | | | |
| void update(U const &) | | void update(U const &) | |
| { | | { | |
| this->setDirty(); | | this->setDirty(); | |
| } | | } | |
| | | | |
| void update(U const &, double) | | void update(U const &, double) | |
| { | | { | |
| | | | |
| skipping to change at line 4356 | | skipping to change at line 4734 | |
| { | | { | |
| value_.first = element_type(); | | value_.first = element_type(); | |
| value_.second = element_type(); | | value_.second = element_type(); | |
| this->setClean(); | | this->setClean(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
| int size = prod(s); | | int size = prod(s); | |
|
| detail::reshapeImpl(value_.first, Shape1(size)); | | acc_detail::reshapeImpl(value_.first, Shape1(size)); | |
| detail::reshapeImpl(value_.second, Shape2(size,size)); | | acc_detail::reshapeImpl(value_.second, Shape2(size,size)); | |
| } | | } | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| if(this->isDirty()) | | if(this->isDirty()) | |
| { | | { | |
| compute(getDependency<FlatScatterMatrix>(*this), value_.fir
st, value_.second); | | compute(getDependency<FlatScatterMatrix>(*this), value_.fir
st, value_.second); | |
| this->setClean(); | | this->setClean(); | |
| } | | } | |
| return value_; | | return value_; | |
| } | | } | |
| | | | |
| private: | | private: | |
| template <class Flat, class EW, class EV> | | template <class Flat, class EW, class EV> | |
| static void compute(Flat const & flatScatter, EW & ew, EV & ev) | | static void compute(Flat const & flatScatter, EW & ew, EV & ev) | |
| { | | { | |
| EigenvectorType scatter(ev.shape()); | | EigenvectorType scatter(ev.shape()); | |
|
| detail::flatScatterMatrixToScatterMatrix(scatter, flatScatter); | | acc_detail::flatScatterMatrixToScatterMatrix(scatter, flatScatt
er); | |
| // create a view because EW could be a TinyVector | | // create a view because EW could be a TinyVector | |
| MultiArrayView<2, element_type> ewview(Shape2(ev.shape(0), 1),
&ew[0]); | | MultiArrayView<2, element_type> ewview(Shape2(ev.shape(0), 1),
&ew[0]); | |
| symmetricEigensystem(scatter, ewview, ev); | | symmetricEigensystem(scatter, ewview, ev); | |
| } | | } | |
| | | | |
| static void compute(double v, double & ew, double & ev) | | static void compute(double v, double & ew, double & ev) | |
| { | | { | |
| ew = v; | | ew = v; | |
| ev = 1.0; | | ev = 1.0; | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
| // CovarianceEigensystem | | // CovarianceEigensystem | |
| template <> | | template <> | |
| class DivideByCount<ScatterMatrixEigensystem> | | class DivideByCount<ScatterMatrixEigensystem> | |
| { | | { | |
| public: | | public: | |
| typedef Select<ScatterMatrixEigensystem, Count> Dependencies; | | typedef Select<ScatterMatrixEigensystem, Count> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("DivideByCount<ScatterMatrixEigensystem> | | return "DivideByCount<ScatterMatrixEigensystem>"; | |
| "); | | // static const std::string n("DivideByCount<ScatterMatrixEigensyst | |
| return n; | | em>"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename LookupDependency<ScatterMatrixEigensystem, BASE>::
type SMImpl; | | typedef typename LookupDependency<ScatterMatrixEigensystem, BASE>::
type SMImpl; | |
| typedef typename SMImpl::element_type e
lement_type; | | typedef typename SMImpl::element_type e
lement_type; | |
| typedef typename SMImpl::EigenvalueType E
igenvalueType; | | typedef typename SMImpl::EigenvalueType E
igenvalueType; | |
| typedef typename SMImpl::EigenvectorType E
igenvectorType; | | typedef typename SMImpl::EigenvectorType E
igenvectorType; | |
| | | | |
| skipping to change at line 4444 | | skipping to change at line 4823 | |
| void reset() | | void reset() | |
| { | | { | |
| value_.first = element_type(); | | value_.first = element_type(); | |
| this->setClean(); | | this->setClean(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
| int size = prod(s); | | int size = prod(s); | |
|
| detail::reshapeImpl(value_.first, Shape2(size,1)); | | acc_detail::reshapeImpl(value_.first, Shape2(size,1)); | |
| } | | } | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| if(this->isDirty()) | | if(this->isDirty()) | |
| { | | { | |
| value_.first = getDependency<ScatterMatrixEigensystem>(*thi
s).first / getDependency<Count>(*this); | | value_.first = getDependency<ScatterMatrixEigensystem>(*thi
s).first / getDependency<Count>(*this); | |
| this->setClean(); | | this->setClean(); | |
| } | | } | |
| return value_; | | return value_; | |
| | | | |
| skipping to change at line 4509 | | skipping to change at line 4888 | |
| // { | | // { | |
| // value_.first = element_type(); | | // value_.first = element_type(); | |
| // value_.second = element_type(); | | // value_.second = element_type(); | |
| // this->setClean(); | | // this->setClean(); | |
| // } | | // } | |
| | | | |
| // template <class Shape> | | // template <class Shape> | |
| // void reshape(Shape const & s) | | // void reshape(Shape const & s) | |
| // { | | // { | |
| // int size = prod(s); | | // int size = prod(s); | |
|
| // detail::reshapeImpl(value_.first, Shape2(size,1)); | | // acc_detail::reshapeImpl(value_.first, Shape2(size,1)); | |
| // detail::reshapeImpl(value_.second, Shape2(size,size)); | | // acc_detail::reshapeImpl(value_.second, Shape2(size,size)); | |
| // } | | // } | |
| | | | |
| // result_type operator()() const | | // result_type operator()() const | |
| // { | | // { | |
| // if(this->isDirty()) | | // if(this->isDirty()) | |
| // { | | // { | |
| // compute(getDependency<Covariance>(*this), value_.first,
value_.second); | | // compute(getDependency<Covariance>(*this), value_.first,
value_.second); | |
| // this->setClean(); | | // this->setClean(); | |
| // } | | // } | |
| // return value_; | | // return value_; | |
| | | | |
| skipping to change at line 4549 | | skipping to change at line 4928 | |
| | | | |
| // covariance eigenvalues | | // covariance eigenvalues | |
| /** \brief Specialization (covariance eigenvalues): works in pass 1, %opera
tor+=() supported (merging). | | /** \brief Specialization (covariance eigenvalues): works in pass 1, %opera
tor+=() supported (merging). | |
| */ | | */ | |
| template <> | | template <> | |
| class Principal<PowerSum<2> > | | class Principal<PowerSum<2> > | |
| { | | { | |
| public: | | public: | |
| typedef Select<ScatterMatrixEigensystem> Dependencies; | | typedef Select<ScatterMatrixEigensystem> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Principal<PowerSum<2> >"); | | return "Principal<PowerSum<2> >"; | |
| return n; | | // static const std::string n("Principal<PowerSum<2> >"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename LookupDependency<ScatterMatrixEigensystem, BASE>::
type::EigenvalueType value_type; | | typedef typename LookupDependency<ScatterMatrixEigensystem, BASE>::
type::EigenvalueType value_type; | |
| typedef value_type const &
result_type; | | typedef value_type const &
result_type; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| | | | |
| skipping to change at line 4578 | | skipping to change at line 4958 | |
| | | | |
| // Principal<CoordinateSystem> == covariance eigenvectors | | // Principal<CoordinateSystem> == covariance eigenvectors | |
| /** \brief Specialization (covariance eigenvectors): works in pass 1, %oper
ator+=() supported (merging). | | /** \brief Specialization (covariance eigenvectors): works in pass 1, %oper
ator+=() supported (merging). | |
| */ | | */ | |
| template <> | | template <> | |
| class Principal<CoordinateSystem> | | class Principal<CoordinateSystem> | |
| { | | { | |
| public: | | public: | |
| typedef Select<ScatterMatrixEigensystem> Dependencies; | | typedef Select<ScatterMatrixEigensystem> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Principal<CoordinateSystem>"); | | return "Principal<CoordinateSystem>"; | |
| return n; | | // static const std::string n("Principal<CoordinateSystem>"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename LookupDependency<ScatterMatrixEigensystem, BASE>::
type::EigenvectorType value_type; | | typedef typename LookupDependency<ScatterMatrixEigensystem, BASE>::
type::EigenvectorType value_type; | |
| typedef value_type const &
result_type; | | typedef value_type const &
result_type; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| | | | |
| skipping to change at line 4607 | | skipping to change at line 4988 | |
| | | | |
| /** \brief Basic statistic. %Minimum value. | | /** \brief Basic statistic. %Minimum value. | |
| | | | |
| Works in pass 1, %operator+=() supported (merging supported). | | Works in pass 1, %operator+=() supported (merging supported). | |
| */ | | */ | |
| class Minimum | | class Minimum | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Minimum"); | | return "Minimum"; | |
| return n; | | // static const std::string n("Minimum"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename AccumulatorResultTraits<U>::element_type element_t
ype; | | typedef typename AccumulatorResultTraits<U>::element_type element_t
ype; | |
| typedef typename AccumulatorResultTraits<U>::MinmaxType value_typ
e; | | typedef typename AccumulatorResultTraits<U>::MinmaxType value_typ
e; | |
| typedef value_type const & result_ty
pe; | | typedef value_type const & result_ty
pe; | |
| | | | |
| | | | |
| skipping to change at line 4636 | | skipping to change at line 5018 | |
| } | | } | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| value_ = NumericTraits<element_type>::max(); | | value_ = NumericTraits<element_type>::max(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
|
| detail::reshapeImpl(value_, s, NumericTraits<element_type>::max
()); | | acc_detail::reshapeImpl(value_, s, NumericTraits<element_type>:
:max()); | |
| } | | } | |
| | | | |
| void operator+=(Impl const & o) | | void operator+=(Impl const & o) | |
| { | | { | |
| updateImpl(o.value_); // necessary because std::min causes ambi
guous overload | | updateImpl(o.value_); // necessary because std::min causes ambi
guous overload | |
| } | | } | |
| | | | |
| void update(U const & t) | | void update(U const & t) | |
| { | | { | |
| updateImpl(t); | | updateImpl(t); | |
| | | | |
| skipping to change at line 4684 | | skipping to change at line 5066 | |
| | | | |
| /** \brief Basic statistic. %Maximum value. | | /** \brief Basic statistic. %Maximum value. | |
| | | | |
| Works in pass 1, %operator+=() supported (merging supported). | | Works in pass 1, %operator+=() supported (merging supported). | |
| */ | | */ | |
| class Maximum | | class Maximum | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("Maximum"); | | return "Maximum"; | |
| return n; | | // static const std::string n("Maximum"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename AccumulatorResultTraits<U>::element_type element_t
ype; | | typedef typename AccumulatorResultTraits<U>::element_type element_t
ype; | |
| typedef typename AccumulatorResultTraits<U>::MinmaxType value_typ
e; | | typedef typename AccumulatorResultTraits<U>::MinmaxType value_typ
e; | |
| typedef value_type const & result_ty
pe; | | typedef value_type const & result_ty
pe; | |
| | | | |
| | | | |
| skipping to change at line 4713 | | skipping to change at line 5096 | |
| } | | } | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| value_ = NumericTraits<element_type>::min(); | | value_ = NumericTraits<element_type>::min(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
|
| detail::reshapeImpl(value_, s, NumericTraits<element_type>::min
()); | | acc_detail::reshapeImpl(value_, s, NumericTraits<element_type>:
:min()); | |
| } | | } | |
| | | | |
| void operator+=(Impl const & o) | | void operator+=(Impl const & o) | |
| { | | { | |
| updateImpl(o.value_); // necessary because std::max causes ambi
guous overload | | updateImpl(o.value_); // necessary because std::max causes ambi
guous overload | |
| } | | } | |
| | | | |
| void update(U const & t) | | void update(U const & t) | |
| { | | { | |
| updateImpl(t); | | updateImpl(t); | |
| | | | |
| skipping to change at line 4752 | | skipping to change at line 5135 | |
| } | | } | |
| | | | |
| template <class T, class Alloc> | | template <class T, class Alloc> | |
| void updateImpl(MultiArray<1, T, Alloc> const & o) | | void updateImpl(MultiArray<1, T, Alloc> const & o) | |
| { | | { | |
| value_ = multi_math::max(value_, o); | | value_ = multi_math::max(value_, o); | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
|
| | | /** \brief Basic statistic. First data value seen of the object. | |
| | | | |
| | | Usually used as <tt>Coord<FirstSeen></tt> (alias <tt>RegionAnchor</tt>) | |
| | | which provides a well-defined anchor point for the region. | |
| | | */ | |
| | | class FirstSeen | |
| | | { | |
| | | public: | |
| | | typedef Select<Count> Dependencies; | |
| | | | |
| | | static std::string name() | |
| | | { | |
| | | return "FirstSeen"; | |
| | | // static const std::string n("FirstSeen"); | |
| | | // return n; | |
| | | } | |
| | | | |
| | | template <class U, class BASE> | |
| | | struct Impl | |
| | | : public BASE | |
| | | { | |
| | | typedef typename AccumulatorResultTraits<U>::element_type element_t | |
| | | ype; | |
| | | typedef typename AccumulatorResultTraits<U>::MinmaxType value_typ | |
| | | e; | |
| | | typedef value_type const & result_ty | |
| | | pe; | |
| | | | |
| | | value_type value_; | |
| | | | |
| | | Impl() | |
| | | : value_() | |
| | | {} | |
| | | | |
| | | void reset() | |
| | | { | |
| | | value_ = element_type(); | |
| | | } | |
| | | | |
| | | template <class Shape> | |
| | | void reshape(Shape const & s) | |
| | | { | |
| | | acc_detail::reshapeImpl(value_, s); | |
| | | } | |
| | | | |
| | | void operator+=(Impl const & o) | |
| | | { | |
| | | // FIXME: only works for Coord<FirstSeen> | |
| | | if(reverse(o.value_) < reverse(value_)) | |
| | | value_ = o.value_; | |
| | | } | |
| | | | |
| | | void update(U const & t) | |
| | | { | |
| | | if(getDependency<Count>(*this) == 1) | |
| | | value_ = t; | |
| | | } | |
| | | | |
| | | void update(U const & t, double weight) | |
| | | { | |
| | | update(t); | |
| | | } | |
| | | | |
| | | result_type operator()() const | |
| | | { | |
| | | return value_; | |
| | | } | |
| | | }; | |
| | | }; | |
| | | | |
| | | /** \brief Return both the minimum and maximum in <tt>std::pair</tt>. | |
| | | | |
| | | Usually used as <tt>Coord<Range></tt> (alias <tt>BoundingBox</tt>). | |
| | | Note that <tt>Range</tt> returns a closed interval, i.e. the upper | |
| | | limit is part of the range. | |
| | | */ | |
| | | class Range | |
| | | { | |
| | | public: | |
| | | typedef Select<Minimum, Maximum> Dependencies; | |
| | | | |
| | | static std::string name() | |
| | | { | |
| | | return "Range"; | |
| | | // static const std::string n("Range"); | |
| | | // return n; | |
| | | } | |
| | | | |
| | | template <class U, class BASE> | |
| | | struct Impl | |
| | | : public BASE | |
| | | { | |
| | | typedef typename AccumulatorResultTraits<U>::MinmaxType minmax_ty | |
| | | pe; | |
| | | typedef std::pair<minmax_type, minmax_type> value_typ | |
| | | e; | |
| | | typedef value_type result_ty | |
| | | pe; | |
| | | | |
| | | result_type operator()() const | |
| | | { | |
| | | return value_type(getDependency<Minimum>(*this), getDependency< | |
| | | Maximum>(*this)); | |
| | | } | |
| | | }; | |
| | | }; | |
| | | | |
| /** \brief Basic statistic. Data value where weight assumes its minimal val
ue. | | /** \brief Basic statistic. Data value where weight assumes its minimal val
ue. | |
| | | | |
| Weights must be given. Coord<ArgMinWeight> gives coordinate where weigh
t assumes its minimal value. Works in pass 1, %operator+=() supported (merg
ing supported). | | Weights must be given. Coord<ArgMinWeight> gives coordinate where weigh
t assumes its minimal value. Works in pass 1, %operator+=() supported (merg
ing supported). | |
| */ | | */ | |
| class ArgMinWeight | | class ArgMinWeight | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("ArgMinWeight"); | | return "ArgMinWeight"; | |
| return n; | | // static const std::string n("ArgMinWeight"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename AccumulatorResultTraits<U>::element_type element_t
ype; | | typedef typename AccumulatorResultTraits<U>::element_type element_t
ype; | |
| typedef typename AccumulatorResultTraits<U>::MinmaxType value_typ
e; | | typedef typename AccumulatorResultTraits<U>::MinmaxType value_typ
e; | |
| typedef value_type const & result_ty
pe; | | typedef value_type const & result_ty
pe; | |
| | | | |
| | | | |
| skipping to change at line 4792 | | skipping to change at line 5276 | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| min_weight_ = NumericTraits<double>::max(); | | min_weight_ = NumericTraits<double>::max(); | |
| value_ = element_type(); | | value_ = element_type(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
|
| detail::reshapeImpl(value_, s); | | acc_detail::reshapeImpl(value_, s); | |
| } | | } | |
| | | | |
| void operator+=(Impl const & o) | | void operator+=(Impl const & o) | |
| { | | { | |
| using namespace multi_math; | | using namespace multi_math; | |
| if(o.min_weight_ < min_weight_) | | if(o.min_weight_ < min_weight_) | |
| { | | { | |
| min_weight_ = o.min_weight_; | | min_weight_ = o.min_weight_; | |
| value_ = o.value_; | | value_ = o.value_; | |
| } | | } | |
| | | | |
| skipping to change at line 4835 | | skipping to change at line 5319 | |
| | | | |
| /** \brief Basic statistic. Data where weight assumes its maximal value. | | /** \brief Basic statistic. Data where weight assumes its maximal value. | |
| | | | |
| Weights must be given. Coord<ArgMinWeight> gives coordinate where weigh
t assumes its maximal value. Works in pass 1, %operator+=() supported (merg
ing supported). | | Weights must be given. Coord<ArgMinWeight> gives coordinate where weigh
t assumes its maximal value. Works in pass 1, %operator+=() supported (merg
ing supported). | |
| */ | | */ | |
| class ArgMaxWeight | | class ArgMaxWeight | |
| { | | { | |
| public: | | public: | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n("ArgMaxWeight"); | | return "ArgMaxWeight"; | |
| return n; | | // static const std::string n("ArgMaxWeight"); | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public BASE | | : public BASE | |
| { | | { | |
| typedef typename AccumulatorResultTraits<U>::element_type element_t
ype; | | typedef typename AccumulatorResultTraits<U>::element_type element_t
ype; | |
| typedef typename AccumulatorResultTraits<U>::MinmaxType value_typ
e; | | typedef typename AccumulatorResultTraits<U>::MinmaxType value_typ
e; | |
| typedef value_type const & result_ty
pe; | | typedef value_type const & result_ty
pe; | |
| | | | |
| | | | |
| skipping to change at line 4866 | | skipping to change at line 5351 | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| max_weight_ = NumericTraits<double>::min(); | | max_weight_ = NumericTraits<double>::min(); | |
| value_ = element_type(); | | value_ = element_type(); | |
| } | | } | |
| | | | |
| template <class Shape> | | template <class Shape> | |
| void reshape(Shape const & s) | | void reshape(Shape const & s) | |
| { | | { | |
|
| detail::reshapeImpl(value_, s); | | acc_detail::reshapeImpl(value_, s); | |
| } | | } | |
| | | | |
| void operator+=(Impl const & o) | | void operator+=(Impl const & o) | |
| { | | { | |
| using namespace multi_math; | | using namespace multi_math; | |
| if(o.max_weight_ > max_weight_) | | if(o.max_weight_ > max_weight_) | |
| { | | { | |
| max_weight_ = o.max_weight_; | | max_weight_ = o.max_weight_; | |
| value_ = o.value_; | | value_ = o.value_; | |
| } | | } | |
| | | | |
| skipping to change at line 4967 | | skipping to change at line 5452 | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| value_ = element_type(); | | value_ = element_type(); | |
| left_outliers = 0.0; | | left_outliers = 0.0; | |
| right_outliers = 0.0; | | right_outliers = 0.0; | |
| } | | } | |
| | | | |
| void operator+=(HistogramBase const & o) | | void operator+=(HistogramBase const & o) | |
| { | | { | |
|
| value_ += o.value_; | | if(value_.size() == 0) | |
| | | { | |
| | | value_ = o.value_; | |
| | | } | |
| | | else if(o.value_.size() > 0) | |
| | | { | |
| | | vigra_precondition(value_.size() == o.value_.size(), | |
| | | "HistogramBase::operator+=(): bin counts must be equal."); | |
| | | value_ += o.value_; | |
| | | } | |
| left_outliers += o.left_outliers; | | left_outliers += o.left_outliers; | |
| right_outliers += o.right_outliers; | | right_outliers += o.right_outliers; | |
| } | | } | |
| | | | |
| void setBinCount(int binCount) | | void setBinCount(int binCount) | |
| { | | { | |
| vigra_precondition(binCount > 0, | | vigra_precondition(binCount > 0, | |
| "HistogramBase:.setBinCount(): binCount > 0 required."); | | "HistogramBase:.setBinCount(): binCount > 0 required."); | |
| value_type(Shape1(binCount)).swap(value_); | | value_type(Shape1(binCount)).swap(value_); | |
| } | | } | |
| | | | |
| skipping to change at line 5043 | | skipping to change at line 5537 | |
| else if(index >= (int)this->value_.size()) | | else if(index >= (int)this->value_.size()) | |
| this->right_outliers += weight; | | this->right_outliers += weight; | |
| else | | else | |
| this->value_[index] += weight; | | this->value_[index] += weight; | |
| } | | } | |
| | | | |
| void setMinMax(double mi, double ma) | | void setMinMax(double mi, double ma) | |
| { | | { | |
| vigra_precondition(this->value_.size() > 0, | | vigra_precondition(this->value_.size() > 0, | |
| "RangeHistogramBase::setMinMax(...): setBinCount(...) has not b
een called."); | | "RangeHistogramBase::setMinMax(...): setBinCount(...) has not b
een called."); | |
|
| vigra_precondition(mi < ma, | | vigra_precondition(mi <= ma, | |
| "RangeHistogramBase::setMinMax(...): min < max required."); | | "RangeHistogramBase::setMinMax(...): min <= max required."); | |
| | | if(mi == ma) | |
| | | ma += this->value_.size() * NumericTraits<double>::epsilon(); | |
| offset_ = mi; | | offset_ = mi; | |
| scale_ = (double)this->value_.size() / (ma - mi); | | scale_ = (double)this->value_.size() / (ma - mi); | |
| inverse_scale_ = 1.0 / scale_; | | inverse_scale_ = 1.0 / scale_; | |
| } | | } | |
| | | | |
| double mapItem(double t) const | | double mapItem(double t) const | |
| { | | { | |
| return scale_ * (t - offset_); | | return scale_ * (t - offset_); | |
| } | | } | |
| | | | |
| double mapItemInverse(double t) const | | double mapItemInverse(double t) const | |
| { | | { | |
| return inverse_scale_ * t + offset_; | | return inverse_scale_ * t + offset_; | |
| } | | } | |
| | | | |
| template <class ArrayLike> | | template <class ArrayLike> | |
| void computeStandardQuantiles(double minimum, double maximum, double co
unt, | | void computeStandardQuantiles(double minimum, double maximum, double co
unt, | |
| ArrayLike const & desiredQuantiles, Array
Like & res) const | | ArrayLike const & desiredQuantiles, Array
Like & res) const | |
| { | | { | |
|
| | | if(count == 0.0) { | |
| | | return; | |
| | | } | |
| | | | |
| ArrayVector<double> keypoints, cumhist; | | ArrayVector<double> keypoints, cumhist; | |
| double mappedMinimum = mapItem(minimum); | | double mappedMinimum = mapItem(minimum); | |
| double mappedMaximum = mapItem(maximum); | | double mappedMaximum = mapItem(maximum); | |
| | | | |
| keypoints.push_back(mappedMinimum); | | keypoints.push_back(mappedMinimum); | |
| cumhist.push_back(0.0); | | cumhist.push_back(0.0); | |
| | | | |
| if(this->left_outliers > 0.0) | | if(this->left_outliers > 0.0) | |
| { | | { | |
| keypoints.push_back(0.0); | | keypoints.push_back(0.0); | |
| | | | |
| skipping to change at line 5157 | | skipping to change at line 5657 | |
| - Note that histogram options (for all histograms in the accumulator ch
ain) can also be set by passing an instance of HistogramOptions to the accu
mulator chain via acc_chain.setHistogramOptions(). | | - Note that histogram options (for all histograms in the accumulator ch
ain) can also be set by passing an instance of HistogramOptions to the accu
mulator chain via acc_chain.setHistogramOptions(). | |
| Works in pass 1, %operator+=() supported (merging supported). | | Works in pass 1, %operator+=() supported (merging supported). | |
| */ | | */ | |
| template <int BinCount> | | template <int BinCount> | |
| class IntegerHistogram | | class IntegerHistogram | |
| { | | { | |
| public: | | public: | |
| | | | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("IntegerHistogram<") + asS | | return std::string("IntegerHistogram<") + asString(BinCount) + ">"; | |
| tring(BinCount) + ">"; | | // static const std::string n = std::string("IntegerHistogram<") + | |
| return n; | | asString(BinCount) + ">"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public HistogramBase<BASE, BinCount> | | : public HistogramBase<BASE, BinCount> | |
| { | | { | |
| void update(int index) | | void update(int index) | |
| { | | { | |
| if(index < 0) | | if(index < 0) | |
| ++this->left_outliers; | | ++this->left_outliers; | |
| | | | |
| skipping to change at line 5269 | | skipping to change at line 5770 | |
| - Outliers can be accessed via getAccumulator<...>(a).left_outliers and
getAccumulator<...>(a).right_outliers. | | - Outliers can be accessed via getAccumulator<...>(a).left_outliers and
getAccumulator<...>(a).right_outliers. | |
| - Note that histogram options (for all histograms in the accumulator ch
ain) can also be set by passing an instance of HistogramOptions to the accu
mulator chain via acc_chain.setHistogramOptions(). | | - Note that histogram options (for all histograms in the accumulator ch
ain) can also be set by passing an instance of HistogramOptions to the accu
mulator chain via acc_chain.setHistogramOptions(). | |
| */ | | */ | |
| template <int BinCount> | | template <int BinCount> | |
| class UserRangeHistogram | | class UserRangeHistogram | |
| { | | { | |
| public: | | public: | |
| | | | |
| typedef Select<> Dependencies; | | typedef Select<> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("UserRangeHistogram<") + a | | return std::string("UserRangeHistogram<") + asString(BinCount) + "> | |
| sString(BinCount) + ">"; | | "; | |
| return n; | | // static const std::string n = std::string("UserRangeHistogram<") | |
| | | + asString(BinCount) + ">"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public RangeHistogramBase<BASE, BinCount, U> | | : public RangeHistogramBase<BASE, BinCount, U> | |
| { | | { | |
| void update(U const & t) | | void update(U const & t) | |
| { | | { | |
| update(t, 1.0); | | update(t, 1.0); | |
| } | | } | |
| | | | |
| skipping to change at line 5310 | | skipping to change at line 5812 | |
| - Outliers can be accessed via getAccumulator<...>(acc_chain).left_outl
iers and getAccumulator<...>(acc_chain).right_outliers . | | - Outliers can be accessed via getAccumulator<...>(acc_chain).left_outl
iers and getAccumulator<...>(acc_chain).right_outliers . | |
| - Note that histogram options (for all histograms in the accumulator ch
ain) can also be set by passing an instance of HistogramOptions to the accu
mulator chain via acc_chain.setHistogramOptions(). | | - Note that histogram options (for all histograms in the accumulator ch
ain) can also be set by passing an instance of HistogramOptions to the accu
mulator chain via acc_chain.setHistogramOptions(). | |
| */ | | */ | |
| template <int BinCount> | | template <int BinCount> | |
| class AutoRangeHistogram | | class AutoRangeHistogram | |
| { | | { | |
| public: | | public: | |
| | | | |
| typedef Select<Minimum, Maximum> Dependencies; | | typedef Select<Minimum, Maximum> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("AutoRangeHistogram<") + a | | return std::string("AutoRangeHistogram<") + asString(BinCount) + "> | |
| sString(BinCount) + ">"; | | "; | |
| return n; | | // static const std::string n = std::string("AutoRangeHistogram<") | |
| | | + asString(BinCount) + ">"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public RangeHistogramBase<BASE, BinCount, U> | | : public RangeHistogramBase<BASE, BinCount, U> | |
| { | | { | |
| static const unsigned int workInPass = LookupDependency<Minimum, BA
SE>::type::workInPass + 1; | | static const unsigned int workInPass = LookupDependency<Minimum, BA
SE>::type::workInPass + 1; | |
| | | | |
| void update(U const & t) | | void update(U const & t) | |
| { | | { | |
| | | | |
| skipping to change at line 5353 | | skipping to change at line 5856 | |
| - Outliers can be accessed via getAccumulator<GlobalRangeHistogram<Binc
ount>>(acc_chain).left_outliers and getAccumulator<...>(acc_chain).right_ou
tliers . | | - Outliers can be accessed via getAccumulator<GlobalRangeHistogram<Binc
ount>>(acc_chain).left_outliers and getAccumulator<...>(acc_chain).right_ou
tliers . | |
| - Histogram options (for all histograms in the accumulator chain) can a
lso be set by passing an instance of HistogramOptions to the accumulator ch
ain via acc_chain.setHistogramOptions(). | | - Histogram options (for all histograms in the accumulator chain) can a
lso be set by passing an instance of HistogramOptions to the accumulator ch
ain via acc_chain.setHistogramOptions(). | |
| */ | | */ | |
| template <int BinCount> | | template <int BinCount> | |
| class GlobalRangeHistogram | | class GlobalRangeHistogram | |
| { | | { | |
| public: | | public: | |
| | | | |
| typedef Select<Global<Minimum>, Global<Maximum>, Minimum, Maximum> Depe
ndencies; | | typedef Select<Global<Minimum>, Global<Maximum>, Minimum, Maximum> Depe
ndencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("GlobalRangeHistogram<") + | | return std::string("GlobalRangeHistogram<") + asString(BinCount) + | |
| asString(BinCount) + ">"; | | ">"; | |
| return n; | | // static const std::string n = std::string("GlobalRangeHistogram<" | |
| | | ) + asString(BinCount) + ">"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public RangeHistogramBase<BASE, BinCount, U> | | : public RangeHistogramBase<BASE, BinCount, U> | |
| { | | { | |
| static const unsigned int workInPass = LookupDependency<Minimum, BA
SE>::type::workInPass + 1; | | static const unsigned int workInPass = LookupDependency<Minimum, BA
SE>::type::workInPass + 1; | |
| | | | |
| bool useLocalMinimax_; | | bool useLocalMinimax_; | |
| | | | |
| | | | |
| skipping to change at line 5409 | | skipping to change at line 5913 | |
| Return type is TinyVector<double, 7> . | | Return type is TinyVector<double, 7> . | |
| */ | | */ | |
| template <class HistogramAccumulator> | | template <class HistogramAccumulator> | |
| class StandardQuantiles | | class StandardQuantiles | |
| { | | { | |
| public: | | public: | |
| | | | |
| typedef typename StandardizeTag<HistogramAccumulator>::type HistogramTa
g; | | typedef typename StandardizeTag<HistogramAccumulator>::type HistogramTa
g; | |
| typedef Select<HistogramTag, Minimum, Maximum, Count> Dependencies; | | typedef Select<HistogramTag, Minimum, Maximum, Count> Dependencies; | |
| | | | |
|
| static std::string const & name() | | static std::string name() | |
| { | | { | |
|
| static const std::string n = std::string("StandardQuantiles<") + Hi | | return std::string("StandardQuantiles<") + HistogramTag::name() + " | |
| stogramTag::name() + " >"; | | >"; | |
| return n; | | // static const std::string n = std::string("StandardQuantiles<") + | |
| | | HistogramTag::name() + " >"; | |
| | | // return n; | |
| } | | } | |
| | | | |
| template <class U, class BASE> | | template <class U, class BASE> | |
| struct Impl | | struct Impl | |
| : public CachedResultBase<BASE, TinyVector<double, 7>, U> | | : public CachedResultBase<BASE, TinyVector<double, 7>, U> | |
| { | | { | |
| typedef typename CachedResultBase<BASE, TinyVector<double, 7>, U>::
result_type result_type; | | typedef typename CachedResultBase<BASE, TinyVector<double, 7>, U>::
result_type result_type; | |
| typedef typename CachedResultBase<BASE, TinyVector<double, 7>, U>::
value_type value_type; | | typedef typename CachedResultBase<BASE, TinyVector<double, 7>, U>::
value_type value_type; | |
| | | | |
| static const unsigned int workInPass = LookupDependency<HistogramTa
g, BASE>::type::workInPass; | | static const unsigned int workInPass = LookupDependency<HistogramTa
g, BASE>::type::workInPass; | |
| | | | |
| result_type operator()() const | | result_type operator()() const | |
| { | | { | |
| if(this->isDirty()) | | if(this->isDirty()) | |
| { | | { | |
|
| static const double desiredQuantiles[] = {0.0, 0.1, 0.25, 0
.5, 0.75, 0.9, 1.0 }; | | double desiredQuantiles[] = {0.0, 0.1, 0.25, 0.5, 0.75, 0.9
, 1.0 }; | |
| getAccumulator<HistogramTag>(*this).computeStandardQuantile
s(getDependency<Minimum>(*this), getDependency<Maximum>(*this), | | getAccumulator<HistogramTag>(*this).computeStandardQuantile
s(getDependency<Minimum>(*this), getDependency<Maximum>(*this), | |
|
getDependency<Count>(*this), value_type(desiredQuantiles), | |
getDependency<Count>(*this), value_type(desiredQuantiles), | |
|
this->value_); | |
this->value_); | |
| this->setClean(); | | this->setClean(); | |
| } | | } | |
| return this->value_; | | return this->value_; | |
| } | | } | |
| }; | | }; | |
| }; | | }; | |
| | | | |
|
| | | template <int N> | |
| | | struct feature_RegionContour_can_only_be_computed_for_2D_arrays | |
| | | : vigra::staticAssert::AssertBool<N==2> | |
| | | {}; | |
| | | | |
| | | /** \brief Compute the contour of a 2D region. | |
| | | | |
| | | AccumulatorChain must be used with CoupledIterator in order to have acc | |
| | | ess to pixel coordinates. | |
| | | */ | |
| | | class RegionContour | |
| | | { | |
| | | public: | |
| | | typedef Select<Count> Dependencies; | |
| | | | |
| | | static std::string name() | |
| | | { | |
| | | return std::string("RegionContour"); | |
| | | // static const std::string n = std::string("RegionContour"); | |
| | | // return n; | |
| | | } | |
| | | | |
| | | template <class T, class BASE> | |
| | | struct Impl | |
| | | : public BASE | |
| | | { | |
| | | typedef HandleArgSelector<T, LabelArgTag, BASE> Label | |
| | | Handle; | |
| | | typedef TinyVector<double, 2> point | |
| | | _type; | |
| | | typedef Polygon<point_type> value | |
| | | _type; | |
| | | typedef value_type const & resul | |
| | | t_type; | |
| | | | |
| | | point_type offset_; | |
| | | value_type contour_; | |
| | | | |
| | | Impl() | |
| | | : offset_() | |
| | | , contour_() | |
| | | {} | |
| | | | |
| | | void setCoordinateOffset(point_type const & offset) | |
| | | { | |
| | | offset_ = offset; | |
| | | } | |
| | | | |
| | | template <class U, class NEXT> | |
| | | void update(CoupledHandle<U, NEXT> const & t) | |
| | | { | |
| | | VIGRA_STATIC_ASSERT((feature_RegionContour_can_only_be_computed | |
| | | _for_2D_arrays< | |
| | | CoupledHandle<U, NEXT>::dimensions>)); | |
| | | if(getDependency<Count>(*this) == 1) | |
| | | { | |
| | | contour_.clear(); | |
| | | extractContour(LabelHandle::getHandle(t).arrayView(), t.poi | |
| | | nt(), contour_); | |
| | | contour_ += offset_; | |
| | | } | |
| | | } | |
| | | | |
| | | template <class U, class NEXT> | |
| | | void update(CoupledHandle<U, NEXT> const & t, double weight) | |
| | | { | |
| | | update(t); | |
| | | } | |
| | | | |
| | | void operator+=(Impl const & o) | |
| | | { | |
| | | vigra_precondition(false, | |
| | | "RegionContour::operator+=(): RegionContour cannot be merge | |
| | | d."); | |
| | | } | |
| | | | |
| | | result_type operator()() const | |
| | | { | |
| | | return contour_; | |
| | | } | |
| | | }; | |
| | | }; | |
| | | | |
| | | /** \brief Compute the perimeter of a 2D region. | |
| | | | |
| | | This is the length of the polygon returned by RegionContour. | |
| | | | |
| | | AccumulatorChain must be used with CoupledIterator in order to have acc | |
| | | ess to pixel coordinates. | |
| | | */ | |
| | | class RegionPerimeter | |
| | | { | |
| | | public: | |
| | | typedef Select<RegionContour> Dependencies; | |
| | | | |
| | | static std::string name() | |
| | | { | |
| | | return std::string("RegionPerimeter"); | |
| | | // static const std::string n = std::string("RegionPerimeter"); | |
| | | // return n; | |
| | | } | |
| | | | |
| | | template <class T, class BASE> | |
| | | struct Impl | |
| | | : public BASE | |
| | | { | |
| | | typedef double value_type; | |
| | | typedef value_type result_type; | |
| | | | |
| | | result_type operator()() const | |
| | | { | |
| | | return getDependency<RegionContour>(*this).length(); | |
| | | } | |
| | | }; | |
| | | }; | |
| | | | |
| | | /** \brief Compute the circularity of a 2D region. | |
| | | | |
| | | The is the ratio between the perimeter of a circle with the same area a | |
| | | s the | |
| | | present region and the perimeter of the region, i.e. \f[c = \frac{2 \sq | |
| | | rt{\pi a}}{p} \f], where a and p are the area and length of the polygon ret | |
| | | urned by RegionContour. | |
| | | | |
| | | AccumulatorChain must be used with CoupledIterator in order to have acc | |
| | | ess to pixel coordinates. | |
| | | */ | |
| | | class RegionCircularity | |
| | | { | |
| | | public: | |
| | | typedef Select<Count, RegionContour> Dependencies; | |
| | | | |
| | | static std::string name() | |
| | | { | |
| | | return std::string("RegionCircularity"); | |
| | | // static const std::string n = std::string("RegionCircularity"); | |
| | | // return n; | |
| | | } | |
| | | | |
| | | template <class T, class BASE> | |
| | | struct Impl | |
| | | : public BASE | |
| | | { | |
| | | typedef double value_type; | |
| | | typedef value_type result_type; | |
| | | | |
| | | result_type operator()() const | |
| | | { | |
| | | return 2.0*sqrt(M_PI*getDependency<RegionContour>(*this).area() | |
| | | ) / getDependency<RegionContour>(*this).length(); | |
| | | } | |
| | | }; | |
| | | }; | |
| | | | |
| | | /** \brief Compute the eccentricity of a 2D region in terms of its prinipal | |
| | | radii. | |
| | | | |
| | | Formula: \f[ e = \sqrt{1 - m^2 / M^2 } \f], where m and M are the minor | |
| | | and major principal radius. | |
| | | | |
| | | AccumulatorChain must be used with CoupledIterator in order to have acc | |
| | | ess to pixel coordinates. | |
| | | */ | |
| | | class RegionEccentricity | |
| | | { | |
| | | public: | |
| | | typedef Select<RegionRadii> Dependencies; | |
| | | | |
| | | static std::string name() | |
| | | { | |
| | | return std::string("RegionEccentricity"); | |
| | | // static const std::string n = std::string("RegionEccentricity"); | |
| | | // return n; | |
| | | } | |
| | | | |
| | | template <class T, class BASE> | |
| | | struct Impl | |
| | | : public BASE | |
| | | { | |
| | | typedef double value_type; | |
| | | typedef value_type result_type; | |
| | | | |
| | | result_type operator()() const | |
| | | { | |
| | | double M = getDependency<RegionRadii>(*this).front(), | |
| | | m = getDependency<RegionRadii>(*this).back(); | |
| | | return sqrt(1.0 - sq(m/M)); | |
| | | } | |
| | | }; | |
| | | }; | |
| | | | |
| | | template <int N> | |
| | | struct feature_ConvexHull_can_only_be_computed_for_2D_arrays | |
| | | : vigra::staticAssert::AssertBool<N==2> | |
| | | {}; | |
| | | | |
| | | /** \brief Compute the contour of a 2D region. | |
| | | | |
| | | AccumulatorChain must be used with CoupledIterator in order to have acc | |
| | | ess to pixel coordinates. | |
| | | */ | |
| | | class ConvexHull | |
| | | { | |
| | | public: | |
| | | typedef Select<BoundingBox, RegionContour, RegionCenter> Dependencies; | |
| | | | |
| | | static std::string name() | |
| | | { | |
| | | return std::string("ConvexHull"); | |
| | | // static const std::string n = std::string("ConvexHull"); | |
| | | // return n; | |
| | | } | |
| | | | |
| | | template <class T, class BASE> | |
| | | struct Impl | |
| | | : public BASE | |
| | | { | |
| | | static const unsigned int workInPass = 2; | |
| | | | |
| | | typedef HandleArgSelector<T, LabelArgTag, BASE> Label | |
| | | Handle; | |
| | | typedef TinyVector<double, 2> point | |
| | | _type; | |
| | | typedef Polygon<point_type> polyg | |
| | | on_type; | |
| | | typedef Impl value | |
| | | _type; | |
| | | typedef value_type const & resul | |
| | | t_type; | |
| | | | |
| | | polygon_type convex_hull_; | |
| | | point_type input_center_, convex_hull_center_, defect_center_; | |
| | | double convexity_, rugosity_, mean_defect_displacement_, | |
| | | defect_area_mean_, defect_area_variance_, defect_area_skewne | |
| | | ss_, defect_area_kurtosis_; | |
| | | int convexity_defect_count_; | |
| | | ArrayVector<MultiArrayIndex> convexity_defect_area_; | |
| | | bool features_computed_; | |
| | | | |
| | | Impl() | |
| | | : convex_hull_() | |
| | | , input_center_() | |
| | | , convex_hull_center_() | |
| | | , defect_center_() | |
| | | , convexity_() | |
| | | , rugosity_() | |
| | | , mean_defect_displacement_() | |
| | | , defect_area_mean_() | |
| | | , defect_area_variance_() | |
| | | , defect_area_skewness_() | |
| | | , defect_area_kurtosis_() | |
| | | , convexity_defect_count_() | |
| | | , convexity_defect_area_() | |
| | | , features_computed_(false) | |
| | | {} | |
| | | | |
| | | template <class U, class NEXT> | |
| | | void update(CoupledHandle<U, NEXT> const & t) | |
| | | { | |
| | | VIGRA_STATIC_ASSERT((feature_ConvexHull_can_only_be_computed_fo | |
| | | r_2D_arrays< | |
| | | CoupledHandle<U, NEXT>::dimensions>)); | |
| | | if(!features_computed_) | |
| | | { | |
| | | using namespace functor; | |
| | | Shape2 start = getDependency<Coord<Minimum> >(*this), | |
| | | stop = getDependency<Coord<Maximum> >(*this) + Shap | |
| | | e2(1); | |
| | | point_type offset(start); | |
| | | input_center_ = getDependency<RegionCenter>(*this); | |
| | | MultiArrayIndex label = LabelHandle::getValue(t); | |
| | | | |
| | | convex_hull_.clear(); | |
| | | convexHull(getDependency<RegionContour>(*this), convex_hull | |
| | | _); | |
| | | convex_hull_center_ = centroid(convex_hull_); | |
| | | | |
| | | convexity_ = getDependency<RegionContour>(*this).area() / c | |
| | | onvex_hull_.area(); | |
| | | rugosity_ = getDependency<RegionContour>(*this).length() / | |
| | | convex_hull_.length(); | |
| | | | |
| | | MultiArray<2, UInt8> convex_hull_difference(stop-start); | |
| | | fillPolygon(convex_hull_ - offset, convex_hull_difference, | |
| | | 1); | |
| | | combineTwoMultiArrays(convex_hull_difference, | |
| | | LabelHandle::getHandle(t).arrayView() | |
| | | .subarray(start, stop), | |
| | | convex_hull_difference, | |
| | | ifThenElse(Arg2() == Param(label), Pa | |
| | | ram(0), Arg1())); | |
| | | | |
| | | MultiArray<2, UInt32> convexity_defects(stop-start); | |
| | | convexity_defect_count_ = | |
| | | labelImageWithBackground(convex_hull_difference, convexi | |
| | | ty_defects, false, 0); | |
| | | | |
| | | if (convexity_defect_count_ != 0) | |
| | | { | |
| | | AccumulatorChainArray<CoupledArrays<2, UInt32>, | |
| | | Select<LabelArg<1>, Count, Region | |
| | | Center> > convexity_defects_stats; | |
| | | convexity_defects_stats.ignoreLabel(0); | |
| | | extractFeatures(convexity_defects, convexity_defects_st | |
| | | ats); | |
| | | | |
| | | double total_defect_area = 0.0; | |
| | | mean_defect_displacement_ = 0.0; | |
| | | defect_center_ = point_type(); | |
| | | for (int k = 1; k <= convexity_defect_count_; ++k) | |
| | | { | |
| | | double area = get<Count>(convexity_defects_stats, k | |
| | | ); | |
| | | point_type center = get<RegionCenter>(convexity_def | |
| | | ects_stats, k) + offset; | |
| | | | |
| | | convexity_defect_area_.push_back(area); | |
| | | total_defect_area += area; | |
| | | defect_center_ += area*center; | |
| | | mean_defect_displacement_ += area*norm(input_center | |
| | | _ - center); | |
| | | } | |
| | | sort(convexity_defect_area_.begin(), convexity_defect_a | |
| | | rea_.end(), | |
| | | std::greater<MultiArrayIndex>()); | |
| | | mean_defect_displacement_ /= total_defect_area; | |
| | | defect_center_ /= total_defect_area; | |
| | | | |
| | | AccumulatorChain<MultiArrayIndex, | |
| | | Select<Mean, UnbiasedVariance, Unbiase | |
| | | dSkewness, UnbiasedKurtosis> > defect_area_stats; | |
| | | extractFeatures(convexity_defect_area_.begin(), | |
| | | convexity_defect_area_.end(), defect_ar | |
| | | ea_stats); | |
| | | | |
| | | defect_area_mean_ = convexity_defect_count_ > 0 | |
| | | ? get<Mean>(defect_area_stats) | |
| | | : 0.0; | |
| | | defect_area_variance_ = convexity_defect_count_ > 1 | |
| | | ? get<UnbiasedVariance>(defect_area_stats) | |
| | | : 0.0; | |
| | | defect_area_skewness_ = convexity_defect_count_ > 2 | |
| | | ? get<UnbiasedSkewness>(defect_area_stats) | |
| | | : 0.0; | |
| | | defect_area_kurtosis_ = convexity_defect_count_ > 3 | |
| | | ? get<UnbiasedKurtosis>(defect_area_stats) | |
| | | : 0.0; | |
| | | } | |
| | | /**********************************************/ | |
| | | features_computed_ = true; | |
| | | } | |
| | | } | |
| | | | |
| | | template <class U, class NEXT> | |
| | | void update(CoupledHandle<U, NEXT> const & t, double weight) | |
| | | { | |
| | | update(t); | |
| | | } | |
| | | | |
| | | void operator+=(Impl const & o) | |
| | | { | |
| | | vigra_precondition(false, | |
| | | "ConvexHull::operator+=(): ConvexHull features cannot be me | |
| | | rged."); | |
| | | } | |
| | | | |
| | | result_type operator()() const | |
| | | { | |
| | | return *this; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the convex hull polygon. | |
| | | */ | |
| | | polygon_type const & hull() const | |
| | | { | |
| | | return convex_hull_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the area enclosed by the input polygon. | |
| | | */ | |
| | | double inputArea() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return getDependency<RegionContour>(*this).area(); | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the area enclosed by the convex hull polygon. | |
| | | */ | |
| | | double hullArea() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return convex_hull_.area(); | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the perimeter of the input polygon. | |
| | | */ | |
| | | double inputPerimeter() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return getDependency<RegionContour>(*this).length(); | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the perimeter of the convex hull polygon. | |
| | | */ | |
| | | double hullPerimeter() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return convex_hull_.length(); | |
| | | } | |
| | | | |
| | | /* | |
| | | * Center of the original region. | |
| | | */ | |
| | | point_type const & inputCenter() const | |
| | | { | |
| | | return input_center_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Center of the region enclosed by the convex hull. | |
| | | */ | |
| | | point_type const & hullCenter() const | |
| | | { | |
| | | return convex_hull_center_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Center of difference between the convex hull and the original re | |
| | | gion. | |
| | | */ | |
| | | point_type const & convexityDefectCenter() const | |
| | | { | |
| | | return defect_center_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the ratio between the input area and the convex hull are | |
| | | a. | |
| | | * This is always <tt><= 1</tt>, and the smaller the value is, | |
| | | * the less convex is the input polygon. | |
| | | */ | |
| | | double convexity() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return convexity_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the ratio between the input perimeter and the convex per | |
| | | imeter. | |
| | | * This is always <tt>>= 1</tt>, and the higher the value is, the l | |
| | | ess | |
| | | * convex is the input polygon. | |
| | | */ | |
| | | double rugosity() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return rugosity_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the number of convexity defects (i.e. number of connecte | |
| | | d components | |
| | | * of the difference between convex hull and input region). | |
| | | */ | |
| | | int convexityDefectCount() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return convexity_defect_count_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the mean area of the convexity defects. | |
| | | */ | |
| | | double convexityDefectAreaMean() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return defect_area_mean_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the variance of the convexity defect areas. | |
| | | */ | |
| | | double convexityDefectAreaVariance() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return defect_area_variance_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the skewness of the convexity defect areas. | |
| | | */ | |
| | | double convexityDefectAreaSkewness() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return defect_area_skewness_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the kurtosis of the convexity defect areas. | |
| | | */ | |
| | | double convexityDefectAreaKurtosis() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return defect_area_kurtosis_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the mean distance between the defect areas and the cente | |
| | | r of | |
| | | * the input region, weighted by the area of each defect region. | |
| | | */ | |
| | | double meanDefectDisplacement() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return mean_defect_displacement_; | |
| | | } | |
| | | | |
| | | /* | |
| | | * Returns the areas of the convexity defect regions (ordered desce | |
| | | nding). | |
| | | */ | |
| | | ArrayVector<MultiArrayIndex> const & defectAreaList() const | |
| | | { | |
| | | vigra_precondition(features_computed_, | |
| | | "ConvexHull: features must be calculated first."); | |
| | | return convexity_defect_area_; | |
| | | } | |
| | | }; | |
| | | }; | |
| | | | |
| }} // namespace vigra::acc | | }} // namespace vigra::acc | |
| | | | |
| #endif // VIGRA_ACCUMULATOR_HXX | | #endif // VIGRA_ACCUMULATOR_HXX | |
| | | | |
End of changes. 272 change blocks. |
| 474 lines changed or deleted | | 1621 lines changed or added | |
|
| algorithm.hxx | | algorithm.hxx | |
| | | | |
| skipping to change at line 51 | | skipping to change at line 51 | |
| #include "inspector_passes.hxx" | | #include "inspector_passes.hxx" | |
| #include <algorithm> | | #include <algorithm> | |
| #include <functional> | | #include <functional> | |
| #include <iterator> | | #include <iterator> | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup MathFunctions | | /** \addtogroup MathFunctions | |
| */ | | */ | |
| //@{ | | //@{ | |
|
| /*! Find the minimum element in a sequence. | | /** \brief Find the minimum element in a sequence. | |
| | | | |
| The function returns the iterator referring to the minimum element. | | The function returns the iterator referring to the minimum element. | |
| This is identical to the function <tt>std::min_element()</tt>. | | This is identical to the function <tt>std::min_element()</tt>. | |
| | | | |
| <b>Required Interface:</b> | | <b>Required Interface:</b> | |
| | | | |
| \code | | \code | |
| Iterator is a standard forward iterator. | | Iterator is a standard forward iterator. | |
| | | | |
| bool f = *first < NumericTraits<typename std::iterator_traits<Itera
tor>::value_type>::max(); | | bool f = *first < NumericTraits<typename std::iterator_traits<Itera
tor>::value_type>::max(); | |
| | | | |
| skipping to change at line 79 | | skipping to change at line 79 | |
| { | | { | |
| if(first == last) | | if(first == last) | |
| return last; | | return last; | |
| Iterator best = first; | | Iterator best = first; | |
| for(++first; first != last; ++first) | | for(++first; first != last; ++first) | |
| if(*first < *best) | | if(*first < *best) | |
| best = first; | | best = first; | |
| return best; | | return best; | |
| } | | } | |
| | | | |
|
| /*! Find the maximum element in a sequence. | | /** \brief Find the maximum element in a sequence. | |
| | | | |
| The function returns the iterator referring to the maximum element. | | The function returns the iterator referring to the maximum element. | |
| This is identical to the function <tt>std::max_element()</tt>. | | This is identical to the function <tt>std::max_element()</tt>. | |
| | | | |
| <b>Required Interface:</b> | | <b>Required Interface:</b> | |
| | | | |
| \code | | \code | |
| Iterator is a standard forward iterator. | | Iterator is a standard forward iterator. | |
| | | | |
| bool f = NumericTraits<typename std::iterator_traits<Iterator>::val
ue_type>::min() < *first; | | bool f = NumericTraits<typename std::iterator_traits<Iterator>::val
ue_type>::min() < *first; | |
| | | | |
| skipping to change at line 107 | | skipping to change at line 107 | |
| { | | { | |
| if(first == last) | | if(first == last) | |
| return last; | | return last; | |
| Iterator best = first; | | Iterator best = first; | |
| for(++first; first != last; ++first) | | for(++first; first != last; ++first) | |
| if(*best < *first) | | if(*best < *first) | |
| best = first; | | best = first; | |
| return best; | | return best; | |
| } | | } | |
| | | | |
|
| /*! Find the minimum element in a sequence conforming to a condition. | | /** \brief Find the minimum element in a sequence conforming to a condi
tion. | |
| | | | |
| The function returns the iterator referring to the minimum element, | | The function returns the iterator referring to the minimum element, | |
| where only elements conforming to the condition (i.e. where | | where only elements conforming to the condition (i.e. where | |
| <tt>condition(*iterator)</tt> evaluates to <tt>true</tt>) are consi
dered. | | <tt>condition(*iterator)</tt> evaluates to <tt>true</tt>) are consi
dered. | |
| If no element conforms to the condition, or the sequence is empty, | | If no element conforms to the condition, or the sequence is empty, | |
| the end iterator \a last is returned. | | the end iterator \a last is returned. | |
| | | | |
| <b>Required Interface:</b> | | <b>Required Interface:</b> | |
| | | | |
| \code | | \code | |
| | | | |
| skipping to change at line 143 | | skipping to change at line 143 | |
| break; | | break; | |
| if(first == last) | | if(first == last) | |
| return last; | | return last; | |
| Iterator best = first; | | Iterator best = first; | |
| for(++first; first != last; ++first) | | for(++first; first != last; ++first) | |
| if(condition(*first) && *first < *best) | | if(condition(*first) && *first < *best) | |
| best = first; | | best = first; | |
| return best; | | return best; | |
| } | | } | |
| | | | |
|
| /*! Find the maximum element in a sequence conforming to a condition. | | /** \brief Find the maximum element in a sequence conforming to a condi
tion. | |
| | | | |
| The function returns the iterator referring to the maximum element, | | The function returns the iterator referring to the maximum element, | |
| where only elements conforming to the condition (i.e. where | | where only elements conforming to the condition (i.e. where | |
| <tt>condition(*iterator)</tt> evaluates to <tt>true</tt>) are consi
dered. | | <tt>condition(*iterator)</tt> evaluates to <tt>true</tt>) are consi
dered. | |
| If no element conforms to the condition, or the sequence is empty, | | If no element conforms to the condition, or the sequence is empty, | |
| the end iterator \a last is returned. | | the end iterator \a last is returned. | |
| | | | |
| <b>Required Interface:</b> | | <b>Required Interface:</b> | |
| | | | |
| \code | | \code | |
| | | | |
| skipping to change at line 179 | | skipping to change at line 179 | |
| break; | | break; | |
| if(first == last) | | if(first == last) | |
| return last; | | return last; | |
| Iterator best = first; | | Iterator best = first; | |
| for(++first; first != last; ++first) | | for(++first; first != last; ++first) | |
| if(condition(*first) && *best < *first) | | if(condition(*first) && *best < *first) | |
| best = first; | | best = first; | |
| return best; | | return best; | |
| } | | } | |
| | | | |
|
| /*! Fill an array with a sequence of numbers. | | /** \brief Fill an array with a sequence of numbers. | |
| | | | |
| The sequence starts at \a start and is incremented with \a step. De
fault start | | The sequence starts at \a start and is incremented with \a step. De
fault start | |
|
| and stepsize are 0 and 1 respectively. | | and stepsize are 0 and 1 respectively. This is a generalization of | |
| | | function | |
| | | <tt>std::iota()</tt> in C++11. | |
| | | | |
| <b> Declaration:</b> | | <b> Declaration:</b> | |
| | | | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Iterator, class Value> | | template <class Iterator, class Value> | |
| void linearSequence(Iterator first, Iterator last, | | void linearSequence(Iterator first, Iterator last, | |
| Value const & start = 0, Value const & step = 1); | | Value const & start = 0, Value const & step = 1); | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
| skipping to change at line 216 | | skipping to change at line 217 | |
| template <class Iterator, class Value> | | template <class Iterator, class Value> | |
| void linearSequence(Iterator first, Iterator last, Value start, Value step) | | void linearSequence(Iterator first, Iterator last, Value start, Value step) | |
| { | | { | |
| for(; first != last; ++first, start += step) | | for(; first != last; ++first, start += step) | |
| *first = start; | | *first = start; | |
| } | | } | |
| | | | |
| template <class Iterator, class Value> | | template <class Iterator, class Value> | |
| void linearSequence(Iterator first, Iterator last, Value start) | | void linearSequence(Iterator first, Iterator last, Value start) | |
| { | | { | |
|
| for(; first != last; ++first, ++start) | | linearSequence(first, last, start, NumericTraits<Value>::one()); | |
| *first = start; | | | |
| } | | } | |
| | | | |
| template <class Iterator> | | template <class Iterator> | |
| void linearSequence(Iterator first, Iterator last) | | void linearSequence(Iterator first, Iterator last) | |
| { | | { | |
| typedef typename std::iterator_traits<Iterator>::value_type Value; | | typedef typename std::iterator_traits<Iterator>::value_type Value; | |
| | | | |
| linearSequence(first, last, NumericTraits<Value>::zero()); | | linearSequence(first, last, NumericTraits<Value>::zero()); | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 294 | | skipping to change at line 294 | |
| template <class InputIterator, class Functor> | | template <class InputIterator, class Functor> | |
| inline void | | inline void | |
| inspectSequence(InputIterator first, InputIterator last, Functor & f) | | inspectSequence(InputIterator first, InputIterator last, Functor & f) | |
| { | | { | |
| detail::inspectSequence_binder<InputIterator> g(first, last); | | detail::inspectSequence_binder<InputIterator> g(first, last); | |
| detail::extra_passes_select(g, f); | | detail::extra_passes_select(g, f); | |
| } | | } | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
|
| template <class Iterator, class Compare> | | template <class ArrayLike, class Compare> | |
| struct IndexCompare | | struct IndexCompare | |
| { | | { | |
|
| Iterator i_; | | ArrayLike i_; | |
| Compare c_; | | Compare c_; | |
| | | | |
|
| IndexCompare(Iterator i, Compare c) | | IndexCompare(ArrayLike i, Compare c) | |
| : i_(i), | | : i_(i), | |
| c_(c) | | c_(c) | |
| {} | | {} | |
| | | | |
| template <class Index> | | template <class Index> | |
| bool operator()(Index const & l, Index const & r) const | | bool operator()(Index const & l, Index const & r) const | |
| { | | { | |
| return c_(i_[l], i_[r]); | | return c_(i_[l], i_[r]); | |
| } | | } | |
| }; | | }; | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! Return the index permutation that would sort the input array. | | /** \brief Create a compare functor for indirect sort. | |
| | | | |
| | | Indirect sorting refers to the situation where you have an array ho | |
| | | lding | |
| | | data and another array holding indices referencing the first array, | |
| | | and you want to sort the index array according to some property of | |
| | | the data array without changing the data array itself. The factory | |
| | | function <tt>makeIndexComparator()</tt> creates a sorting predicate | |
| | | for this task, given a sorting predicate for the data array. | |
| | | | |
| | | \see vigra::indexSort(), vigra::applyPermutation() | |
| | | | |
| | | <b>Usage:</b> | |
| | | | |
| | | <b>\#include</b> \<vigra/algorithm.hxx\><br> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | const std:vector<double> data(...); // data is immutable | |
| | | | |
| | | std::vector<int> index(data.size()); | |
| | | std::iota(index.begin(), index.end()); | |
| | | | |
| | | // sort the indices such that data[index[k]] is an ascending sequen | |
| | | ce in k | |
| | | std::sort(index.begin(), index.end(), makeIndexComparator(data)); | |
| | | \endcode | |
| | | | |
| | | <b>Declarations:</b> | |
| | | | |
| | | \code | |
| | | namespace vigra { | |
| | | // compare using std::less | |
| | | template <class ArrayLike> | |
| | | auto makeIndexComparator(ArrayLike a); | |
| | | | |
| | | // compare using functor Compare | |
| | | template <class ArrayLike, class Compare> | |
| | | auto makeIndexComparator(ArrayLike a, Compare c); | |
| | | } | |
| | | \endcode | |
| | | */ | |
| | | template <class ArrayLike, class Compare> | |
| | | inline detail::IndexCompare<ArrayLike, Compare> | |
| | | makeIndexComparator(ArrayLike a, Compare c) | |
| | | { | |
| | | return detail::IndexCompare<ArrayLike, Compare>(a, c); | |
| | | } | |
| | | | |
| | | template <class ArrayLike> | |
| | | inline detail::IndexCompare<ArrayLike, std::less<typename ArrayLike::value_ | |
| | | type> > | |
| | | makeIndexComparator(ArrayLike a) | |
| | | { | |
| | | typedef std::less<typename ArrayLike::value_type> Compare; | |
| | | return detail::IndexCompare<ArrayLike, Compare>(a, Compare()); | |
| | | } | |
| | | | |
| | | /** \brief Return the index permutation that would sort the input array | |
| | | . | |
| | | | |
| To actually sort an array according to the ordering thus determined
, use | | To actually sort an array according to the ordering thus determined
, use | |
| \ref applyPermutation(). | | \ref applyPermutation(). | |
| | | | |
|
| | | <b>Usage:</b> | |
| | | | |
| | | <b>\#include</b> \<vigra/algorithm.hxx\><br> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | const std:vector<double> data(...); // data is immutable | |
| | | | |
| | | std::vector<int> index(data.size()); | |
| | | | |
| | | // arrange indices such that data[index[k]] is an ascending sequenc | |
| | | e in k | |
| | | indexSort(data.begin(), data.end(), index.begin()); | |
| | | \endcode | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // compare using std::less | | // compare using std::less | |
| template <class Iterator, class IndexIterator> | | template <class Iterator, class IndexIterator> | |
| void indexSort(Iterator first, Iterator last, IndexIterator ind
ex_first); | | void indexSort(Iterator first, Iterator last, IndexIterator ind
ex_first); | |
| | | | |
| // compare using functor Compare | | // compare using functor Compare | |
| template <class Iterator, class IndexIterator, class Compare> | | template <class Iterator, class IndexIterator, class Compare> | |
| | | | |
| skipping to change at line 349 | | skipping to change at line 418 | |
| \endcode | | \endcode | |
| | | | |
| <b>\#include</b> \<vigra/algorithm.hxx\><br> | | <b>\#include</b> \<vigra/algorithm.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class Iterator, class IndexIterator, class Compare> | | template <class Iterator, class IndexIterator, class Compare> | |
| void indexSort(Iterator first, Iterator last, IndexIterator index_first, Co
mpare c) | | void indexSort(Iterator first, Iterator last, IndexIterator index_first, Co
mpare c) | |
| { | | { | |
| int size = last - first; | | int size = last - first; | |
| linearSequence(index_first, index_first+size); | | linearSequence(index_first, index_first+size); | |
|
| std::sort(index_first, index_first+size, | | std::sort(index_first, index_first+size, makeIndexComparator(first, c)) | |
| detail::IndexCompare<Iterator, Compare>(first, c)); | | ; | |
| } | | } | |
| | | | |
| template <class Iterator, class IndexIterator> | | template <class Iterator, class IndexIterator> | |
| void indexSort(Iterator first, Iterator last, IndexIterator index_first) | | void indexSort(Iterator first, Iterator last, IndexIterator index_first) | |
| { | | { | |
| typedef typename std::iterator_traits<Iterator>::value_type Value; | | typedef typename std::iterator_traits<Iterator>::value_type Value; | |
| indexSort(first, last, index_first, std::less<Value>()); | | indexSort(first, last, index_first, std::less<Value>()); | |
| } | | } | |
| | | | |
|
| /*! Sort an array according to the given index permutation. | | /** \brief Sort an array according to the given index permutation. | |
| | | | |
| The iterators \a in and \a out may not refer to the same array, as | | The iterators \a in and \a out may not refer to the same array, as | |
| this would overwrite the input prematurely. | | this would overwrite the input prematurely. | |
| | | | |
| <b> Declaration:</b> | | <b> Declaration:</b> | |
| | | | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class IndexIterator, class InIterator, class OutItera
tor> | | template <class IndexIterator, class InIterator, class OutItera
tor> | |
| void applyPermutation(IndexIterator index_first, IndexIterator
index_last, | | void applyPermutation(IndexIterator index_first, IndexIterator
index_last, | |
| | | | |
| skipping to change at line 395 | | skipping to change at line 463 | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class IndexIterator, class InIterator, class OutIterator> | | template <class IndexIterator, class InIterator, class OutIterator> | |
| void applyPermutation(IndexIterator index_first, IndexIterator index_last, | | void applyPermutation(IndexIterator index_first, IndexIterator index_last, | |
| InIterator in, OutIterator out) | | InIterator in, OutIterator out) | |
| { | | { | |
| for(; index_first != index_last; ++index_first, ++out) | | for(; index_first != index_last; ++index_first, ++out) | |
| *out = in[*index_first]; | | *out = in[*index_first]; | |
| } | | } | |
| | | | |
|
| /*! Compute the inverse of a given permutation. | | /** \brief Compute the inverse of a given permutation. | |
| | | | |
| This is just another name for \ref indexSort(), referring to | | This is just another name for \ref indexSort(), referring to | |
| another semantics. | | another semantics. | |
| | | | |
| <b> Declaration:</b> | | <b> Declaration:</b> | |
| | | | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class InIterator, class OutIterator> | | template <class InIterator, class OutIterator> | |
| void inversePermutation(InIterator first, InIterator last, | | void inversePermutation(InIterator first, InIterator last, | |
| | | | |
| skipping to change at line 436 | | skipping to change at line 504 | |
| } | | } | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| static bool isLittleEndian() | | static bool isLittleEndian() | |
| { | | { | |
| static const UIntBiggest testint = 0x01; | | static const UIntBiggest testint = 0x01; | |
| return ((UInt8 *)&testint)[0] == 0x01; | | return ((UInt8 *)&testint)[0] == 0x01; | |
| } | | } | |
| | | | |
|
| template <class InIterator> | | template <class INT> | |
| UInt32 checksumImpl(InIterator i, unsigned int size, UInt32 crc = 0xFFFFFFF | | struct ChecksumImpl | |
| F) | | | |
| { | | { | |
|
| static const UInt32 table[256] = { | | static UInt32 table0[256]; | |
| 0x0U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x76dc419U, 0x706af48f | | static UInt32 table1[256]; | |
| U, | | static UInt32 table2[256]; | |
| 0xe963a535U, 0x9e6495a3U, 0xedb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x9 | | static UInt32 table3[256]; | |
| 7d2d988U, | | | |
| 0x9b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, 0x6 | | | |
| ab020f2U, | | | |
| 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x | | | |
| 83d385c7U, | | | |
| 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x | | | |
| 63066cd9U, | | | |
| 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0x | | | |
| a2677172U, | | | |
| 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, 0x | | | |
| 42b2986cU, | | | |
| 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0x | | | |
| abd13d59U, | | | |
| 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x | | | |
| 56b3c423U, | | | |
| 0xcfba9599U, 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0x | | | |
| b10be924U, | | | |
| 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, 0x | | | |
| 1db7106U, | | | |
| 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x6b6b51fU, 0x9fbfe4a5U, 0xe | | | |
| 8b8d433U, | | | |
| 0x7807c9a2U, 0xf00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x8 | | | |
| 6d3d2dU, | | | |
| 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0x | | | |
| f262004eU, | | | |
| 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x | | | |
| 12b7e950U, | | | |
| 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0x | | | |
| fbd44c65U, | | | |
| 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x | | | |
| 3dd895d7U, | | | |
| 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0x | | | |
| da60b8d0U, | | | |
| 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x | | | |
| 270241aaU, | | | |
| 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0x | | | |
| ce61e49fU, | | | |
| 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x | | | |
| 2eb40d81U, | | | |
| 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x3b6e20cU, 0x7 | | | |
| 4b1d29aU, | | | |
| 0xead54739U, 0x9dd277afU, 0x4db2615U, 0x73dc1683U, 0xe3630b12U, 0x9 | | | |
| 4643b84U, | | | |
| 0xd6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0xa00ae27U, 0x7d | | | |
| 079eb1U, | | | |
| 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x | | | |
| 806567cbU, | | | |
| 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x | | | |
| 67dd4accU, | | | |
| 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 0xd6d6a3e8U, 0x | | | |
| a1d1937eU, | | | |
| 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x | | | |
| 48b2364bU, | | | |
| 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0x | | | |
| a867df55U, | | | |
| 0x316e8eefU, 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x | | | |
| 5268e236U, | | | |
| 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, 0x | | | |
| b2bd0b28U, | | | |
| 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x | | | |
| 5bdeae1dU, | | | |
| 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x26d930aU, 0x9c0906a9U, 0xe | | | |
| b0e363fU, | | | |
| 0x72076785U, 0x5005713U, 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0xc | | | |
| b61b38U, | | | |
| 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0xbdbdf21U, 0x86d3d2d4U, 0xf | | | |
| 1d4e242U, | | | |
| 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x | | | |
| 18b74777U, | | | |
| 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0x | | | |
| f862ae69U, | | | |
| 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x | | | |
| 3903b3c2U, | | | |
| 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0x | | | |
| d9d65adcU, | | | |
| 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x | | | |
| 30b5ffe9U, | | | |
| 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0x | | | |
| cdd70693U, | | | |
| 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x | | | |
| 2a6f2b94U, | | | |
| 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU }; | | | |
| | | | |
| static const UInt32 table1[256] = { | | | |
| 0x00000000U, 0x191b3141U, 0x32366282U, 0x2b2d53c3U, 0x646cc504U, | | | |
| 0x7d77f445U, 0x565aa786U, 0x4f4196c7U, 0xc8d98a08U, 0xd1c2bb49U, | | | |
| 0xfaefe88aU, 0xe3f4d9cbU, 0xacb54f0cU, 0xb5ae7e4dU, 0x9e832d8eU, | | | |
| 0x87981ccfU, 0x4ac21251U, 0x53d92310U, 0x78f470d3U, 0x61ef4192U, | | | |
| 0x2eaed755U, 0x37b5e614U, 0x1c98b5d7U, 0x05838496U, 0x821b9859U, | | | |
| 0x9b00a918U, 0xb02dfadbU, 0xa936cb9aU, 0xe6775d5dU, 0xff6c6c1cU, | | | |
| 0xd4413fdfU, 0xcd5a0e9eU, 0x958424a2U, 0x8c9f15e3U, 0xa7b24620U, | | | |
| 0xbea97761U, 0xf1e8e1a6U, 0xe8f3d0e7U, 0xc3de8324U, 0xdac5b265U, | | | |
| 0x5d5daeaaU, 0x44469febU, 0x6f6bcc28U, 0x7670fd69U, 0x39316baeU, | | | |
| 0x202a5aefU, 0x0b07092cU, 0x121c386dU, 0xdf4636f3U, 0xc65d07b2U, | | | |
| 0xed705471U, 0xf46b6530U, 0xbb2af3f7U, 0xa231c2b6U, 0x891c9175U, | | | |
| 0x9007a034U, 0x179fbcfbU, 0x0e848dbaU, 0x25a9de79U, 0x3cb2ef38U, | | | |
| 0x73f379ffU, 0x6ae848beU, 0x41c51b7dU, 0x58de2a3cU, 0xf0794f05U, | | | |
| 0xe9627e44U, 0xc24f2d87U, 0xdb541cc6U, 0x94158a01U, 0x8d0ebb40U, | | | |
| 0xa623e883U, 0xbf38d9c2U, 0x38a0c50dU, 0x21bbf44cU, 0x0a96a78fU, | | | |
| 0x138d96ceU, 0x5ccc0009U, 0x45d73148U, 0x6efa628bU, 0x77e153caU, | | | |
| 0xbabb5d54U, 0xa3a06c15U, 0x888d3fd6U, 0x91960e97U, 0xded79850U, | | | |
| 0xc7cca911U, 0xece1fad2U, 0xf5facb93U, 0x7262d75cU, 0x6b79e61dU, | | | |
| 0x4054b5deU, 0x594f849fU, 0x160e1258U, 0x0f152319U, 0x243870daU, | | | |
| 0x3d23419bU, 0x65fd6ba7U, 0x7ce65ae6U, 0x57cb0925U, 0x4ed03864U, | | | |
| 0x0191aea3U, 0x188a9fe2U, 0x33a7cc21U, 0x2abcfd60U, 0xad24e1afU, | | | |
| 0xb43fd0eeU, 0x9f12832dU, 0x8609b26cU, 0xc94824abU, 0xd05315eaU, | | | |
| 0xfb7e4629U, 0xe2657768U, 0x2f3f79f6U, 0x362448b7U, 0x1d091b74U, | | | |
| 0x04122a35U, 0x4b53bcf2U, 0x52488db3U, 0x7965de70U, 0x607eef31U, | | | |
| 0xe7e6f3feU, 0xfefdc2bfU, 0xd5d0917cU, 0xcccba03dU, 0x838a36faU, | | | |
| 0x9a9107bbU, 0xb1bc5478U, 0xa8a76539U, 0x3b83984bU, 0x2298a90aU, | | | |
| 0x09b5fac9U, 0x10aecb88U, 0x5fef5d4fU, 0x46f46c0eU, 0x6dd93fcdU, | | | |
| 0x74c20e8cU, 0xf35a1243U, 0xea412302U, 0xc16c70c1U, 0xd8774180U, | | | |
| 0x9736d747U, 0x8e2de606U, 0xa500b5c5U, 0xbc1b8484U, 0x71418a1aU, | | | |
| 0x685abb5bU, 0x4377e898U, 0x5a6cd9d9U, 0x152d4f1eU, 0x0c367e5fU, | | | |
| 0x271b2d9cU, 0x3e001cddU, 0xb9980012U, 0xa0833153U, 0x8bae6290U, | | | |
| 0x92b553d1U, 0xddf4c516U, 0xc4eff457U, 0xefc2a794U, 0xf6d996d5U, | | | |
| 0xae07bce9U, 0xb71c8da8U, 0x9c31de6bU, 0x852aef2aU, 0xca6b79edU, | | | |
| 0xd37048acU, 0xf85d1b6fU, 0xe1462a2eU, 0x66de36e1U, 0x7fc507a0U, | | | |
| 0x54e85463U, 0x4df36522U, 0x02b2f3e5U, 0x1ba9c2a4U, 0x30849167U, | | | |
| 0x299fa026U, 0xe4c5aeb8U, 0xfdde9ff9U, 0xd6f3cc3aU, 0xcfe8fd7bU, | | | |
| 0x80a96bbcU, 0x99b25afdU, 0xb29f093eU, 0xab84387fU, 0x2c1c24b0U, | | | |
| 0x350715f1U, 0x1e2a4632U, 0x07317773U, 0x4870e1b4U, 0x516bd0f5U, | | | |
| 0x7a468336U, 0x635db277U, 0xcbfad74eU, 0xd2e1e60fU, 0xf9ccb5ccU, | | | |
| 0xe0d7848dU, 0xaf96124aU, 0xb68d230bU, 0x9da070c8U, 0x84bb4189U, | | | |
| 0x03235d46U, 0x1a386c07U, 0x31153fc4U, 0x280e0e85U, 0x674f9842U, | | | |
| 0x7e54a903U, 0x5579fac0U, 0x4c62cb81U, 0x8138c51fU, 0x9823f45eU, | | | |
| 0xb30ea79dU, 0xaa1596dcU, 0xe554001bU, 0xfc4f315aU, 0xd7626299U, | | | |
| 0xce7953d8U, 0x49e14f17U, 0x50fa7e56U, 0x7bd72d95U, 0x62cc1cd4U, | | | |
| 0x2d8d8a13U, 0x3496bb52U, 0x1fbbe891U, 0x06a0d9d0U, 0x5e7ef3ecU, | | | |
| 0x4765c2adU, 0x6c48916eU, 0x7553a02fU, 0x3a1236e8U, 0x230907a9U, | | | |
| 0x0824546aU, 0x113f652bU, 0x96a779e4U, 0x8fbc48a5U, 0xa4911b66U, | | | |
| 0xbd8a2a27U, 0xf2cbbce0U, 0xebd08da1U, 0xc0fdde62U, 0xd9e6ef23U, | | | |
| 0x14bce1bdU, 0x0da7d0fcU, 0x268a833fU, 0x3f91b27eU, 0x70d024b9U, | | | |
| 0x69cb15f8U, 0x42e6463bU, 0x5bfd777aU, 0xdc656bb5U, 0xc57e5af4U, | | | |
| 0xee530937U, 0xf7483876U, 0xb809aeb1U, 0xa1129ff0U, 0x8a3fcc33U, | | | |
| 0x9324fd72U }; | | | |
| | | | |
| static const UInt32 table2[256] = { | | | |
| 0x00000000U, 0x01c26a37U, 0x0384d46eU, 0x0246be59U, 0x0709a8dcU, | | | |
| 0x06cbc2ebU, 0x048d7cb2U, 0x054f1685U, 0x0e1351b8U, 0x0fd13b8fU, | | | |
| 0x0d9785d6U, 0x0c55efe1U, 0x091af964U, 0x08d89353U, 0x0a9e2d0aU, | | | |
| 0x0b5c473dU, 0x1c26a370U, 0x1de4c947U, 0x1fa2771eU, 0x1e601d29U, | | | |
| 0x1b2f0bacU, 0x1aed619bU, 0x18abdfc2U, 0x1969b5f5U, 0x1235f2c8U, | | | |
| 0x13f798ffU, 0x11b126a6U, 0x10734c91U, 0x153c5a14U, 0x14fe3023U, | | | |
| 0x16b88e7aU, 0x177ae44dU, 0x384d46e0U, 0x398f2cd7U, 0x3bc9928eU, | | | |
| 0x3a0bf8b9U, 0x3f44ee3cU, 0x3e86840bU, 0x3cc03a52U, 0x3d025065U, | | | |
| 0x365e1758U, 0x379c7d6fU, 0x35dac336U, 0x3418a901U, 0x3157bf84U, | | | |
| 0x3095d5b3U, 0x32d36beaU, 0x331101ddU, 0x246be590U, 0x25a98fa7U, | | | |
| 0x27ef31feU, 0x262d5bc9U, 0x23624d4cU, 0x22a0277bU, 0x20e69922U, | | | |
| 0x2124f315U, 0x2a78b428U, 0x2bbade1fU, 0x29fc6046U, 0x283e0a71U, | | | |
| 0x2d711cf4U, 0x2cb376c3U, 0x2ef5c89aU, 0x2f37a2adU, 0x709a8dc0U, | | | |
| 0x7158e7f7U, 0x731e59aeU, 0x72dc3399U, 0x7793251cU, 0x76514f2bU, | | | |
| 0x7417f172U, 0x75d59b45U, 0x7e89dc78U, 0x7f4bb64fU, 0x7d0d0816U, | | | |
| 0x7ccf6221U, 0x798074a4U, 0x78421e93U, 0x7a04a0caU, 0x7bc6cafdU, | | | |
| 0x6cbc2eb0U, 0x6d7e4487U, 0x6f38fadeU, 0x6efa90e9U, 0x6bb5866cU, | | | |
| 0x6a77ec5bU, 0x68315202U, 0x69f33835U, 0x62af7f08U, 0x636d153fU, | | | |
| 0x612bab66U, 0x60e9c151U, 0x65a6d7d4U, 0x6464bde3U, 0x662203baU, | | | |
| 0x67e0698dU, 0x48d7cb20U, 0x4915a117U, 0x4b531f4eU, 0x4a917579U, | | | |
| 0x4fde63fcU, 0x4e1c09cbU, 0x4c5ab792U, 0x4d98dda5U, 0x46c49a98U, | | | |
| 0x4706f0afU, 0x45404ef6U, 0x448224c1U, 0x41cd3244U, 0x400f5873U, | | | |
| 0x4249e62aU, 0x438b8c1dU, 0x54f16850U, 0x55330267U, 0x5775bc3eU, | | | |
| 0x56b7d609U, 0x53f8c08cU, 0x523aaabbU, 0x507c14e2U, 0x51be7ed5U, | | | |
| 0x5ae239e8U, 0x5b2053dfU, 0x5966ed86U, 0x58a487b1U, 0x5deb9134U, | | | |
| 0x5c29fb03U, 0x5e6f455aU, 0x5fad2f6dU, 0xe1351b80U, 0xe0f771b7U, | | | |
| 0xe2b1cfeeU, 0xe373a5d9U, 0xe63cb35cU, 0xe7fed96bU, 0xe5b86732U, | | | |
| 0xe47a0d05U, 0xef264a38U, 0xeee4200fU, 0xeca29e56U, 0xed60f461U, | | | |
| 0xe82fe2e4U, 0xe9ed88d3U, 0xebab368aU, 0xea695cbdU, 0xfd13b8f0U, | | | |
| 0xfcd1d2c7U, 0xfe976c9eU, 0xff5506a9U, 0xfa1a102cU, 0xfbd87a1bU, | | | |
| 0xf99ec442U, 0xf85cae75U, 0xf300e948U, 0xf2c2837fU, 0xf0843d26U, | | | |
| 0xf1465711U, 0xf4094194U, 0xf5cb2ba3U, 0xf78d95faU, 0xf64fffcdU, | | | |
| 0xd9785d60U, 0xd8ba3757U, 0xdafc890eU, 0xdb3ee339U, 0xde71f5bcU, | | | |
| 0xdfb39f8bU, 0xddf521d2U, 0xdc374be5U, 0xd76b0cd8U, 0xd6a966efU, | | | |
| 0xd4efd8b6U, 0xd52db281U, 0xd062a404U, 0xd1a0ce33U, 0xd3e6706aU, | | | |
| 0xd2241a5dU, 0xc55efe10U, 0xc49c9427U, 0xc6da2a7eU, 0xc7184049U, | | | |
| 0xc25756ccU, 0xc3953cfbU, 0xc1d382a2U, 0xc011e895U, 0xcb4dafa8U, | | | |
| 0xca8fc59fU, 0xc8c97bc6U, 0xc90b11f1U, 0xcc440774U, 0xcd866d43U, | | | |
| 0xcfc0d31aU, 0xce02b92dU, 0x91af9640U, 0x906dfc77U, 0x922b422eU, | | | |
| 0x93e92819U, 0x96a63e9cU, 0x976454abU, 0x9522eaf2U, 0x94e080c5U, | | | |
| 0x9fbcc7f8U, 0x9e7eadcfU, 0x9c381396U, 0x9dfa79a1U, 0x98b56f24U, | | | |
| 0x99770513U, 0x9b31bb4aU, 0x9af3d17dU, 0x8d893530U, 0x8c4b5f07U, | | | |
| 0x8e0de15eU, 0x8fcf8b69U, 0x8a809decU, 0x8b42f7dbU, 0x89044982U, | | | |
| 0x88c623b5U, 0x839a6488U, 0x82580ebfU, 0x801eb0e6U, 0x81dcdad1U, | | | |
| 0x8493cc54U, 0x8551a663U, 0x8717183aU, 0x86d5720dU, 0xa9e2d0a0U, | | | |
| 0xa820ba97U, 0xaa6604ceU, 0xaba46ef9U, 0xaeeb787cU, 0xaf29124bU, | | | |
| 0xad6fac12U, 0xacadc625U, 0xa7f18118U, 0xa633eb2fU, 0xa4755576U, | | | |
| 0xa5b73f41U, 0xa0f829c4U, 0xa13a43f3U, 0xa37cfdaaU, 0xa2be979dU, | | | |
| 0xb5c473d0U, 0xb40619e7U, 0xb640a7beU, 0xb782cd89U, 0xb2cddb0cU, | | | |
| 0xb30fb13bU, 0xb1490f62U, 0xb08b6555U, 0xbbd72268U, 0xba15485fU, | | | |
| 0xb853f606U, 0xb9919c31U, 0xbcde8ab4U, 0xbd1ce083U, 0xbf5a5edaU, | | | |
| 0xbe9834edU }; | | | |
| | | | |
| static const UInt32 table3[256] = { | | | |
| 0x00000000U, 0xb8bc6765U, 0xaa09c88bU, 0x12b5afeeU, 0x8f629757U, | | | |
| 0x37def032U, 0x256b5fdcU, 0x9dd738b9U, 0xc5b428efU, 0x7d084f8aU, | | | |
| 0x6fbde064U, 0xd7018701U, 0x4ad6bfb8U, 0xf26ad8ddU, 0xe0df7733U, | | | |
| 0x58631056U, 0x5019579fU, 0xe8a530faU, 0xfa109f14U, 0x42acf871U, | | | |
| 0xdf7bc0c8U, 0x67c7a7adU, 0x75720843U, 0xcdce6f26U, 0x95ad7f70U, | | | |
| 0x2d111815U, 0x3fa4b7fbU, 0x8718d09eU, 0x1acfe827U, 0xa2738f42U, | | | |
| 0xb0c620acU, 0x087a47c9U, 0xa032af3eU, 0x188ec85bU, 0x0a3b67b5U, | | | |
| 0xb28700d0U, 0x2f503869U, 0x97ec5f0cU, 0x8559f0e2U, 0x3de59787U, | | | |
| 0x658687d1U, 0xdd3ae0b4U, 0xcf8f4f5aU, 0x7733283fU, 0xeae41086U, | | | |
| 0x525877e3U, 0x40edd80dU, 0xf851bf68U, 0xf02bf8a1U, 0x48979fc4U, | | | |
| 0x5a22302aU, 0xe29e574fU, 0x7f496ff6U, 0xc7f50893U, 0xd540a77dU, | | | |
| 0x6dfcc018U, 0x359fd04eU, 0x8d23b72bU, 0x9f9618c5U, 0x272a7fa0U, | | | |
| 0xbafd4719U, 0x0241207cU, 0x10f48f92U, 0xa848e8f7U, 0x9b14583dU, | | | |
| 0x23a83f58U, 0x311d90b6U, 0x89a1f7d3U, 0x1476cf6aU, 0xaccaa80fU, | | | |
| 0xbe7f07e1U, 0x06c36084U, 0x5ea070d2U, 0xe61c17b7U, 0xf4a9b859U, | | | |
| 0x4c15df3cU, 0xd1c2e785U, 0x697e80e0U, 0x7bcb2f0eU, 0xc377486bU, | | | |
| 0xcb0d0fa2U, 0x73b168c7U, 0x6104c729U, 0xd9b8a04cU, 0x446f98f5U, | | | |
| 0xfcd3ff90U, 0xee66507eU, 0x56da371bU, 0x0eb9274dU, 0xb6054028U, | | | |
| 0xa4b0efc6U, 0x1c0c88a3U, 0x81dbb01aU, 0x3967d77fU, 0x2bd27891U, | | | |
| 0x936e1ff4U, 0x3b26f703U, 0x839a9066U, 0x912f3f88U, 0x299358edU, | | | |
| 0xb4446054U, 0x0cf80731U, 0x1e4da8dfU, 0xa6f1cfbaU, 0xfe92dfecU, | | | |
| 0x462eb889U, 0x549b1767U, 0xec277002U, 0x71f048bbU, 0xc94c2fdeU, | | | |
| 0xdbf98030U, 0x6345e755U, 0x6b3fa09cU, 0xd383c7f9U, 0xc1366817U, | | | |
| 0x798a0f72U, 0xe45d37cbU, 0x5ce150aeU, 0x4e54ff40U, 0xf6e89825U, | | | |
| 0xae8b8873U, 0x1637ef16U, 0x048240f8U, 0xbc3e279dU, 0x21e91f24U, | | | |
| 0x99557841U, 0x8be0d7afU, 0x335cb0caU, 0xed59b63bU, 0x55e5d15eU, | | | |
| 0x47507eb0U, 0xffec19d5U, 0x623b216cU, 0xda874609U, 0xc832e9e7U, | | | |
| 0x708e8e82U, 0x28ed9ed4U, 0x9051f9b1U, 0x82e4565fU, 0x3a58313aU, | | | |
| 0xa78f0983U, 0x1f336ee6U, 0x0d86c108U, 0xb53aa66dU, 0xbd40e1a4U, | | | |
| 0x05fc86c1U, 0x1749292fU, 0xaff54e4aU, 0x322276f3U, 0x8a9e1196U, | | | |
| 0x982bbe78U, 0x2097d91dU, 0x78f4c94bU, 0xc048ae2eU, 0xd2fd01c0U, | | | |
| 0x6a4166a5U, 0xf7965e1cU, 0x4f2a3979U, 0x5d9f9697U, 0xe523f1f2U, | | | |
| 0x4d6b1905U, 0xf5d77e60U, 0xe762d18eU, 0x5fdeb6ebU, 0xc2098e52U, | | | |
| 0x7ab5e937U, 0x680046d9U, 0xd0bc21bcU, 0x88df31eaU, 0x3063568fU, | | | |
| 0x22d6f961U, 0x9a6a9e04U, 0x07bda6bdU, 0xbf01c1d8U, 0xadb46e36U, | | | |
| 0x15080953U, 0x1d724e9aU, 0xa5ce29ffU, 0xb77b8611U, 0x0fc7e174U, | | | |
| 0x9210d9cdU, 0x2aacbea8U, 0x38191146U, 0x80a57623U, 0xd8c66675U, | | | |
| 0x607a0110U, 0x72cfaefeU, 0xca73c99bU, 0x57a4f122U, 0xef189647U, | | | |
| 0xfdad39a9U, 0x45115eccU, 0x764dee06U, 0xcef18963U, 0xdc44268dU, | | | |
| 0x64f841e8U, 0xf92f7951U, 0x41931e34U, 0x5326b1daU, 0xeb9ad6bfU, | | | |
| 0xb3f9c6e9U, 0x0b45a18cU, 0x19f00e62U, 0xa14c6907U, 0x3c9b51beU, | | | |
| 0x842736dbU, 0x96929935U, 0x2e2efe50U, 0x2654b999U, 0x9ee8defcU, | | | |
| 0x8c5d7112U, 0x34e11677U, 0xa9362eceU, 0x118a49abU, 0x033fe645U, | | | |
| 0xbb838120U, 0xe3e09176U, 0x5b5cf613U, 0x49e959fdU, 0xf1553e98U, | | | |
| 0x6c820621U, 0xd43e6144U, 0xc68bceaaU, 0x7e37a9cfU, 0xd67f4138U, | | | |
| 0x6ec3265dU, 0x7c7689b3U, 0xc4caeed6U, 0x591dd66fU, 0xe1a1b10aU, | | | |
| 0xf3141ee4U, 0x4ba87981U, 0x13cb69d7U, 0xab770eb2U, 0xb9c2a15cU, | | | |
| 0x017ec639U, 0x9ca9fe80U, 0x241599e5U, 0x36a0360bU, 0x8e1c516eU, | | | |
| 0x866616a7U, 0x3eda71c2U, 0x2c6fde2cU, 0x94d3b949U, 0x090481f0U, | | | |
| 0xb1b8e695U, 0xa30d497bU, 0x1bb12e1eU, 0x43d23e48U, 0xfb6e592dU, | | | |
| 0xe9dbf6c3U, 0x516791a6U, 0xccb0a91fU, 0x740cce7aU, 0x66b96194U, | | | |
| 0xde0506f1U }; | | | |
| | | | |
|
| | | template <class InIterator> | |
| | | static UInt32 exec(InIterator i, unsigned int size, UInt32 crc = 0xFFFF | |
| | | FFFF); | |
| | | }; | |
| | | | |
| | | template <class INT> | |
| | | UInt32 ChecksumImpl<INT>::table0[256] = { | |
| | | 0x0U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x76dc419U, 0x706af48fU, | |
| | | 0xe963a535U, 0x9e6495a3U, 0xedb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d | |
| | | 988U, | |
| | | 0x9b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, 0x6ab02 | |
| | | 0f2U, | |
| | | 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d3 | |
| | | 85c7U, | |
| | | 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x6306 | |
| | | 6cd9U, | |
| | | 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa267 | |
| | | 7172U, | |
| | | 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, 0x42b2 | |
| | | 986cU, | |
| | | 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd1 | |
| | | 3d59U, | |
| | | 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3 | |
| | | c423U, | |
| | | 0xcfba9599U, 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10b | |
| | | e924U, | |
| | | 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, 0x1db7 | |
| | | 106U, | |
| | | 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x6b6b51fU, 0x9fbfe4a5U, 0xe8b8d | |
| | | 433U, | |
| | | 0x7807c9a2U, 0xf00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x86d3d | |
| | | 2dU, | |
| | | 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262 | |
| | | 004eU, | |
| | | 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7 | |
| | | e950U, | |
| | | 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd4 | |
| | | 4c65U, | |
| | | 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd8 | |
| | | 95d7U, | |
| | | 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60 | |
| | | b8d0U, | |
| | | 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x2702 | |
| | | 41aaU, | |
| | | 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61 | |
| | | e49fU, | |
| | | 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb4 | |
| | | 0d81U, | |
| | | 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x3b6e20cU, 0x74b1d | |
| | | 29aU, | |
| | | 0xead54739U, 0x9dd277afU, 0x4db2615U, 0x73dc1683U, 0xe3630b12U, 0x94643 | |
| | | b84U, | |
| | | 0xd6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0xa00ae27U, 0x7d079e | |
| | | b1U, | |
| | | 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x8065 | |
| | | 67cbU, | |
| | | 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd | |
| | | 4accU, | |
| | | 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 0xd6d6a3e8U, 0xa1d1 | |
| | | 937eU, | |
| | | 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2 | |
| | | 364bU, | |
| | | 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867 | |
| | | df55U, | |
| | | 0x316e8eefU, 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268 | |
| | | e236U, | |
| | | 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, 0xb2bd | |
| | | 0b28U, | |
| | | 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bde | |
| | | ae1dU, | |
| | | 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x26d930aU, 0x9c0906a9U, 0xeb0e3 | |
| | | 63fU, | |
| | | 0x72076785U, 0x5005713U, 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0xcb61b | |
| | | 38U, | |
| | | 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0xbdbdf21U, 0x86d3d2d4U, 0xf1d4e | |
| | | 242U, | |
| | | 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b7 | |
| | | 4777U, | |
| | | 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862 | |
| | | ae69U, | |
| | | 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903 | |
| | | b3c2U, | |
| | | 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d6 | |
| | | 5adcU, | |
| | | 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5 | |
| | | ffe9U, | |
| | | 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd7 | |
| | | 0693U, | |
| | | 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f | |
| | | 2b94U, | |
| | | 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU }; | |
| | | | |
| | | template <class INT> | |
| | | UInt32 ChecksumImpl<INT>::table1[256] = { | |
| | | 0x00000000U, 0x191b3141U, 0x32366282U, 0x2b2d53c3U, 0x646cc504U, | |
| | | 0x7d77f445U, 0x565aa786U, 0x4f4196c7U, 0xc8d98a08U, 0xd1c2bb49U, | |
| | | 0xfaefe88aU, 0xe3f4d9cbU, 0xacb54f0cU, 0xb5ae7e4dU, 0x9e832d8eU, | |
| | | 0x87981ccfU, 0x4ac21251U, 0x53d92310U, 0x78f470d3U, 0x61ef4192U, | |
| | | 0x2eaed755U, 0x37b5e614U, 0x1c98b5d7U, 0x05838496U, 0x821b9859U, | |
| | | 0x9b00a918U, 0xb02dfadbU, 0xa936cb9aU, 0xe6775d5dU, 0xff6c6c1cU, | |
| | | 0xd4413fdfU, 0xcd5a0e9eU, 0x958424a2U, 0x8c9f15e3U, 0xa7b24620U, | |
| | | 0xbea97761U, 0xf1e8e1a6U, 0xe8f3d0e7U, 0xc3de8324U, 0xdac5b265U, | |
| | | 0x5d5daeaaU, 0x44469febU, 0x6f6bcc28U, 0x7670fd69U, 0x39316baeU, | |
| | | 0x202a5aefU, 0x0b07092cU, 0x121c386dU, 0xdf4636f3U, 0xc65d07b2U, | |
| | | 0xed705471U, 0xf46b6530U, 0xbb2af3f7U, 0xa231c2b6U, 0x891c9175U, | |
| | | 0x9007a034U, 0x179fbcfbU, 0x0e848dbaU, 0x25a9de79U, 0x3cb2ef38U, | |
| | | 0x73f379ffU, 0x6ae848beU, 0x41c51b7dU, 0x58de2a3cU, 0xf0794f05U, | |
| | | 0xe9627e44U, 0xc24f2d87U, 0xdb541cc6U, 0x94158a01U, 0x8d0ebb40U, | |
| | | 0xa623e883U, 0xbf38d9c2U, 0x38a0c50dU, 0x21bbf44cU, 0x0a96a78fU, | |
| | | 0x138d96ceU, 0x5ccc0009U, 0x45d73148U, 0x6efa628bU, 0x77e153caU, | |
| | | 0xbabb5d54U, 0xa3a06c15U, 0x888d3fd6U, 0x91960e97U, 0xded79850U, | |
| | | 0xc7cca911U, 0xece1fad2U, 0xf5facb93U, 0x7262d75cU, 0x6b79e61dU, | |
| | | 0x4054b5deU, 0x594f849fU, 0x160e1258U, 0x0f152319U, 0x243870daU, | |
| | | 0x3d23419bU, 0x65fd6ba7U, 0x7ce65ae6U, 0x57cb0925U, 0x4ed03864U, | |
| | | 0x0191aea3U, 0x188a9fe2U, 0x33a7cc21U, 0x2abcfd60U, 0xad24e1afU, | |
| | | 0xb43fd0eeU, 0x9f12832dU, 0x8609b26cU, 0xc94824abU, 0xd05315eaU, | |
| | | 0xfb7e4629U, 0xe2657768U, 0x2f3f79f6U, 0x362448b7U, 0x1d091b74U, | |
| | | 0x04122a35U, 0x4b53bcf2U, 0x52488db3U, 0x7965de70U, 0x607eef31U, | |
| | | 0xe7e6f3feU, 0xfefdc2bfU, 0xd5d0917cU, 0xcccba03dU, 0x838a36faU, | |
| | | 0x9a9107bbU, 0xb1bc5478U, 0xa8a76539U, 0x3b83984bU, 0x2298a90aU, | |
| | | 0x09b5fac9U, 0x10aecb88U, 0x5fef5d4fU, 0x46f46c0eU, 0x6dd93fcdU, | |
| | | 0x74c20e8cU, 0xf35a1243U, 0xea412302U, 0xc16c70c1U, 0xd8774180U, | |
| | | 0x9736d747U, 0x8e2de606U, 0xa500b5c5U, 0xbc1b8484U, 0x71418a1aU, | |
| | | 0x685abb5bU, 0x4377e898U, 0x5a6cd9d9U, 0x152d4f1eU, 0x0c367e5fU, | |
| | | 0x271b2d9cU, 0x3e001cddU, 0xb9980012U, 0xa0833153U, 0x8bae6290U, | |
| | | 0x92b553d1U, 0xddf4c516U, 0xc4eff457U, 0xefc2a794U, 0xf6d996d5U, | |
| | | 0xae07bce9U, 0xb71c8da8U, 0x9c31de6bU, 0x852aef2aU, 0xca6b79edU, | |
| | | 0xd37048acU, 0xf85d1b6fU, 0xe1462a2eU, 0x66de36e1U, 0x7fc507a0U, | |
| | | 0x54e85463U, 0x4df36522U, 0x02b2f3e5U, 0x1ba9c2a4U, 0x30849167U, | |
| | | 0x299fa026U, 0xe4c5aeb8U, 0xfdde9ff9U, 0xd6f3cc3aU, 0xcfe8fd7bU, | |
| | | 0x80a96bbcU, 0x99b25afdU, 0xb29f093eU, 0xab84387fU, 0x2c1c24b0U, | |
| | | 0x350715f1U, 0x1e2a4632U, 0x07317773U, 0x4870e1b4U, 0x516bd0f5U, | |
| | | 0x7a468336U, 0x635db277U, 0xcbfad74eU, 0xd2e1e60fU, 0xf9ccb5ccU, | |
| | | 0xe0d7848dU, 0xaf96124aU, 0xb68d230bU, 0x9da070c8U, 0x84bb4189U, | |
| | | 0x03235d46U, 0x1a386c07U, 0x31153fc4U, 0x280e0e85U, 0x674f9842U, | |
| | | 0x7e54a903U, 0x5579fac0U, 0x4c62cb81U, 0x8138c51fU, 0x9823f45eU, | |
| | | 0xb30ea79dU, 0xaa1596dcU, 0xe554001bU, 0xfc4f315aU, 0xd7626299U, | |
| | | 0xce7953d8U, 0x49e14f17U, 0x50fa7e56U, 0x7bd72d95U, 0x62cc1cd4U, | |
| | | 0x2d8d8a13U, 0x3496bb52U, 0x1fbbe891U, 0x06a0d9d0U, 0x5e7ef3ecU, | |
| | | 0x4765c2adU, 0x6c48916eU, 0x7553a02fU, 0x3a1236e8U, 0x230907a9U, | |
| | | 0x0824546aU, 0x113f652bU, 0x96a779e4U, 0x8fbc48a5U, 0xa4911b66U, | |
| | | 0xbd8a2a27U, 0xf2cbbce0U, 0xebd08da1U, 0xc0fdde62U, 0xd9e6ef23U, | |
| | | 0x14bce1bdU, 0x0da7d0fcU, 0x268a833fU, 0x3f91b27eU, 0x70d024b9U, | |
| | | 0x69cb15f8U, 0x42e6463bU, 0x5bfd777aU, 0xdc656bb5U, 0xc57e5af4U, | |
| | | 0xee530937U, 0xf7483876U, 0xb809aeb1U, 0xa1129ff0U, 0x8a3fcc33U, | |
| | | 0x9324fd72U }; | |
| | | | |
| | | template <class INT> | |
| | | UInt32 ChecksumImpl<INT>::table2[256] = { | |
| | | 0x00000000U, 0x01c26a37U, 0x0384d46eU, 0x0246be59U, 0x0709a8dcU, | |
| | | 0x06cbc2ebU, 0x048d7cb2U, 0x054f1685U, 0x0e1351b8U, 0x0fd13b8fU, | |
| | | 0x0d9785d6U, 0x0c55efe1U, 0x091af964U, 0x08d89353U, 0x0a9e2d0aU, | |
| | | 0x0b5c473dU, 0x1c26a370U, 0x1de4c947U, 0x1fa2771eU, 0x1e601d29U, | |
| | | 0x1b2f0bacU, 0x1aed619bU, 0x18abdfc2U, 0x1969b5f5U, 0x1235f2c8U, | |
| | | 0x13f798ffU, 0x11b126a6U, 0x10734c91U, 0x153c5a14U, 0x14fe3023U, | |
| | | 0x16b88e7aU, 0x177ae44dU, 0x384d46e0U, 0x398f2cd7U, 0x3bc9928eU, | |
| | | 0x3a0bf8b9U, 0x3f44ee3cU, 0x3e86840bU, 0x3cc03a52U, 0x3d025065U, | |
| | | 0x365e1758U, 0x379c7d6fU, 0x35dac336U, 0x3418a901U, 0x3157bf84U, | |
| | | 0x3095d5b3U, 0x32d36beaU, 0x331101ddU, 0x246be590U, 0x25a98fa7U, | |
| | | 0x27ef31feU, 0x262d5bc9U, 0x23624d4cU, 0x22a0277bU, 0x20e69922U, | |
| | | 0x2124f315U, 0x2a78b428U, 0x2bbade1fU, 0x29fc6046U, 0x283e0a71U, | |
| | | 0x2d711cf4U, 0x2cb376c3U, 0x2ef5c89aU, 0x2f37a2adU, 0x709a8dc0U, | |
| | | 0x7158e7f7U, 0x731e59aeU, 0x72dc3399U, 0x7793251cU, 0x76514f2bU, | |
| | | 0x7417f172U, 0x75d59b45U, 0x7e89dc78U, 0x7f4bb64fU, 0x7d0d0816U, | |
| | | 0x7ccf6221U, 0x798074a4U, 0x78421e93U, 0x7a04a0caU, 0x7bc6cafdU, | |
| | | 0x6cbc2eb0U, 0x6d7e4487U, 0x6f38fadeU, 0x6efa90e9U, 0x6bb5866cU, | |
| | | 0x6a77ec5bU, 0x68315202U, 0x69f33835U, 0x62af7f08U, 0x636d153fU, | |
| | | 0x612bab66U, 0x60e9c151U, 0x65a6d7d4U, 0x6464bde3U, 0x662203baU, | |
| | | 0x67e0698dU, 0x48d7cb20U, 0x4915a117U, 0x4b531f4eU, 0x4a917579U, | |
| | | 0x4fde63fcU, 0x4e1c09cbU, 0x4c5ab792U, 0x4d98dda5U, 0x46c49a98U, | |
| | | 0x4706f0afU, 0x45404ef6U, 0x448224c1U, 0x41cd3244U, 0x400f5873U, | |
| | | 0x4249e62aU, 0x438b8c1dU, 0x54f16850U, 0x55330267U, 0x5775bc3eU, | |
| | | 0x56b7d609U, 0x53f8c08cU, 0x523aaabbU, 0x507c14e2U, 0x51be7ed5U, | |
| | | 0x5ae239e8U, 0x5b2053dfU, 0x5966ed86U, 0x58a487b1U, 0x5deb9134U, | |
| | | 0x5c29fb03U, 0x5e6f455aU, 0x5fad2f6dU, 0xe1351b80U, 0xe0f771b7U, | |
| | | 0xe2b1cfeeU, 0xe373a5d9U, 0xe63cb35cU, 0xe7fed96bU, 0xe5b86732U, | |
| | | 0xe47a0d05U, 0xef264a38U, 0xeee4200fU, 0xeca29e56U, 0xed60f461U, | |
| | | 0xe82fe2e4U, 0xe9ed88d3U, 0xebab368aU, 0xea695cbdU, 0xfd13b8f0U, | |
| | | 0xfcd1d2c7U, 0xfe976c9eU, 0xff5506a9U, 0xfa1a102cU, 0xfbd87a1bU, | |
| | | 0xf99ec442U, 0xf85cae75U, 0xf300e948U, 0xf2c2837fU, 0xf0843d26U, | |
| | | 0xf1465711U, 0xf4094194U, 0xf5cb2ba3U, 0xf78d95faU, 0xf64fffcdU, | |
| | | 0xd9785d60U, 0xd8ba3757U, 0xdafc890eU, 0xdb3ee339U, 0xde71f5bcU, | |
| | | 0xdfb39f8bU, 0xddf521d2U, 0xdc374be5U, 0xd76b0cd8U, 0xd6a966efU, | |
| | | 0xd4efd8b6U, 0xd52db281U, 0xd062a404U, 0xd1a0ce33U, 0xd3e6706aU, | |
| | | 0xd2241a5dU, 0xc55efe10U, 0xc49c9427U, 0xc6da2a7eU, 0xc7184049U, | |
| | | 0xc25756ccU, 0xc3953cfbU, 0xc1d382a2U, 0xc011e895U, 0xcb4dafa8U, | |
| | | 0xca8fc59fU, 0xc8c97bc6U, 0xc90b11f1U, 0xcc440774U, 0xcd866d43U, | |
| | | 0xcfc0d31aU, 0xce02b92dU, 0x91af9640U, 0x906dfc77U, 0x922b422eU, | |
| | | 0x93e92819U, 0x96a63e9cU, 0x976454abU, 0x9522eaf2U, 0x94e080c5U, | |
| | | 0x9fbcc7f8U, 0x9e7eadcfU, 0x9c381396U, 0x9dfa79a1U, 0x98b56f24U, | |
| | | 0x99770513U, 0x9b31bb4aU, 0x9af3d17dU, 0x8d893530U, 0x8c4b5f07U, | |
| | | 0x8e0de15eU, 0x8fcf8b69U, 0x8a809decU, 0x8b42f7dbU, 0x89044982U, | |
| | | 0x88c623b5U, 0x839a6488U, 0x82580ebfU, 0x801eb0e6U, 0x81dcdad1U, | |
| | | 0x8493cc54U, 0x8551a663U, 0x8717183aU, 0x86d5720dU, 0xa9e2d0a0U, | |
| | | 0xa820ba97U, 0xaa6604ceU, 0xaba46ef9U, 0xaeeb787cU, 0xaf29124bU, | |
| | | 0xad6fac12U, 0xacadc625U, 0xa7f18118U, 0xa633eb2fU, 0xa4755576U, | |
| | | 0xa5b73f41U, 0xa0f829c4U, 0xa13a43f3U, 0xa37cfdaaU, 0xa2be979dU, | |
| | | 0xb5c473d0U, 0xb40619e7U, 0xb640a7beU, 0xb782cd89U, 0xb2cddb0cU, | |
| | | 0xb30fb13bU, 0xb1490f62U, 0xb08b6555U, 0xbbd72268U, 0xba15485fU, | |
| | | 0xb853f606U, 0xb9919c31U, 0xbcde8ab4U, 0xbd1ce083U, 0xbf5a5edaU, | |
| | | 0xbe9834edU }; | |
| | | | |
| | | template <class INT> | |
| | | UInt32 ChecksumImpl<INT>::table3[256] = { | |
| | | 0x00000000U, 0xb8bc6765U, 0xaa09c88bU, 0x12b5afeeU, 0x8f629757U, | |
| | | 0x37def032U, 0x256b5fdcU, 0x9dd738b9U, 0xc5b428efU, 0x7d084f8aU, | |
| | | 0x6fbde064U, 0xd7018701U, 0x4ad6bfb8U, 0xf26ad8ddU, 0xe0df7733U, | |
| | | 0x58631056U, 0x5019579fU, 0xe8a530faU, 0xfa109f14U, 0x42acf871U, | |
| | | 0xdf7bc0c8U, 0x67c7a7adU, 0x75720843U, 0xcdce6f26U, 0x95ad7f70U, | |
| | | 0x2d111815U, 0x3fa4b7fbU, 0x8718d09eU, 0x1acfe827U, 0xa2738f42U, | |
| | | 0xb0c620acU, 0x087a47c9U, 0xa032af3eU, 0x188ec85bU, 0x0a3b67b5U, | |
| | | 0xb28700d0U, 0x2f503869U, 0x97ec5f0cU, 0x8559f0e2U, 0x3de59787U, | |
| | | 0x658687d1U, 0xdd3ae0b4U, 0xcf8f4f5aU, 0x7733283fU, 0xeae41086U, | |
| | | 0x525877e3U, 0x40edd80dU, 0xf851bf68U, 0xf02bf8a1U, 0x48979fc4U, | |
| | | 0x5a22302aU, 0xe29e574fU, 0x7f496ff6U, 0xc7f50893U, 0xd540a77dU, | |
| | | 0x6dfcc018U, 0x359fd04eU, 0x8d23b72bU, 0x9f9618c5U, 0x272a7fa0U, | |
| | | 0xbafd4719U, 0x0241207cU, 0x10f48f92U, 0xa848e8f7U, 0x9b14583dU, | |
| | | 0x23a83f58U, 0x311d90b6U, 0x89a1f7d3U, 0x1476cf6aU, 0xaccaa80fU, | |
| | | 0xbe7f07e1U, 0x06c36084U, 0x5ea070d2U, 0xe61c17b7U, 0xf4a9b859U, | |
| | | 0x4c15df3cU, 0xd1c2e785U, 0x697e80e0U, 0x7bcb2f0eU, 0xc377486bU, | |
| | | 0xcb0d0fa2U, 0x73b168c7U, 0x6104c729U, 0xd9b8a04cU, 0x446f98f5U, | |
| | | 0xfcd3ff90U, 0xee66507eU, 0x56da371bU, 0x0eb9274dU, 0xb6054028U, | |
| | | 0xa4b0efc6U, 0x1c0c88a3U, 0x81dbb01aU, 0x3967d77fU, 0x2bd27891U, | |
| | | 0x936e1ff4U, 0x3b26f703U, 0x839a9066U, 0x912f3f88U, 0x299358edU, | |
| | | 0xb4446054U, 0x0cf80731U, 0x1e4da8dfU, 0xa6f1cfbaU, 0xfe92dfecU, | |
| | | 0x462eb889U, 0x549b1767U, 0xec277002U, 0x71f048bbU, 0xc94c2fdeU, | |
| | | 0xdbf98030U, 0x6345e755U, 0x6b3fa09cU, 0xd383c7f9U, 0xc1366817U, | |
| | | 0x798a0f72U, 0xe45d37cbU, 0x5ce150aeU, 0x4e54ff40U, 0xf6e89825U, | |
| | | 0xae8b8873U, 0x1637ef16U, 0x048240f8U, 0xbc3e279dU, 0x21e91f24U, | |
| | | 0x99557841U, 0x8be0d7afU, 0x335cb0caU, 0xed59b63bU, 0x55e5d15eU, | |
| | | 0x47507eb0U, 0xffec19d5U, 0x623b216cU, 0xda874609U, 0xc832e9e7U, | |
| | | 0x708e8e82U, 0x28ed9ed4U, 0x9051f9b1U, 0x82e4565fU, 0x3a58313aU, | |
| | | 0xa78f0983U, 0x1f336ee6U, 0x0d86c108U, 0xb53aa66dU, 0xbd40e1a4U, | |
| | | 0x05fc86c1U, 0x1749292fU, 0xaff54e4aU, 0x322276f3U, 0x8a9e1196U, | |
| | | 0x982bbe78U, 0x2097d91dU, 0x78f4c94bU, 0xc048ae2eU, 0xd2fd01c0U, | |
| | | 0x6a4166a5U, 0xf7965e1cU, 0x4f2a3979U, 0x5d9f9697U, 0xe523f1f2U, | |
| | | 0x4d6b1905U, 0xf5d77e60U, 0xe762d18eU, 0x5fdeb6ebU, 0xc2098e52U, | |
| | | 0x7ab5e937U, 0x680046d9U, 0xd0bc21bcU, 0x88df31eaU, 0x3063568fU, | |
| | | 0x22d6f961U, 0x9a6a9e04U, 0x07bda6bdU, 0xbf01c1d8U, 0xadb46e36U, | |
| | | 0x15080953U, 0x1d724e9aU, 0xa5ce29ffU, 0xb77b8611U, 0x0fc7e174U, | |
| | | 0x9210d9cdU, 0x2aacbea8U, 0x38191146U, 0x80a57623U, 0xd8c66675U, | |
| | | 0x607a0110U, 0x72cfaefeU, 0xca73c99bU, 0x57a4f122U, 0xef189647U, | |
| | | 0xfdad39a9U, 0x45115eccU, 0x764dee06U, 0xcef18963U, 0xdc44268dU, | |
| | | 0x64f841e8U, 0xf92f7951U, 0x41931e34U, 0x5326b1daU, 0xeb9ad6bfU, | |
| | | 0xb3f9c6e9U, 0x0b45a18cU, 0x19f00e62U, 0xa14c6907U, 0x3c9b51beU, | |
| | | 0x842736dbU, 0x96929935U, 0x2e2efe50U, 0x2654b999U, 0x9ee8defcU, | |
| | | 0x8c5d7112U, 0x34e11677U, 0xa9362eceU, 0x118a49abU, 0x033fe645U, | |
| | | 0xbb838120U, 0xe3e09176U, 0x5b5cf613U, 0x49e959fdU, 0xf1553e98U, | |
| | | 0x6c820621U, 0xd43e6144U, 0xc68bceaaU, 0x7e37a9cfU, 0xd67f4138U, | |
| | | 0x6ec3265dU, 0x7c7689b3U, 0xc4caeed6U, 0x591dd66fU, 0xe1a1b10aU, | |
| | | 0xf3141ee4U, 0x4ba87981U, 0x13cb69d7U, 0xab770eb2U, 0xb9c2a15cU, | |
| | | 0x017ec639U, 0x9ca9fe80U, 0x241599e5U, 0x36a0360bU, 0x8e1c516eU, | |
| | | 0x866616a7U, 0x3eda71c2U, 0x2c6fde2cU, 0x94d3b949U, 0x090481f0U, | |
| | | 0xb1b8e695U, 0xa30d497bU, 0x1bb12e1eU, 0x43d23e48U, 0xfb6e592dU, | |
| | | 0xe9dbf6c3U, 0x516791a6U, 0xccb0a91fU, 0x740cce7aU, 0x66b96194U, | |
| | | 0xde0506f1U }; | |
| | | | |
| | | template <class INT> | |
| | | template <class InIterator> | |
| | | UInt32 ChecksumImpl<INT>::exec(InIterator i, unsigned int size, UInt32 crc) | |
| | | { | |
| InIterator end = i + size; | | InIterator end = i + size; | |
| | | | |
| if(isLittleEndian() && size > 3) | | if(isLittleEndian() && size > 3) | |
| { | | { | |
| // take care of alignment | | // take care of alignment | |
| for(; (std::size_t)i % 4 != 0; ++i) | | for(; (std::size_t)i % 4 != 0; ++i) | |
| { | | { | |
|
| crc = (crc >> 8) ^ table[(crc ^ *i) & 0xFF]; | | crc = (crc >> 8) ^ table0[(crc ^ *i) & 0xFF]; | |
| } | | } | |
| for(; i < end-3; i+=4) | | for(; i < end-3; i+=4) | |
| { | | { | |
| crc ^= *((UInt32 *)i); | | crc ^= *((UInt32 *)i); | |
| crc = table3[crc & 0xFF] ^ | | crc = table3[crc & 0xFF] ^ | |
| table2[(crc >> 8) & 0xFF] ^ | | table2[(crc >> 8) & 0xFF] ^ | |
| table1[(crc >> 16) & 0xFF] ^ | | table1[(crc >> 16) & 0xFF] ^ | |
|
| table[crc >> 24]; | | table0[crc >> 24]; | |
| } | | } | |
| } | | } | |
| for(; i < end; ++i) | | for(; i < end; ++i) | |
| { | | { | |
|
| crc = (crc >> 8) ^ table[(crc ^ *i) & 0xFF]; | | crc = (crc >> 8) ^ table0[(crc ^ *i) & 0xFF]; | |
| } | | } | |
| return ~crc; | | return ~crc; | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! Compute the CRC-32 checksum of a byte array. | | /** \brief Compute the CRC-32 checksum of a byte array. | |
| | | | |
| Implementation note: This function is slower on big-endian machines | | Implementation note: This function is slower on big-endian machines | |
| because the "4 bytes at a time" optimization is only implemented fo
r | | because the "4 bytes at a time" optimization is only implemented fo
r | |
| little-endian. | | little-endian. | |
| */ | | */ | |
| inline UInt32 checksum(const char * data, unsigned int size) | | inline UInt32 checksum(const char * data, unsigned int size) | |
| { | | { | |
|
| return detail::checksumImpl(data, size); | | return detail::ChecksumImpl<UInt32>::exec(data, size); | |
| } | | } | |
| | | | |
|
| /*! Concatenate a byte array to an existing CRC-32 checksum. | | /** Concatenate a byte array to an existing CRC-32 checksum. | |
| */ | | */ | |
| inline UInt32 concatenateChecksum(UInt32 checksum, const char * data, unsig
ned int size) | | inline UInt32 concatenateChecksum(UInt32 checksum, const char * data, unsig
ned int size) | |
| { | | { | |
| | | | |
|
| return detail::checksumImpl(data, size, ~checksum); | | return detail::ChecksumImpl<UInt32>::exec(data, size, ~checksum); | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| void updateMin(T & x, const T & y) | | void updateMin(T & x, const T & y) | |
| { | | { | |
| using std::min; | | using std::min; | |
| x = min(x, y); | | x = min(x, y); | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| | | | |
End of changes. 25 change blocks. |
| 274 lines changed or deleted | | 365 lines changed or added | |
|
| convolution.hxx | | convolution.hxx | |
| | | | |
| skipping to change at line 45 | | skipping to change at line 45 | |
| | | | |
| #ifndef VIGRA_CONVOLUTION_HXX | | #ifndef VIGRA_CONVOLUTION_HXX | |
| #define VIGRA_CONVOLUTION_HXX | | #define VIGRA_CONVOLUTION_HXX | |
| | | | |
| #include <functional> | | #include <functional> | |
| #include "stdconvolution.hxx" | | #include "stdconvolution.hxx" | |
| #include "separableconvolution.hxx" | | #include "separableconvolution.hxx" | |
| #include "recursiveconvolution.hxx" | | #include "recursiveconvolution.hxx" | |
| #include "nonlineardiffusion.hxx" | | #include "nonlineardiffusion.hxx" | |
| #include "combineimages.hxx" | | #include "combineimages.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| /** \page Convolution Functions to Convolve Images and Signals | | /** \page Convolution Functions to Convolve Images and Signals | |
| | | | |
| 1D and 2D filters, including separable and recursive convolution, and n
on-linear diffusion | | 1D and 2D filters, including separable and recursive convolution, and n
on-linear diffusion | |
| | | | |
| <b>\#include</b> \<vigra/convolution.hxx\><br> | | <b>\#include</b> \<vigra/convolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| <UL style="list-style-image:url(documents/bullet.gif)"> | | <UL style="list-style-image:url(documents/bullet.gif)"> | |
| <LI> \ref CommonConvolutionFilters | | <LI> \ref CommonConvolutionFilters | |
|
| <BR> <em>Short-hands for the most common 2D convo
lution filters</em> | | <BR> <em>Short-hands for many common 2D convoluti
on filters (including normalized convolution)</em> | |
| <LI> \ref MultiArrayConvolutionFilters | | <LI> \ref MultiArrayConvolutionFilters | |
| <BR> <em>Convolution filters for arbitrary dimens
ional arrays (MultiArray etc.)</em> | | <BR> <em>Convolution filters for arbitrary dimens
ional arrays (MultiArray etc.)</em> | |
| <LI> \ref ResamplingConvolutionFilters | | <LI> \ref ResamplingConvolutionFilters | |
| <BR> <em>Resampling convolution filters</em> | | <BR> <em>Resampling convolution filters</em> | |
|
| <LI> \ref StandardConvolution | | | |
| <BR> <em>2D non-separable convolution, with and w | | | |
| ithout ROI mask </em> | | | |
| <LI> \ref vigra::Kernel2D | | <LI> \ref vigra::Kernel2D | |
| <BR> <em>Generic 2-dimensional discrete convoluti
on kernel </em> | | <BR> <em>Generic 2-dimensional discrete convoluti
on kernel </em> | |
| <LI> \ref SeparableConvolution | | <LI> \ref SeparableConvolution | |
| <BR> <em>1D convolution and separable filters in
2 dimensions </em> | | <BR> <em>1D convolution and separable filters in
2 dimensions </em> | |
| <LI> \ref vigra::Kernel1D | | <LI> \ref vigra::Kernel1D | |
| <BR> <em>Generic 1-dimensional discrete convoluti
on kernel </em> | | <BR> <em>Generic 1-dimensional discrete convoluti
on kernel </em> | |
| <LI> \ref RecursiveConvolution | | <LI> \ref RecursiveConvolution | |
| <BR> <em>Recursive filters (1st and 2nd order)</e
m> | | <BR> <em>Recursive filters (1st and 2nd order)</e
m> | |
| <LI> \ref NonLinearDiffusion | | <LI> \ref NonLinearDiffusion | |
| <BR> <em>Edge-preserving smoothing </em> | | <BR> <em>Edge-preserving smoothing </em> | |
| | | | |
| skipping to change at line 127 | | skipping to change at line 126 | |
| <TT>kernel1d(kerneliterator, kernelaccessor,</TT><br> | | <TT>kernel1d(kerneliterator, kernelaccessor,</TT><br> | |
| <TT> kernelleft, kernelright,</TT><br> | | <TT> kernelleft, kernelright,</TT><br> | |
| <TT> vigra::BORDER_TREATMENT_CLIP)</TT> | | <TT> vigra::BORDER_TREATMENT_CLIP)</TT> | |
| </td><td> | | </td><td> | |
| create argument object from explicitly given iterator | | create argument object from explicitly given iterator | |
| (pointing to the center of th kernel), accessor, | | (pointing to the center of th kernel), accessor, | |
| left and right boundaries, and border treatment mode | | left and right boundaries, and border treatment mode | |
| | | | |
| </table> | | </table> | |
| | | | |
|
| For usage examples see | | For usage examples see \ref convolveImage(). | |
| \ref SeparableConvolution "one-dimensional and separable convolutio | | | |
| n functions". | | | |
| | | | |
| \section Kernel2dFactory kernel2d() | | \section Kernel2dFactory kernel2d() | |
| | | | |
| Pass a \ref vigra::Kernel2D to a 2D (non-separable) convolution alg
orithm. | | Pass a \ref vigra::Kernel2D to a 2D (non-separable) convolution alg
orithm. | |
| | | | |
| These factories can be used to create argument objects when we | | These factories can be used to create argument objects when we | |
| are given instances or subclasses of \ref vigra::Kernel2D | | are given instances or subclasses of \ref vigra::Kernel2D | |
| (analogous to the \ref ArgumentObjectFactories for images). | | (analogous to the \ref ArgumentObjectFactories for images). | |
| These factory functions access <TT>kernel.center()</TT>, | | These factory functions access <TT>kernel.center()</TT>, | |
| <TT>kernel.upperLeft()</TT>, <TT>kernel.lowerRight()</TT>, <TT>kern
el.accessor()</TT>, | | <TT>kernel.upperLeft()</TT>, <TT>kernel.lowerRight()</TT>, <TT>kern
el.accessor()</TT>, | |
| | | | |
| skipping to change at line 172 | | skipping to change at line 170 | |
| <TT>kernel2d(kerneliterator, kernelaccessor,</TT> | | <TT>kernel2d(kerneliterator, kernelaccessor,</TT> | |
| <TT> upperleft, lowerright,</TT> | | <TT> upperleft, lowerright,</TT> | |
| <TT> vigra::BORDER_TREATMENT_CLIP)</TT> | | <TT> vigra::BORDER_TREATMENT_CLIP)</TT> | |
| </td><td> | | </td><td> | |
| create argument object from explicitly given iterator | | create argument object from explicitly given iterator | |
| (pointing to the center of th kernel), accessor, | | (pointing to the center of th kernel), accessor, | |
| upper left and lower right corners, and border treatment mode | | upper left and lower right corners, and border treatment mode | |
| | | | |
| </table> | | </table> | |
| | | | |
|
| For usage examples see \ref StandardConvolution "two-dimensional co
nvolution functions". | | For usage examples see \ref convolveImage(). | |
| */ | | */ | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* Common convolution filters */ | | /* Common convolution filters */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \addtogroup CommonConvolutionFilters Common Filters | | /** \addtogroup CommonConvolutionFilters Common Filters | |
| | | | |
| These functions calculate common filters by appropriate sequences of ca
lls | | These functions calculate common filters by appropriate sequences of ca
lls | |
|
| to \ref separableConvolveX() and \ref separableConvolveY(). | | to \ref separableConvolveX() and \ref separableConvolveY() or explicit | |
| | | 2-dimensional | |
| | | convolution. | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
|
| /********************************************************/ | | /** \brief Convolve an image with the given kernel(s). | |
| /* */ | | | |
| /* convolveImage */ | | | |
| /* */ | | | |
| /********************************************************/ | | | |
| | | | |
|
| /** \brief Apply two separable filters successively, the first in x-directi | | If you pass \ref vigra::Kernel2D to this function, it will perform an e | |
| on, | | xplicit 2-dimensional | |
| the second in y-direction. | | convolution. If you pass a single \ref vigra::Kernel1D, it performs a s | |
| | | eparable convolution, | |
| This function is a shorthand for the concatenation of a call to | | i.e. it concatenates two 1D convolutions (along the x-axis and along th | |
| \ref separableConvolveX() and \ref separableConvolveY() | | e y-axis) with the same | |
| with the given kernels. | | kernel via internal calls to \ref separableConvolveX() and \ref separab | |
| | | leConvolveY(). If two | |
| | | 1D kernels are specified, separable convolution uses different kernels | |
| | | for the x- and y-axis. | |
| | | | |
| | | All \ref BorderTreatmentMode "border treatment modes" are supported. | |
| | | | |
| | | The unput pixel type <tt>T1</tt> must be a \ref LinearSpace "linear spa | |
| | | ce" over | |
| | | the kernel's value_type <tt>T</tt>, i.e. addition of source values, mul | |
| | | tiplication with kernel values, | |
| | | and NumericTraits must be defined. The kernel's value_type must be an \ | |
| | | ref AlgebraicField "algebraic field", | |
| | | i.e. the arithmetic operations (+, -, *, /) and NumericTraits must be d | |
| | | efined. Typically, you will use | |
| | | <tt>double</tt> for the kernel type. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // use the same 1D kernel for all axes | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T> | |
| | | void | |
| | | convolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel1D<T> const & k); | |
| | | | |
| | | // use a different kernel for each axis | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T> | |
| | | void | |
| | | convolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel1D<T> const & kx, Kernel1D<T> const & ky); | |
| | | | |
| | | // use a non-separable 2D kernel | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3> | |
| | | void | |
| | | convolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel2D<T3> const & kernel); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{convolveImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| | | // use a different kernel for each axis | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class T> | | class T> | |
| void convolveImage(SrcIterator supperleft, | | void convolveImage(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIterator dupperleft, DestAccessor da, | | DestIterator dupperleft, DestAccessor da, | |
| Kernel1D<T> const & kx, Kernel1D<T> const & ky); | | Kernel1D<T> const & kx, Kernel1D<T> const & ky); | |
|
| | | | |
| | | // use a non-separable 2D kernel | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class KernelIterator, class KernelAccessor> | |
| | | void convolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAcces | |
| | | sor src_acc, | |
| | | DestIterator dest_ul, DestAccessor dest_acc, | |
| | | KernelIterator ki, KernelAccessor ak, | |
| | | Diff2D kul, Diff2D klr, BorderTreatmentMode bord | |
| | | er); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| | | // use a different kernel for each axis | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class T> | | class T> | |
|
| inline void | | void | |
| convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| Kernel1D<T> const & kx, Kernel1D<T> const & ky); | | Kernel1D<T> const & kx, Kernel1D<T> const & ky); | |
|
| | | | |
| | | // use a non-separable 2D kernel | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class KernelIterator, class KernelAccessor> | |
| | | void convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> sr | |
| | | c, | |
| | | pair<DestIterator, DestAccessor> dest, | |
| | | tuple5<KernelIterator, KernelAccessor, Diff2D, D | |
| | | iff2D, | |
| | | BorderTreatmentMode> kernel); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/convolution.hxx\> | | <b>\#include</b> \<vigra/convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, float> src(w,h), dest1(w,h), dest2(w,h); | |
| | | ... | |
| | | | |
| | | // create horizontal sobel filter (symmetric difference in x-direction, | |
| | | smoothing in y direction) | |
| | | Kernel1D<double> kx, ky; | |
| | | kx.initSymmetricDifference(); | |
| | | ky.initBinomial(1); | |
| | | | |
| | | // calls separable convolution with the two 1D kernels | |
| | | convolveImage(src, dest1, kx, ky); | |
| | | | |
| | | // create a 3x3 Laplacian filter | |
| | | Kernel2D<double> laplace; | |
| | | laplace.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = | |
| | | 0.375, 0.25, 0.375, | |
| | | 0.25, -2.5, 0.25, | |
| | | 0.375, 0.25, 0.375; | |
| | | | |
|
| | | // calls 2D convolution | |
| | | convolveImage(src, dest2, laplace); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{convolveImage} | |
| \code | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
|
| // implement sobel filter in x-direction | | // create horizontal sobel filter (symmetric difference in x-direction,
smoothing in y direction) | |
| Kernel1D<double> kx, ky; | | Kernel1D<double> kx, ky; | |
|
| kx.initSymmetricGradient(); | | kx.initSymmetricDifference(); | |
| ky.initBinomial(1); | | ky.initBinomial(1); | |
| | | | |
|
| | | // calls separable convolution with the two 1D kernels | |
| vigra::convolveImage(srcImageRange(src), destImage(dest), kx, ky); | | vigra::convolveImage(srcImageRange(src), destImage(dest), kx, ky); | |
| | | | |
|
| | | // create a 3x3 Laplacian filter | |
| | | Kernel2D<double> laplace; | |
| | | laplace.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = | |
| | | 0.375, 0.25, 0.375, | |
| | | 0.25, -2.5, 0.25, | |
| | | 0.375, 0.25, 0.375; | |
| | | | |
| | | // calls 2D convolution | |
| | | vigra::convolveImage(srcImageRange(src), destImage(dest), kernel2d(lapl | |
| | | ace)); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| | | <b> Preconditions:</b> | |
| | | | |
|
| | | The image must be larger than the kernel radius. | |
| | | <ul> | |
| | | <li>For 1D kernels, <tt>w > std::max(xkernel.right(), -xkernel.keft())< | |
| | | /tt> and | |
| | | <tt>h > std::max(ykernel.right(), -ykernel.left())</tt> are requir | |
| | | ed. | |
| | | <li>For 2D kernels, <tt>w > std::max(kernel.lowerRight().x, -kernel.upp | |
| | | erLeft().x)</tt> and | |
| | | <tt>h > std::max(kernel.lowerRight().y, -kernel.upperLeft().y)</tt | |
| | | > are required. | |
| | | </ul> | |
| | | If <tt>BORDER_TREATMENT_CLIP</tt> is requested: the sum of kernel eleme | |
| | | nts must be != 0. | |
| */ | | */ | |
|
| | | doxygen_overloaded_function(template <...> void convolveImage) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class T> | | class T> | |
| void convolveImage(SrcIterator supperleft, | | void convolveImage(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIterator dupperleft, DestAccessor da, | | DestIterator dupperleft, DestAccessor da, | |
| Kernel1D<T> const & kx, Kernel1D<T> const & ky) | | Kernel1D<T> const & kx, Kernel1D<T> const & ky) | |
| { | | { | |
| typedef typename | | typedef typename | |
| NumericTraits<typename SrcAccessor::value_type>::RealPromote | | NumericTraits<typename SrcAccessor::value_type>::RealPromote | |
| | | | |
| skipping to change at line 280 | | skipping to change at line 383 | |
| class T> | | class T> | |
| inline void | | inline void | |
| convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| Kernel1D<T> const & kx, Kernel1D<T> const & ky) | | Kernel1D<T> const & kx, Kernel1D<T> const & ky) | |
| { | | { | |
| convolveImage(src.first, src.second, src.third, | | convolveImage(src.first, src.second, src.third, | |
| dest.first, dest.second, kx, ky); | | dest.first, dest.second, kx, ky); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T> | |
| | | inline void | |
| | | convolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel1D<T> const & k) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "convolveImage(): shape mismatch between input and output."); | |
| | | convolveImage(srcImageRange(src), | |
| | | destImage(dest), k, k); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T> | |
| | | inline void | |
| | | convolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel1D<T> const & kx, Kernel1D<T> const & ky) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "convolveImage(): shape mismatch between input and output."); | |
| | | convolveImage(srcImageRange(src), | |
| | | destImage(dest), kx, ky); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* simpleSharpening */ | | /* simpleSharpening */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Perform simple sharpening function. | | /** \brief Perform simple sharpening function. | |
| | | | |
|
| This function uses \ref convolveImage() with the following filter: | | This function uses \ref convolveImage() with the following 3x3 filter: | |
| | | | |
| \code | | \code | |
| -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_fact
or/16.0, | | -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_fact
or/16.0, | |
| -sharpening_factor/8.0, 1.0+sharpening_factor*0.75, -sharpening_fact
or/8.0, | | -sharpening_factor/8.0, 1.0+sharpening_factor*0.75, -sharpening_fact
or/8.0, | |
| -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_fact
or/16.0; | | -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_fact
or/16.0; | |
| \endcode | | \endcode | |
| | | | |
| and uses <TT>BORDER_TREATMENT_REFLECT</TT> as border treatment mode. | | and uses <TT>BORDER_TREATMENT_REFLECT</TT> as border treatment mode. | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| \code | | \code | |
| 1. sharpening_factor >= 0 | | 1. sharpening_factor >= 0 | |
| 2. scale >= 0 | | 2. scale >= 0 | |
| \endcode | | \endcode | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| <b> Declarations:</b> | | pass 2D array views: | |
| | | | |
| pass arguments explicitly: | | | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| template <class SrcIterator, class SrcAccessor, | | template <class T1, class S1, | |
| class DestIterator, class DestAccessor> | | class T2, class S2> | |
| void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAcce | | void | |
| ssor src_acc, | | simpleSharpening(MultiArrayView<2, T1, S1> const & src, | |
| DestIterator dest_ul, DestAccessor dest_acc, do | | MultiArrayView<2, T2, S2> dest, | |
| uble sharpening_factor) | | double sharpening_factor); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedAPI{simpleSharpening} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor> | |
| | | void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAc | |
| | | cessor src_acc, | |
| | | DestIterator dest_ul, DestAccessor dest_acc, | |
| | | double sharpening_factor); | |
| | | } | |
| | | \endcode | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline | | void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> | |
| void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> s | | src, | |
| rc, | | pair<DestIterator, DestAccessor> dest, double | |
| pair<DestIterator, DestAccessor> dest, | | sharpening_factor); | |
| double sharpening_factor) | | | |
| { | | | |
| simpleSharpening(src.first, src.second, src.third, | | | |
| dest.first, dest.second, sharpening_factor); | | | |
| } | | | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/convolution.hxx\> | | <b>\#include</b> \<vigra/convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | // sharpening with sharpening_factor = 0.1 | |
| | | vigra::simpleSharpening(src, dest, 0.1); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{simpleSharpening} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| // sharpening with sharpening_factor = 0.1 | | // sharpening with sharpening_factor = 0.1 | |
| vigra::simpleSharpening(srcImageRange(src), destImage(dest), 0.1); | | vigra::simpleSharpening(srcImageRange(src), destImage(dest), 0.1); | |
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void simpleSharpening) | | doxygen_overloaded_function(template <...> void simpleSharpening) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor s
rc_acc, | | void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor s
rc_acc, | |
| DestIterator dest_ul, DestAccessor dest_acc, double sha
rpening_factor) | | DestIterator dest_ul, DestAccessor dest_acc, double sha
rpening_factor) | |
| { | | { | |
| | | | |
| vigra_precondition(sharpening_factor >= 0.0, | | vigra_precondition(sharpening_factor >= 0.0, | |
| | | | |
| skipping to change at line 375 | | skipping to change at line 520 | |
| | | | |
| convolveImage(src_ul, src_lr, src_acc, dest_ul, dest_acc, | | convolveImage(src_ul, src_lr, src_acc, dest_ul, dest_acc, | |
| kernel.center(), kernel.accessor(), | | kernel.center(), kernel.accessor(), | |
| kernel.upperLeft(), kernel.lowerRight() , BORDER_TREATMEN
T_REFLECT ); | | kernel.upperLeft(), kernel.lowerRight() , BORDER_TREATMEN
T_REFLECT ); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline | | inline | |
| void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIterator, DestAccessor> dest, double sharpenin
g_factor) | | pair<DestIterator, DestAccessor> dest, double sharpen
ing_factor) | |
| { | | { | |
| simpleSharpening(src.first, src.second, src.third, | | simpleSharpening(src.first, src.second, src.third, | |
| dest.first, dest.second, sharpening_factor); | | dest.first, dest.second, sharpening_factor); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | simpleSharpening(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double sharpening_factor) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "simpleSharpening(): shape mismatch between input and output."); | |
| | | simpleSharpening(srcImageRange(src), | |
| | | destImage(dest), sharpening_factor); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* gaussianSharpening */ | | /* gaussianSharpening */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Perform sharpening function with gaussian filter. | | /** \brief Perform sharpening function with gaussian filter. | |
| | | | |
| This function uses \ref gaussianSmoothing() at the given scale to creat
e a | | This function uses \ref gaussianSmoothing() at the given scale to creat
e a | |
| temporary image 'smooth' and than blends the original and smoothed imag
e | | temporary image 'smooth' and than blends the original and smoothed imag
e | |
| | | | |
| skipping to change at line 405 | | skipping to change at line 563 | |
| \endcode | | \endcode | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| \code | | \code | |
| 1. sharpening_factor >= 0 | | 1. sharpening_factor >= 0 | |
| 2. scale >= 0 | | 2. scale >= 0 | |
| \endcode | | \endcode | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianSharpening(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double sharpening_factor, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{gaussianSharpening} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAc
cessor src_acc, | | void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAc
cessor src_acc, | |
| DestIterator dest_ul, DestAccessor dest_acc, | | DestIterator dest_ul, DestAccessor dest_acc, | |
| double sharpening_factor, double scale) | | double sharpening_factor, double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor>
src, | | void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor>
src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double sharpening_factor, double scale) | | double sharpening_factor, double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/convolution.hxx\> | | <b>\#include</b> \<vigra/convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| vigra::FImage src(w,h), dest(w,h); | | MultiArray<2, float> src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| // sharpening with sharpening_factor = 3.0 | | // sharpening with sharpening_factor = 3.0 | |
| // smoothing with scale = 0.5 | | // smoothing with scale = 0.5 | |
|
| vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0, 0.5) | | gaussianSharpening(src, dest, 3.0, 0.5); | |
| ; | | | |
| | | | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{gaussianSharpening} | |
| | | \code | |
| | | vigra::FImage src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | // sharpening with sharpening_factor = 3.0 | |
| | | // smoothing with scale = 0.5 | |
| | | vigra::gaussianSharpening(srcImageRange(src), destImage(dest), 3.0, 0.5 | |
| | | ); | |
| | | \endcode | |
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void gaussianSharpening) | | doxygen_overloaded_function(template <...> void gaussianSharpening) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor
src_acc, | | void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor
src_acc, | |
| DestIterator dest_ul, DestAccessor dest_acc, double
sharpening_factor, | | DestIterator dest_ul, DestAccessor dest_acc, double
sharpening_factor, | |
| double scale) | | double scale) | |
| { | | { | |
| vigra_precondition(sharpening_factor >= 0.0, | | vigra_precondition(sharpening_factor >= 0.0, | |
| | | | |
| skipping to change at line 481 | | skipping to change at line 663 | |
| dest_acc.set((1.0 + sharpening_factor)*src_acc(i_src) - sharpen
ing_factor*tmp_acc(i_tmp), i_dest); | | dest_acc.set((1.0 + sharpening_factor)*src_acc(i_src) - sharpen
ing_factor*tmp_acc(i_tmp), i_dest); | |
| } | | } | |
| i_src.x = src_ul.x; | | i_src.x = src_ul.x; | |
| i_dest.x = dest_ul.x; | | i_dest.x = dest_ul.x; | |
| i_tmp.x = tmp_ul.x; | | i_tmp.x = tmp_ul.x; | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | inline void | |
| pair<DestIterator, DestAccessor> dest, double sharp | | gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| ening_factor, | | pair<DestIterator, DestAccessor> dest, double sharpening | |
| double scale) | | _factor, | |
| | | double scale) | |
| { | | { | |
| gaussianSharpening(src.first, src.second, src.third, | | gaussianSharpening(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| sharpening_factor, scale); | | sharpening_factor, scale); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianSharpening(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double sharpening_factor, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "gaussianSharpening(): shape mismatch between input and output."); | |
| | | gaussianSharpening(srcImageRange(src), | |
| | | destImage(dest), | |
| | | sharpening_factor, scale); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* gaussianSmoothing */ | | /* gaussianSmoothing */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Perform isotropic Gaussian convolution. | | /** \brief Perform isotropic Gaussian convolution. | |
| | | | |
| This function is a shorthand for the concatenation of a call to | | This function is a shorthand for the concatenation of a call to | |
| \ref separableConvolveX() and \ref separableConvolveY() with a | | \ref separableConvolveX() and \ref separableConvolveY() with a | |
| Gaussian kernel of the given scale. If two scales are provided, | | Gaussian kernel of the given scale. If two scales are provided, | |
| smoothing in x and y direction will have different strength. | | smoothing in x and y direction will have different strength. | |
| The function uses <TT>BORDER_TREATMENT_REFLECT</TT>. | | The function uses <TT>BORDER_TREATMENT_REFLECT</TT>. | |
| | | | |
|
| | | Function \ref gaussianSmoothMultiArray() performs the same filter opera | |
| | | tion | |
| | | on arbitrary dimensional arrays. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianSmoothing(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale_x, double scale_y = scale_x); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{gaussianSmoothing} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void gaussianSmoothing(SrcIterator supperleft, | | void gaussianSmoothing(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIterator dupperleft, DestAccessor da, | | DestIterator dupperleft, DestAccessor da, | |
| double scale_x, double scale_y = scale_x); | | double scale_x, double scale_y = scale_x); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline void | | void | |
| gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src
, | | gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src
, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale_x, double scale_y = scale_x); | | double scale_x, double scale_y = scale_x); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/convolution.hxx\> | | <b>\#include</b> \<vigra/convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | // smooth with scale = 3.0 | |
| | | gaussianSmoothing(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{gaussianSmoothing} | |
| \code | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| // smooth with scale = 3.0 | | // smooth with scale = 3.0 | |
| vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0); | | vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void gaussianSmoothing) | | doxygen_overloaded_function(template <...> void gaussianSmoothing) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianSmoothing(SrcIterator supperleft, SrcIterator slowerright, SrcAcces
sor sa, | | gaussianSmoothing(SrcIterator supperleft, SrcIterator slowerright, SrcAcces
sor sa, | |
| DestIterator dupperleft, DestAccessor da, | | DestIterator dupperleft, DestAccessor da, | |
| double scale_x, double scale_y) | | double scale_x, double scale_y) | |
| { | | { | |
| | | | |
| skipping to change at line 604 | | skipping to change at line 827 | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale) | | double scale) | |
| { | | { | |
| gaussianSmoothing(src.first, src.second, src.third, | | gaussianSmoothing(src.first, src.second, src.third, | |
| dest.first, dest.second, scale, scale); | | dest.first, dest.second, scale, scale); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianSmoothing(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale_x, double scale_y) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "gaussianSmoothing(): shape mismatch between input and output."); | |
| | | gaussianSmoothing(srcImageRange(src), | |
| | | destImage(dest), scale_x, scale_y); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianSmoothing(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "gaussianSmoothing(): shape mismatch between input and output."); | |
| | | gaussianSmoothing(srcImageRange(src), | |
| | | destImage(dest), scale, scale); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* gaussianGradient */ | | /* gaussianGradient */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Calculate the gradient vector by means of a 1st derivatives of | | /** \brief Calculate the gradient vector by means of a 1st derivatives of | |
| Gaussian filter. | | Gaussian filter. | |
| | | | |
| This function is a shorthand for the concatenation of a call to | | This function is a shorthand for the concatenation of a call to | |
| \ref separableConvolveX() and \ref separableConvolveY() with the | | \ref separableConvolveX() and \ref separableConvolveY() with the | |
| appropriate kernels at the given scale. Note that this function can eit
her produce | | appropriate kernels at the given scale. Note that this function can eit
her produce | |
| two separate result images for the x- and y-components of the gradient,
or write | | two separate result images for the x- and y-components of the gradient,
or write | |
| into a vector valued image (with at least two components). | | into a vector valued image (with at least two components). | |
| | | | |
|
| | | Function \ref gaussianGradientMultiArray() performs the same filter ope | |
| | | ration | |
| | | on arbitrary dimensional arrays. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // write x and y component of the gradient into separate images | |
| | | template <class T1, class S1, | |
| | | class T2X, class S2X, | |
| | | class T2Y, class S2Y> | |
| | | void | |
| | | gaussianGradient(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2X, S2X> destx, | |
| | | MultiArrayView<2, T2Y, S2Y> desty, | |
| | | double scale); | |
| | | | |
| | | // write x and y component of the gradient into a vector-valued imag | |
| | | e | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianGradient(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TinyVector<T2, 2>, S2> dest, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{gaussianGradient} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // write x and y component of the gradient into separate images | | // write x and y component of the gradient into separate images | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
| void gaussianGradient(SrcIterator supperleft, | | void gaussianGradient(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIteratorX dupperleftx, DestAccessorX dax, | | DestIteratorX dupperleftx, DestAccessorX dax, | |
| DestIteratorY dupperlefty, DestAccessorY day, | | DestIteratorY dupperlefty, DestAccessorY day, | |
| | | | |
| skipping to change at line 643 | | skipping to change at line 919 | |
| | | | |
| // write x and y component of the gradient into a vector-valued ima
ge | | // write x and y component of the gradient into a vector-valued ima
ge | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void gaussianGradient(SrcIterator supperleft, | | void gaussianGradient(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor src, | | SrcIterator slowerright, SrcAccessor src, | |
| DestIterator dupperleft, DestAccessor dest, | | DestIterator dupperleft, DestAccessor dest, | |
| double scale); | | double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // write x and y component of the gradient into separate images | | // write x and y component of the gradient into separate images | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
| void | | void | |
| gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIteratorX, DestAccessorX> destx, | | pair<DestIteratorX, DestAccessorX> destx, | |
| | | | |
| skipping to change at line 666 | | skipping to change at line 941 | |
| | | | |
| // write x and y component of the gradient into a vector-valued ima
ge | | // write x and y component of the gradient into a vector-valued ima
ge | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale); | | double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/convolution.hxx\> | | <b>\#include</b> \<vigra/convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, float> src(w,h), gradx(w,h), grady(w,h); | |
| | | ... | |
| | | | |
| | | // calculate gradient vector at scale = 3.0 | |
| | | gaussianGradient(src, gradx, grady, 3.0); | |
| | | | |
| | | // likewise, but use a vector image to store the gradient | |
| | | MultiArray<2, TinyVector<float, 2> > dest(w,h); | |
| | | gaussianGradient(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{gaussianGradient} | |
| \code | | \code | |
| vigra::FImage src(w,h), gradx(w,h), grady(w,h); | | vigra::FImage src(w,h), gradx(w,h), grady(w,h); | |
| ... | | ... | |
| | | | |
| // calculate gradient vector at scale = 3.0 | | // calculate gradient vector at scale = 3.0 | |
| vigra::gaussianGradient(srcImageRange(src), | | vigra::gaussianGradient(srcImageRange(src), | |
| destImage(gradx), destImage(grady), 3.0); | | destImage(gradx), destImage(grady), 3.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void gaussianGradient) | | doxygen_overloaded_function(template <...> void gaussianGradient) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
| void gaussianGradient(SrcIterator supperleft, | | void gaussianGradient(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIteratorX dupperleftx, DestAccessorX dax, | | DestIteratorX dupperleftx, DestAccessorX dax, | |
| DestIteratorY dupperlefty, DestAccessorY day, | | DestIteratorY dupperlefty, DestAccessorY day, | |
| | | | |
| skipping to change at line 748 | | skipping to change at line 1037 | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale) | | double scale) | |
| { | | { | |
| gaussianGradient(src.first, src.second, src.third, | | gaussianGradient(src.first, src.second, src.third, | |
| dest.first, dest.second, scale); | | dest.first, dest.second, scale); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2X, class S2X, | |
| | | class T2Y, class S2Y> | |
| | | inline void | |
| | | gaussianGradient(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2X, S2X> destx, | |
| | | MultiArrayView<2, T2Y, S2Y> desty, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == destx.shape(), | |
| | | "gaussianGradient(): shape mismatch between input and output."); | |
| | | gaussianGradient(srcImageRange(src), | |
| | | destImage(destx), destImage(desty), scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianGradient(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TinyVector<T2, 2>, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "gaussianGradient(): shape mismatch between input and output."); | |
| | | gaussianGradient(srcImageRange(src), | |
| | | destImage(dest), scale); | |
| | | } | |
| | | | |
| /** \brief Calculate the gradient magnitude by means of a 1st derivatives o
f | | /** \brief Calculate the gradient magnitude by means of a 1st derivatives o
f | |
| Gaussian filter. | | Gaussian filter. | |
| | | | |
| This function calls gaussianGradient() and returns the pixel-wise magni
tude of | | This function calls gaussianGradient() and returns the pixel-wise magni
tude of | |
| the resulting gradient vectors. If the original image has multiple band
s, | | the resulting gradient vectors. If the original image has multiple band
s, | |
| the squared gradient magnitude is computed for each band separately, an
d the | | the squared gradient magnitude is computed for each band separately, an
d the | |
| return value is the square root of the sum of these squared magnitudes. | | return value is the square root of the sum of these squared magnitudes. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | use arbitrary-dimensional arrays: | |
| | | \code | |
| | | namespace vigra { | |
| | | // pass filter scale explicitly | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianGradientMagnitude(MultiArrayView<N, T1, S1> const & src, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOp | |
| | | tions<N>()); | |
| | | | |
| | | template <unsigned int N, class MT, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianGradientMagnitude(MultiArrayView<N+1, Multiband<MT>, S1> co | |
| | | nst & src, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOp | |
| | | tions<N>()); | |
| | | | |
| | | // pass filter scale(s) in option object | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianGradientMagnitude(MultiArrayView<N, T1, S1> const & src, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> const & opt); | |
| | | | |
| | | template <unsigned int N, class MT, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianGradientMagnitude(MultiArrayView<N+1, Multiband<MT>, S1> co | |
| | | nst & src, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> const & opt); | |
| | | } | |
| | | \endcode | |
| | | Here, the input element types <tt>T1</tt> and <tt>MT</tt> can be arbitr | |
| | | ary scalar types, and <tt>T1</tt> | |
| | | may also be <tt>TinyVector</tt> or <tt>RGBValue</tt>. The output elemen | |
| | | t type <tt>T2</tt> should | |
| | | be the corresponding norm type (see \ref NormTraits "NormTraits"). In t | |
| | | he <tt>Multiband<MT></tt>-version, | |
| | | the input array's right-most dimension is interpreted as a channel axis | |
| | | , therefore it must | |
| | | have one dimension more than the output array. | |
| | | | |
| | | \deprecatedAPI{gaussianGradientMagnitude} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void gaussianGradientMagnitude(SrcIterator sul, | | void gaussianGradientMagnitude(SrcIterator sul, | |
| SrcIterator slr, SrcAccessor src, | | SrcIterator slr, SrcAccessor src, | |
| DestIterator dupperleft, DestAccesso
r dest, | | DestIterator dupperleft, DestAccesso
r dest, | |
| double scale); | | double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianGradientMagnitude(triple<SrcIterator, SrcIterator, SrcAcces
sor> src, | | gaussianGradientMagnitude(triple<SrcIterator, SrcIterator, SrcAcces
sor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale); | | double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\> (or \<vigra/convolutio | |
| | | n.hxx\> to use the old API)<br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | // example 1 | |
| | | { | |
| | | // use a 3-dimensional float array | |
| | | MultiArray<3, float> volume(Shape3(w, h, d)), grad(volume.shape()); | |
| | | ... | |
| | | | |
| | | // calculate gradient magnitude at scale = 3.0 | |
| | | gaussianGradientMagnitude(volume, grad, 3.0); | |
| | | } | |
| | | | |
| | | // example 2 | |
| | | { | |
| | | // use a 2-dimensional RGB array | |
| | | MultiArray<2, RGBValue<float> > rgb(Shape2(w, h)); | |
| | | MultiArray<2, float> grad(rgb.shape()); | |
| | | ... | |
| | | | |
| | | // calculate the color gradient magnitude at scale = 3.0 | |
| | | gaussianGradientMagnitude(rgb, grad, 3.0); | |
| | | } | |
| | | | |
| | | // example 3 | |
| | | { | |
| | | // use a 3-dimensional array whose right-most axis is interpreted a | |
| | | s | |
| | | // a multi-spectral axis with arbitrary many channels | |
| | | MultiArray<3, Multiband<float> > spectral(Shape3(w, h, channelCount | |
| | | )); | |
| | | MultiArray<2, float> grad(Shape2(w, h)); | |
| | | ... | |
| | | | |
| | | // calculate the multi-channel gradient magnitude at scale = 3.0 | |
| | | // (note that the template parameter N (number of spatial dimension | |
| | | s) | |
| | | // must be provided explicitly as gaussianGradientMagnitude<2>(... | |
| | | ) ) | |
| | | MultiArrayView<3, Multiband<float> > view(spectral); | |
| | | gaussianGradientMagnitude<2>(view, grad, 3.0); | |
| | | } | |
| | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{gaussianGradientMagnitude} | |
| \code | | \code | |
|
| vigra::FImage src(w,h), grad(w,h); | | // use a traditional float or RGB image | |
| | | FImage image(w, h), grad(w, h); | |
| | | FRGBImage rgb(w, h); | |
| ... | | ... | |
| | | | |
| // calculate gradient magnitude at scale = 3.0 | | // calculate gradient magnitude at scale = 3.0 | |
|
| vigra::gaussianGradientMagnitude(srcImageRange(src), destImage(grad), 3
.0); | | gaussianGradientMagnitude(srcImageRange(image), destImage(grad), 3.0); | |
| | | | |
|
| | | // calculate color gradient magnitude at scale = 3.0 | |
| | | gaussianGradientMagnitude(srcImageRange(rgb), destImage(grad), 3.0); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void gaussianGradientMagnitude) | | doxygen_overloaded_function(template <...> void gaussianGradientMagnitude) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void gaussianGradientMagnitude(SrcIterator sul, | | void gaussianGradientMagnitude(SrcIterator sul, | |
| SrcIterator slr, SrcAccessor src, | | SrcIterator slr, SrcAccessor src, | |
| DestIterator dupperleft, DestAccessor dest, | | DestIterator dupperleft, DestAccessor dest, | |
| double scale) | | double scale) | |
| { | | { | |
| | | | |
| skipping to change at line 838 | | skipping to change at line 1242 | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Filter image with the Laplacian of Gaussian operator | | /** \brief Filter image with the Laplacian of Gaussian operator | |
| at the given scale. | | at the given scale. | |
| | | | |
| This function calls \ref separableConvolveX() and \ref separableConvolv
eY() with the appropriate 2nd derivative | | This function calls \ref separableConvolveX() and \ref separableConvolv
eY() with the appropriate 2nd derivative | |
| of Gaussian kernels in x- and y-direction and then sums the results | | of Gaussian kernels in x- and y-direction and then sums the results | |
| to get the Laplacian. | | to get the Laplacian. | |
| | | | |
|
| | | Function \ref laplacianOfGaussianMultiArray() performs the same filter | |
| | | operation | |
| | | on arbitrary dimensional arrays. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | laplacianOfGaussian(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{laplacianOfGaussian} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void laplacianOfGaussian(SrcIterator supperleft, | | void laplacianOfGaussian(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIterator dupperleft, DestAccessor da, | | DestIterator dupperleft, DestAccessor da, | |
| double scale); | | double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline void | | void | |
| laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | | laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale); | | double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/convolution.hxx\> | | <b>\#include</b> \<vigra/convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | // calculate Laplacian of Gaussian at scale = 3.0 | |
| | | laplacianOfGaussian(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{laplacianOfGaussian} | |
| \code | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| // calculate Laplacian of Gaussian at scale = 3.0 | | // calculate Laplacian of Gaussian at scale = 3.0 | |
| vigra::laplacianOfGaussian(srcImageRange(src), destImage(dest), 3.0); | | vigra::laplacianOfGaussian(srcImageRange(src), destImage(dest), 3.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void laplacianOfGaussian) | | doxygen_overloaded_function(template <...> void laplacianOfGaussian) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void laplacianOfGaussian(SrcIterator supperleft, | | void laplacianOfGaussian(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIterator dupperleft, DestAccessor da, | | DestIterator dupperleft, DestAccessor da, | |
| double scale) | | double scale) | |
| { | | { | |
| | | | |
| skipping to change at line 914 | | skipping to change at line 1343 | |
| separableConvolveY(srcImageRange(tmp), | | separableConvolveY(srcImageRange(tmp), | |
| destImage(tmpy), kernel1d(deriv)); | | destImage(tmpy), kernel1d(deriv)); | |
| combineTwoImages(srcImageRange(tmpx), srcImage(tmpy), | | combineTwoImages(srcImageRange(tmpx), srcImage(tmpy), | |
| destIter(dupperleft, da), std::plus<TmpType>()); | | destIter(dupperleft, da), std::plus<TmpType>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale) | | double scale) | |
| { | | { | |
| laplacianOfGaussian(src.first, src.second, src.third, | | laplacianOfGaussian(src.first, src.second, src.third, | |
|
| dest.first, dest.second, scale); | | dest.first, dest.second, scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | laplacianOfGaussian(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "laplacianOfGaussian(): shape mismatch between input and output."); | |
| | | laplacianOfGaussian(srcImageRange(src), | |
| | | destImage(dest), scale); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* hessianMatrixOfGaussian */ | | /* hessianMatrixOfGaussian */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Filter image with the 2nd derivatives of the Gaussian | | /** \brief Filter image with the 2nd derivatives of the Gaussian | |
| at the given scale to get the Hessian matrix. | | at the given scale to get the Hessian matrix. | |
| | | | |
| skipping to change at line 950 | | skipping to change at line 1392 | |
| where \f$G_{xx}, G_{xy}, G_{yy}\f$ denote 2nd derivatives of Gaussians | | where \f$G_{xx}, G_{xy}, G_{yy}\f$ denote 2nd derivatives of Gaussians | |
| at the given scale, and | | at the given scale, and | |
| \f$\ast\f$ is the convolution symbol. This function calls | | \f$\ast\f$ is the convolution symbol. This function calls | |
| \ref separableConvolveX() and \ref separableConvolveY() | | \ref separableConvolveX() and \ref separableConvolveY() | |
| with the appropriate 2nd derivative | | with the appropriate 2nd derivative | |
| of Gaussian kernels and puts the results in | | of Gaussian kernels and puts the results in | |
| the three destination images. The first destination image will | | the three destination images. The first destination image will | |
| contain the second derivative in x-direction, the second one the mixed | | contain the second derivative in x-direction, the second one the mixed | |
| derivative, and the third one holds the derivative in y-direction. | | derivative, and the third one holds the derivative in y-direction. | |
| | | | |
|
| | | Function \ref hessianOfGaussianMultiArray() performs the same filter op | |
| | | eration | |
| | | on arbitrary dimensional arrays. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | hessianMatrixOfGaussian(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TinyVector<T2, 3>, S2> de | |
| | | st, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{hessianMatrixOfGaussian} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorXY, class DestAccessorXY, | | class DestIteratorXY, class DestAccessorXY, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
| void hessianMatrixOfGaussian(SrcIterator supperleft, | | void hessianMatrixOfGaussian(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIteratorX dupperleftx, DestAccessorX da
x, | | DestIteratorX dupperleftx, DestAccessorX da
x, | |
| DestIteratorXY dupperleftxy, DestAccessorXY
daxy, | | DestIteratorXY dupperleftxy, DestAccessorXY
daxy, | |
| DestIteratorY dupperlefty, DestAccessorY da
y, | | DestIteratorY dupperlefty, DestAccessorY da
y, | |
| double scale); | | double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorXY, class DestAccessorXY, | | class DestIteratorXY, class DestAccessorXY, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
|
| inline void | | void | |
| hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | | hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | |
| pair<DestIteratorX, DestAccessorX> destx, | | pair<DestIteratorX, DestAccessorX> destx, | |
| pair<DestIteratorXY, DestAccessorXY> destxy, | | pair<DestIteratorXY, DestAccessorXY> destxy, | |
| pair<DestIteratorY, DestAccessorY> desty, | | pair<DestIteratorY, DestAccessorY> desty, | |
| double scale); | | double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/convolution.hxx\> | | <b>\#include</b> \<vigra/convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| vigra::FImage src(w,h), hxx(w,h), hxy(w,h), hyy(w,h); | | MultiArray<2, float> src(w,h); | |
| | | MultiArray<2, TinyVector<float, 3> > hessian(w,h); // will hold the t | |
| | | hree components of the Hessian | |
| ... | | ... | |
| | | | |
|
| // calculate Hessian of Gaussian at scale = 3.0 | | // calculate Hessian of Gaussian at scale = 3.0, use a 3-band output im | |
| vigra::hessianMatrixOfGaussian(srcImageRange(src), | | age | |
| destImage(hxx), destImage(hxy), destImage(hyy), 3.0); | | hessianMatrixOfGaussian(src, hessian, 3.0); | |
| | | | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{hessianMatrixOfGaussian} | |
| | | \code | |
| | | vigra::FImage src(w,h), | |
| | | hxx(w,h), hxy(w,h), hyy(w,h); // use a separate image for | |
| | | each component of the Hessian | |
| | | ... | |
| | | | |
| | | // calculate Hessian of Gaussian at scale = 3.0, use 3 single.band outp | |
| | | ut images | |
| | | vigra::hessianMatrixOfGaussian(srcImageRange(src), | |
| | | destImage(hxx), destImage(hxy), destImag | |
| | | e(hyy), 3.0); | |
| | | \endcode | |
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void hessianMatrixOfGaussian) | | doxygen_overloaded_function(template <...> void hessianMatrixOfGaussian) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorXY, class DestAccessorXY, | | class DestIteratorXY, class DestAccessorXY, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
| void hessianMatrixOfGaussian(SrcIterator supperleft, | | void hessianMatrixOfGaussian(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIteratorX dupperleftx, DestAccessorX dax, | | DestIteratorX dupperleftx, DestAccessorX dax, | |
| | | | |
| skipping to change at line 1042 | | skipping to change at line 1511 | |
| separableConvolveY(srcImageRange(tmp), | | separableConvolveY(srcImageRange(tmp), | |
| destIter(dupperleftxy, daxy), kernel1d(deriv1)); | | destIter(dupperleftxy, daxy), kernel1d(deriv1)); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorXY, class DestAccessorXY, | | class DestIteratorXY, class DestAccessorXY, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
| inline void | | inline void | |
| hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIteratorX, DestAccessorX> destx, | | pair<DestIteratorX, DestAccessorX> destx, | |
| pair<DestIteratorXY, DestAccessorXY> destxy, | | pair<DestIteratorXY, DestAccessorXY> destxy, | |
| pair<DestIteratorY, DestAccessorY> desty, | | pair<DestIteratorY, DestAccessorY> desty, | |
| double scale) | | double scale) | |
| { | | { | |
| hessianMatrixOfGaussian(src.first, src.second, src.third, | | hessianMatrixOfGaussian(src.first, src.second, src.third, | |
|
| destx.first, destx.second, | | destx.first, destx.second, | |
| destxy.first, destxy.second, | | destxy.first, destxy.second, | |
| desty.first, desty.second, | | desty.first, desty.second, | |
| scale); | | scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2X, class S2X, | |
| | | class T2XY, class S2XY, | |
| | | class T2Y, class S2Y> | |
| | | inline void | |
| | | hessianMatrixOfGaussian(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2X, S2X> destx, | |
| | | MultiArrayView<2, T2XY, S2XY> destxy, | |
| | | MultiArrayView<2, T2Y, S2Y> desty, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == destx.shape() && src.shape() == destx | |
| | | y.shape() && src.shape() == desty.shape(), | |
| | | "hessianMatrixOfGaussian(): shape mismatch between input and output | |
| | | ."); | |
| | | hessianMatrixOfGaussian(srcImageRange(src), | |
| | | destImage(destx), | |
| | | destImage(destxy), | |
| | | destImage(desty), | |
| | | scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | hessianMatrixOfGaussian(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TinyVector<T2, 3>, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "hessianMatrixOfGaussian(): shape mismatch between input and output | |
| | | ."); | |
| | | | |
| | | MultiArrayView<3, T2> expanded(dest.expandElements(0)); | |
| | | | |
| | | hessianMatrixOfGaussian(srcImageRange(src), | |
| | | destImage(expanded.bind<0>(0)), | |
| | | destImage(expanded.bind<0>(1)), | |
| | | destImage(expanded.bind<0>(2)), | |
| | | scale); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* structureTensor */ | | /* structureTensor */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Calculate the Structure Tensor for each pixel of | | /** \brief Calculate the Structure Tensor for each pixel of | |
| and image, using Gaussian (derivative) filters. | | and image, using Gaussian (derivative) filters. | |
| | | | |
| skipping to change at line 1091 | | skipping to change at line 1599 | |
| products of the 1st derivative images. This function calls | | products of the 1st derivative images. This function calls | |
| \ref separableConvolveX() and \ref separableConvolveY() with the | | \ref separableConvolveX() and \ref separableConvolveY() with the | |
| appropriate Gaussian kernels and puts the results in | | appropriate Gaussian kernels and puts the results in | |
| the three separate destination images (where the first one will | | the three separate destination images (where the first one will | |
| contain \f$G \ast (I_x I_x)\f$, the second one \f$G \ast (I_x I_y)\f$,
and the | | contain \f$G \ast (I_x I_x)\f$, the second one \f$G \ast (I_x I_y)\f$,
and the | |
| third one holds \f$G \ast (I_y I_y)\f$), or into a single 3-band image
(where the bands | | third one holds \f$G \ast (I_y I_y)\f$), or into a single 3-band image
(where the bands | |
| hold the result in the same order as above). The latter form is also ap
plicable when | | hold the result in the same order as above). The latter form is also ap
plicable when | |
| the source image is a multi-band image (e.g. RGB). In this case, tensor
s are | | the source image is a multi-band image (e.g. RGB). In this case, tensor
s are | |
| first computed for each band separately, and then summed up to get a si
ngle result tensor. | | first computed for each band separately, and then summed up to get a si
ngle result tensor. | |
| | | | |
|
| | | Function \ref structureTensorMultiArray() performs the same filter oper | |
| | | ation | |
| | | on arbitrary dimensional arrays. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // create three separate destination images | |
| | | template <class T, class S, | |
| | | class TX, class SX, | |
| | | class TXY, class SXY, | |
| | | class TY, class SY> | |
| | | void | |
| | | structureTensor(MultiArrayView<2, S, T> const & src, | |
| | | MultiArrayView<2, TX, SX> destx, | |
| | | MultiArrayView<2, TXY, SXY> destxy, | |
| | | MultiArrayView<2, TY, SY> desty, | |
| | | double inner_scale, double outer_scale); | |
| | | | |
| | | // create a single 3-band destination image | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | structureTensor(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TinyVector<T2, 3>, S2> dest, | |
| | | double inner_scale, double outer_scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{structureTensor} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // create three separate destination images | | // create three separate destination images | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorXY, class DestAccessorXY, | | class DestIteratorXY, class DestAccessorXY, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
| void structureTensor(SrcIterator supperleft, | | void structureTensor(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIteratorX dupperleftx, DestAccessorX da
x, | | DestIteratorX dupperleftx, DestAccessorX da
x, | |
| | | | |
| skipping to change at line 1117 | | skipping to change at line 1654 | |
| | | | |
| // create a single 3-band destination image | | // create a single 3-band destination image | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void structureTensor(SrcIterator supperleft, | | void structureTensor(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIterator dupperleft, DestAccessor da, | | DestIterator dupperleft, DestAccessor da, | |
| double inner_scale, double outer_scale); | | double inner_scale, double outer_scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // create three separate destination images | | // create three separate destination images | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorXY, class DestAccessorXY, | | class DestIteratorXY, class DestAccessorXY, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
| void | | void | |
| structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| | | | |
| skipping to change at line 1142 | | skipping to change at line 1678 | |
| | | | |
| // create a single 3-band destination image | | // create a single 3-band destination image | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double nner_scale, double outer_scale); | | double nner_scale, double outer_scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/convolution.hxx\> | | <b>\#include</b> \<vigra/convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| vigra::FImage src(w,h), stxx(w,h), stxy(w,h), styy(w,h); | | MultiArray<2, flost> src(w,h), | |
| vigra::BasicImage<TinyVector<float, 3> > st(w,h); | | stxx(w,h), stxy(w,h), styy(w,h); // use a separat | |
| | | e image for each component | |
| ... | | ... | |
| | | | |
| // calculate Structure Tensor at inner scale = 1.0 and outer scale = 3.
0 | | // calculate Structure Tensor at inner scale = 1.0 and outer scale = 3.
0 | |
|
| | | structureTensor(src, stxx, stxy, styy, 1.0, 3.0); | |
| | | | |
| | | // likwise with a single 3-band destination image | |
| | | MultiArray<2, TinyVector<float, 3> > st(w,h); | |
| | | structureTensor(src, st, 1.0, 3.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{structureTensor} | |
| | | \code | |
| | | vigra::FImage src(w,h), | |
| | | stxx(w,h), stxy(w,h), styy(w,h); | |
| | | vigra::BasicImage<TinyVector<float, 3> > st(w,h); | |
| | | ... | |
| | | | |
| vigra::structureTensor(srcImageRange(src), | | vigra::structureTensor(srcImageRange(src), | |
|
| destImage(stxx), destImage(stxy), destImage(styy), 1.0, 3.0); | | destImage(stxx), destImage(stxy), destImage(styy
), 1.0, 3.0); | |
| | | | |
|
| // dto. with a single 3-band destination image | | | |
| vigra::structureTensor(srcImageRange(src), destImage(st), 1.0, 3.0); | | vigra::structureTensor(srcImageRange(src), destImage(st), 1.0, 3.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void structureTensor) | | doxygen_overloaded_function(template <...> void structureTensor) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIteratorX, class DestAccessorX, | | class DestIteratorX, class DestAccessorX, | |
| class DestIteratorXY, class DestAccessorXY, | | class DestIteratorXY, class DestAccessorXY, | |
| class DestIteratorY, class DestAccessorY> | | class DestIteratorY, class DestAccessorY> | |
| void structureTensor(SrcIterator supperleft, | | void structureTensor(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIteratorX dupperleftx, DestAccessorX dax, | | DestIteratorX dupperleftx, DestAccessorX dax, | |
| | | | |
| skipping to change at line 1216 | | skipping to change at line 1766 | |
| pair<DestIteratorY, DestAccessorY> desty, | | pair<DestIteratorY, DestAccessorY> desty, | |
| double inner_scale, double outer_scale) | | double inner_scale, double outer_scale) | |
| { | | { | |
| structureTensor(src.first, src.second, src.third, | | structureTensor(src.first, src.second, src.third, | |
| destx.first, destx.second, | | destx.first, destx.second, | |
| destxy.first, destxy.second, | | destxy.first, destxy.second, | |
| desty.first, desty.second, | | desty.first, desty.second, | |
| inner_scale, outer_scale); | | inner_scale, outer_scale); | |
| } | | } | |
| | | | |
|
| | | template <class T, class S, | |
| | | class TX, class SX, | |
| | | class TXY, class SXY, | |
| | | class TY, class SY> | |
| | | inline void | |
| | | structureTensor(MultiArrayView<2, S, T> const & src, | |
| | | MultiArrayView<2, TX, SX> destx, | |
| | | MultiArrayView<2, TXY, SXY> destxy, | |
| | | MultiArrayView<2, TY, SY> desty, | |
| | | double inner_scale, double outer_scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == destx.shape(), | |
| | | "structureTensor(): shape mismatch between input and output."); | |
| | | structureTensor(srcImageRange(src), | |
| | | destImage(destx), destImage(destxy), destImage(desty), | |
| | | inner_scale, outer_scale); | |
| | | } | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void structureTensor(SrcIterator supperleft, | | void structureTensor(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor src, | | SrcIterator slowerright, SrcAccessor src, | |
| DestIterator dupperleft, DestAccessor dest, | | DestIterator dupperleft, DestAccessor dest, | |
| double inner_scale, double outer_scale, | | double inner_scale, double outer_scale, | |
| VigraTrueType /* isScalar */) | | VigraTrueType /* isScalar */) | |
| { | | { | |
| | | | |
| skipping to change at line 1281 | | skipping to change at line 1849 | |
| typedef typename | | typedef typename | |
| NumericTraits<typename SrcAccessor::value_type>::isScalar isScalar; | | NumericTraits<typename SrcAccessor::value_type>::isScalar isScalar; | |
| detail::structureTensor(supperleft, slowerright, src, | | detail::structureTensor(supperleft, slowerright, src, | |
| dupperleft, dest, inner_scale, outer_scale, isS
calar()); | | dupperleft, dest, inner_scale, outer_scale, isS
calar()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double inner_scale, double outer_scale) | | double inner_scale, double outer_scale) | |
| { | | { | |
| structureTensor(src.first, src.second, src.third, | | structureTensor(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| inner_scale, outer_scale); | | inner_scale, outer_scale); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | structureTensor(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TinyVector<T2, 3>, S2> dest, | |
| | | double inner_scale, double outer_scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "structureTensor(): shape mismatch between input and output."); | |
| | | structureTensor(srcImageRange(src), | |
| | | destImage(dest), | |
| | | inner_scale, outer_scale); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_CONVOLUTION_HXX | | #endif // VIGRA_CONVOLUTION_HXX | |
| | | | |
End of changes. 110 change blocks. |
| 118 lines changed or deleted | | 747 lines changed or added | |
|
| edgedetection.hxx | | edgedetection.hxx | |
| | | | |
| skipping to change at line 54 | | skipping to change at line 54 | |
| #include "stdimage.hxx" | | #include "stdimage.hxx" | |
| #include "stdimagefunctions.hxx" | | #include "stdimagefunctions.hxx" | |
| #include "recursiveconvolution.hxx" | | #include "recursiveconvolution.hxx" | |
| #include "separableconvolution.hxx" | | #include "separableconvolution.hxx" | |
| #include "convolution.hxx" | | #include "convolution.hxx" | |
| #include "labelimage.hxx" | | #include "labelimage.hxx" | |
| #include "mathutil.hxx" | | #include "mathutil.hxx" | |
| #include "pixelneighborhood.hxx" | | #include "pixelneighborhood.hxx" | |
| #include "linear_solve.hxx" | | #include "linear_solve.hxx" | |
| #include "functorexpression.hxx" | | #include "functorexpression.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup EdgeDetection Edge Detection | | /** \addtogroup EdgeDetection Edge Detection | |
| Edge detectors based on first and second derivatives, | | Edge detectors based on first and second derivatives, | |
| and related post-processing. | | and related post-processing. | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| skipping to change at line 101 | | skipping to change at line 102 | |
| | | | |
| The source value type | | The source value type | |
| (<TT>SrcAccessor::value_type</TT>) must be a linear algebra, i.e. addit
ion, | | (<TT>SrcAccessor::value_type</TT>) must be a linear algebra, i.e. addit
ion, | |
| subtraction and multiplication of the type with itself, and multiplicat
ion | | subtraction and multiplication of the type with itself, and multiplicat
ion | |
| with double and | | with double and | |
| \ref NumericTraits "NumericTraits" must | | \ref NumericTraits "NumericTraits" must | |
| be defined. In addition, this type must be less-comparable. | | be defined. In addition, this type must be less-comparable. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class GradValue, class DestValue> | |
| | | void | |
| | | differenceOfExponentialEdgeImage(MultiArrayView<2, T1, S1> const & | |
| | | src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale, | |
| | | GradValue gradient_threshold, | |
| | | DestValue edge_marker = NumericTra | |
| | | its<DestValue>::one()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{differenceOfExponentialEdgeImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, | | class GradValue, | |
| class DestValue = DestAccessor::value_type> | | class DestValue = DestAccessor::value_type> | |
| void differenceOfExponentialEdgeImage( | | void differenceOfExponentialEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| double scale, GradValue gradient_threshold, | | double scale, GradValue gradient_threshold, | |
| DestValue edge_marker = NumericTraits<DestValue>::one()) | | DestValue edge_marker = NumericTraits<DestValue>::one()) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, | | class GradValue, | |
| class DestValue = DestAccessor::value_type> | | class DestValue = DestAccessor::value_type> | |
| void differenceOfExponentialEdgeImage( | | void differenceOfExponentialEdgeImage( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale, GradValue gradient_threshold, | | double scale, GradValue gradient_threshold, | |
| DestValue edge_marker = NumericTraits<DestValue>::one()) | | DestValue edge_marker = NumericTraits<DestValue>::one()) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h), edges(w,h); | |
| | | ... | |
| | | | |
| | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| | | differenceOfExponentialEdgeImage(src, edges, | |
| | | 0.8, 4.0, 1); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{differenceOfExponentialEdgeImage} | |
| | | \code | |
| vigra::BImage src(w,h), edges(w,h); | | vigra::BImage src(w,h), edges(w,h); | |
| | | | |
| // empty edge image | | // empty edge image | |
| edges = 0; | | edges = 0; | |
| ... | | ... | |
| | | | |
| // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| vigra::differenceOfExponentialEdgeImage(srcImageRange(src), destImage(e
dges), | | vigra::differenceOfExponentialEdgeImage(srcImageRange(src), destImage(e
dges), | |
| 0.8, 4.0, 1); | | 0.8, 4.0, 1); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| double d; | | double d; | |
| GradValue gradient_threshold; | | GradValue gradient_threshold; | |
| | | | |
| u = u + u | | u = u + u | |
| u = u - u | | u = u - u | |
| u = u * u | | u = u * u | |
| u = d * u | | u = d * u | |
| u < gradient_threshold | | u < gradient_threshold | |
| | | | |
| DestValue edge_marker; | | DestValue edge_marker; | |
| dest_accessor.set(edge_marker, dest_upperleft); | | dest_accessor.set(edge_marker, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| gradient_threshold > 0 | | gradient_threshold > 0 | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void differenceOfExponentialEdge
Image) | | doxygen_overloaded_function(template <...> void differenceOfExponentialEdge
Image) | |
| | | | |
| | | | |
| skipping to change at line 217 | | skipping to change at line 243 | |
| recursiveSmoothX(srcIterRange(sul, slr, sa), destImage(tmp), scale / 2.
0); | | recursiveSmoothX(srcIterRange(sul, slr, sa), destImage(tmp), scale / 2.
0); | |
| recursiveSmoothY(srcImageRange(tmp), destImage(tmp), scale / 2.0); | | recursiveSmoothY(srcImageRange(tmp), destImage(tmp), scale / 2.0); | |
| | | | |
| recursiveSmoothX(srcImageRange(tmp), destImage(smooth), scale); | | recursiveSmoothX(srcImageRange(tmp), destImage(smooth), scale); | |
| recursiveSmoothY(srcImageRange(smooth), destImage(smooth), scale); | | recursiveSmoothY(srcImageRange(smooth), destImage(smooth), scale); | |
| | | | |
| typename TMPIMG::Iterator iy = smooth.upperLeft(); | | typename TMPIMG::Iterator iy = smooth.upperLeft(); | |
| typename TMPIMG::Iterator ty = tmp.upperLeft(); | | typename TMPIMG::Iterator ty = tmp.upperLeft(); | |
| DestIterator dy = dul; | | DestIterator dy = dul; | |
| | | | |
|
| static const Diff2D right(1, 0); | | const Diff2D right(1, 0); | |
| static const Diff2D bottom(0, 1); | | const Diff2D bottom(0, 1); | |
| | | | |
| TMPTYPE thresh = detail::RequiresExplicitCast<TMPTYPE>::cast((gradient_
threshold * gradient_threshold) * | | TMPTYPE thresh = detail::RequiresExplicitCast<TMPTYPE>::cast((gradient_
threshold * gradient_threshold) * | |
| NumericTraits<TMPTYPE>::one()); | | NumericTraits<TMPTYPE>::one()); | |
| TMPTYPE zero = NumericTraits<TMPTYPE>::zero(); | | TMPTYPE zero = NumericTraits<TMPTYPE>::zero(); | |
| | | | |
| for(y=0; y<h-1; ++y, ++iy.y, ++ty.y, ++dy.y) | | for(y=0; y<h-1; ++y, ++iy.y, ++ty.y, ++dy.y) | |
| { | | { | |
| typename TMPIMG::Iterator ix = iy; | | typename TMPIMG::Iterator ix = iy; | |
| typename TMPIMG::Iterator tx = ty; | | typename TMPIMG::Iterator tx = ty; | |
| DestIterator dx = dy; | | DestIterator dx = dy; | |
| | | | |
| skipping to change at line 302 | | skipping to change at line 328 | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| double scale, GradValue gradient_threshold) | | double scale, GradValue gradient_threshold) | |
| { | | { | |
| differenceOfExponentialEdgeImage(sul, slr, sa, dul, da, | | differenceOfExponentialEdgeImage(sul, slr, sa, dul, da, | |
| scale, gradient_threshold, 1); | | scale, gradient_threshold, 1); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
|
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| inline | | inline void | |
| void differenceOfExponentialEdgeImage( | | differenceOfExponentialEdgeImage(triple<SrcIterator, SrcIterator, SrcAccess | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | or> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale, GradValue gradient_threshold, | | double scale, GradValue gradient_threshold | |
| DestValue edge_marker) | | , | |
| | | DestValue edge_marker) | |
| { | | { | |
| differenceOfExponentialEdgeImage(src.first, src.second, src.third, | | differenceOfExponentialEdgeImage(src.first, src.second, src.third, | |
|
| dest.first, dest.second, | | dest.first, dest.second, | |
| scale, gradient_threshold, | | scale, gradient_threshold, edge_marker | |
| edge_marker); | | ); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue> | | class GradValue> | |
|
| inline | | inline void | |
| void differenceOfExponentialEdgeImage( | | differenceOfExponentialEdgeImage(triple<SrcIterator, SrcIterator, SrcAccess | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | or> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale, GradValue gradient_threshold) | | double scale, GradValue gradient_threshold | |
| | | ) | |
| { | | { | |
| differenceOfExponentialEdgeImage(src.first, src.second, src.third, | | differenceOfExponentialEdgeImage(src.first, src.second, src.third, | |
|
| dest.first, dest.second, | | dest.first, dest.second, | |
| scale, gradient_threshold, 1); | | scale, gradient_threshold, 1); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class GradValue, class DestValue> | |
| | | inline void | |
| | | differenceOfExponentialEdgeImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale, | |
| | | GradValue gradient_threshold, | |
| | | DestValue edge_marker) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "differenceOfExponentialEdgeImage(): shape mismatch between input a | |
| | | nd output."); | |
| | | differenceOfExponentialEdgeImage(srcImageRange(src), | |
| | | destImage(dest), | |
| | | scale, gradient_threshold, edge_marker | |
| | | ); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class GradValue> | |
| | | inline void | |
| | | differenceOfExponentialEdgeImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale, GradValue gradient_threshold | |
| | | ) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "differenceOfExponentialEdgeImage(): shape mismatch between input a | |
| | | nd output."); | |
| | | differenceOfExponentialEdgeImage(srcImageRange(src), | |
| | | destImage(dest), | |
| | | scale, gradient_threshold, T2(1)); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* differenceOfExponentialCrackEdgeImage */ | | /* differenceOfExponentialCrackEdgeImage */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Detect and mark edges in a crack edge image using the Shen/Casta
n zero-crossing detector. | | /** \brief Detect and mark edges in a crack edge image using the Shen/Casta
n zero-crossing detector. | |
| | | | |
| | | | |
| skipping to change at line 352 | | skipping to change at line 407 | |
| an edge point is marked (using <TT>edge_marker</TT>) in the destination
image | | an edge point is marked (using <TT>edge_marker</TT>) in the destination
image | |
| <i>between</i> the corresponding original pixels. Topologically, this m
eans we | | <i>between</i> the corresponding original pixels. Topologically, this m
eans we | |
| must insert additional pixels between the original ones to represent th
e | | must insert additional pixels between the original ones to represent th
e | |
| boundaries between the pixels (the so called zero- and one-cells, with
the original | | boundaries between the pixels (the so called zero- and one-cells, with
the original | |
| pixels being two-cells). Within VIGRA, such an image is called \ref Cra
ckEdgeImage. | | pixels being two-cells). Within VIGRA, such an image is called \ref Cra
ckEdgeImage. | |
| To allow insertion of the zero- and one-cells, the destination image mu
st have twice the | | To allow insertion of the zero- and one-cells, the destination image mu
st have twice the | |
| size of the original (precisely, <TT>(2*w-1)</TT> by <TT>(2*h-1)</TT> p
ixels). Then the algorithm | | size of the original (precisely, <TT>(2*w-1)</TT> by <TT>(2*h-1)</TT> p
ixels). Then the algorithm | |
| proceeds as follows: | | proceeds as follows: | |
| | | | |
| \code | | \code | |
|
| sign of difference image insert zero- and one-cells resulting edge
points (*) | | sign of difference image insert zero- and one-cells resulting e
dge points (*) | |
| | | | |
|
| + . - . - . * . . . | | + . - . - . * . | |
| + - - . . . . . . * * * . | | . . | |
| + + - => + . + . - => . . . * . | | + - - . . . . . . * * | |
| + + + . . . . . . . . * * | | * . | |
| + . + . + . . . . . | | + + - => + . + . - => . . . | |
| | | * . | |
| | | + + + . . . . . . . . | |
| | | * * | |
| | | + . + . + . . . | |
| | | . . | |
| \endcode | | \endcode | |
| | | | |
| Thus the edge points are marked where they actually are - in between th
e pixels. | | Thus the edge points are marked where they actually are - in between th
e pixels. | |
| An important property of the resulting edge image is that it conforms t
o the notion | | An important property of the resulting edge image is that it conforms t
o the notion | |
| of well-composedness as defined by Latecki et al., i.e. connected regio
ns and edges | | of well-composedness as defined by Latecki et al., i.e. connected regio
ns and edges | |
| obtained by a subsequent \ref Labeling do not depend on | | obtained by a subsequent \ref Labeling do not depend on | |
| whether 4- or 8-connectivity is used. | | whether 4- or 8-connectivity is used. | |
| The non-edge pixels (<TT>.</TT>) in the destination image remain unchan
ged. | | The non-edge pixels (<TT>.</TT>) in the destination image remain unchan
ged. | |
| The result conforms to the requirements of a \ref CrackEdgeImage. It ca
n be further | | The result conforms to the requirements of a \ref CrackEdgeImage. It ca
n be further | |
| improved by the post-processing operations \ref removeShortEdges() and | | improved by the post-processing operations \ref removeShortEdges() and | |
| \ref closeGapsInCrackEdgeImage(). | | \ref closeGapsInCrackEdgeImage(). | |
| | | | |
| The source value type (<TT>SrcAccessor::value_type</TT>) must be a line
ar algebra, i.e. addition, | | The source value type (<TT>SrcAccessor::value_type</TT>) must be a line
ar algebra, i.e. addition, | |
| subtraction and multiplication of the type with itself, and multiplicat
ion | | subtraction and multiplication of the type with itself, and multiplicat
ion | |
| with double and | | with double and | |
| \ref NumericTraits "NumericTraits" must | | \ref NumericTraits "NumericTraits" must | |
| be defined. In addition, this type must be less-comparable. | | be defined. In addition, this type must be less-comparable. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class GradValue, class DestValue> | |
| | | void | |
| | | differenceOfExponentialCrackEdgeImage(MultiArrayView<2, T1, S1> con | |
| | | st & src, | |
| | | MultiArrayView<2, T2, S2> des | |
| | | t, | |
| | | double scale, | |
| | | GradValue gradient_threshold, | |
| | | DestValue edge_marker = Numer | |
| | | icTraits<DestValue>::one()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{differenceOfExponentialCrackEdgeImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, | | class GradValue, | |
| class DestValue = DestAccessor::value_type> | | class DestValue = DestAccessor::value_type> | |
| void differenceOfExponentialCrackEdgeImage( | | void differenceOfExponentialCrackEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| double scale, GradValue gradient_threshold, | | double scale, GradValue gradient_threshold, | |
| DestValue edge_marker = NumericTraits<DestValue>::one()) | | DestValue edge_marker = NumericTraits<DestValue>::one()) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, | | class GradValue, | |
| class DestValue = DestAccessor::value_type> | | class DestValue = DestAccessor::value_type> | |
| void differenceOfExponentialCrackEdgeImage( | | void differenceOfExponentialCrackEdgeImage( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale, GradValue gradient_threshold, | | double scale, GradValue gradient_threshold, | |
| DestValue edge_marker = NumericTraits<DestValue>::one()) | | DestValue edge_marker = NumericTraits<DestValue>::one()) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h), edges(2*w-1,2*h-1); | |
| | | ... | |
| | | | |
| | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| | | differenceOfExponentialCrackEdgeImage(src, edges, | |
| | | 0.8, 4.0, 1); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{differenceOfExponentialCrackEdgeImage} | |
| | | \code | |
| vigra::BImage src(w,h), edges(2*w-1,2*h-1); | | vigra::BImage src(w,h), edges(2*w-1,2*h-1); | |
| | | | |
| // empty edge image | | // empty edge image | |
| edges = 0; | | edges = 0; | |
| ... | | ... | |
| | | | |
| // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| vigra::differenceOfExponentialCrackEdgeImage(srcImageRange(src), destIm
age(edges), | | vigra::differenceOfExponentialCrackEdgeImage(srcImageRange(src), destIm
age(edges), | |
| 0.8, 4.0, 1); | | 0.8, 4.0, 1); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| double d; | | double d; | |
| GradValue gradient_threshold; | | GradValue gradient_threshold; | |
| | | | |
| u = u + u | | u = u + u | |
| u = u - u | | u = u - u | |
| u = u * u | | u = u * u | |
| u = d * u | | u = d * u | |
| u < gradient_threshold | | u < gradient_threshold | |
| | | | |
| DestValue edge_marker; | | DestValue edge_marker; | |
| dest_accessor.set(edge_marker, dest_upperleft); | | dest_accessor.set(edge_marker, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| gradient_threshold > 0 | | gradient_threshold > 0 | |
| \endcode | | \endcode | |
| | | | |
| The destination image must have twice the size of the source: | | The destination image must have twice the size of the source: | |
| \code | | \code | |
| | | | |
| skipping to change at line 494 | | skipping to change at line 574 | |
| typedef typename | | typedef typename | |
| NumericTraits<typename SrcAccessor::value_type>::RealPromote | | NumericTraits<typename SrcAccessor::value_type>::RealPromote | |
| TMPTYPE; | | TMPTYPE; | |
| typedef BasicImage<TMPTYPE> TMPIMG; | | typedef BasicImage<TMPTYPE> TMPIMG; | |
| | | | |
| TMPIMG tmp(w,h); | | TMPIMG tmp(w,h); | |
| TMPIMG smooth(w,h); | | TMPIMG smooth(w,h); | |
| | | | |
| TMPTYPE zero = NumericTraits<TMPTYPE>::zero(); | | TMPTYPE zero = NumericTraits<TMPTYPE>::zero(); | |
| | | | |
|
| static const Diff2D right(1,0); | | const Diff2D right(1,0); | |
| static const Diff2D bottom(0,1); | | const Diff2D bottom(0,1); | |
| static const Diff2D left(-1,0); | | const Diff2D left(-1,0); | |
| static const Diff2D top(0,-1); | | const Diff2D top(0,-1); | |
| | | | |
| recursiveSmoothX(srcIterRange(sul, slr, sa), destImage(tmp), scale / 2.
0); | | recursiveSmoothX(srcIterRange(sul, slr, sa), destImage(tmp), scale / 2.
0); | |
| recursiveSmoothY(srcImageRange(tmp), destImage(tmp), scale / 2.0); | | recursiveSmoothY(srcImageRange(tmp), destImage(tmp), scale / 2.0); | |
| | | | |
| recursiveSmoothX(srcImageRange(tmp), destImage(smooth), scale); | | recursiveSmoothX(srcImageRange(tmp), destImage(smooth), scale); | |
| recursiveSmoothY(srcImageRange(smooth), destImage(smooth), scale); | | recursiveSmoothY(srcImageRange(smooth), destImage(smooth), scale); | |
| | | | |
| typename TMPIMG::Iterator iy = smooth.upperLeft(); | | typename TMPIMG::Iterator iy = smooth.upperLeft(); | |
| typename TMPIMG::Iterator ty = tmp.upperLeft(); | | typename TMPIMG::Iterator ty = tmp.upperLeft(); | |
| DestIterator dy = dul; | | DestIterator dy = dul; | |
| | | | |
| skipping to change at line 547 | | skipping to change at line 627 | |
| TMPTYPE diff = *tx - *ix; | | TMPTYPE diff = *tx - *ix; | |
| TMPTYPE gy = tx[bottom] - *tx; | | TMPTYPE gy = tx[bottom] - *tx; | |
| | | | |
| if((gy * gy > thresh) && | | if((gy * gy > thresh) && | |
| (diff * (tx[bottom] - ix[bottom]) < zero)) | | (diff * (tx[bottom] - ix[bottom]) < zero)) | |
| { | | { | |
| da.set(edge_marker, dx, bottom); | | da.set(edge_marker, dx, bottom); | |
| } | | } | |
| } | | } | |
| | | | |
|
| typename TMPIMG::Iterator ix = iy; | | | |
| typename TMPIMG::Iterator tx = ty; | | | |
| DestIterator dx = dy; | | | |
| | | | |
| for(x=0; x<w-1; ++x, ++ix.x, ++tx.x, dx.x+=2) | | | |
| { | | { | |
|
| TMPTYPE diff = *tx - *ix; | | typename TMPIMG::Iterator ix = iy; | |
| TMPTYPE gx = tx[right] - *tx; | | typename TMPIMG::Iterator tx = ty; | |
| | | DestIterator dx = dy; | |
| | | | |
|
| if((gx * gx > thresh) && | | for(x=0; x<w-1; ++x, ++ix.x, ++tx.x, dx.x+=2) | |
| (diff * (tx[right] - ix[right]) < zero)) | | | |
| { | | { | |
|
| da.set(edge_marker, dx, right); | | TMPTYPE diff = *tx - *ix; | |
| | | TMPTYPE gx = tx[right] - *tx; | |
| | | | |
| | | if((gx * gx > thresh) && | |
| | | (diff * (tx[right] - ix[right]) < zero)) | |
| | | { | |
| | | da.set(edge_marker, dx, right); | |
| | | } | |
| } | | } | |
| } | | } | |
| | | | |
| iy = smooth.upperLeft() + Diff2D(0,1); | | iy = smooth.upperLeft() + Diff2D(0,1); | |
| ty = tmp.upperLeft() + Diff2D(0,1); | | ty = tmp.upperLeft() + Diff2D(0,1); | |
| dy = dul + Diff2D(1,2); | | dy = dul + Diff2D(1,2); | |
| | | | |
|
| static const Diff2D topleft(-1,-1); | | const Diff2D topleft(-1,-1); | |
| static const Diff2D topright(1,-1); | | const Diff2D topright(1,-1); | |
| static const Diff2D bottomleft(-1,1); | | const Diff2D bottomleft(-1,1); | |
| static const Diff2D bottomright(1,1); | | const Diff2D bottomright(1,1); | |
| | | | |
| // find missing 1-cells below threshold (x-direction) | | // find missing 1-cells below threshold (x-direction) | |
| for(y=0; y<h-2; ++y, ++iy.y, ++ty.y, dy.y+=2) | | for(y=0; y<h-2; ++y, ++iy.y, ++ty.y, dy.y+=2) | |
| { | | { | |
| typename TMPIMG::Iterator ix = iy; | | typename TMPIMG::Iterator ix = iy; | |
| typename TMPIMG::Iterator tx = ty; | | typename TMPIMG::Iterator tx = ty; | |
| DestIterator dx = dy; | | DestIterator dx = dy; | |
| | | | |
| for(int x=0; x<w-2; ++x, ++ix.x, ++tx.x, dx.x+=2) | | for(int x=0; x<w-2; ++x, ++ix.x, ++tx.x, dx.x+=2) | |
| { | | { | |
| | | | |
| skipping to change at line 635 | | skipping to change at line 717 | |
| | | | |
| dy = dul + Diff2D(1,1); | | dy = dul + Diff2D(1,1); | |
| | | | |
| // find missing 0-cells | | // find missing 0-cells | |
| for(y=0; y<h-1; ++y, dy.y+=2) | | for(y=0; y<h-1; ++y, dy.y+=2) | |
| { | | { | |
| DestIterator dx = dy; | | DestIterator dx = dy; | |
| | | | |
| for(int x=0; x<w-1; ++x, dx.x+=2) | | for(int x=0; x<w-1; ++x, dx.x+=2) | |
| { | | { | |
|
| static const Diff2D dist[] = {right, top, left, bottom }; | | const Diff2D dist[] = {right, top, left, bottom }; | |
| | | | |
| int i; | | int i; | |
| for(i=0; i<4; ++i) | | for(i=0; i<4; ++i) | |
| { | | { | |
| if(da(dx, dist[i]) == edge_marker) break; | | if(da(dx, dist[i]) == edge_marker) break; | |
| } | | } | |
| | | | |
| if(i < 4) da.set(edge_marker, dx); | | if(i < 4) da.set(edge_marker, dx); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
|
| inline | | inline void | |
| void differenceOfExponentialCrackEdgeImage( | | differenceOfExponentialCrackEdgeImage(triple<SrcIterator, SrcIterator, SrcA | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | ccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest | |
| double scale, GradValue gradient_threshold, | | , | |
| DestValue edge_marker) | | double scale, GradValue gradient_thre | |
| | | shold, | |
| | | DestValue edge_marker) | |
| { | | { | |
| differenceOfExponentialCrackEdgeImage(src.first, src.second, src.third, | | differenceOfExponentialCrackEdgeImage(src.first, src.second, src.third, | |
|
| dest.first, dest.second, | | dest.first, dest.second, | |
| scale, gradient_threshold, | | scale, gradient_threshold, edge_m | |
| edge_marker); | | arker); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class GradValue, class DestValue> | |
| | | inline void | |
| | | differenceOfExponentialCrackEdgeImage(MultiArrayView<2, T1, S1> const & src | |
| | | , | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale, | |
| | | GradValue gradient_threshold, | |
| | | DestValue edge_marker) | |
| | | { | |
| | | vigra_precondition(2*src.shape() - Shape2(1) == dest.shape(), | |
| | | "differenceOfExponentialCrackEdgeImage(): shape mismatch between in | |
| | | put and output."); | |
| | | differenceOfExponentialCrackEdgeImage(srcImageRange(src), | |
| | | destImage(dest), | |
| | | scale, gradient_threshold, edge_m | |
| | | arker); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* removeShortEdges */ | | /* removeShortEdges */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Remove short edges from an edge image. | | /** \brief Remove short edges from an edge image. | |
| | | | |
| | | | |
| skipping to change at line 689 | | skipping to change at line 786 | |
| | | | |
| If the source image fulfills the requirements of a \ref CrackEdgeImage, | | If the source image fulfills the requirements of a \ref CrackEdgeImage, | |
| it will still do so after application of this algorithm. | | it will still do so after application of this algorithm. | |
| | | | |
| Note that this algorithm, unlike most other algorithms in VIGRA, operat
es in-place, | | Note that this algorithm, unlike most other algorithms in VIGRA, operat
es in-place, | |
| i.e. on only one image. Also, the algorithm assumes that all non-edges
pixels are already | | i.e. on only one image. Also, the algorithm assumes that all non-edges
pixels are already | |
| marked with the given <TT>non_edge_marker</TT> value. | | marked with the given <TT>non_edge_marker</TT> value. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T, class S, class Value> | |
| | | void | |
| | | removeShortEdges(MultiArrayView<2, T, S> image, | |
| | | unsigned int min_edge_length, Value non_edge_marke | |
| | | r); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{removeShortEdges} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Iterator, class Accessor, class SrcValue> | | template <class Iterator, class Accessor, class SrcValue> | |
| void removeShortEdges( | | void removeShortEdges( | |
| Iterator sul, Iterator slr, Accessor sa, | | Iterator sul, Iterator slr, Accessor sa, | |
| int min_edge_length, SrcValue non_edge_marker) | | int min_edge_length, SrcValue non_edge_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Iterator, class Accessor, class SrcValue> | | template <class Iterator, class Accessor, class SrcValue> | |
| void removeShortEdges( | | void removeShortEdges( | |
| triple<Iterator, Iterator, Accessor> src, | | triple<Iterator, Iterator, Accessor> src, | |
| int min_edge_length, SrcValue non_edge_marker) | | int min_edge_length, SrcValue non_edge_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h), edges(w,h); | |
| | | ... | |
| | | | |
| | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| | | differenceOfExponentialEdgeImage(src, edges, | |
| | | 0.8, 4.0, 1); | |
| | | | |
| | | // zero edges shorter than 10 pixels | |
| | | removeShortEdges(edges, 10, 0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{removeShortEdges} | |
| | | \code | |
| vigra::BImage src(w,h), edges(w,h); | | vigra::BImage src(w,h), edges(w,h); | |
| | | | |
| // empty edge image | | // empty edge image | |
| edges = 0; | | edges = 0; | |
| ... | | ... | |
| | | | |
| // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| vigra::differenceOfExponentialEdgeImage(srcImageRange(src), destImage(e
dges), | | vigra::differenceOfExponentialEdgeImage(srcImageRange(src), destImage(e
dges), | |
| 0.8, 4.0, 1); | | 0.8, 4.0, 1); | |
| | | | |
| // zero edges shorter than 10 pixels | | // zero edges shorter than 10 pixels | |
| vigra::removeShortEdges(srcImageRange(edges), 10, 0); | | vigra::removeShortEdges(srcImageRange(edges), 10, 0); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| u == u | | u == u | |
| | | | |
| SrcValue non_edge_marker; | | SrcValue non_edge_marker; | |
| src_accessor.set(non_edge_marker, src_upperleft); | | src_accessor.set(non_edge_marker, src_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void removeShortEdges) | | doxygen_overloaded_function(template <...> void removeShortEdges) | |
| | | | |
| template <class Iterator, class Accessor, class Value> | | template <class Iterator, class Accessor, class Value> | |
| void removeShortEdges( | | void removeShortEdges( | |
| Iterator sul, Iterator slr, Accessor sa, | | Iterator sul, Iterator slr, Accessor sa, | |
| unsigned int min_edge_length, Value non_edge_marker) | | unsigned int min_edge_length, Value non_edge_marker) | |
| { | | { | |
| int w = slr.x - sul.x; | | int w = slr.x - sul.x; | |
| int h = slr.y - sul.y; | | int h = slr.y - sul.y; | |
| | | | |
| skipping to change at line 789 | | skipping to change at line 909 | |
| if(sa(ox) == non_edge_marker) continue; | | if(sa(ox) == non_edge_marker) continue; | |
| if((region_stats[*lx].count) < min_edge_length) | | if((region_stats[*lx].count) < min_edge_length) | |
| { | | { | |
| sa.set(non_edge_marker, ox); | | sa.set(non_edge_marker, ox); | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class Iterator, class Accessor, class Value> | | template <class Iterator, class Accessor, class Value> | |
|
| inline | | inline void | |
| void removeShortEdges( | | removeShortEdges(triple<Iterator, Iterator, Accessor> src, | |
| triple<Iterator, Iterator, Accessor> src, | | unsigned int min_edge_length, Value non_edge_marker) | |
| unsigned int min_edge_length, Value non_edge_marker) | | | |
| { | | { | |
| removeShortEdges(src.first, src.second, src.third, | | removeShortEdges(src.first, src.second, src.third, | |
| min_edge_length, non_edge_marker); | | min_edge_length, non_edge_marker); | |
| } | | } | |
| | | | |
|
| | | template <class T, class S, class Value> | |
| | | inline void | |
| | | removeShortEdges(MultiArrayView<2, T, S> image, | |
| | | unsigned int min_edge_length, Value non_edge_marker) | |
| | | { | |
| | | removeShortEdges(destImageRange(image), | |
| | | min_edge_length, non_edge_marker); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* closeGapsInCrackEdgeImage */ | | /* closeGapsInCrackEdgeImage */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Close one-pixel wide gaps in a cell grid edge image. | | /** \brief Close one-pixel wide gaps in a cell grid edge image. | |
| | | | |
| This algorithm is typically applied as a post-processing operation of | | This algorithm is typically applied as a post-processing operation of | |
| \ref differenceOfExponentialCrackEdgeImage(). The source image must ful
fill | | \ref differenceOfExponentialCrackEdgeImage(). The source image must ful
fill | |
| | | | |
| skipping to change at line 822 | | skipping to change at line 950 | |
| Since these gaps are usually caused by zero crossing slightly below the
gradient | | Since these gaps are usually caused by zero crossing slightly below the
gradient | |
| threshold used in edge detection, this algorithms acts like a weak hyst
eresis | | threshold used in edge detection, this algorithms acts like a weak hyst
eresis | |
| thresholding. The newly found edge pixels are marked with the given <TT
>edge_marker</TT>. | | thresholding. The newly found edge pixels are marked with the given <TT
>edge_marker</TT>. | |
| The image's value type must be equality comparable. | | The image's value type must be equality comparable. | |
| | | | |
| Note that this algorithm, unlike most other algorithms in VIGRA, operat
es in-place, | | Note that this algorithm, unlike most other algorithms in VIGRA, operat
es in-place, | |
| i.e. on only one image. | | i.e. on only one image. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T, class S, class Value> | |
| | | void | |
| | | closeGapsInCrackEdgeImage(MultiArrayView<2, T, S> image, Value edge | |
| | | _marker); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{closeGapsInCrackEdgeImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, class SrcValue> | | template <class SrcIterator, class SrcAccessor, class SrcValue> | |
| void closeGapsInCrackEdgeImage( | | void closeGapsInCrackEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| SrcValue edge_marker) | | SrcValue edge_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, class SrcValue> | | template <class SrcIterator, class SrcAccessor, class SrcValue> | |
| void closeGapsInCrackEdgeImage( | | void closeGapsInCrackEdgeImage( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| SrcValue edge_marker) | | SrcValue edge_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h), edges(2*w-1, 2*h-1); | |
| | | ... | |
| | | | |
| | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| | | differenceOfExponentialCrackEdgeImage(src, edges, | |
| | | 0.8, 4.0, 1); | |
| | | | |
| | | // close gaps, mark with 1 | |
| | | closeGapsInCrackEdgeImage(edges, 1); | |
| | | | |
| | | // zero edges shorter than 20 pixels | |
| | | removeShortEdges(edges, 10, 0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{closeGapsInCrackEdgeImage} | |
| | | \code | |
| vigra::BImage src(w,h), edges(2*w-1, 2*h-1); | | vigra::BImage src(w,h), edges(2*w-1, 2*h-1); | |
| | | | |
| // empty edge image | | // empty edge image | |
| edges = 0; | | edges = 0; | |
| ... | | ... | |
| | | | |
| // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| vigra::differenceOfExponentialCrackEdgeImage(srcImageRange(src), destIm
age(edges), | | vigra::differenceOfExponentialCrackEdgeImage(srcImageRange(src), destIm
age(edges), | |
| 0.8, 4.0, 1); | | 0.8, 4.0, 1); | |
| | | | |
| // close gaps, mark with 1 | | // close gaps, mark with 1 | |
| vigra::closeGapsInCrackEdgeImage(srcImageRange(edges), 1); | | vigra::closeGapsInCrackEdgeImage(srcImageRange(edges), 1); | |
| | | | |
| // zero edges shorter than 20 pixels | | // zero edges shorter than 20 pixels | |
| vigra::removeShortEdges(srcImageRange(edges), 10, 0); | | vigra::removeShortEdges(srcImageRange(edges), 10, 0); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| u == u | | u == u | |
| u != u | | u != u | |
| | | | |
| SrcValue edge_marker; | | SrcValue edge_marker; | |
| src_accessor.set(edge_marker, src_upperleft); | | src_accessor.set(edge_marker, src_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void closeGapsInCrackEdgeImage) | | doxygen_overloaded_function(template <...> void closeGapsInCrackEdgeImage) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class SrcValue> | | template <class SrcIterator, class SrcAccessor, class SrcValue> | |
| void closeGapsInCrackEdgeImage( | | void closeGapsInCrackEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| SrcValue edge_marker) | | SrcValue edge_marker) | |
| { | | { | |
| int w = slr.x - sul.x; | | int w = slr.x - sul.x; | |
| int h = slr.y - sul.y; | | int h = slr.y - sul.y; | |
| | | | |
| vigra_precondition(w % 2 == 1 && h % 2 == 1, | | vigra_precondition(w % 2 == 1 && h % 2 == 1, | |
| "closeGapsInCrackEdgeImage(): Input is not a crack edge image (must
have odd-numbered shape)."); | | "closeGapsInCrackEdgeImage(): Input is not a crack edge image (must
have odd-numbered shape)."); | |
| | | | |
| int w2 = w / 2, h2 = h / 2, x, y; | | int w2 = w / 2, h2 = h / 2, x, y; | |
| | | | |
| int count1, count2, count3; | | int count1, count2, count3; | |
| | | | |
|
| static const Diff2D right(1,0); | | const Diff2D right(1,0); | |
| static const Diff2D bottom(0,1); | | const Diff2D bottom(0,1); | |
| static const Diff2D left(-1,0); | | const Diff2D left(-1,0); | |
| static const Diff2D top(0,-1); | | const Diff2D top(0,-1); | |
| | | | |
| static const Diff2D leftdist[] = { | | const Diff2D leftdist[] = { Diff2D(0, 0), Diff2D(-1, 1), Diff2D(-2, 0), | |
| Diff2D(0, 0), Diff2D(-1, 1), Diff2D(-2, 0), Diff2D(-1, -1)}; | | Diff2D(-1, -1)}; | |
| static const Diff2D rightdist[] = { | | const Diff2D rightdist[] = { Diff2D(2, 0), Diff2D(1, 1), Diff2D(0, 0), | |
| Diff2D(2, 0), Diff2D(1, 1), Diff2D(0, 0), Diff2D(1, -1)}; | | Diff2D(1, -1)}; | |
| static const Diff2D topdist[] = { | | const Diff2D topdist[] = { Diff2D(1, -1), Diff2D(0, 0), Diff2D(-1, -1), | |
| Diff2D(1, -1), Diff2D(0, 0), Diff2D(-1, -1), Diff2D(0, -2)}; | | Diff2D(0, -2)}; | |
| static const Diff2D bottomdist[] = { | | const Diff2D bottomdist[] = { Diff2D(1, 1), Diff2D(0, 2), Diff2D(-1, 1) | |
| Diff2D(1, 1), Diff2D(0, 2), Diff2D(-1, 1), Diff2D(0, 0)}; | | , Diff2D(0, 0)}; | |
| | | | |
| int i; | | int i; | |
| | | | |
| SrcIterator sy = sul + Diff2D(0,1); | | SrcIterator sy = sul + Diff2D(0,1); | |
| SrcIterator sx; | | SrcIterator sx; | |
| | | | |
| // close 1-pixel wide gaps (x-direction) | | // close 1-pixel wide gaps (x-direction) | |
| for(y=0; y<h2; ++y, sy.y+=2) | | for(y=0; y<h2; ++y, sy.y+=2) | |
| { | | { | |
| sx = sy + Diff2D(2,0); | | sx = sy + Diff2D(2,0); | |
| | | | |
| skipping to change at line 996 | | skipping to change at line 1145 | |
| | | | |
| if(count1 <= 1 || count2 <= 1 || count3 == 15) | | if(count1 <= 1 || count2 <= 1 || count3 == 15) | |
| { | | { | |
| sa.set(edge_marker, sx); | | sa.set(edge_marker, sx); | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class SrcValue> | | template <class SrcIterator, class SrcAccessor, class SrcValue> | |
|
| inline | | inline void | |
| void closeGapsInCrackEdgeImage( | | closeGapsInCrackEdgeImage(triple<SrcIterator, SrcIterator, SrcAccessor> src | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | , | |
| SrcValue edge_marker) | | SrcValue edge_marker) | |
| { | | { | |
| closeGapsInCrackEdgeImage(src.first, src.second, src.third, | | closeGapsInCrackEdgeImage(src.first, src.second, src.third, | |
|
| edge_marker); | | edge_marker); | |
| | | } | |
| | | | |
| | | template <class T, class S, class Value> | |
| | | inline void | |
| | | closeGapsInCrackEdgeImage(MultiArrayView<2, T, S> image, Value edge_marker) | |
| | | { | |
| | | closeGapsInCrackEdgeImage(destImageRange(image), edge_marker); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* beautifyCrackEdgeImage */ | | /* beautifyCrackEdgeImage */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Beautify crack edge image for visualization. | | /** \brief Beautify crack edge image for visualization. | |
| | | | |
| | | | |
| skipping to change at line 1039 | | skipping to change at line 1194 | |
| Therefore, this algorithm should only be applied as a visualization aid
, i.e. | | Therefore, this algorithm should only be applied as a visualization aid
, i.e. | |
| for human inspection. The algorithm assumes that edges are marked with
<TT>edge_marker</TT>, | | for human inspection. The algorithm assumes that edges are marked with
<TT>edge_marker</TT>, | |
| and background pixels with <TT>background_marker</TT>. The image's valu
e type must be | | and background pixels with <TT>background_marker</TT>. The image's valu
e type must be | |
| equality comparable. | | equality comparable. | |
| | | | |
| Note that this algorithm, unlike most other algorithms in VIGRA, operat
es in-place, | | Note that this algorithm, unlike most other algorithms in VIGRA, operat
es in-place, | |
| i.e. on only one image. | | i.e. on only one image. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T, class S, class Value> | |
| | | void | |
| | | beautifyCrackEdgeImage(MultiArrayView<2, T, S> image, | |
| | | Value edge_marker, Value background_marker); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{beautifyCrackEdgeImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, class SrcValue> | | template <class SrcIterator, class SrcAccessor, class SrcValue> | |
| void beautifyCrackEdgeImage( | | void beautifyCrackEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| SrcValue edge_marker, SrcValue background_marker) | | SrcValue edge_marker, SrcValue background_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, class SrcValue> | | template <class SrcIterator, class SrcAccessor, class SrcValue> | |
| void beautifyCrackEdgeImage( | | void beautifyCrackEdgeImage( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| SrcValue edge_marker, SrcValue background_marker) | | SrcValue edge_marker, SrcValue background_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h), edges(2*w-1, 2*h-1); | |
| | | ... | |
| | | | |
| | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| | | differenceOfExponentialCrackEdgeImage(src, edges, | |
| | | 0.8, 4.0, 1); | |
| | | | |
| | | // beautify edge image for visualization | |
| | | beautifyCrackEdgeImage(edges, 1, 0); | |
| | | | |
| | | // show to the user ('window' is an unspecified GUI widget to display V | |
| | | IGRA images) | |
| | | window.open(edges); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{beautifyCrackEdgeImage} | |
| | | \code | |
| vigra::BImage src(w,h), edges(2*w-1, 2*h-1); | | vigra::BImage src(w,h), edges(2*w-1, 2*h-1); | |
| | | | |
| // empty edge image | | // empty edge image | |
| edges = 0; | | edges = 0; | |
| ... | | ... | |
| | | | |
| // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| vigra::differenceOfExponentialCrackEdgeImage(srcImageRange(src), destIm
age(edges), | | vigra::differenceOfExponentialCrackEdgeImage(srcImageRange(src), destIm
age(edges), | |
| 0.8, 4.0, 1); | | 0.8, 4.0, 1); | |
| | | | |
| // beautify edge image for visualization | | // beautify edge image for visualization | |
| vigra::beautifyCrackEdgeImage(destImageRange(edges), 1, 0); | | vigra::beautifyCrackEdgeImage(destImageRange(edges), 1, 0); | |
| | | | |
| // show to the user | | // show to the user | |
| window.open(edges); | | window.open(edges); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| u == u | | u == u | |
| u != u | | u != u | |
| | | | |
| SrcValue background_marker; | | SrcValue background_marker; | |
| src_accessor.set(background_marker, src_upperleft); | | src_accessor.set(background_marker, src_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void beautifyCrackEdgeImage) | | doxygen_overloaded_function(template <...> void beautifyCrackEdgeImage) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class SrcValue> | | template <class SrcIterator, class SrcAccessor, class SrcValue> | |
| void beautifyCrackEdgeImage( | | void beautifyCrackEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| SrcValue edge_marker, SrcValue background_marker) | | SrcValue edge_marker, SrcValue background_marker) | |
| { | | { | |
| int w = slr.x - sul.x; | | int w = slr.x - sul.x; | |
| int h = slr.y - sul.y; | | int h = slr.y - sul.y; | |
| | | | |
| vigra_precondition(w % 2 == 1 && h % 2 == 1, | | vigra_precondition(w % 2 == 1 && h % 2 == 1, | |
| "beautifyCrackEdgeImage(): Input is not a crack edge image (must ha
ve odd-numbered shape)."); | | "beautifyCrackEdgeImage(): Input is not a crack edge image (must ha
ve odd-numbered shape)."); | |
| | | | |
| int w2 = w / 2, h2 = h / 2, x, y; | | int w2 = w / 2, h2 = h / 2, x, y; | |
| | | | |
| SrcIterator sy = sul + Diff2D(1,1); | | SrcIterator sy = sul + Diff2D(1,1); | |
| SrcIterator sx; | | SrcIterator sx; | |
| | | | |
|
| static const Diff2D right(1,0); | | const Diff2D right(1,0); | |
| static const Diff2D bottom(0,1); | | const Diff2D bottom(0,1); | |
| static const Diff2D left(-1,0); | | const Diff2D left(-1,0); | |
| static const Diff2D top(0,-1); | | const Diff2D top(0,-1); | |
| | | | |
| // delete 0-cells at corners | | // delete 0-cells at corners | |
| for(y=0; y<h2; ++y, sy.y+=2) | | for(y=0; y<h2; ++y, sy.y+=2) | |
| { | | { | |
| sx = sy; | | sx = sy; | |
| | | | |
| for(x=0; x<w2; ++x, sx.x+=2) | | for(x=0; x<w2; ++x, sx.x+=2) | |
| { | | { | |
| if(sa(sx) != edge_marker) continue; | | if(sa(sx) != edge_marker) continue; | |
| | | | |
| if(sa(sx, right) == edge_marker && sa(sx, left) == edge_marker)
continue; | | if(sa(sx, right) == edge_marker && sa(sx, left) == edge_marker)
continue; | |
| if(sa(sx, bottom) == edge_marker && sa(sx, top) == edge_marker)
continue; | | if(sa(sx, bottom) == edge_marker && sa(sx, top) == edge_marker)
continue; | |
| | | | |
| sa.set(background_marker, sx); | | sa.set(background_marker, sx); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class SrcValue> | | template <class SrcIterator, class SrcAccessor, class SrcValue> | |
|
| inline | | inline void | |
| void beautifyCrackEdgeImage( | | beautifyCrackEdgeImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | SrcValue edge_marker, SrcValue background_marker) | |
| SrcValue edge_marker, SrcValue background_marker) | | | |
| { | | { | |
| beautifyCrackEdgeImage(src.first, src.second, src.third, | | beautifyCrackEdgeImage(src.first, src.second, src.third, | |
|
| edge_marker, background_marker); | | edge_marker, background_marker); | |
| | | } | |
| | | | |
| | | template <class T, class S, class Value> | |
| | | inline void | |
| | | beautifyCrackEdgeImage(MultiArrayView<2, T, S> image, | |
| | | Value edge_marker, Value background_marker) | |
| | | { | |
| | | beautifyCrackEdgeImage(destImageRange(image), | |
| | | edge_marker, background_marker); | |
| } | | } | |
| | | | |
| /** Helper class that stores edgel attributes. | | /** Helper class that stores edgel attributes. | |
| */ | | */ | |
| class Edgel | | class Edgel | |
| { | | { | |
| public: | | public: | |
| | | | |
| /** The type of an Edgel's members. | | /** The type of an Edgel's members. | |
| */ | | */ | |
| | | | |
| skipping to change at line 1171 | | skipping to change at line 1360 | |
| value_type x; | | value_type x; | |
| | | | |
| /** The edgel's sub-pixel y coordinate. | | /** The edgel's sub-pixel y coordinate. | |
| */ | | */ | |
| value_type y; | | value_type y; | |
| | | | |
| /** The edgel's strength (magnitude of the gradient vector). | | /** The edgel's strength (magnitude of the gradient vector). | |
| */ | | */ | |
| value_type strength; | | value_type strength; | |
| | | | |
|
| /** | | /** \brief The edgel's orientation. | |
| The edgel's orientation. This is the clockwise angle in radians | | | |
| | | This is the clockwise angle in radians | |
| between the x-axis and the edge, so that the bright side of the | | between the x-axis and the edge, so that the bright side of the | |
| edge is on the left when one looks along the orientation vector. | | edge is on the left when one looks along the orientation vector. | |
| The angle is measured clockwise because the y-axis increases | | The angle is measured clockwise because the y-axis increases | |
| downwards (left-handed coordinate system): | | downwards (left-handed coordinate system): | |
| | | | |
| \code | | \code | |
| | | | |
|
| edgel axis | | edgel axis | |
| \ | | \ | |
| (dark \ (bright side) | | (dark \ (bright side) | |
| side) \ | | side) \ | |
| \ | | \ | |
| +------------> x-axis | | +------------> x-axis | |
| |\ | | | |\ | | |
| | \ /_/ orientation angle | | | \ /_/ orientation angle | |
| | \\ | | | \\ | |
| | \ | | | \ | |
| | | | | | |
| y-axis V | | y-axis V | |
| \endcode | | \endcode | |
| | | | |
| So, for example a vertical edge with its dark side on the left | | So, for example a vertical edge with its dark side on the left | |
| has orientation PI/2, and a horizontal edge with dark side on top | | has orientation PI/2, and a horizontal edge with dark side on top | |
| has orientation PI. Obviously, the edge's orientation changes | | has orientation PI. Obviously, the edge's orientation changes | |
| by PI if the contrast is reversed. | | by PI if the contrast is reversed. | |
| | | | |
| Note that this convention changed as of VIGRA version 1.7.0. | | Note that this convention changed as of VIGRA version 1.7.0. | |
| | | | |
| */ | | */ | |
| | | | |
| skipping to change at line 1295 | | skipping to change at line 1485 | |
| larger gradient magnitude than its two neighbors in gradient direction | | larger gradient magnitude than its two neighbors in gradient direction | |
| (where the direction is rounded into octants). If this is the case, | | (where the direction is rounded into octants). If this is the case, | |
| a new \ref Edgel is appended to the given vector of <TT>edgels</TT>. Th
e subpixel | | a new \ref Edgel is appended to the given vector of <TT>edgels</TT>. Th
e subpixel | |
| edgel position is determined by fitting a parabola to the three gradien
t | | edgel position is determined by fitting a parabola to the three gradien
t | |
| magnitude values mentioned above. The sub-pixel location of the parabol
a's tip | | magnitude values mentioned above. The sub-pixel location of the parabol
a's tip | |
| and the gradient magnitude and direction (from the pixel center) | | and the gradient magnitude and direction (from the pixel center) | |
| are written in the newly created edgel. | | are written in the newly created edgel. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // compute edgels from a scalar image (determine gradient internall | |
| | | y at 'scale') | |
| | | template <class T, class S, class BackInsertable> | |
| | | void | |
| | | cannyEdgelList(MultiArrayView<2, T, S> const & src, | |
| | | BackInsertable & edgels, | |
| | | double scale); | |
| | | | |
| | | // compute edgels from a pre-computed gradient image | |
| | | template <class T, class S, class BackInsertable> | |
| | | void | |
| | | cannyEdgelList(MultiArrayView<2, TinyVector<T, 2>, S> const & src, | |
| | | BackInsertable & edgels); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{cannyEdgelList} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // compute edgels from a gradient image | | // compute edgels from a gradient image | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void | | void | |
| cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src, | | cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src, | |
| BackInsertable & edgels); | | BackInsertable & edgels); | |
| | | | |
| // compute edgels from a scalar image (determine gradient internall
y at 'scale') | | // compute edgels from a scalar image (determine gradient internall
y at 'scale') | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void | | void | |
| cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src, | | cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src, | |
| BackInsertable & edgels, double scale); | | BackInsertable & edgels, double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // compute edgels from a gradient image | | // compute edgels from a gradient image | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void | | void | |
| cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| BackInsertable & edgels); | | BackInsertable & edgels); | |
| | | | |
| // compute edgels from a scalar image (determine gradient internall
y at 'scale') | | // compute edgels from a scalar image (determine gradient internall
y at 'scale') | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void | | void | |
| cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| BackInsertable & edgels, double scale); | | BackInsertable & edgels, double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h); | |
| | | | |
| | | // create empty edgel list | |
| | | std::vector<vigra::Edgel> edgels; | |
| | | ... | |
| | | | |
| | | // find edgels at scale 0.8 | |
| | | cannyEdgelList(src, edgels, 0.8); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{cannyEdgelList} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| | | | |
| // empty edgel list | | // empty edgel list | |
| std::vector<vigra::Edgel> edgels; | | std::vector<vigra::Edgel> edgels; | |
| ... | | ... | |
| | | | |
| // find edgels at scale 0.8 | | // find edgels at scale 0.8 | |
| vigra::cannyEdgelList(srcImageRange(src), edgels, 0.8); | | vigra::cannyEdgelList(srcImageRange(src), edgels, 0.8); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft; | | SrcImageIterator src_upperleft; | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| | | | |
| src_accessor(src_upperleft); | | src_accessor(src_upperleft); | |
| | | | |
| BackInsertable edgels; | | BackInsertable edgels; | |
| edgels.push_back(Edgel()); | | edgels.push_back(Edgel()); | |
| \endcode | | \endcode | |
|
| | | | |
| SrcAccessor::value_type must be a type convertible to float | | SrcAccessor::value_type must be a type convertible to float | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void cannyEdgelList) | | doxygen_overloaded_function(template <...> void cannyEdgelList) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
| | | | |
| skipping to change at line 1380 | | skipping to change at line 1599 | |
| BackInsertable & edgels, double scale) | | BackInsertable & edgels, double scale) | |
| { | | { | |
| typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | | typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | |
| BasicImage<TinyVector<TmpType, 2> > grad(lr-ul); | | BasicImage<TinyVector<TmpType, 2> > grad(lr-ul); | |
| gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale); | | gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale); | |
| | | | |
| cannyEdgelList(srcImageRange(grad), edgels); | | cannyEdgelList(srcImageRange(grad), edgels); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
|
| inline void | | | |
| cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | | |
| BackInsertable & edgels, double scale) | | | |
| { | | | |
| cannyEdgelList(src.first, src.second, src.third, edgels, scale); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | | |
| void | | void | |
| cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src, | | cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src, | |
| BackInsertable & edgels) | | BackInsertable & edgels) | |
| { | | { | |
| using namespace functor; | | using namespace functor; | |
| | | | |
| typedef typename SrcAccessor::value_type SrcType; | | typedef typename SrcAccessor::value_type SrcType; | |
| typedef typename NumericTraits<typename SrcType::value_type>::RealPromo
te TmpType; | | typedef typename NumericTraits<typename SrcType::value_type>::RealPromo
te TmpType; | |
| BasicImage<TmpType> magnitude(lr-ul); | | BasicImage<TmpType> magnitude(lr-ul); | |
| transformImage(srcIterRange(ul, lr, src), destImage(magnitude), norm(Ar
g1())); | | transformImage(srcIterRange(ul, lr, src), destImage(magnitude), norm(Ar
g1())); | |
| | | | |
| // find edgels | | // find edgels | |
| internalCannyFindEdgels(ul, src, magnitude, edgels, NumericTraits<TmpTy
pe>::zero()); | | internalCannyFindEdgels(ul, src, magnitude, edgels, NumericTraits<TmpTy
pe>::zero()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
| inline void | | inline void | |
| cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| | | BackInsertable & edgels, double scale) | |
| | | { | |
| | | cannyEdgelList(src.first, src.second, src.third, edgels, scale); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
| | | inline void | |
| | | cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| BackInsertable & edgels) | | BackInsertable & edgels) | |
| { | | { | |
| cannyEdgelList(src.first, src.second, src.third, edgels); | | cannyEdgelList(src.first, src.second, src.third, edgels); | |
| } | | } | |
| | | | |
|
| | | template <class T, class S, class BackInsertable> | |
| | | inline void | |
| | | cannyEdgelList(MultiArrayView<2, T, S> const & src, | |
| | | BackInsertable & edgels, double scale) | |
| | | { | |
| | | cannyEdgelList(srcImageRange(src), edgels, scale); | |
| | | } | |
| | | | |
| | | template <class T, class S, class BackInsertable> | |
| | | inline void | |
| | | cannyEdgelList(MultiArrayView<2, TinyVector<T, 2>, S> const & src, | |
| | | BackInsertable & edgels) | |
| | | { | |
| | | cannyEdgelList(srcImageRange(src), edgels); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* cannyEdgelListThreshold */ | | /* cannyEdgelListThreshold */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Canny's edge detector with thresholding. | | /** \brief Canny's edge detector with thresholding. | |
| | | | |
| This function works exactly like \ref cannyEdgelList(), but | | This function works exactly like \ref cannyEdgelList(), but | |
| you also pass a threshold for the minimal gradient magnitude, | | you also pass a threshold for the minimal gradient magnitude, | |
| so that edgels whose strength is below the threshold are not | | so that edgels whose strength is below the threshold are not | |
| inserted into the edgel list. | | inserted into the edgel list. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // compute edgels from a scalar image (determine gradient internall | |
| | | y at 'scale') | |
| | | template <class T, class S, | |
| | | class BackInsertable, class GradValue> | |
| | | void | |
| | | cannyEdgelListThreshold(MultiArrayView<2, T, S> const & src, | |
| | | BackInsertable & edgels, | |
| | | double scale, | |
| | | GradValue grad_threshold); | |
| | | | |
| | | // compute edgels from a pre-computed gradient image | |
| | | template <class T, class S, | |
| | | class BackInsertable, class GradValue> | |
| | | void | |
| | | cannyEdgelListThreshold(MultiArrayView<2, TinyVector<T, 2>, S> cons | |
| | | t & src, | |
| | | BackInsertable & edgels, | |
| | | GradValue grad_threshold); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{cannyEdgelListThreshold} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // compute edgels from a gradient image | | // compute edgels from a gradient image | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| void | | void | |
| cannyEdgelListThreshold(SrcIterator ul, SrcIterator lr, SrcAccessor
src, | | cannyEdgelListThreshold(SrcIterator ul, SrcIterator lr, SrcAccessor
src, | |
| BackInsertable & edgels, GradValue grad_thr
eshold); | | BackInsertable & edgels, GradValue grad_thr
eshold); | |
| | | | |
| // compute edgels from a scalar image (determine gradient internall
y at 'scale') | | // compute edgels from a scalar image (determine gradient internall
y at 'scale') | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| void | | void | |
| cannyEdgelListThreshold(SrcIterator ul, SrcIterator lr, SrcAccessor
src, | | cannyEdgelListThreshold(SrcIterator ul, SrcIterator lr, SrcAccessor
src, | |
| BackInsertable & edgels, double scale, Grad
Value grad_threshold); | | BackInsertable & edgels, double scale, Grad
Value grad_threshold); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // compute edgels from a gradient image | | // compute edgels from a gradient image | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| void | | void | |
| cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | | cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | |
| BackInsertable & edgels, GradValue grad_thr
eshold); | | BackInsertable & edgels, GradValue grad_thr
eshold); | |
| | | | |
| // compute edgels from a scalar image (determine gradient internall
y at 'scale') | | // compute edgels from a scalar image (determine gradient internall
y at 'scale') | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| void | | void | |
| cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | | cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | |
| BackInsertable & edgels, double scale, Grad
Value grad_threshold); | | BackInsertable & edgels, double scale, Grad
Value grad_threshold); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h); | |
| | | | |
| | | // create empty edgel list | |
| | | std::vector<vigra::Edgel> edgels; | |
| | | ... | |
| | | | |
| | | // find edgels at scale 0.8, only considering gradient magnitudes above | |
| | | 2.0 | |
| | | cannyEdgelListThreshold(src, edgels, 0.8, 2.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{cannyEdgelListThreshold} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| | | | |
| // empty edgel list | | // empty edgel list | |
| std::vector<vigra::Edgel> edgels; | | std::vector<vigra::Edgel> edgels; | |
| ... | | ... | |
| | | | |
| // find edgels at scale 0.8, only considering gradient above 2.0 | | // find edgels at scale 0.8, only considering gradient above 2.0 | |
| vigra::cannyEdgelListThreshold(srcImageRange(src), edgels, 0.8, 2.0); | | vigra::cannyEdgelListThreshold(srcImageRange(src), edgels, 0.8, 2.0); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft; | | SrcImageIterator src_upperleft; | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| | | | |
| src_accessor(src_upperleft); | | src_accessor(src_upperleft); | |
| | | | |
| BackInsertable edgels; | | BackInsertable edgels; | |
| edgels.push_back(Edgel()); | | edgels.push_back(Edgel()); | |
| \endcode | | \endcode | |
|
| | | | |
| SrcAccessor::value_type must be a type convertible to float | | SrcAccessor::value_type must be a type convertible to float | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void cannyEdgelListThreshold) | | doxygen_overloaded_function(template <...> void cannyEdgelListThreshold) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| | | | |
| skipping to change at line 1517 | | skipping to change at line 1785 | |
| { | | { | |
| typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | | typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | |
| BasicImage<TinyVector<TmpType, 2> > grad(lr-ul); | | BasicImage<TinyVector<TmpType, 2> > grad(lr-ul); | |
| gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale); | | gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale); | |
| | | | |
| cannyEdgelListThreshold(srcImageRange(grad), edgels, grad_threshold); | | cannyEdgelListThreshold(srcImageRange(grad), edgels, grad_threshold); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
|
| inline void | | | |
| cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | | |
| BackInsertable & edgels, double scale, GradValue gr | | | |
| ad_threshold) | | | |
| { | | | |
| cannyEdgelListThreshold(src.first, src.second, src.third, edgels, scale | | | |
| , grad_threshold); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class BackInsertable, class GradValue> | | | |
| void | | void | |
| cannyEdgelListThreshold(SrcIterator ul, SrcIterator lr, SrcAccessor src, | | cannyEdgelListThreshold(SrcIterator ul, SrcIterator lr, SrcAccessor src, | |
| BackInsertable & edgels, GradValue grad_threshold) | | BackInsertable & edgels, GradValue grad_threshold) | |
| { | | { | |
| using namespace functor; | | using namespace functor; | |
| | | | |
| typedef typename SrcAccessor::value_type SrcType; | | typedef typename SrcAccessor::value_type SrcType; | |
| typedef typename NumericTraits<typename SrcType::value_type>::RealPromo
te TmpType; | | typedef typename NumericTraits<typename SrcType::value_type>::RealPromo
te TmpType; | |
| BasicImage<TmpType> magnitude(lr-ul); | | BasicImage<TmpType> magnitude(lr-ul); | |
| transformImage(srcIterRange(ul, lr, src), destImage(magnitude), norm(Ar
g1())); | | transformImage(srcIterRange(ul, lr, src), destImage(magnitude), norm(Ar
g1())); | |
| | | | |
| // find edgels | | // find edgels | |
| internalCannyFindEdgels(ul, src, magnitude, edgels, grad_threshold); | | internalCannyFindEdgels(ul, src, magnitude, edgels, grad_threshold); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| inline void | | inline void | |
| cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| | | BackInsertable & edgels, double scale, GradValue gr | |
| | | ad_threshold) | |
| | | { | |
| | | cannyEdgelListThreshold(src.first, src.second, src.third, edgels, scale | |
| | | , grad_threshold); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class BackInsertable, class GradValue> | |
| | | inline void | |
| | | cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| BackInsertable & edgels, GradValue grad_threshold) | | BackInsertable & edgels, GradValue grad_threshold) | |
| { | | { | |
| cannyEdgelListThreshold(src.first, src.second, src.third, edgels, grad_
threshold); | | cannyEdgelListThreshold(src.first, src.second, src.third, edgels, grad_
threshold); | |
| } | | } | |
| | | | |
|
| | | template <class T, class S, | |
| | | class BackInsertable, class GradValue> | |
| | | inline void | |
| | | cannyEdgelListThreshold(MultiArrayView<2, T, S> const & src, | |
| | | BackInsertable & edgels, | |
| | | double scale, | |
| | | GradValue grad_threshold) | |
| | | { | |
| | | cannyEdgelListThreshold(srcImageRange(src), edgels, scale, grad_thresho | |
| | | ld); | |
| | | } | |
| | | | |
| | | template <class T, class S, | |
| | | class BackInsertable, class GradValue> | |
| | | inline void | |
| | | cannyEdgelListThreshold(MultiArrayView<2, TinyVector<T, 2>, S> const & src, | |
| | | BackInsertable & edgels, | |
| | | GradValue grad_threshold) | |
| | | { | |
| | | cannyEdgelListThreshold(srcImageRange(src), edgels, grad_threshold); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* cannyEdgeImage */ | | /* cannyEdgeImage */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Detect and mark edges in an edge image using Canny's algorithm. | | /** \brief Detect and mark edges in an edge image using Canny's algorithm. | |
| | | | |
|
| This operator first calls \ref cannyEdgelList() to generate an | | This operator first calls \ref cannyEdgelList() with the given scale to
generate an | |
| edgel list for the given image. Then it scans this list and selects edg
els | | edgel list for the given image. Then it scans this list and selects edg
els | |
| whose strength is above the given <TT>gradient_threshold</TT>. For each
of these | | whose strength is above the given <TT>gradient_threshold</TT>. For each
of these | |
| edgels, the edgel's location is rounded to the nearest pixel, and that | | edgels, the edgel's location is rounded to the nearest pixel, and that | |
| pixel marked with the given <TT>edge_marker</TT>. | | pixel marked with the given <TT>edge_marker</TT>. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class GradValue, class DestValue> | |
| | | void | |
| | | cannyEdgeImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale, | |
| | | GradValue gradient_threshold, | |
| | | DestValue edge_marker); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{cannyEdgeImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| void cannyEdgeImage( | | void cannyEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| double scale, GradValue gradient_threshold, DestValue ed
ge_marker); | | double scale, GradValue gradient_threshold, DestValue ed
ge_marker); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| void cannyEdgeImage( | | void cannyEdgeImage( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale, GradValue gradient_threshold, DestValue ed
ge_marker); | | double scale, GradValue gradient_threshold, DestValue ed
ge_marker); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h), edges(w,h); | |
| | | ... | |
| | | | |
| | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| | | cannyEdgeImage(src, edges, 0.8, 4.0, 1); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{cannyEdgeImage} | |
| | | \code | |
| vigra::BImage src(w,h), edges(w,h); | | vigra::BImage src(w,h), edges(w,h); | |
| | | | |
| // empty edge image | | // empty edge image | |
| edges = 0; | | edges = 0; | |
| ... | | ... | |
| | | | |
| // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1 | |
| vigra::cannyEdgeImage(srcImageRange(src), destImage(edges), | | vigra::cannyEdgeImage(srcImageRange(src), destImage(edges), | |
| 0.8, 4.0, 1); | | 0.8, 4.0, 1); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| see also: \ref cannyEdgelList(). | | see also: \ref cannyEdgelList(). | |
|
| | | | |
| \code | | \code | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| DestValue edge_marker; | | DestValue edge_marker; | |
| | | | |
| dest_accessor.set(edge_marker, dest_upperleft, vigra::Diff2D(1,1)); | | dest_accessor.set(edge_marker, dest_upperleft, vigra::Diff2D(1,1)); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| gradient_threshold > 0 | | gradient_threshold > 0 | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void cannyEdgeImage) | | doxygen_overloaded_function(template <...> void cannyEdgeImage) | |
| | | | |
| | | | |
| skipping to change at line 1659 | | skipping to change at line 1971 | |
| if(pix.x < 0 || pix.x >= w || pix.y < 0 || pix.y >= h) | | if(pix.x < 0 || pix.x >= w || pix.y < 0 || pix.y >= h) | |
| continue; | | continue; | |
| | | | |
| da.set(edge_marker, dul, pix); | | da.set(edge_marker, dul, pix); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
|
| inline void cannyEdgeImage( | | inline void | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | cannyEdgeImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale, GradValue gradient_threshold, DestValue edge_marke | | double scale, GradValue gradient_threshold, DestValue edge_m | |
| r) | | arker) | |
| { | | { | |
| cannyEdgeImage(src.first, src.second, src.third, | | cannyEdgeImage(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| scale, gradient_threshold, edge_marker); | | scale, gradient_threshold, edge_marker); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class GradValue, class DestValue> | |
| | | inline void | |
| | | cannyEdgeImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale, GradValue gradient_threshold, DestValue edge_m | |
| | | arker) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "cannyEdgeImage(): shape mismatch between input and output."); | |
| | | cannyEdgeImage(srcImageRange(src), | |
| | | destImage(dest), | |
| | | scale, gradient_threshold, edge_marker); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| template <class DestIterator> | | template <class DestIterator> | |
| int neighborhoodConfiguration(DestIterator dul) | | int neighborhoodConfiguration(DestIterator dul) | |
| { | | { | |
| int v = 0; | | int v = 0; | |
| NeighborhoodCirculator<DestIterator, EightNeighborCode> c(dul, EightNei
ghborCode::SouthEast); | | NeighborhoodCirculator<DestIterator, EightNeighborCode> c(dul, EightNei
ghborCode::SouthEast); | |
| for(int i=0; i<8; ++i, --c) | | for(int i=0; i<8; ++i, --c) | |
| | | | |
| skipping to change at line 1779 | | skipping to change at line 2106 | |
| da.set(edge_marker, dx); | | da.set(edge_marker, dx); | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
|
| /* cannyEdgeImageWithThinning */ | | /* cannyEdgeImageFromGradWithThinning */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Detect and mark edges in an edge image using Canny's algorithm. | | /** \brief Detect and mark edges in an edge image using Canny's algorithm. | |
| | | | |
|
| The input pixels of this algorithms must be vectors of length 2 (see Re
quired Interface below). | | The input pixels of this algorithm must be vectors of length 2 (see Req
uired Interface below). | |
| It first searches for all pixels whose gradient magnitude is larger | | It first searches for all pixels whose gradient magnitude is larger | |
| than the given <tt>gradient_threshold</tt> and larger than the magnitud
e of its two neighbors | | than the given <tt>gradient_threshold</tt> and larger than the magnitud
e of its two neighbors | |
| in gradient direction (where these neighbors are determined by nearest
neighbor | | in gradient direction (where these neighbors are determined by nearest
neighbor | |
| interpolation, i.e. according to the octant where the gradient points i
nto). | | interpolation, i.e. according to the octant where the gradient points i
nto). | |
| The resulting edge pixel candidates are then subjected to topological t
hinning | | The resulting edge pixel candidates are then subjected to topological t
hinning | |
| so that the remaining edge pixels can be linked into edgel chains with
a provable, | | so that the remaining edge pixels can be linked into edgel chains with
a provable, | |
| non-heuristic algorithm. Thinning is performed so that the pixels with
highest gradient | | non-heuristic algorithm. Thinning is performed so that the pixels with
highest gradient | |
| magnitude survive. Optionally, the outermost pixels are marked as edge
pixels | | magnitude survive. Optionally, the outermost pixels are marked as edge
pixels | |
| as well when <tt>addBorder</tt> is true. The remaining pixels will be m
arked in the destination | | as well when <tt>addBorder</tt> is true. The remaining pixels will be m
arked in the destination | |
| image with the value of <tt>edge_marker</tt> (all non-edge pixels remai
n untouched). | | image with the value of <tt>edge_marker</tt> (all non-edge pixels remai
n untouched). | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class GradValue, class DestValue> | |
| | | void | |
| | | cannyEdgeImageFromGradWithThinning(MultiArrayView<2, TinyVector<T1, | |
| | | 2>, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | GradValue gradient_threshold, | |
| | | DestValue edge_marker, | |
| | | bool addBorder = true); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{cannyEdgeImageFromGradWithThinning} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| void cannyEdgeImageFromGradWithThinning( | | void cannyEdgeImageFromGradWithThinning( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| GradValue gradient_threshold, | | GradValue gradient_threshold, | |
| DestValue edge_marker, bool addBorder = true); | | DestValue edge_marker, bool addBorder = true); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| void cannyEdgeImageFromGradWithThinning( | | void cannyEdgeImageFromGradWithThinning( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| GradValue gradient_threshold, | | GradValue gradient_threshold, | |
| DestValue edge_marker, bool addBorder = true); | | DestValue edge_marker, bool addBorder = true); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h), edges(w,h); | |
| | | | |
| | | MultiArray<2, TinyVector<float, 2> > grad(w,h); | |
| | | // compute the image gradient at scale 0.8 | |
| | | gaussianGradient(src, grad, 0.8); | |
| | | | |
| | | // find edges with gradient larger than 4.0, mark with 1, and add borde | |
| | | r | |
| | | cannyEdgeImageFromGradWithThinning(grad, edges, 4.0, 1, true); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{cannyEdgeImageFromGradWithThinning} | |
| | | \code | |
| vigra::BImage src(w,h), edges(w,h); | | vigra::BImage src(w,h), edges(w,h); | |
| | | | |
| vigra::FVector2Image grad(w,h); | | vigra::FVector2Image grad(w,h); | |
| // compute the image gradient at scale 0.8 | | // compute the image gradient at scale 0.8 | |
| vigra::gaussianGradient(srcImageRange(src), destImage(grad), 0.8); | | vigra::gaussianGradient(srcImageRange(src), destImage(grad), 0.8); | |
| | | | |
| // empty edge image | | // empty edge image | |
| edges = 0; | | edges = 0; | |
| // find edges gradient larger than 4.0, mark with 1, and add border | | // find edges gradient larger than 4.0, mark with 1, and add border | |
| vigra::cannyEdgeImageFromGradWithThinning(srcImageRange(grad), destImag
e(edges), | | vigra::cannyEdgeImageFromGradWithThinning(srcImageRange(grad), destImag
e(edges), | |
| 4.0, 1, true); | | 4.0, 1, true); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| // the input pixel type must be a vector with two elements | | // the input pixel type must be a vector with two elements | |
| SrcImageIterator src_upperleft; | | SrcImageIterator src_upperleft; | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| typedef SrcAccessor::value_type SrcPixel; | | typedef SrcAccessor::value_type SrcPixel; | |
| typedef NormTraits<SrcPixel>::SquaredNormType SrcSquaredNormType; | | typedef NormTraits<SrcPixel>::SquaredNormType SrcSquaredNormType; | |
| | | | |
| SrcPixel g = src_accessor(src_upperleft); | | SrcPixel g = src_accessor(src_upperleft); | |
| SrcPixel::value_type g0 = g[0]; | | SrcPixel::value_type g0 = g[0]; | |
| SrcSquaredNormType gn = squaredNorm(g); | | SrcSquaredNormType gn = squaredNorm(g); | |
| | | | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| DestValue edge_marker; | | DestValue edge_marker; | |
| | | | |
| dest_accessor.set(edge_marker, dest_upperleft, vigra::Diff2D(1,1)); | | dest_accessor.set(edge_marker, dest_upperleft, vigra::Diff2D(1,1)); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| gradient_threshold > 0 | | gradient_threshold > 0 | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void cannyEdgeImageFromGradWithT
hinning) | | doxygen_overloaded_function(template <...> void cannyEdgeImageFromGradWithT
hinning) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| void cannyEdgeImageFromGradWithThinning( | | void cannyEdgeImageFromGradWithThinning( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| GradValue gradient_threshold, | | GradValue gradient_threshold, | |
|
| DestValue edge_marker, bool addBorder) | | DestValue edge_marker, bool addBorder = true) | |
| { | | { | |
|
| | | vigra_precondition(gradient_threshold >= NumericTraits<GradValue>::zero | |
| | | (), | |
| | | "cannyEdgeImageFromGradWithThinning(): gradient threshold must not | |
| | | be negative."); | |
| | | | |
| int w = slr.x - sul.x; | | int w = slr.x - sul.x; | |
| int h = slr.y - sul.y; | | int h = slr.y - sul.y; | |
| | | | |
| BImage edgeImage(w, h, BImage::value_type(0)); | | BImage edgeImage(w, h, BImage::value_type(0)); | |
| BImage::traverser eul = edgeImage.upperLeft(); | | BImage::traverser eul = edgeImage.upperLeft(); | |
| BImage::Accessor ea = edgeImage.accessor(); | | BImage::Accessor ea = edgeImage.accessor(); | |
| if(addBorder) | | if(addBorder) | |
| initImageBorder(destImageRange(edgeImage), 1, 1); | | initImageBorder(destImageRange(edgeImage), 1, 1); | |
| detail::cannyEdgeImageFromGrad(sul, slr, sa, eul, ea, gradient_threshol
d, 1); | | detail::cannyEdgeImageFromGrad(sul, slr, sa, eul, ea, gradient_threshol
d, 1); | |
| | | | |
|
| static bool isSimplePoint[256] = { | | bool isSimplePoint[256] = { | |
| 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, | | 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, | |
| 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, | | 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, | |
| 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, | | 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, | |
| 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, | | 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, | |
| 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, | | 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, | |
| 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, | | 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, | |
| 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, | | 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, | |
| 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, | | 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| | | | |
| skipping to change at line 1936 | | skipping to change at line 2293 | |
| continue; | | continue; | |
| int v = detail::neighborhoodConfiguration(e); | | int v = detail::neighborhoodConfiguration(e); | |
| if(isSimplePoint[v]) | | if(isSimplePoint[v]) | |
| { | | { | |
| pqueue.push(SP(p, norm(sa(sul+p)))); | | pqueue.push(SP(p, norm(sa(sul+p)))); | |
| *e = 2; // remember that it is already in queue | | *e = 2; // remember that it is already in queue | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
|
| static const Diff2D dist[] = { Diff2D(-1,0), Diff2D(0,-1), | | const Diff2D dist[] = { Diff2D(-1,0), Diff2D(0,-1), Diff2D(1,0), Diff2 | |
| Diff2D(1,0), Diff2D(0,1) }; | | D(0,1) }; | |
| | | | |
| while(pqueue.size()) | | while(pqueue.size()) | |
| { | | { | |
| p = pqueue.top().point; | | p = pqueue.top().point; | |
| pqueue.pop(); | | pqueue.pop(); | |
| | | | |
| BImage::traverser e = eul + p; | | BImage::traverser e = eul + p; | |
| int v = detail::neighborhoodConfiguration(e); | | int v = detail::neighborhoodConfiguration(e); | |
| if(!isSimplePoint[v]) | | if(!isSimplePoint[v]) | |
| continue; // point may no longer be simple because its neighbor
s changed | | continue; // point may no longer be simple because its neighbor
s changed | |
| | | | |
| skipping to change at line 1960 | | skipping to change at line 2316 | |
| | | | |
| for(int i=0; i<4; ++i) | | for(int i=0; i<4; ++i) | |
| { | | { | |
| Diff2D pneu = p + dist[i]; | | Diff2D pneu = p + dist[i]; | |
| if(pneu.x == -1 || pneu.y == -1 || pneu.x == w2 || pneu.y == h2
) | | if(pneu.x == -1 || pneu.y == -1 || pneu.x == w2 || pneu.y == h2
) | |
| continue; // do not remove points at the border | | continue; // do not remove points at the border | |
| | | | |
| BImage::traverser eneu = eul + pneu; | | BImage::traverser eneu = eul + pneu; | |
| if(*eneu == 1) // point is boundary and not yet in the queue | | if(*eneu == 1) // point is boundary and not yet in the queue | |
| { | | { | |
|
| int v = detail::neighborhoodConfiguration(eneu); | | v = detail::neighborhoodConfiguration(eneu); | |
| if(isSimplePoint[v]) | | if(isSimplePoint[v]) | |
| { | | { | |
| pqueue.push(SP(pneu, norm(sa(sul+pneu)))); | | pqueue.push(SP(pneu, norm(sa(sul+pneu)))); | |
| *eneu = 2; // remember that it is already in queue | | *eneu = 2; // remember that it is already in queue | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| initImageIf(destIterRange(dul, dul+Diff2D(w,h), da), | | initImageIf(destIterRange(dul, dul+Diff2D(w,h), da), | |
| maskImage(edgeImage), edge_marker); | | maskImage(edgeImage), edge_marker); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| inline void cannyEdgeImageFromGradWithThinning( | | inline void cannyEdgeImageFromGradWithThinning( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| GradValue gradient_threshold, | | GradValue gradient_threshold, | |
|
| DestValue edge_marker, bool addBorder) | | DestValue edge_marker, bool addBorder = true) | |
| { | | { | |
| cannyEdgeImageFromGradWithThinning(src.first, src.second, src.third, | | cannyEdgeImageFromGradWithThinning(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| gradient_threshold, edge_marker, addBorder); | | gradient_threshold, edge_marker, addBorder); | |
| } | | } | |
| | | | |
|
| template <class SrcIterator, class SrcAccessor, | | template <class T1, class S1, | |
| class DestIterator, class DestAccessor, | | class T2, class S2, | |
| class GradValue, class DestValue> | | | |
| inline void cannyEdgeImageFromGradWithThinning( | | | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | | |
| DestIterator dul, DestAccessor da, | | | |
| GradValue gradient_threshold, DestValue edge_marker) | | | |
| { | | | |
| cannyEdgeImageFromGradWithThinning(sul, slr, sa, | | | |
| dul, da, | | | |
| gradient_threshold, edge_marker, true); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor, | | | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
|
| inline void cannyEdgeImageFromGradWithThinning( | | inline void | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | cannyEdgeImageFromGradWithThinning(MultiArrayView<2, TinyVector<T1, 2>, S1> | |
| pair<DestIterator, DestAccessor> dest, | | const & src, | |
| GradValue gradient_threshold, DestValue edge_marker) | | MultiArrayView<2, T2, S2> dest, | |
| { | | GradValue gradient_threshold, | |
| cannyEdgeImageFromGradWithThinning(src.first, src.second, src.third, | | DestValue edge_marker, bool addBorder = | |
| dest.first, dest.second, | | true) | |
| gradient_threshold, edge_marker, true); | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "cannyEdgeImageFromGradWithThinning(): shape mismatch between input | |
| | | and output."); | |
| | | cannyEdgeImageFromGradWithThinning(srcImageRange(src), | |
| | | destImage(dest), | |
| | | gradient_threshold, edge_marker, add | |
| | | Border); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* cannyEdgeImageWithThinning */ | | /* cannyEdgeImageWithThinning */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Detect and mark edges in an edge image using Canny's algorithm. | | /** \brief Detect and mark edges in an edge image using Canny's algorithm. | |
| | | | |
| This operator first calls \ref gaussianGradient() to compute the gradie
nt of the input | | This operator first calls \ref gaussianGradient() to compute the gradie
nt of the input | |
| image, ad then \ref cannyEdgeImageFromGradWithThinning() to generate an | | image, ad then \ref cannyEdgeImageFromGradWithThinning() to generate an | |
| edge image. See there for more detailed documentation. | | edge image. See there for more detailed documentation. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class GradValue, class DestValue> | |
| | | void | |
| | | cannyEdgeImageWithThinning(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale, | |
| | | GradValue gradient_threshold, | |
| | | DestValue edge_marker, | |
| | | bool addBorder = true); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{cannyEdgeImageWithThinning} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| void cannyEdgeImageWithThinning( | | void cannyEdgeImageWithThinning( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| double scale, GradValue gradient_threshold, | | double scale, GradValue gradient_threshold, | |
| DestValue edge_marker, bool addBorder = true); | | DestValue edge_marker, bool addBorder = true); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| void cannyEdgeImageWithThinning( | | void cannyEdgeImageWithThinning( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double scale, GradValue gradient_threshold, | | double scale, GradValue gradient_threshold, | |
| DestValue edge_marker, bool addBorder = true); | | DestValue edge_marker, bool addBorder = true); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h), edges(w,h); | |
| | | ... | |
| | | | |
| | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1, | |
| | | and add border | |
| | | cannyEdgeImageWithThinning(src, edges, 0.8, 4.0, 1, true); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{cannyEdgeImageWithThinning} | |
| | | \code | |
| vigra::BImage src(w,h), edges(w,h); | | vigra::BImage src(w,h), edges(w,h); | |
| | | | |
| // empty edge image | | // empty edge image | |
| edges = 0; | | edges = 0; | |
| ... | | ... | |
| | | | |
| // find edges at scale 0.8 with gradient larger than 4.0, mark with 1,
annd add border | | // find edges at scale 0.8 with gradient larger than 4.0, mark with 1,
annd add border | |
| vigra::cannyEdgeImageWithThinning(srcImageRange(src), destImage(edges), | | vigra::cannyEdgeImageWithThinning(srcImageRange(src), destImage(edges), | |
| 0.8, 4.0, 1, true); | | 0.8, 4.0, 1, true); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| see also: \ref cannyEdgelList(). | | see also: \ref cannyEdgelList(). | |
|
| | | | |
| \code | | \code | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| DestValue edge_marker; | | DestValue edge_marker; | |
| | | | |
| dest_accessor.set(edge_marker, dest_upperleft, vigra::Diff2D(1,1)); | | dest_accessor.set(edge_marker, dest_upperleft, vigra::Diff2D(1,1)); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| gradient_threshold > 0 | | gradient_threshold > 0 | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void cannyEdgeImageWithThinning) | | doxygen_overloaded_function(template <...> void cannyEdgeImageWithThinning) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
| void cannyEdgeImageWithThinning( | | void cannyEdgeImageWithThinning( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| double scale, GradValue gradient_threshold, | | double scale, GradValue gradient_threshold, | |
|
| DestValue edge_marker, bool addBorder) | | DestValue edge_marker, bool addBorder = true) | |
| { | | { | |
| // mark pixels that are higher than their neighbors in gradient directi
on | | // mark pixels that are higher than their neighbors in gradient directi
on | |
| typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | | typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | |
| BasicImage<TinyVector<TmpType, 2> > grad(slr-sul); | | BasicImage<TinyVector<TmpType, 2> > grad(slr-sul); | |
| gaussianGradient(srcIterRange(sul, slr, sa), destImage(grad), scale); | | gaussianGradient(srcIterRange(sul, slr, sa), destImage(grad), scale); | |
| cannyEdgeImageFromGradWithThinning(srcImageRange(grad), destIter(dul, d
a), | | cannyEdgeImageFromGradWithThinning(srcImageRange(grad), destIter(dul, d
a), | |
| gradient_threshold, edge_marker, addBorder); | | gradient_threshold, edge_marker, addBorder); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
|
| inline void cannyEdgeImageWithThinning( | | inline void | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | cannyEdgeImageWithThinning(triple<SrcIterator, SrcIterator, SrcAccessor> sr | |
| pair<DestIterator, DestAccessor> dest, | | c, | |
| double scale, GradValue gradient_threshold, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue edge_marker, bool addBorder) | | double scale, GradValue gradient_threshold, | |
| | | DestValue edge_marker, bool addBorder = true) | |
| { | | { | |
| cannyEdgeImageWithThinning(src.first, src.second, src.third, | | cannyEdgeImageWithThinning(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| scale, gradient_threshold, edge_marker, addB
order); | | scale, gradient_threshold, edge_marker, addB
order); | |
| } | | } | |
| | | | |
|
| template <class SrcIterator, class SrcAccessor, | | template <class T1, class S1, | |
| class DestIterator, class DestAccessor, | | class T2, class S2, | |
| class GradValue, class DestValue> | | class GradValue, class DestValue> | |
|
| inline void cannyEdgeImageWithThinning( | | inline void | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | cannyEdgeImageWithThinning(MultiArrayView<2, T1, S1> const & src, | |
| DestIterator dul, DestAccessor da, | | MultiArrayView<2, T2, S2> dest, | |
| double scale, GradValue gradient_threshold, DestValue edge_marke | | double scale, GradValue gradient_threshold, | |
| r) | | DestValue edge_marker, bool addBorder = true) | |
| { | | { | |
| cannyEdgeImageWithThinning(sul, slr, sa, | | vigra_precondition(src.shape() == dest.shape(), | |
| dul, da, | | "cannyEdgeImageWithThinning(): shape mismatch between input and out | |
| scale, gradient_threshold, edge_marker, true | | put."); | |
| ); | | cannyEdgeImageWithThinning(srcImageRange(src), | |
| } | | destImage(dest), | |
| | | scale, gradient_threshold, edge_marker, addB | |
| template <class SrcIterator, class SrcAccessor, | | order); | |
| class DestIterator, class DestAccessor, | | | |
| class GradValue, class DestValue> | | | |
| inline void cannyEdgeImageWithThinning( | | | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | | |
| pair<DestIterator, DestAccessor> dest, | | | |
| double scale, GradValue gradient_threshold, DestValue edge_marke | | | |
| r) | | | |
| { | | | |
| cannyEdgeImageWithThinning(src.first, src.second, src.third, | | | |
| dest.first, dest.second, | | | |
| scale, gradient_threshold, edge_marker, true | | | |
| ); | | | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskImage, class BackInsertable, class GradValue> | | class MaskImage, class BackInsertable, class GradValue> | |
| void internalCannyFindEdgels3x3(SrcIterator ul, SrcAccessor grad, | | void internalCannyFindEdgels3x3(SrcIterator ul, SrcAccessor grad, | |
| MaskImage const & mask, | | MaskImage const & mask, | |
| BackInsertable & edgels, | | BackInsertable & edgels, | |
| GradValue grad_thresh) | | GradValue grad_thresh) | |
| | | | |
| skipping to change at line 2243 | | skipping to change at line 2603 | |
| is fitted to 9 points rather than 3 points as in cannyEdgelList(), the
accuracy is higher. | | is fitted to 9 points rather than 3 points as in cannyEdgelList(), the
accuracy is higher. | |
| | | | |
| The function can be called in two modes: If you pass a 'scale', it is a
ssumed that the | | The function can be called in two modes: If you pass a 'scale', it is a
ssumed that the | |
| original image is scalar, and the Gaussian gradient is internally compu
ted at the | | original image is scalar, and the Gaussian gradient is internally compu
ted at the | |
| given 'scale'. If the function is called without scale parameter, it is
assumed that | | given 'scale'. If the function is called without scale parameter, it is
assumed that | |
| the given image already contains the gradient (i.e. its value_type must
be | | the given image already contains the gradient (i.e. its value_type must
be | |
| a vector of length 2). | | a vector of length 2). | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // compute edgels from a scalar image (determine gradient internall | |
| | | y at 'scale') | |
| | | template <class T, class S, class BackInsertable> | |
| | | void | |
| | | cannyEdgelList3x3(MultiArrayView<2, T, S> const & src, | |
| | | BackInsertable & edgels, | |
| | | double scale); | |
| | | | |
| | | // compute edgels from a pre-computed gradient image | |
| | | template <class T, class S, class BackInsertable> | |
| | | void | |
| | | cannyEdgelList3x3(MultiArrayView<2, TinyVector<T, 2>, S> const & sr | |
| | | c, | |
| | | BackInsertable & edgels); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{cannyEdgelList3x3} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // compute edgels from a gradient image | | // compute edgels from a gradient image | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor
src, | | void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor
src, | |
| BackInsertable & edgels); | | BackInsertable & edgels); | |
| | | | |
| // compute edgels from a scalar image (determine gradient internall
y at 'scale') | | // compute edgels from a scalar image (determine gradient internall
y at 'scale') | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor
src, | | void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor
src, | |
| BackInsertable & edgels, double scale); | | BackInsertable & edgels, double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // compute edgels from a gradient image | | // compute edgels from a gradient image | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void | | void | |
| cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src
, | | cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src
, | |
| BackInsertable & edgels); | | BackInsertable & edgels); | |
| | | | |
| // compute edgels from a scalar image (determine gradient internall
y at 'scale') | | // compute edgels from a scalar image (determine gradient internall
y at 'scale') | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void | | void | |
| cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src
, | | cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src
, | |
| BackInsertable & edgels, double scale); | | BackInsertable & edgels, double scale); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h); | |
| | | | |
| | | // create empty edgel list | |
| | | std::vector<vigra::Edgel> edgels; | |
| | | ... | |
| | | | |
| | | // find edgels at scale 0.8 | |
| | | cannyEdgelList3x3(src, edgels, 0.8); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{cannyEdgelList3x3} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| | | | |
| // empty edgel list | | // empty edgel list | |
| std::vector<vigra::Edgel> edgels; | | std::vector<vigra::Edgel> edgels; | |
| ... | | ... | |
| | | | |
| // find edgels at scale 0.8 | | // find edgels at scale 0.8 | |
| vigra::cannyEdgelList3x3(srcImageRange(src), edgels, 0.8); | | vigra::cannyEdgelList3x3(srcImageRange(src), edgels, 0.8); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft; | | SrcImageIterator src_upperleft; | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| | | | |
| src_accessor(src_upperleft); | | src_accessor(src_upperleft); | |
| | | | |
| BackInsertable edgels; | | BackInsertable edgels; | |
| edgels.push_back(Edgel()); | | edgels.push_back(Edgel()); | |
| \endcode | | \endcode | |
|
| | | | |
| SrcAccessor::value_type must be a type convertible to float | | SrcAccessor::value_type must be a type convertible to float | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void cannyEdgelList3x3) | | doxygen_overloaded_function(template <...> void cannyEdgelList3x3) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
| | | | |
| skipping to change at line 2326 | | skipping to change at line 2715 | |
| BackInsertable & edgels, double scale) | | BackInsertable & edgels, double scale) | |
| { | | { | |
| typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | | typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | |
| BasicImage<TinyVector<TmpType, 2> > grad(lr-ul); | | BasicImage<TinyVector<TmpType, 2> > grad(lr-ul); | |
| gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale); | | gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale); | |
| | | | |
| cannyEdgelList3x3(srcImageRange(grad), edgels); | | cannyEdgelList3x3(srcImageRange(grad), edgels); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
|
| inline void | | | |
| cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | | |
| BackInsertable & edgels, double scale) | | | |
| { | | | |
| cannyEdgelList3x3(src.first, src.second, src.third, edgels, scale); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | | |
| void | | void | |
| cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor src, | | cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor src, | |
| BackInsertable & edgels) | | BackInsertable & edgels) | |
| { | | { | |
| typedef typename NormTraits<typename SrcAccessor::value_type>::NormType
NormType; | | typedef typename NormTraits<typename SrcAccessor::value_type>::NormType
NormType; | |
| | | | |
| UInt8Image edges(lr-ul); | | UInt8Image edges(lr-ul); | |
| cannyEdgeImageFromGradWithThinning(srcIterRange(ul, lr, src), destImage
(edges), | | cannyEdgeImageFromGradWithThinning(srcIterRange(ul, lr, src), destImage
(edges), | |
| 0.0, 1, false); | | 0.0, 1, false); | |
| | | | |
| // find edgels | | // find edgels | |
| internalCannyFindEdgels3x3(ul, src, edges, edgels, NumericTraits<NormTy
pe>::zero()); | | internalCannyFindEdgels3x3(ul, src, edges, edgels, NumericTraits<NormTy
pe>::zero()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
| inline void | | inline void | |
| cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| | | BackInsertable & edgels, double scale) | |
| | | { | |
| | | cannyEdgelList3x3(src.first, src.second, src.third, edgels, scale); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
| | | inline void | |
| | | cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| BackInsertable & edgels) | | BackInsertable & edgels) | |
| { | | { | |
| cannyEdgelList3x3(src.first, src.second, src.third, edgels); | | cannyEdgelList3x3(src.first, src.second, src.third, edgels); | |
| } | | } | |
| | | | |
|
| | | template <class T, class S, class BackInsertable> | |
| | | inline void | |
| | | cannyEdgelList3x3(MultiArrayView<2, T, S> const & src, | |
| | | BackInsertable & edgels, double scale) | |
| | | { | |
| | | cannyEdgelList3x3(srcImageRange(src), edgels, scale); | |
| | | } | |
| | | | |
| | | template <class T, class S, class BackInsertable> | |
| | | inline void | |
| | | cannyEdgelList3x3(MultiArrayView<2, TinyVector<T, 2>, S> const & src, | |
| | | BackInsertable & edgels) | |
| | | { | |
| | | cannyEdgelList3x3(srcImageRange(src), edgels); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* cannyEdgelList3x3Threshold */ | | /* cannyEdgelList3x3Threshold */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Improved implementation of Canny's edge detector with thresholdi
ng. | | /** \brief Improved implementation of Canny's edge detector with thresholdi
ng. | |
| | | | |
| This function works exactly like \ref cannyEdgelList3x3(), but | | This function works exactly like \ref cannyEdgelList3x3(), but | |
| you also pass a threshold for the minimal gradient magnitude, | | you also pass a threshold for the minimal gradient magnitude, | |
| so that edgels whose strength is below the threshold are not | | so that edgels whose strength is below the threshold are not | |
| inserted into the edgel list. | | inserted into the edgel list. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // compute edgels from a gradient image | | // compute edgels from a gradient image | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| void | | void | |
| cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAcces
sor src, | | cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAcces
sor src, | |
| BackInsertable & edgels, GradValue grad_
thresh); | | BackInsertable & edgels, GradValue grad_
thresh); | |
| | | | |
| // compute edgels from a scalar image (determine gradient internall
y at 'scale') | | // compute edgels from a scalar image (determine gradient internall
y at 'scale') | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| void | | void | |
| cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAcces
sor src, | | cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAcces
sor src, | |
| BackInsertable & edgels, double scale, G
radValue grad_thresh); | | BackInsertable & edgels, double scale, G
radValue grad_thresh); | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedAPI{cannyEdgelList3x3Threshold} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| | | \code | |
| | | namespace vigra { | |
| | | // compute edgels from a gradient image | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class BackInsertable, class GradValue> | |
| | | void | |
| | | cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAcces | |
| | | sor src, | |
| | | BackInsertable & edgels, GradValue grad_ | |
| | | thresh); | |
| | | | |
| | | // compute edgels from a scalar image (determine gradient internall | |
| | | y at 'scale') | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class BackInsertable, class GradValue> | |
| | | void | |
| | | cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAcces | |
| | | sor src, | |
| | | BackInsertable & edgels, double scale, G | |
| | | radValue grad_thresh); | |
| | | } | |
| | | \endcode | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // compute edgels from a gradient image | | // compute edgels from a gradient image | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| void | | void | |
| cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAcce
ssor> src, | | cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAcce
ssor> src, | |
| BackInsertable & edgels, GradValue grad_
thresh); | | BackInsertable & edgels, GradValue grad_
thresh); | |
| | | | |
| // compute edgels from a scalar image (determine gradient internall
y at 'scale') | | // compute edgels from a scalar image (determine gradient internall
y at 'scale') | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| void | | void | |
| cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAcce
ssor> src, | | cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAcce
ssor> src, | |
| BackInsertable & edgels, double scale, G
radValue grad_thresh); | | BackInsertable & edgels, double scale, G
radValue grad_thresh); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/edgedetection.hxx\><br> | | <b>\#include</b> \<vigra/edgedetection.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h); | |
| | | | |
| | | // create empty edgel list | |
| | | std::vector<vigra::Edgel> edgels; | |
| | | ... | |
| | | | |
| | | // find edgels at scale 0.8 whose gradient is at least 4.0 | |
| | | cannyEdgelList3x3Threshold(src, edgels, 0.8, 4.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{cannyEdgelList3x3Threshold} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| | | | |
| // empty edgel list | | // empty edgel list | |
| std::vector<vigra::Edgel> edgels; | | std::vector<vigra::Edgel> edgels; | |
| ... | | ... | |
| | | | |
|
| // find edgels at scale 0.8 | | // find edgels at scale 0.8 whose gradient is at least 4.0 | |
| vigra::cannyEdgelList3x3(srcImageRange(src), edgels, 0.8); | | vigra::cannyEdgelList3x3Threshold(srcImageRange(src), edgels, 0.8, 4.0) | |
| | | ; | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft; | | SrcImageIterator src_upperleft; | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| | | | |
| src_accessor(src_upperleft); | | src_accessor(src_upperleft); | |
| | | | |
| BackInsertable edgels; | | BackInsertable edgels; | |
| edgels.push_back(Edgel()); | | edgels.push_back(Edgel()); | |
| \endcode | | \endcode | |
|
| | | | |
| SrcAccessor::value_type must be a type convertible to float | | SrcAccessor::value_type must be a type convertible to float | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void cannyEdgelList3x3Threshold) | | doxygen_overloaded_function(template <...> void cannyEdgelList3x3Threshold) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| | | | |
| skipping to change at line 2462 | | skipping to change at line 2897 | |
| { | | { | |
| typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | | typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP
romote TmpType; | |
| BasicImage<TinyVector<TmpType, 2> > grad(lr-ul); | | BasicImage<TinyVector<TmpType, 2> > grad(lr-ul); | |
| gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale); | | gaussianGradient(srcIterRange(ul, lr, src), destImage(grad), scale); | |
| | | | |
| cannyEdgelList3x3Threshold(srcImageRange(grad), edgels, grad_thresh); | | cannyEdgelList3x3Threshold(srcImageRange(grad), edgels, grad_thresh); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
|
| inline void | | | |
| cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAccessor> sr | | | |
| c, | | | |
| BackInsertable & edgels, double scale, GradValue | | | |
| grad_thresh) | | | |
| { | | | |
| cannyEdgelList3x3Threshold(src.first, src.second, src.third, edgels, sc | | | |
| ale, grad_thresh); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class BackInsertable, class GradValue> | | | |
| void | | void | |
| cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAccessor src, | | cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAccessor src, | |
| BackInsertable & edgels, GradValue grad_thresh) | | BackInsertable & edgels, GradValue grad_thresh) | |
| { | | { | |
| UInt8Image edges(lr-ul); | | UInt8Image edges(lr-ul); | |
| cannyEdgeImageFromGradWithThinning(srcIterRange(ul, lr, src), destImage
(edges), | | cannyEdgeImageFromGradWithThinning(srcIterRange(ul, lr, src), destImage
(edges), | |
| 0.0, 1, false); | | 0.0, 1, false); | |
| | | | |
| // find edgels | | // find edgels | |
| internalCannyFindEdgels3x3(ul, src, edges, edgels, grad_thresh); | | internalCannyFindEdgels3x3(ul, src, edges, edgels, grad_thresh); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class BackInsertable, class GradValue> | | class BackInsertable, class GradValue> | |
| inline void | | inline void | |
| cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAccessor> sr
c, | | cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAccessor> sr
c, | |
|
| | | BackInsertable & edgels, double scale, GradValue | |
| | | grad_thresh) | |
| | | { | |
| | | cannyEdgelList3x3Threshold(src.first, src.second, src.third, edgels, sc | |
| | | ale, grad_thresh); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class BackInsertable, class GradValue> | |
| | | inline void | |
| | | cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAccessor> sr | |
| | | c, | |
| BackInsertable & edgels, GradValue grad_thresh) | | BackInsertable & edgels, GradValue grad_thresh) | |
| { | | { | |
| cannyEdgelList3x3Threshold(src.first, src.second, src.third, edgels, gr
ad_thresh); | | cannyEdgelList3x3Threshold(src.first, src.second, src.third, edgels, gr
ad_thresh); | |
| } | | } | |
| | | | |
|
| | | template <class T, class S, | |
| | | class BackInsertable, class GradValue> | |
| | | inline void | |
| | | cannyEdgelList3x3Threshold(MultiArrayView<2, T, S> const & src, | |
| | | BackInsertable & edgels, double scale, GradValue | |
| | | grad_thresh) | |
| | | { | |
| | | cannyEdgelList3x3Threshold(srcImageRange(src), edgels, scale, grad_thre | |
| | | sh); | |
| | | } | |
| | | | |
| | | template <class T, class S, | |
| | | class BackInsertable, class GradValue> | |
| | | inline void | |
| | | cannyEdgelList3x3Threshold(MultiArrayView<2, TinyVector<T, 2>, S> const & s | |
| | | rc, | |
| | | BackInsertable & edgels, | |
| | | GradValue grad_thresh) | |
| | | { | |
| | | cannyEdgelList3x3Threshold(srcImageRange(src), edgels, grad_thresh); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| /** \page CrackEdgeImage Crack Edge Image | | /** \page CrackEdgeImage Crack Edge Image | |
| | | | |
| Crack edges are marked <i>between</i> the pixels of an image. | | Crack edges are marked <i>between</i> the pixels of an image. | |
| A Crack Edge Image is an image that represents these edges. In order | | A Crack Edge Image is an image that represents these edges. In order | |
| to accommodate the cracks, the Crack Edge Image must be twice as large | | to accommodate the cracks, the Crack Edge Image must be twice as large | |
| as the original image (precisely (2*w - 1) by (2*h - 1)). A Crack Edge Imag
e | | as the original image (precisely (2*w - 1) by (2*h - 1)). A Crack Edge Imag
e | |
| can easily be derived from a binary image or from the signs of the | | can easily be derived from a binary image or from the signs of the | |
| response of a Laplacian filter. Consider the following sketch, where | | response of a Laplacian filter. Consider the following sketch, where | |
| | | | |
End of changes. 152 change blocks. |
| 267 lines changed or deleted | | 781 lines changed or added | |
|
| flatmorphology.hxx | | flatmorphology.hxx | |
| | | | |
| skipping to change at line 42 | | skipping to change at line 42 | |
| /* OTHER DEALINGS IN THE SOFTWARE. */ | | /* OTHER DEALINGS IN THE SOFTWARE. */ | |
| /* */ | | /* */ | |
| /************************************************************************/ | | /************************************************************************/ | |
| | | | |
| #ifndef VIGRA_FLATMORPHOLOGY_HXX | | #ifndef VIGRA_FLATMORPHOLOGY_HXX | |
| #define VIGRA_FLATMORPHOLOGY_HXX | | #define VIGRA_FLATMORPHOLOGY_HXX | |
| | | | |
| #include <cmath> | | #include <cmath> | |
| #include <vector> | | #include <vector> | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup Morphology Basic Morphological Operations | | /** \addtogroup Morphology Basic Morphological Operations | |
| Perform erosion, dilation, and median with disc structuring functions | | Perform erosion, dilation, and median with disc structuring functions | |
| | | | |
| See also: \ref MultiArrayMorphology Separable morphology with parabola
structuring functions in arbitrary dimensions | | See also: \ref MultiArrayMorphology Separable morphology with parabola
structuring functions in arbitrary dimensions | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| | | | |
| skipping to change at line 68 | | skipping to change at line 69 | |
| /** \brief Apply rank order filter with disc structuring function to the im
age. | | /** \brief Apply rank order filter with disc structuring function to the im
age. | |
| | | | |
| The pixel values of the source image <b> must</b> be in the range | | The pixel values of the source image <b> must</b> be in the range | |
| 0...255. Radius must be >= 0. Rank must be in the range 0.0 <= rank | | 0...255. Radius must be >= 0. Rank must be in the range 0.0 <= rank | |
| <= 1.0. The filter acts as a minimum filter if rank = 0.0, | | <= 1.0. The filter acts as a minimum filter if rank = 0.0, | |
| as a median if rank = 0.5, and as a maximum filter if rank = 1.0. | | as a median if rank = 0.5, and as a maximum filter if rank = 1.0. | |
| Accessor are used to access the pixel data. | | Accessor are used to access the pixel data. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | discRankOrderFilter(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius, float rank); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{discRankOrderFilter} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discRankOrderFilter(SrcIterator upperleft1, | | discRankOrderFilter(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius, float rank) | | int radius, float rank) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discRankOrderFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | | discRankOrderFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius, float rank) | | int radius, float rank) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/flatmorphology.hxx\><br> | | <b>\#include</b> \<vigra/flatmorphology.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w, h), dest(w, h); | |
| | | | |
| | | // do median filtering (because rank=0.5) in a cricle with radius 10 | |
| | | discRankOrderFilter(src, dest, 10, 0.5); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{discRankOrderFilter} | |
| | | \code | |
| vigra::CImage src, dest; | | vigra::CImage src, dest; | |
| | | | |
| // do median filtering | | // do median filtering | |
| vigra::discRankOrderFilter(srcImageRange(src), destImage(dest), 10, 0.5
); | | vigra::discRankOrderFilter(srcImageRange(src), destImage(dest), 10, 0.5
); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcIterator src_upperleft; | | SrcIterator src_upperleft; | |
| DestIterator dest_upperleft; | | DestIterator dest_upperleft; | |
| int x, y; | | int x, y; | |
| unsigned char value; | | unsigned char value; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| // value_type of accessor must be convertible to unsigned char | | // value_type of accessor must be convertible to unsigned char | |
| value = src_accessor(src_upperleft, x, y); | | value = src_accessor(src_upperleft, x, y); | |
| | | | |
| dest_accessor.set(value, dest_upperleft, x, y); | | dest_accessor.set(value, dest_upperleft, x, y); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| for all source pixels: 0 <= value <= 255 | | for all source pixels: 0 <= value <= 255 | |
| | | | |
| (rank >= 0.0) && (rank <= 1.0) | | (rank >= 0.0) && (rank <= 1.0) | |
| radius >= 0 | | radius >= 0 | |
| \endcode | | \endcode | |
|
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void discRankOrderFilter) | | doxygen_overloaded_function(template <...> void discRankOrderFilter) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discRankOrderFilter(SrcIterator upperleft1, | | discRankOrderFilter(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius, float rank) | | int radius, float rank) | |
| | | | |
| skipping to change at line 353 | | skipping to change at line 373 | |
| } | | } | |
| } | | } | |
| | | | |
| da.set(rankpos, xd); | | da.set(rankpos, xd); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| void | | inline void | |
| discRankOrderFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | discRankOrderFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius, float rank) | | int radius, float rank) | |
| { | | { | |
| discRankOrderFilter(src.first, src.second, src.third, | | discRankOrderFilter(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| radius, rank); | | radius, rank); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | discRankOrderFilter(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius, float rank) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "discRankOrderFilter(): shape mismatch between input and output."); | |
| | | discRankOrderFilter(srcImageRange(src), | |
| | | destImage(dest), | |
| | | radius, rank); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* discErosion */ | | /* discErosion */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply erosion (minimum) filter with disc of given radius to imag
e. | | /** \brief Apply erosion (minimum) filter with disc of given radius to imag
e. | |
| | | | |
|
| This is an abbreviation vor the rank order filter with rank = 0.0. | | This is an abbreviation for the rank order filter with rank = 0.0. | |
| See \ref discRankOrderFilter() for more information. | | See \ref discRankOrderFilter() for more information. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | discErosion(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{discErosion} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discErosion(SrcIterator upperleft1, | | discErosion(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discErosion(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | discErosion(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void discErosion) | | doxygen_overloaded_function(template <...> void discErosion) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| discErosion(SrcIterator upperleft1, | | discErosion(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| | | | |
| skipping to change at line 432 | | skipping to change at line 478 | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| { | | { | |
| vigra_precondition(radius >= 0, "discErosion(): Radius must be >= 0."); | | vigra_precondition(radius >= 0, "discErosion(): Radius must be >= 0."); | |
| | | | |
| discRankOrderFilter(src.first, src.second, src.third, | | discRankOrderFilter(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| radius, 0.0); | | radius, 0.0); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | discErosion(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "discErosion(): shape mismatch between input and output."); | |
| | | discErosion(srcImageRange(src), destImage(dest), radius); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* discDilation */ | | /* discDilation */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply dilation (maximum) filter with disc of given radius to ima
ge. | | /** \brief Apply dilation (maximum) filter with disc of given radius to ima
ge. | |
| | | | |
|
| This is an abbreviation vor the rank order filter with rank = 1.0. | | This is an abbreviation for the rank order filter with rank = 1.0. | |
| See \ref discRankOrderFilter() for more information. | | See \ref discRankOrderFilter() for more information. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | discDilation(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{discDilation} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discDilation(SrcIterator upperleft1, | | discDilation(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discDilation(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | discDilation(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void discDilation) | | doxygen_overloaded_function(template <...> void discDilation) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| discDilation(SrcIterator upperleft1, | | discDilation(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| | | | |
| skipping to change at line 491 | | skipping to change at line 561 | |
| vigra_precondition(radius >= 0, "discDilation(): Radius must be >= 0.")
; | | vigra_precondition(radius >= 0, "discDilation(): Radius must be >= 0.")
; | |
| | | | |
| discRankOrderFilter(upperleft1, lowerright1, sa, | | discRankOrderFilter(upperleft1, lowerright1, sa, | |
| upperleft2, da, radius, 1.0); | | upperleft2, da, radius, 1.0); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discDilation(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | discDilation(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| { | | { | |
| vigra_precondition(radius >= 0, "discDilation(): Radius must be >= 0.")
; | | vigra_precondition(radius >= 0, "discDilation(): Radius must be >= 0.")
; | |
| | | | |
| discRankOrderFilter(src.first, src.second, src.third, | | discRankOrderFilter(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| radius, 1.0); | | radius, 1.0); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | discDilation(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "discDilation(): shape mismatch between input and output."); | |
| | | discDilation(srcImageRange(src), destImage(dest), radius); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* discMedian */ | | /* discMedian */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply median filter with disc of given radius to image. | | /** \brief Apply median filter with disc of given radius to image. | |
| | | | |
|
| This is an abbreviation vor the rank order filter with rank = 0.5. | | This is an abbreviation for the rank order filter with rank = 0.5. | |
| See \ref discRankOrderFilter() for more information. | | See \ref discRankOrderFilter() for more information. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | discMedian(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{discMedian} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discMedian(SrcIterator upperleft1, | | discMedian(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discMedian(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | discMedian(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void discMedian) | | doxygen_overloaded_function(template <...> void discMedian) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| discMedian(SrcIterator upperleft1, | | discMedian(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| | | | |
| skipping to change at line 560 | | skipping to change at line 654 | |
| vigra_precondition(radius >= 0, "discMedian(): Radius must be >= 0."); | | vigra_precondition(radius >= 0, "discMedian(): Radius must be >= 0."); | |
| | | | |
| discRankOrderFilter(upperleft1, lowerright1, sa, | | discRankOrderFilter(upperleft1, lowerright1, sa, | |
| upperleft2, da, radius, 0.5); | | upperleft2, da, radius, 0.5); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discMedian(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | discMedian(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| { | | { | |
| vigra_precondition(radius >= 0, "discMedian(): Radius must be >= 0."); | | vigra_precondition(radius >= 0, "discMedian(): Radius must be >= 0."); | |
| | | | |
| discRankOrderFilter(src.first, src.second, src.third, | | discRankOrderFilter(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| radius, 0.5); | | radius, 0.5); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | discMedian(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "discMedian(): shape mismatch between input and output."); | |
| | | discMedian(srcImageRange(src), destImage(dest), radius); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* discRankOrderFilterWithMask */ | | /* discRankOrderFilterWithMask */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply rank order filter with disc structuring function to the im
age | | /** \brief Apply rank order filter with disc structuring function to the im
age | |
| using a mask. | | using a mask. | |
| | | | |
| The pixel values of the source image <b> must</b> be in the range | | The pixel values of the source image <b> must</b> be in the range | |
| | | | |
| skipping to change at line 592 | | skipping to change at line 698 | |
| as a median if rank = 0.5, and as a maximum filter if rank = 1.0. | | as a median if rank = 0.5, and as a maximum filter if rank = 1.0. | |
| Accessor are used to access the pixel data. | | Accessor are used to access the pixel data. | |
| | | | |
| The mask is only applied to th input image, i.e. the function | | The mask is only applied to th input image, i.e. the function | |
| generates an output wherever the current disc contains at least | | generates an output wherever the current disc contains at least | |
| one pixel with mask value 'true'. Source pixels with mask value | | one pixel with mask value 'true'. Source pixels with mask value | |
| 'false' are ignored during the calculation of the rank order. | | 'false' are ignored during the calculation of the rank order. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class TM, class SM, | |
| | | class T2, class S2> | |
| | | void | |
| | | discRankOrderFilterWithMask(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius, float rank); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{discRankOrderFilterWithMask} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discRankOrderFilterWithMask(SrcIterator upperleft1, | | discRankOrderFilterWithMask(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa
, | | SrcIterator lowerright1, SrcAccessor sa
, | |
| MaskIterator upperleftm, MaskAccessor m
ask, | | MaskIterator upperleftm, MaskAccessor m
ask, | |
| DestIterator upperleft2, DestAccessor d
a, | | DestIterator upperleft2, DestAccessor d
a, | |
| int radius, float rank) | | int radius, float rank) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| group arguments (use in conjunction with \ref ArgumentObjectFactories): | | group arguments (use in conjunction with \ref ArgumentObjectFactories): | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discRankOrderFilterWithMask(triple<SrcIterator, SrcIterator, SrcAcc
essor> src, | | discRankOrderFilterWithMask(triple<SrcIterator, SrcIterator, SrcAcc
essor> src, | |
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius, float rank) | | int radius, float rank) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/flatmorphology.hxx\><br> | | <b>\#include</b> \<vigra/flatmorphology.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w, h), dest(w, h), mask(w, h); | |
| | | ... | |
| | | // do median filtering (since rank=0.5) in a circle with radius 10 | |
| | | // but change only the pixels under the mask | |
| | | discRankOrderFilterWithMask(src, mask, dest, 10, 0.5); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{discRankOrderFilterWithMask} | |
| | | \code | |
| vigra::CImage src, dest, mask; | | vigra::CImage src, dest, mask; | |
| | | | |
| // do median filtering | | // do median filtering | |
| vigra::discRankOrderFilterWithMask(srcImageRange(src), | | vigra::discRankOrderFilterWithMask(srcImageRange(src), | |
| maskImage(mask), destImage(dest), 10, 0.5); | | maskImage(mask), destImage(dest), 10, 0.5); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcIterator src_upperleft; | | SrcIterator src_upperleft; | |
| DestIterator dest_upperleft; | | DestIterator dest_upperleft; | |
| MaskIterator mask_upperleft; | | MaskIterator mask_upperleft; | |
| int x, y; | | int x, y; | |
| unsigned char value; | | unsigned char value; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| MaskAccessor mask_accessor; | | MaskAccessor mask_accessor; | |
| | | | |
| mask_accessor(mask_upperleft, x, y) // convertible to bool | | mask_accessor(mask_upperleft, x, y) // convertible to bool | |
| | | | |
| // value_type of accessor must be convertible to unsigned char | | // value_type of accessor must be convertible to unsigned char | |
| value = src_accessor(src_upperleft, x, y); | | value = src_accessor(src_upperleft, x, y); | |
| | | | |
| dest_accessor.set(value, dest_upperleft, x, y); | | dest_accessor.set(value, dest_upperleft, x, y); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| for all source pixels: 0 <= value <= 255 | | for all source pixels: 0 <= value <= 255 | |
| | | | |
| (rank >= 0.0) && (rank <= 1.0) | | (rank >= 0.0) && (rank <= 1.0) | |
| radius >= 0 | | radius >= 0 | |
| \endcode | | \endcode | |
|
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void discRankOrderFilterWithMask
) | | doxygen_overloaded_function(template <...> void discRankOrderFilterWithMask
) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discRankOrderFilterWithMask(SrcIterator upperleft1, | | discRankOrderFilterWithMask(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| MaskIterator upperleftm, MaskAccessor mask, | | MaskIterator upperleftm, MaskAccessor mask, | |
| | | | |
| skipping to change at line 927 | | skipping to change at line 1055 | |
| leftsum = 0; | | leftsum = 0; | |
| rankpos = 0; | | rankpos = 0; | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| void | | inline void | |
| discRankOrderFilterWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | | discRankOrderFilterWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | |
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius, float rank) | | int radius, float rank) | |
| { | | { | |
| discRankOrderFilterWithMask(src.first, src.second, src.third, | | discRankOrderFilterWithMask(src.first, src.second, src.third, | |
|
| mask.first, mask.second, | | mask.first, mask.second, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| radius, rank); | | radius, rank); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class TM, class SM, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | discRankOrderFilterWithMask(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius, float rank) | |
| | | { | |
| | | vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.s | |
| | | hape(), | |
| | | "discRankOrderFilterWithMask(): shape mismatch between input and ou | |
| | | tput."); | |
| | | discRankOrderFilterWithMask(srcImageRange(src), | |
| | | maskImage(mask), | |
| | | destImage(dest), | |
| | | radius, rank); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* discErosionWithMask */ | | /* discErosionWithMask */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply erosion (minimum) filter with disc of given radius to imag
e | | /** \brief Apply erosion (minimum) filter with disc of given radius to imag
e | |
| using a mask. | | using a mask. | |
| | | | |
|
| This is an abbreviation vor the masked rank order filter with | | This is an abbreviation for the masked rank order filter with | |
| rank = 0.0. See \ref discRankOrderFilterWithMask() for more information
. | | rank = 0.0. See \ref discRankOrderFilterWithMask() for more information
. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class TM, class SM, | |
| | | class T2, class S2> | |
| | | void | |
| | | discErosionWithMask(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{discErosionWithMask} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discErosionWithMask(SrcIterator upperleft1, | | discErosionWithMask(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| MaskIterator upperleftm, MaskAccessor mask, | | MaskIterator upperleftm, MaskAccessor mask, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| group arguments (use in conjunction with \ref ArgumentObjectFactories): | | group arguments (use in conjunction with \ref ArgumentObjectFactories): | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discErosionWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | | discErosionWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | |
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void discErosionWithMask) | | doxygen_overloaded_function(template <...> void discErosionWithMask) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| discErosionWithMask(SrcIterator upperleft1, | | discErosionWithMask(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| MaskIterator upperleftm, MaskAccessor mask, | | MaskIterator upperleftm, MaskAccessor mask, | |
| | | | |
| skipping to change at line 1015 | | skipping to change at line 1174 | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| discErosionWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | discErosionWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| { | | { | |
| vigra_precondition(radius >= 0, "discErosionWithMask(): Radius must be
>= 0."); | | vigra_precondition(radius >= 0, "discErosionWithMask(): Radius must be
>= 0."); | |
| | | | |
| discRankOrderFilterWithMask(src.first, src.second, src.third, | | discRankOrderFilterWithMask(src.first, src.second, src.third, | |
|
| mask.first, mask.second, | | mask.first, mask.second, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| radius, 0.0); | | radius, 0.0); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class TM, class SM, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | discErosionWithMask(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius) | |
| | | { | |
| | | vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.s | |
| | | hape(), | |
| | | "discErosionWithMask(): shape mismatch between input and output."); | |
| | | discErosionWithMask(srcImageRange(src), maskImage(mask), destImage(dest | |
| | | ), radius); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* discDilationWithMask */ | | /* discDilationWithMask */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply dilation (maximum) filter with disc of given radius to ima
ge | | /** \brief Apply dilation (maximum) filter with disc of given radius to ima
ge | |
| using a mask. | | using a mask. | |
| | | | |
|
| This is an abbreviation vor the masked rank order filter with | | This is an abbreviation for the masked rank order filter with | |
| rank = 1.0. See \ref discRankOrderFilterWithMask() for more information
. | | rank = 1.0. See \ref discRankOrderFilterWithMask() for more information
. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class TM, class SM, | |
| | | class T2, class S2> | |
| | | void | |
| | | discDilationWithMask(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{discDilationWithMask} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discDilationWithMask(SrcIterator upperleft1, | | discDilationWithMask(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| MaskIterator upperleftm, MaskAccessor mask, | | MaskIterator upperleftm, MaskAccessor mask, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| group arguments (use in conjunction with \ref ArgumentObjectFactories): | | group arguments (use in conjunction with \ref ArgumentObjectFactories): | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discDilationWithMask(triple<SrcIterator, SrcIterator, SrcAccessor>
src, | | discDilationWithMask(triple<SrcIterator, SrcIterator, SrcAccessor>
src, | |
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void discDilationWithMask) | | doxygen_overloaded_function(template <...> void discDilationWithMask) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| discDilationWithMask(SrcIterator upperleft1, | | discDilationWithMask(SrcIterator upperleft1, | |
|
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| MaskIterator upperleftm, MaskAccessor mask, | | MaskIterator upperleftm, MaskAccessor mask, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| { | | { | |
| vigra_precondition(radius >= 0, "discDilationWithMask(): Radius must be
>= 0."); | | vigra_precondition(radius >= 0, "discDilationWithMask(): Radius must be
>= 0."); | |
| | | | |
| discRankOrderFilterWithMask(upperleft1, lowerright1, sa, | | discRankOrderFilterWithMask(upperleft1, lowerright1, sa, | |
| upperleftm, mask, | | upperleftm, mask, | |
| upperleft2, da, | | upperleft2, da, | |
| radius, 1.0); | | radius, 1.0); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| discDilationWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | discDilationWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| { | | { | |
| vigra_precondition(radius >= 0, "discDilationWithMask(): Radius must be
>= 0."); | | vigra_precondition(radius >= 0, "discDilationWithMask(): Radius must be
>= 0."); | |
| | | | |
| discRankOrderFilterWithMask(src.first, src.second, src.third, | | discRankOrderFilterWithMask(src.first, src.second, src.third, | |
|
| mask.first, mask.second, | | mask.first, mask.second, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| radius, 1.0); | | radius, 1.0); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class TM, class SM, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | discDilationWithMask(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius) | |
| | | { | |
| | | vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.s | |
| | | hape(), | |
| | | "discDilationWithMask(): shape mismatch between input and output.") | |
| | | ; | |
| | | discDilationWithMask(srcImageRange(src), maskImage(mask), destImage(des | |
| | | t), radius); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* discMedianWithMask */ | | /* discMedianWithMask */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply median filter with disc of given radius to image | | /** \brief Apply median filter with disc of given radius to image | |
| using a mask. | | using a mask. | |
| | | | |
|
| This is an abbreviation vor the masked rank order filter with | | This is an abbreviation for the masked rank order filter with | |
| rank = 0.5. See \ref discRankOrderFilterWithMask() for more information
. | | rank = 0.5. See \ref discRankOrderFilterWithMask() for more information
. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class TM, class SM, | |
| | | class T2, class S2> | |
| | | void | |
| | | discMedianWithMask(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{discMedianWithMask} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discMedianWithMask(SrcIterator upperleft1, | | discMedianWithMask(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| MaskIterator upperleftm, MaskAccessor mask, | | MaskIterator upperleftm, MaskAccessor mask, | |
| DestIterator upperleft2, DestAccessor da, | | DestIterator upperleft2, DestAccessor da, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| group arguments (use in conjunction with \ref ArgumentObjectFactories): | | group arguments (use in conjunction with \ref ArgumentObjectFactories): | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| discMedianWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> sr
c, | | discMedianWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> sr
c, | |
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void discMedianWithMask) | | doxygen_overloaded_function(template <...> void discMedianWithMask) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| discMedianWithMask(SrcIterator upperleft1, | | discMedianWithMask(SrcIterator upperleft1, | |
| SrcIterator lowerright1, SrcAccessor sa, | | SrcIterator lowerright1, SrcAccessor sa, | |
| MaskIterator upperleftm, MaskAccessor mask, | | MaskIterator upperleftm, MaskAccessor mask, | |
| | | | |
| skipping to change at line 1170 | | skipping to change at line 1385 | |
| upperleftm, mask, | | upperleftm, mask, | |
| upperleft2, da, | | upperleft2, da, | |
| radius, 0.5); | | radius, 0.5); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| discMedianWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | discMedianWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| int radius) | | int radius) | |
| { | | { | |
| vigra_precondition(radius >= 0, "discMedianWithMask(): Radius must be >
= 0."); | | vigra_precondition(radius >= 0, "discMedianWithMask(): Radius must be >
= 0."); | |
| | | | |
| discRankOrderFilterWithMask(src.first, src.second, src.third, | | discRankOrderFilterWithMask(src.first, src.second, src.third, | |
| mask.first, mask.second, | | mask.first, mask.second, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| radius, 0.5); | | radius, 0.5); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class TM, class SM, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | discMedianWithMask(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | int radius) | |
| | | { | |
| | | vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.s | |
| | | hape(), | |
| | | "discMedianWithMask(): shape mismatch between input and output."); | |
| | | discMedianWithMask(srcImageRange(src), maskImage(mask), destImage(dest) | |
| | | , radius); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_FLATMORPHOLOGY_HXX | | #endif // VIGRA_FLATMORPHOLOGY_HXX | |
| | | | |
End of changes. 57 change blocks. |
| 60 lines changed or deleted | | 298 lines changed or added | |
|
| hdf5impex.hxx | | hdf5impex.hxx | |
| | | | |
| skipping to change at line 40 | | skipping to change at line 40 | |
| /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | | /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | |
| /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | | /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | |
| /* OTHER DEALINGS IN THE SOFTWARE. */ | | /* OTHER DEALINGS IN THE SOFTWARE. */ | |
| /* */ | | /* */ | |
| /************************************************************************/ | | /************************************************************************/ | |
| | | | |
| #ifndef VIGRA_HDF5IMPEX_HXX | | #ifndef VIGRA_HDF5IMPEX_HXX | |
| #define VIGRA_HDF5IMPEX_HXX | | #define VIGRA_HDF5IMPEX_HXX | |
| | | | |
| #include <string> | | #include <string> | |
|
| | | #include <algorithm> | |
| | | #include <utility> | |
| | | | |
| #define H5Gcreate_vers 2 | | #define H5Gcreate_vers 2 | |
| #define H5Gopen_vers 2 | | #define H5Gopen_vers 2 | |
| #define H5Dopen_vers 2 | | #define H5Dopen_vers 2 | |
| #define H5Dcreate_vers 2 | | #define H5Dcreate_vers 2 | |
| #define H5Acreate_vers 2 | | #define H5Acreate_vers 2 | |
| | | | |
| #include <hdf5.h> | | #include <hdf5.h> | |
| | | | |
| #if (H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6) | | #if (H5_VERS_MAJOR == 1 && H5_VERS_MINOR <= 6) | |
| | | | |
| skipping to change at line 75 | | skipping to change at line 77 | |
| # ifndef H5Pset_obj_track_times | | # ifndef H5Pset_obj_track_times | |
| # define H5Pset_obj_track_times(a, b) do {} while (0) | | # define H5Pset_obj_track_times(a, b) do {} while (0) | |
| # endif | | # endif | |
| # include <H5LT.h> | | # include <H5LT.h> | |
| #else | | #else | |
| # include <hdf5_hl.h> | | # include <hdf5_hl.h> | |
| #endif | | #endif | |
| | | | |
| #include "impex.hxx" | | #include "impex.hxx" | |
| #include "multi_array.hxx" | | #include "multi_array.hxx" | |
|
| | | #include "multi_iterator_coupled.hxx" | |
| #include "multi_impex.hxx" | | #include "multi_impex.hxx" | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "error.hxx" | | #include "error.hxx" | |
| | | | |
|
| #include <algorithm> | | #if defined(_MSC_VER) | |
| | | # include <io.h> | |
| | | #else | |
| | | # include <unistd.h> | |
| | | #endif | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup VigraHDF5Impex Import/Export of Images and Arrays in HDF5 F
ormat | | /** \addtogroup VigraHDF5Impex Import/Export of Images and Arrays in HDF5 F
ormat | |
| | | | |
| Supports arrays with arbitrary element types and arbitrary many dimensi
ons. | | Supports arrays with arbitrary element types and arbitrary many dimensi
ons. | |
| See the <a href="http://www.hdfgroup.org/HDF5/">HDF5 Website</a> for mo
re | | See the <a href="http://www.hdfgroup.org/HDF5/">HDF5 Website</a> for mo
re | |
| information on the HDF5 file format. | | information on the HDF5 file format. | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
|
| /** \brief Wrapper for hid_t objects. | | /** \brief Check if given filename refers to a HDF5 file. | |
| | | */ | |
| | | inline bool isHDF5(char const * filename) | |
| | | { | |
| | | #ifdef _MSC_VER | |
| | | return _access(filename, 0) != -1 && H5Fis_hdf5(filename); | |
| | | #else | |
| | | return access(filename, F_OK) == 0 && H5Fis_hdf5(filename); | |
| | | #endif | |
| | | } | |
| | | | |
| | | /** \brief Temporarily disable HDF5's native error output. | |
| | | | |
| | | This should be used when you want to call an HDF5 function | |
| | | that is known to fail (e.g. during testing), or when you want | |
| | | to use an alternative error reporting mechanism (e.g. exceptions). | |
| | | | |
| | | <b>Usage:</b> | |
| | | | |
| | | <b>\#include</b> \<vigra/hdf5impex.hxx\><br> | |
| | | Namespace: vigra | |
| | | \code | |
| | | { | |
| | | HDF5DisableErrorOutput hdf5DisableErrorOutput; | |
| | | | |
| | | ... // call some HDF5 function | |
| | | | |
| | | } // restore the original error reporting in the destructor of HDF5 | |
| | | DisableErrorOutput | |
| | | \endcode | |
| | | */ | |
| | | class HDF5DisableErrorOutput | |
| | | { | |
| | | H5E_auto2_t old_func_; | |
| | | void *old_client_data_; | |
| | | | |
| | | HDF5DisableErrorOutput(HDF5DisableErrorOutput const &); | |
| | | HDF5DisableErrorOutput & operator=(HDF5DisableErrorOutput const &); | |
| | | | |
| | | public: | |
| | | HDF5DisableErrorOutput() | |
| | | : old_func_(0) | |
| | | , old_client_data_(0) | |
| | | { | |
| | | H5Eget_auto2(H5E_DEFAULT, &old_func_, &old_client_data_); | |
| | | H5Eset_auto2(H5E_DEFAULT, NULL, NULL); | |
| | | } | |
| | | | |
| | | ~HDF5DisableErrorOutput() | |
| | | { | |
| | | H5Eset_auto2(H5E_DEFAULT, old_func_, old_client_data_); | |
| | | } | |
| | | }; | |
| | | | |
| | | /** \brief Wrapper for unique hid_t objects. | |
| | | | |
| | | This class offers the functionality of <tt>std::unique_ptr</tt> for HDF | |
| | | 5 handles | |
| | | (type <tt>hid_t</tt>). Unfortunately, <tt>std::unique_ptr</tt> cannot b | |
| | | e used directly | |
| | | for this purpose because it only works with pointers, whereas <tt>hid_t | |
| | | </tt> is an integer type. | |
| | | | |
|
| Newly created or opened HDF5 handles are usually stored as objects of t
ype 'hid_t'. When the handle | | Newly created or opened HDF5 handles are stored as objects of type <tt>
hid_t</tt>. When the handle | |
| is no longer needed, the appropriate close function must be called. How
ever, if a function is | | is no longer needed, the appropriate close function must be called. How
ever, if a function is | |
| aborted by an exception, this is difficult to ensure. Class HDF5Handle
is a smart pointer that | | aborted by an exception, this is difficult to ensure. Class HDF5Handle
is a smart pointer that | |
| solves this problem by calling the close function in the destructor (Th
is is analogous to how | | solves this problem by calling the close function in the destructor (Th
is is analogous to how | |
|
| VIGRA_UNIQUE_PTR calls 'delete' on the contained pointer). A pointer to | | <tt>std::unique_ptr</tt> calls 'delete' on the contained pointer). A po | |
| the close function must be | | inter to the close function | |
| passed to the constructor, along with an error message that is raised w | | must be passed to the constructor, along with an error message that is | |
| hen creation/opening fails. | | raised when | |
| | | creation/opening fails. | |
| | | | |
|
| Since HDF5Handle objects are convertible to hid_t, they can be used in | | When a <tt>HDF5Handle</tt> is created or assigned from another one, own | |
| the code in place | | ership passes on to the | |
| of the latter. | | left-hand-side handle object, and the right-hand-side objects is resest | |
| | | to a NULL handle. | |
| | | | |
| | | Since <tt>HDF5Handle</tt> objects are convertible to <tt>hid_t</tt>, th | |
| | | ey can be used in the code | |
| | | in place of the latter. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| | | | |
| \code | | \code | |
| HDF5Handle file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT), | | HDF5Handle file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT), | |
| &H5Fclose, | | &H5Fclose, | |
|
| "Error message."); | | "Error message when H5Fopen() fails."); | |
| | | | |
| ... // use file_id in the same way as a plain hid_t object | | ... // use file_id in the same way as a plain hid_t object | |
|
| | | | |
| | | // pass ownership to a new handle object | |
| | | HDF5Handle new_handle(file_id); | |
| | | | |
| | | assert(file_id.get() == 0); | |
| \endcode | | \endcode | |
| | | | |
| <b>\#include</b> \<vigra/hdf5impex.hxx\><br> | | <b>\#include</b> \<vigra/hdf5impex.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| class HDF5Handle | | class HDF5Handle | |
| { | | { | |
| public: | | public: | |
| typedef herr_t (*Destructor)(hid_t); | | typedef herr_t (*Destructor)(hid_t); | |
| | | | |
| | | | |
| skipping to change at line 141 | | skipping to change at line 214 | |
| : handle_( 0 ), | | : handle_( 0 ), | |
| destructor_(0) | | destructor_(0) | |
| {} | | {} | |
| | | | |
| /** \brief Create a wrapper for a hid_t object. | | /** \brief Create a wrapper for a hid_t object. | |
| | | | |
| The hid_t object \a h is assumed to be the return value of an open
or create function. | | The hid_t object \a h is assumed to be the return value of an open
or create function. | |
| It will be closed with the given close function \a destructor as so
on as this | | It will be closed with the given close function \a destructor as so
on as this | |
| HDF5Handle is destructed, except when \a destructor is a NULL point
er (in which | | HDF5Handle is destructed, except when \a destructor is a NULL point
er (in which | |
| case nothing happens at destruction time). If \a h has a value that
indicates | | case nothing happens at destruction time). If \a h has a value that
indicates | |
|
| failed opening or creation (by HDF5 convention, this means if it is
a negative number), | | failed opening or creation (by HDF5 convention, this means that \a
h is negative), | |
| an exception is raised by calling <tt>vigra_fail(error_message)</tt
>. | | an exception is raised by calling <tt>vigra_fail(error_message)</tt
>. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| | | | |
| \code | | \code | |
| HDF5Handle file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT), | | HDF5Handle file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT), | |
| &H5Fclose, | | &H5Fclose, | |
| "Error message."); | | "Error message."); | |
| | | | |
| ... // use file_id in the same way | | ... // use file_id in the same way | |
| | | | |
| skipping to change at line 163 | | skipping to change at line 236 | |
| */ | | */ | |
| HDF5Handle(hid_t h, Destructor destructor, const char * error_message) | | HDF5Handle(hid_t h, Destructor destructor, const char * error_message) | |
| : handle_( h ), | | : handle_( h ), | |
| destructor_(destructor) | | destructor_(destructor) | |
| { | | { | |
| if(handle_ < 0) | | if(handle_ < 0) | |
| vigra_fail(error_message); | | vigra_fail(error_message); | |
| } | | } | |
| | | | |
| /** \brief Copy constructor. | | /** \brief Copy constructor. | |
|
| Hands over ownership of the RHS handle (analogous to VIGRA_UNIQ | | | |
| UE_PTR). | | Hands over ownership of the RHS handle (analogous to <tt>std::u | |
| | | nique_pt</tt>). | |
| */ | | */ | |
| HDF5Handle(HDF5Handle const & h) | | HDF5Handle(HDF5Handle const & h) | |
| : handle_( h.handle_ ), | | : handle_( h.handle_ ), | |
| destructor_(h.destructor_) | | destructor_(h.destructor_) | |
| { | | { | |
| const_cast<HDF5Handle &>(h).handle_ = 0; | | const_cast<HDF5Handle &>(h).handle_ = 0; | |
| } | | } | |
| | | | |
| /** \brief Assignment. | | /** \brief Assignment. | |
| Calls close() for the LHS handle and hands over ownership of th
e | | Calls close() for the LHS handle and hands over ownership of th
e | |
|
| RHS handle (analogous to VIGRA_UNIQUE_PTR). | | RHS handle (analogous to <tt>std::unique_pt</tt>). | |
| */ | | */ | |
| HDF5Handle & operator=(HDF5Handle const & h) | | HDF5Handle & operator=(HDF5Handle const & h) | |
| { | | { | |
| if(h.handle_ != handle_) | | if(h.handle_ != handle_) | |
| { | | { | |
| close(); | | close(); | |
| handle_ = h.handle_; | | handle_ = h.handle_; | |
| destructor_ = h.destructor_; | | destructor_ = h.destructor_; | |
| const_cast<HDF5Handle &>(h).handle_ = 0; | | const_cast<HDF5Handle &>(h).handle_ = 0; | |
| } | | } | |
| | | | |
| skipping to change at line 196 | | skipping to change at line 270 | |
| } | | } | |
| | | | |
| /** \brief Destructor. | | /** \brief Destructor. | |
| Calls close() for the contained handle. | | Calls close() for the contained handle. | |
| */ | | */ | |
| ~HDF5Handle() | | ~HDF5Handle() | |
| { | | { | |
| close(); | | close(); | |
| } | | } | |
| | | | |
|
| /** \brief Explicitly call the stored function (if one has been sto | | /** \brief Explicitly call the stored destructor (if one has been r | |
| red within | | egistered in the | |
| this object) for the contained handle and set the handle to NU | | constructor) for the contained handle and set the wrapper to N | |
| LL. | | ULL. Returns | |
| | | a negative value when the destructor call for the handle fails | |
| | | , and | |
| | | a non-negative value otherwise. | |
| */ | | */ | |
| herr_t close() | | herr_t close() | |
| { | | { | |
| herr_t res = 1; | | herr_t res = 1; | |
| if(handle_ && destructor_) | | if(handle_ && destructor_) | |
| res = (*destructor_)(handle_); | | res = (*destructor_)(handle_); | |
| handle_ = 0; | | handle_ = 0; | |
|
| | | destructor_ = 0; | |
| | | return res; | |
| | | } | |
| | | | |
| | | /** \brief Return the contained handle and set the wrapper to NULL | |
| | | without calling <tt>close()</tt>. | |
| | | */ | |
| | | hid_t release() | |
| | | { | |
| | | hid_t res = handle_; | |
| | | handle_ = 0; | |
| | | destructor_ = 0; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
|
| | | /** \brief Reset the wrapper to a new handle. | |
| | | | |
| | | Equivalent to <tt>handle = HDF5Handle(h, destructor, error_mes | |
| | | sage)</tt>. | |
| | | */ | |
| | | void reset(hid_t h, Destructor destructor, const char * error_message) | |
| | | { | |
| | | if(h < 0) | |
| | | vigra_fail(error_message); | |
| | | if(h != handle_) | |
| | | { | |
| | | close(); | |
| | | handle_ = h; | |
| | | destructor_ = destructor; | |
| | | } | |
| | | } | |
| | | | |
| | | /** \brief Swap the contents of two handle wrappers. | |
| | | | |
| | | Also available as <tt>std::swap(handle1, handle2)</tt>. | |
| | | */ | |
| | | void swap(HDF5Handle & h) | |
| | | { | |
| | | std::swap(handle_, h.handle_); | |
| | | std::swap(destructor_, h.destructor_); | |
| | | } | |
| | | | |
| /** \brief Get a temporary hid_t object for the contained handle. | | /** \brief Get a temporary hid_t object for the contained handle. | |
| Do not call a close function on the return value - a crash will
be likely | | Do not call a close function on the return value - a crash will
be likely | |
| otherwise. | | otherwise. | |
| */ | | */ | |
| hid_t get() const | | hid_t get() const | |
| { | | { | |
| return handle_; | | return handle_; | |
| } | | } | |
| | | | |
| /** \brief Convert to a plain hid_t object. | | /** \brief Convert to a plain hid_t object. | |
| | | | |
| skipping to change at line 257 | | skipping to change at line 371 | |
| } | | } | |
| | | | |
| /** \brief Inequality comparison of the contained handle. | | /** \brief Inequality comparison of the contained handle. | |
| */ | | */ | |
| bool operator!=(hid_t h) const | | bool operator!=(hid_t h) const | |
| { | | { | |
| return handle_ != h; | | return handle_ != h; | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| | | /** \brief Wrapper for shared hid_t objects. | |
| | | | |
| | | This class offers the functionality of <tt>std::shared_ptr</tt> for HDF | |
| | | 5 handles | |
| | | (type <tt>hid_t</tt>). Unfortunately, <tt>std::shared_ptr</tt> cannot b | |
| | | e used directly | |
| | | for this purpose because it only works with pointers, whereas <tt>hid_t | |
| | | </tt> is an integer type. | |
| | | | |
| | | Newly created or opened HDF5 handles are stored as objects of type <tt> | |
| | | hid_t</tt>. When the handle | |
| | | is no longer needed, the appropriate close function must be called. How | |
| | | ever, if a function is | |
| | | aborted by an exception, this is difficult to ensure. Class HDF5HandleS | |
| | | hared is a smart pointer | |
| | | that solves this problem by calling the close function in the destructo | |
| | | r of the handle's last | |
| | | owner (This is analogous to how <tt>std::shared_ptr</tt> calls 'delete' | |
| | | on the contained | |
| | | pointer). A pointer to the close function must be passed to the constru | |
| | | ctor, along with an error | |
| | | message that is raised when creation/opening fails. | |
| | | | |
| | | When a <tt>HDF5HandleShared</tt> is created or assigned from another on | |
| | | e, ownership is shared | |
| | | between the two handles, and the value returned by <tt>use_count()</tt> | |
| | | increases by one. | |
| | | | |
| | | Since <tt>HDF5HandleShared</tt> objects are convertible to <tt>hid_t</t | |
| | | t>, they can be used in the code | |
| | | in place of the latter. | |
| | | | |
| | | <b>Usage:</b> | |
| | | | |
| | | \code | |
| | | HDF5HandleShared file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAULT), | |
| | | &H5Fclose, | |
| | | "Error message when H5Fopen() fails."); | |
| | | | |
| | | ... // use file_id in the same way as a plain hid_t object | |
| | | | |
| | | // share ownership between same_id and file_id | |
| | | HDF5HandleShared same_id(file_id); | |
| | | assert(same_id.use_count() == 2); | |
| | | assert(same_id.get() == file_id.get()); | |
| | | \endcode | |
| | | | |
| | | <b>\#include</b> \<vigra/hdf5impex.hxx\><br> | |
| | | Namespace: vigra | |
| | | */ | |
| | | class HDF5HandleShared | |
| | | { | |
| | | public: | |
| | | typedef herr_t (*Destructor)(hid_t); | |
| | | | |
| | | private: | |
| | | hid_t handle_; | |
| | | Destructor destructor_; | |
| | | size_t * refcount_; | |
| | | | |
| | | public: | |
| | | | |
| | | /** \brief Default constructor. | |
| | | Creates a NULL handle. | |
| | | **/ | |
| | | HDF5HandleShared() | |
| | | : handle_( 0 ), | |
| | | destructor_(0), | |
| | | refcount_(0) | |
| | | {} | |
| | | | |
| | | /** \brief Create a shared wrapper for a plain hid_t object. | |
| | | | |
| | | The hid_t object \a h is assumed to be the return value of an open | |
| | | or create function. | |
| | | It will be closed with the given close function \a destructor as so | |
| | | on as this | |
| | | HDF5HandleShared is destructed, except when \a destructor is a NULL | |
| | | pointer (in which | |
| | | case nothing happens at destruction time). If \a h has a value that | |
| | | indicates | |
| | | failed opening or creation (by HDF5 convention, this means that \a | |
| | | h is negative), | |
| | | an exception is raised by calling <tt>vigra_fail(error_message)</tt | |
| | | >. | |
| | | | |
| | | <b>Usage:</b> | |
| | | | |
| | | \code | |
| | | HDF5HandleShared file_id(H5Fopen(filename, H5F_ACC_RDWR, H5P_DEFAUL | |
| | | T), | |
| | | &H5Fclose, | |
| | | "Error message."); | |
| | | | |
| | | ... // use file_id in the same way | |
| | | \endcode | |
| | | */ | |
| | | HDF5HandleShared(hid_t h, Destructor destructor, const char * error_mes | |
| | | sage) | |
| | | : handle_( h ), | |
| | | destructor_(destructor), | |
| | | refcount_(0) | |
| | | { | |
| | | if(handle_ < 0) | |
| | | vigra_fail(error_message); | |
| | | if(handle_ > 0) | |
| | | refcount_ = new size_t(1); | |
| | | } | |
| | | | |
| | | /** \brief Copy constructor. | |
| | | Shares ownership with the RHS handle (analogous to <tt>std::sha | |
| | | red_ptr</tt>). | |
| | | */ | |
| | | HDF5HandleShared(HDF5HandleShared const & h) | |
| | | : handle_( h.handle_ ), | |
| | | destructor_(h.destructor_), | |
| | | refcount_(h.refcount_) | |
| | | { | |
| | | if(refcount_) | |
| | | ++(*refcount_); | |
| | | } | |
| | | | |
| | | /** \brief Assignment. | |
| | | Call close() for the present LHS handle and share ownership wit | |
| | | h the | |
| | | RHS handle (analogous to <tt>std::shared_ptr</tt>). | |
| | | */ | |
| | | HDF5HandleShared & operator=(HDF5HandleShared const & h) | |
| | | { | |
| | | if(h.handle_ != handle_) | |
| | | { | |
| | | close(); | |
| | | handle_ = h.handle_; | |
| | | destructor_ = h.destructor_; | |
| | | refcount_ = h.refcount_; | |
| | | if(refcount_) | |
| | | ++(*refcount_); | |
| | | } | |
| | | return *this; | |
| | | } | |
| | | | |
| | | /** \brief Destructor (calls close()) | |
| | | */ | |
| | | ~HDF5HandleShared() | |
| | | { | |
| | | close(); | |
| | | } | |
| | | | |
| | | /** \brief Close the handle if this is the unique (i.e. last) owner | |
| | | . | |
| | | | |
| | | Decrements the reference counter and calls the destructor func | |
| | | tion of | |
| | | the handle (if one has been registered in the constructor) whe | |
| | | n the counter | |
| | | reaches zero. Sets this wrapper to NULL in any case. Returns | |
| | | a negative value when the destructor call for the handle fails | |
| | | , and | |
| | | a non-negative value otherwise. | |
| | | */ | |
| | | herr_t close() | |
| | | { | |
| | | herr_t res = 1; | |
| | | if(refcount_) | |
| | | { | |
| | | --(*refcount_); | |
| | | if(*refcount_ == 0) | |
| | | { | |
| | | if(destructor_) | |
| | | res = (*destructor_)(handle_); | |
| | | delete refcount_; | |
| | | } | |
| | | } | |
| | | handle_ = 0; | |
| | | destructor_ = 0; | |
| | | refcount_ = 0; | |
| | | return res; | |
| | | } | |
| | | | |
| | | /** \brief Reset the handle to a new value. | |
| | | | |
| | | Equivalent to <tt>handle = HDF5HandleShared(h, destructor, err | |
| | | or_message)</tt>. | |
| | | */ | |
| | | void reset(hid_t h, Destructor destructor, const char * error_message) | |
| | | { | |
| | | if(h < 0) | |
| | | vigra_fail(error_message); | |
| | | if(h != handle_) | |
| | | { | |
| | | close(); | |
| | | handle_ = h; | |
| | | destructor_ = destructor; | |
| | | if(handle_ > 0) | |
| | | refcount_ = new size_t(1); | |
| | | } | |
| | | } | |
| | | | |
| | | /** \brief Get the number of owners of the contained handle. | |
| | | */ | |
| | | size_t use_count() const | |
| | | { | |
| | | return refcount_ | |
| | | ? *refcount_ | |
| | | : 0; | |
| | | } | |
| | | | |
| | | /** \brief Check if this is the unique owner of the conatined handl | |
| | | e. | |
| | | | |
| | | Equivalent to <tt>handle.use_count() == 1</tt>. | |
| | | */ | |
| | | bool unique() const | |
| | | { | |
| | | return use_count() == 1; | |
| | | } | |
| | | | |
| | | /** \brief Swap the contents of two handle wrappers. | |
| | | | |
| | | Also available as <tt>std::swap(handle1, handle2)</tt>. | |
| | | */ | |
| | | void swap(HDF5HandleShared & h) | |
| | | { | |
| | | std::swap(handle_, h.handle_); | |
| | | std::swap(destructor_, h.destructor_); | |
| | | std::swap(refcount_, h.refcount_); | |
| | | } | |
| | | | |
| | | /** \brief Get a temporary hid_t object for the contained handle. | |
| | | Do not call a close function on the return value - a crash will | |
| | | be likely | |
| | | otherwise. | |
| | | */ | |
| | | hid_t get() const | |
| | | { | |
| | | return handle_; | |
| | | } | |
| | | | |
| | | /** \brief Convert to a plain hid_t object. | |
| | | | |
| | | This function ensures that hid_t objects can be transparently repla | |
| | | ced with | |
| | | HDF5HandleShared objects in user code. Do not call a close function | |
| | | on the return | |
| | | value - a crash will be likely otherwise. | |
| | | */ | |
| | | operator hid_t() const | |
| | | { | |
| | | return handle_; | |
| | | } | |
| | | | |
| | | /** \brief Equality comparison of the contained handle. | |
| | | */ | |
| | | bool operator==(HDF5HandleShared const & h) const | |
| | | { | |
| | | return handle_ == h.handle_; | |
| | | } | |
| | | | |
| | | /** \brief Equality comparison of the contained handle. | |
| | | */ | |
| | | bool operator==(hid_t h) const | |
| | | { | |
| | | return handle_ == h; | |
| | | } | |
| | | | |
| | | /** \brief Inequality comparison of the contained handle. | |
| | | */ | |
| | | bool operator!=(HDF5HandleShared const & h) const | |
| | | { | |
| | | return handle_ != h.handle_; | |
| | | } | |
| | | | |
| | | /** \brief Inequality comparison of the contained handle. | |
| | | */ | |
| | | bool operator!=(hid_t h) const | |
| | | { | |
| | | return handle_ != h; | |
| | | } | |
| | | }; | |
| | | | |
| | | //@} | |
| | | | |
| | | } // namespace vigra | |
| | | | |
| | | namespace std { | |
| | | | |
| | | inline void swap(vigra::HDF5Handle & l, vigra::HDF5Handle & r) | |
| | | { | |
| | | l.swap(r); | |
| | | } | |
| | | | |
| | | inline void swap(vigra::HDF5HandleShared & l, vigra::HDF5HandleShared & r) | |
| | | { | |
| | | l.swap(r); | |
| | | } | |
| | | | |
| | | } // namespace std | |
| | | | |
| | | namespace vigra { | |
| | | | |
| | | /** \addtogroup VigraHDF5Impex | |
| | | */ | |
| | | //@{ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* HDF5ImportInfo */ | | /* HDF5ImportInfo */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Argument object for the function readHDF5(). | | /** \brief Argument object for the function readHDF5(). | |
| | | | |
| See \ref readHDF5() for a usage example. This object must be | | See \ref readHDF5() for a usage example. This object must be | |
| used to read an image or array from an HDF5 file | | used to read an image or array from an HDF5 file | |
| | | | |
| skipping to change at line 340 | | skipping to change at line 727 | |
| order relative to the file contents. That is, when the axes in
the file are | | order relative to the file contents. That is, when the axes in
the file are | |
| ordered as 'z', 'y', 'x', this function will return the shape i
n the order | | ordered as 'z', 'y', 'x', this function will return the shape i
n the order | |
| 'x', 'y', 'z'. | | 'x', 'y', 'z'. | |
| */ | | */ | |
| VIGRA_EXPORT MultiArrayIndex shapeOfDimension(const int dim) const; | | VIGRA_EXPORT MultiArrayIndex shapeOfDimension(const int dim) const; | |
| | | | |
| /** Query the pixel type of the dataset. | | /** Query the pixel type of the dataset. | |
| | | | |
| Possible values are: | | Possible values are: | |
| <DL> | | <DL> | |
|
| | | <DT>"INT8"<DD> 8-bit signed integer (unsigned char) | |
| <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char) | | <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char) | |
| <DT>"INT16"<DD> 16-bit signed integer (short) | | <DT>"INT16"<DD> 16-bit signed integer (short) | |
| <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short) | | <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short) | |
| <DT>"INT32"<DD> 32-bit signed integer (long) | | <DT>"INT32"<DD> 32-bit signed integer (long) | |
| <DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long) | | <DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long) | |
|
| | | <DT>"INT64"<DD> 64-bit signed integer (long long) | |
| | | <DT>"UINT64"<DD> 64-bit unsigned integer (unsigned long long) | |
| <DT>"FLOAT"<DD> 32-bit floating point (float) | | <DT>"FLOAT"<DD> 32-bit floating point (float) | |
| <DT>"DOUBLE"<DD> 64-bit floating point (double) | | <DT>"DOUBLE"<DD> 64-bit floating point (double) | |
| </DL> | | </DL> | |
| */ | | */ | |
| VIGRA_EXPORT const char * getPixelType() const; | | VIGRA_EXPORT const char * getPixelType() const; | |
| | | | |
| /** Query the pixel type of the dataset. | | /** Query the pixel type of the dataset. | |
| | | | |
| Same as getPixelType(), but the result is returned as a | | Same as getPixelType(), but the result is returned as a | |
| ImageImportInfo::PixelType enum. This is useful to implement | | ImageImportInfo::PixelType enum. This is useful to implement | |
| | | | |
| skipping to change at line 371 | | skipping to change at line 761 | |
| <DT>UINT16<DD> 16-bit unsigned integer (unsigned short) | | <DT>UINT16<DD> 16-bit unsigned integer (unsigned short) | |
| <DT>INT32<DD> 32-bit signed integer (long) | | <DT>INT32<DD> 32-bit signed integer (long) | |
| <DT>UINT32<DD> 32-bit unsigned integer (unsigned long) | | <DT>UINT32<DD> 32-bit unsigned integer (unsigned long) | |
| <DT>FLOAT<DD> 32-bit floating point (float) | | <DT>FLOAT<DD> 32-bit floating point (float) | |
| <DT>DOUBLE<DD> 64-bit floating point (double) | | <DT>DOUBLE<DD> 64-bit floating point (double) | |
| </DL> | | </DL> | |
| */ | | */ | |
| VIGRA_EXPORT PixelType pixelType() const; | | VIGRA_EXPORT PixelType pixelType() const; | |
| | | | |
| private: | | private: | |
|
| HDF5Handle m_file_handle, m_dataset_handle; | | HDF5HandleShared m_file_handle, m_dataset_handle; | |
| std::string m_filename, m_path, m_pixeltype; | | std::string m_filename, m_path, m_pixeltype; | |
| hssize_t m_dimensions; | | hssize_t m_dimensions; | |
| ArrayVector<hsize_t> m_dims; | | ArrayVector<hsize_t> m_dims; | |
| }; | | }; | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
|
| template<class type> | | template <class T> | |
| | | struct HDF5TypeTraits | |
| | | { | |
| | | static hid_t getH5DataType() | |
| | | { | |
| | | std::runtime_error("getH5DataType(): invalid type"); | |
| | | return 0; | |
| | | } | |
| | | | |
| | | static int numberOfBands() | |
| | | { | |
| | | std::runtime_error("numberOfBands(): invalid type"); | |
| | | return 0; | |
| | | } | |
| | | }; | |
| | | | |
| | | template<class T> | |
| inline hid_t getH5DataType() | | inline hid_t getH5DataType() | |
| { | | { | |
|
| std::runtime_error("getH5DataType(): invalid type"); | | return HDF5TypeTraits<T>::getH5DataType(); | |
| return 0; | | | |
| } | | } | |
| | | | |
| #define VIGRA_H5_DATATYPE(type, h5type) \ | | #define VIGRA_H5_DATATYPE(type, h5type) \ | |
|
| template<> \ | | template <> \ | |
| inline hid_t getH5DataType<type>() \ | | struct HDF5TypeTraits<type> \ | |
| { return h5type;} | | { \ | |
| | | static hid_t getH5DataType() \ | |
| | | { \ | |
| | | return h5type; \ | |
| | | } \ | |
| | | static int numberOfBands() \ | |
| | | { \ | |
| | | return 1; \ | |
| | | } \ | |
| | | typedef type value_type; \ | |
| | | }; \ | |
| | | template <int M> \ | |
| | | struct HDF5TypeTraits<TinyVector<type, M> > \ | |
| | | { \ | |
| | | static hid_t getH5DataType() \ | |
| | | { \ | |
| | | return h5type; \ | |
| | | } \ | |
| | | static int numberOfBands() \ | |
| | | { \ | |
| | | return M; \ | |
| | | } \ | |
| | | typedef type value_type; \ | |
| | | }; \ | |
| | | template <> \ | |
| | | struct HDF5TypeTraits<RGBValue<type> > \ | |
| | | { \ | |
| | | static hid_t getH5DataType() \ | |
| | | { \ | |
| | | return h5type; \ | |
| | | } \ | |
| | | static int numberOfBands() \ | |
| | | { \ | |
| | | return 3; \ | |
| | | } \ | |
| | | typedef type value_type; \ | |
| | | }; \ | |
| | | | |
| VIGRA_H5_DATATYPE(char, H5T_NATIVE_CHAR) | | VIGRA_H5_DATATYPE(char, H5T_NATIVE_CHAR) | |
|
| | | VIGRA_H5_DATATYPE(signed char, H5T_NATIVE_SCHAR) | |
| | | VIGRA_H5_DATATYPE(unsigned char, H5T_NATIVE_UCHAR) | |
| | | VIGRA_H5_DATATYPE(signed short, H5T_NATIVE_SHORT) | |
| | | VIGRA_H5_DATATYPE(unsigned short, H5T_NATIVE_USHORT) | |
| | | VIGRA_H5_DATATYPE(signed int, H5T_NATIVE_INT) | |
| | | VIGRA_H5_DATATYPE(unsigned int, H5T_NATIVE_UINT) | |
| | | VIGRA_H5_DATATYPE(signed long, H5T_NATIVE_LONG) | |
| | | VIGRA_H5_DATATYPE(unsigned long, H5T_NATIVE_ULONG) | |
| | | VIGRA_H5_DATATYPE(signed long long, H5T_NATIVE_LLONG) | |
| | | VIGRA_H5_DATATYPE(unsigned long long, H5T_NATIVE_ULLONG) | |
| VIGRA_H5_DATATYPE(float, H5T_NATIVE_FLOAT) | | VIGRA_H5_DATATYPE(float, H5T_NATIVE_FLOAT) | |
| VIGRA_H5_DATATYPE(double, H5T_NATIVE_DOUBLE) | | VIGRA_H5_DATATYPE(double, H5T_NATIVE_DOUBLE) | |
| VIGRA_H5_DATATYPE(long double, H5T_NATIVE_LDOUBLE) | | VIGRA_H5_DATATYPE(long double, H5T_NATIVE_LDOUBLE) | |
| | | | |
| // char arrays with flexible length require 'handcrafted' H5 datatype | | // char arrays with flexible length require 'handcrafted' H5 datatype | |
|
| template<> | | template <> | |
| inline hid_t getH5DataType<char*>() | | struct HDF5TypeTraits<char*> | |
| { | | { | |
|
| hid_t stringtype = H5Tcopy (H5T_C_S1); | | static hid_t getH5DataType() | |
| H5Tset_size(stringtype, H5T_VARIABLE); | | { | |
| return stringtype; | | hid_t stringtype = H5Tcopy (H5T_C_S1); | |
| } | | H5Tset_size(stringtype, H5T_VARIABLE); | |
| template<> | | return stringtype; | |
| inline hid_t getH5DataType<const char*>() | | } | |
| | | | |
| | | static int numberOfBands() | |
| | | { | |
| | | return 1; | |
| | | } | |
| | | }; | |
| | | | |
| | | template <> | |
| | | struct HDF5TypeTraits<const char*> | |
| { | | { | |
|
| hid_t stringtype = H5Tcopy (H5T_C_S1); | | static hid_t getH5DataType() | |
| H5Tset_size(stringtype, H5T_VARIABLE); | | { | |
| return stringtype; | | hid_t stringtype = H5Tcopy (H5T_C_S1); | |
| } | | H5Tset_size(stringtype, H5T_VARIABLE); | |
| #undef VIGRA_H5_DATATYPE | | return stringtype; | |
| | | } | |
| | | | |
|
| #define VIGRA_H5_SIGNED_DATATYPE(type) \ | | static int numberOfBands() | |
| template<> \ | | { | |
| inline hid_t getH5DataType<type>() \ | | return 1; | |
| { static hid_t types[] = {0, H5T_NATIVE_INT8, H5T_NATIVE_INT16, 0, H5T_NATI | | } | |
| VE_INT32, 0,0,0,H5T_NATIVE_INT64}; \ | | }; | |
| return types[sizeof(type)];} | | | |
| | | | |
| VIGRA_H5_SIGNED_DATATYPE(signed char) | | | |
| VIGRA_H5_SIGNED_DATATYPE(signed short) | | | |
| VIGRA_H5_SIGNED_DATATYPE(signed int) | | | |
| VIGRA_H5_SIGNED_DATATYPE(signed long) | | | |
| VIGRA_H5_SIGNED_DATATYPE(signed long long) | | | |
| | | | |
| #undef VIGRA_H5_SIGNED_DATATYPE | | | |
| | | | |
| #define VIGRA_H5_UNSIGNED_DATATYPE(type) \ | | | |
| template<> \ | | | |
| inline hid_t getH5DataType<type>() \ | | | |
| { static hid_t types[] = {0, H5T_NATIVE_UINT8, H5T_NATIVE_UINT16, 0, H5T_NA | | | |
| TIVE_UINT32, 0,0,0,H5T_NATIVE_UINT64}; \ | | | |
| return types[sizeof(type)];} | | | |
| | | | |
| VIGRA_H5_UNSIGNED_DATATYPE(unsigned char) | | | |
| VIGRA_H5_UNSIGNED_DATATYPE(unsigned short) | | | |
| VIGRA_H5_UNSIGNED_DATATYPE(unsigned int) | | | |
| VIGRA_H5_UNSIGNED_DATATYPE(unsigned long) | | | |
| VIGRA_H5_UNSIGNED_DATATYPE(unsigned long long) | | | |
| | | | |
|
| #undef VIGRA_H5_UNSIGNED_DATATYPE | | #undef VIGRA_H5_DATATYPE | |
| | | | |
| #if 0 | | #if 0 | |
| template<> | | template<> | |
| inline hid_t getH5DataType<FFTWComplex<float> >() | | inline hid_t getH5DataType<FFTWComplex<float> >() | |
| { | | { | |
| hid_t complex_id = H5Tcreate (H5T_COMPOUND, sizeof (FFTWComplex<float>)
); | | hid_t complex_id = H5Tcreate (H5T_COMPOUND, sizeof (FFTWComplex<float>)
); | |
| H5Tinsert (complex_id, "real", 0, H5T_NATIVE_FLOAT); | | H5Tinsert (complex_id, "real", 0, H5T_NATIVE_FLOAT); | |
| H5Tinsert (complex_id, "imaginary", sizeof(float), H5T_NATIVE_FLOAT); | | H5Tinsert (complex_id, "imaginary", sizeof(float), H5T_NATIVE_FLOAT); | |
| return complex_id; | | return complex_id; | |
| } | | } | |
| | | | |
| skipping to change at line 471 | | skipping to change at line 912 | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| // helper friend function for callback HDF5_ls_inserter_callback() | | // helper friend function for callback HDF5_ls_inserter_callback() | |
| void HDF5_ls_insert(void*, const std::string &); | | void HDF5_ls_insert(void*, const std::string &); | |
| // callback function for ls(), called via HDF5File::H5Literate() | | // callback function for ls(), called via HDF5File::H5Literate() | |
| // see http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-3
3.2 | | // see http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-3
3.2 | |
| // for as to why. | | // for as to why. | |
| | | | |
| VIGRA_EXPORT H5O_type_t HDF5_get_type(hid_t, const char*); | | VIGRA_EXPORT H5O_type_t HDF5_get_type(hid_t, const char*); | |
| extern "C" VIGRA_EXPORT herr_t HDF5_ls_inserter_callback(hid_t, const char*
, const H5L_info_t*, void*); | | extern "C" VIGRA_EXPORT herr_t HDF5_ls_inserter_callback(hid_t, const char*
, const H5L_info_t*, void*); | |
|
| | | extern "C" VIGRA_EXPORT herr_t HDF5_listAttributes_inserter_callback(hid_t,
const char*, const H5A_info_t*, void*); | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* HDF5File */ | | /* HDF5File */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Access to HDF5 files | | /** \brief Access to HDF5 files | |
| | | | |
| HDF5File provides a convenient way of accessing data in HDF5 files. vigra::
MultiArray | | HDF5File provides a convenient way of accessing data in HDF5 files. vigra::
MultiArray | |
| | | | |
| skipping to change at line 512 | | skipping to change at line 954 | |
| file.read("dataset", in_multi_array); | | file.read("dataset", in_multi_array); | |
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b>\#include</b> \<vigra/hdf5impex.hxx\><br> | | <b>\#include</b> \<vigra/hdf5impex.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| class HDF5File | | class HDF5File | |
| { | | { | |
| protected: | | protected: | |
|
| HDF5Handle fileHandle_; | | HDF5HandleShared fileHandle_; | |
| | | | |
| // current group handle | | // current group handle | |
| HDF5Handle cGroupHandle_; | | HDF5Handle cGroupHandle_; | |
| | | | |
| private: | | private: | |
| // time tagging of datasets, turned off (= 0) by default. | | // time tagging of datasets, turned off (= 0) by default. | |
| int track_time; | | int track_time; | |
| | | | |
|
| // helper class for ls() | | bool read_only_; | |
| | | | |
| | | // helper classes for ls() and listAttributes() | |
| struct ls_closure | | struct ls_closure | |
| { | | { | |
| virtual void insert(const std::string &) = 0; | | virtual void insert(const std::string &) = 0; | |
| virtual ~ls_closure() {} | | virtual ~ls_closure() {} | |
| }; | | }; | |
|
| // datastructure to hold a list of dataset and group names | | | |
| | | // datastructure to hold a std::vector<std::string> | |
| struct lsOpData : public ls_closure | | struct lsOpData : public ls_closure | |
| { | | { | |
| std::vector<std::string> & objects; | | std::vector<std::string> & objects; | |
| lsOpData(std::vector<std::string> & o) : objects(o) {} | | lsOpData(std::vector<std::string> & o) : objects(o) {} | |
| void insert(const std::string & x) | | void insert(const std::string & x) | |
| { | | { | |
| objects.push_back(x); | | objects.push_back(x); | |
| } | | } | |
| }; | | }; | |
|
| // (associative-)container closure | | | |
| | | // datastructure to hold an associative container | |
| template<class Container> | | template<class Container> | |
| struct ls_container_data : public ls_closure | | struct ls_container_data : public ls_closure | |
| { | | { | |
| Container & objects; | | Container & objects; | |
| ls_container_data(Container & o) : objects(o) {} | | ls_container_data(Container & o) : objects(o) {} | |
| void insert(const std::string & x) | | void insert(const std::string & x) | |
| { | | { | |
| objects.insert(std::string(x)); | | objects.insert(std::string(x)); | |
| } | | } | |
| }; | | }; | |
| | | | |
| public: | | public: | |
| | | | |
| // helper for callback HDF5_ls_inserter_callback(), used by ls() | | // helper for callback HDF5_ls_inserter_callback(), used by ls() | |
| friend void HDF5_ls_insert(void*, const std::string &); | | friend void HDF5_ls_insert(void*, const std::string &); | |
| | | | |
| /** \brief Set how a file is opened. | | /** \brief Set how a file is opened. | |
| | | | |
|
| OpenMode::New creates a new file. If the file already exists, o | | OpenMode::New creates a new file. If the file already exists, i | |
| verwrite it. | | t is overwritten. | |
| | | | |
| | | OpenMode::ReadWrite opens a file for reading/writing. The file | |
| | | will be created if it doesn't exist. | |
| | | | |
|
| OpenMode::Open opens a file for reading/writing. The file will | | OpenMode::ReadOnly opens a file for reading. The file as well a | |
| be created, | | s any dataset to be accessed must already exist. | |
| if necessary. | | | |
| */ | | */ | |
| enum OpenMode { | | enum OpenMode { | |
|
| New, // Create new empty file (existing file will be dele | | New, // Create new empty file (existing file will be d | |
| ted). | | eleted). | |
| Open, // Open file. Create if not existing. | | Open, // Open file. Create if not existing. | |
| OpenReadOnly // Open file in read-only mode. | | ReadWrite = Open, // Alias for Open. | |
| | | OpenReadOnly, // Open file in read-only mode. | |
| | | ReadOnly = OpenReadOnly, // Alias for OpenReadOnly | |
| | | Replace, // for ChunkedArrayHDF5: replace dataset if it ex | |
| | | ists, create otherwise | |
| | | Default // for ChunkedArrayHDF5: use New if file doesn't | |
| | | exist, | |
| | | // ReadOnly if file and | |
| | | dataset exist | |
| | | // Open otherwise | |
| }; | | }; | |
| | | | |
| /** \brief Default constructor. | | /** \brief Default constructor. | |
| | | | |
|
| A file can later be opened via the open() function. | | A file can later be opened via the open() function. Time tagging of | |
| | | datasets is disabled. | |
| | | */ | |
| | | HDF5File() | |
| | | : track_time(0) | |
| | | {} | |
| | | | |
| | | /** \brief Construct with time tagging of datasets enabled. | |
| | | | |
|
| If \a track_creation_times is non-zero, time tagging of datasets wi | | If \a track_creation_times is 'true', time tagging of datasets will | |
| ll be enabled (it is disabled | | be enabled. | |
| by default). | | | |
| */ | | */ | |
|
| HDF5File(int track_creation_times = 0) | | explicit HDF5File(bool track_creation_times) | |
| : track_time(track_creation_times) | | : track_time(track_creation_times ? 1 : 0), | |
| | | read_only_(true) | |
| {} | | {} | |
| | | | |
| /** \brief Open or create an HDF5File object. | | /** \brief Open or create an HDF5File object. | |
| | | | |
| Creates or opens HDF5 file with given filename. | | Creates or opens HDF5 file with given filename. | |
| The current group is set to "/". | | The current group is set to "/". | |
| | | | |
| Note that the HDF5File class is not copyable (the copy constructor
is | | Note that the HDF5File class is not copyable (the copy constructor
is | |
| private to enforce this). | | private to enforce this). | |
| */ | | */ | |
|
| HDF5File(std::string filename, OpenMode mode, int track_creation_times | | HDF5File(std::string filePath, OpenMode mode, bool track_creation_times | |
| = 0) | | = false) | |
| : track_time(track_creation_times) | | : track_time(track_creation_times ? 1 : 0) | |
| | | { | |
| | | open(filePath, mode); | |
| | | } | |
| | | | |
| | | /** \brief Initialize an HDF5File object from HDF5 file handle | |
| | | | |
| | | Initializes an HDF5File object corresponding to the HDF5 file | |
| | | opened elsewhere. If \a fileHandle is constructed with a | |
| | | <tt>NULL</tt> destructor, ownership is not transferred | |
| | | to the new HDF5File object, and you must ensure that the file is | |
| | | not closed while the new HDF5File object is in use. Otherwise, | |
| | | ownership will be shared. | |
| | | | |
| | | The current group is set to the specified \a pathname. If | |
| | | \a read_only is 'true', you cannot create new datasets or | |
| | | overwrite data. | |
| | | | |
| | | \warning In case the underlying HDF5 library used by Vigra is not | |
| | | exactly the same library used to open the file with the given id, | |
| | | this method will lead to crashes. | |
| | | */ | |
| | | explicit HDF5File(HDF5HandleShared const & fileHandle, | |
| | | const std::string & pathname = "", | |
| | | bool read_only = false) | |
| | | : fileHandle_(fileHandle), | |
| | | read_only_(read_only) | |
| | | | |
| { | | { | |
|
| open(filename, mode); | | // get group handle for given pathname | |
| | | // calling openCreateGroup_ without setting a valid cGroupHandle do | |
| | | es | |
| | | // not work. Starting from root() is a safe bet. | |
| | | root(); | |
| | | cGroupHandle_ = HDF5Handle(openCreateGroup_(pathname), &H5Gclose, | |
| | | "HDF5File(fileHandle, pathname): Failed to open group"); | |
| | | | |
| | | // extract track_time attribute | |
| | | hbool_t track_times_tmp; | |
| | | HDF5Handle plist_id(H5Fget_create_plist(fileHandle_), &H5Pclose, | |
| | | "HDF5File(fileHandle, pathname): Failed to open file creati | |
| | | on property list"); | |
| | | herr_t status = H5Pget_obj_track_times(plist_id, &track_times_tmp ) | |
| | | ; | |
| | | vigra_postcondition(status >= 0, | |
| | | "HDF5File(fileHandle, pathname): cannot access track time attri | |
| | | bute"); | |
| | | track_time = track_times_tmp; | |
| | | } | |
| | | | |
| | | /** \brief Copy a HDF5File object. | |
| | | | |
| | | The new object will refer to the same file and group as \a othe | |
| | | r. | |
| | | */ | |
| | | HDF5File(HDF5File const & other) | |
| | | : fileHandle_(other.fileHandle_), | |
| | | track_time(other.track_time), | |
| | | read_only_(other.read_only_) | |
| | | { | |
| | | cGroupHandle_ = HDF5Handle(openCreateGroup_(other.currentGroupName_ | |
| | | ()), &H5Gclose, | |
| | | "HDF5File(HDF5File const &): Failed to o | |
| | | pen group."); | |
| } | | } | |
| | | | |
| /** \brief The destructor flushes and closes the file. | | /** \brief The destructor flushes and closes the file. | |
| */ | | */ | |
| ~HDF5File() | | ~HDF5File() | |
| { | | { | |
| // The members fileHandle_ and cGroupHandle_ are automatically clos
ed | | // The members fileHandle_ and cGroupHandle_ are automatically clos
ed | |
| // as they are of type HDF5Handle and are properly initialised. | | // as they are of type HDF5Handle and are properly initialised. | |
| // The closing of fileHandle_ implies flushing the file to | | // The closing of fileHandle_ implies flushing the file to | |
| // the operating system, see | | // the operating system, see | |
| // http://www.hdfgroup.org/HDF5/doc/RM/RM_H5F.html#File-Close . | | // http://www.hdfgroup.org/HDF5/doc/RM/RM_H5F.html#File-Close . | |
| } | | } | |
| | | | |
|
| // copying is not permitted. | | /** \brief Assign a HDF5File object. | |
| private: | | | |
| HDF5File(const HDF5File &); | | | |
| void operator=(const HDF5File &); | | | |
| | | | |
|
| public: | | Calls close() on the present file and The new object will refer | |
| | | to the same file and group as \a other. | |
| | | */ | |
| | | HDF5File & operator=(HDF5File const & other) | |
| | | { | |
| | | if(this != &other) | |
| | | { | |
| | | close(); | |
| | | fileHandle_ = other.fileHandle_; | |
| | | cGroupHandle_ = HDF5Handle(openCreateGroup_(other.currentGroupN | |
| | | ame_()), &H5Gclose, | |
| | | "HDF5File::operator=(): Failed to op | |
| | | en group."); | |
| | | track_time = other.track_time; | |
| | | read_only_ = other.read_only_; | |
| | | } | |
| | | return *this; | |
| | | } | |
| | | | |
| | | int file_use_count() const | |
| | | { | |
| | | return fileHandle_.use_count(); | |
| | | } | |
| | | | |
| | | bool isOpen() const | |
| | | { | |
| | | return fileHandle_ != 0; | |
| | | } | |
| | | | |
| | | bool isReadOnly() const | |
| | | { | |
| | | return read_only_; | |
| | | } | |
| | | | |
| | | void setReadOnly(bool stat=true) | |
| | | { | |
| | | read_only_ = stat; | |
| | | } | |
| | | | |
| /** \brief Open or create the given file in the given mode and set
the group to "/". | | /** \brief Open or create the given file in the given mode and set
the group to "/". | |
| If another file is currently open, it is first closed. | | If another file is currently open, it is first closed. | |
| */ | | */ | |
|
| void open(std::string filename, OpenMode mode) | | void open(std::string filePath, OpenMode mode) | |
| { | | { | |
| close(); | | close(); | |
| | | | |
|
| std::string errorMessage = "HDF5File.open(): Could not open or crea | | std::string errorMessage = "HDF5File.open(): Could not open or crea | |
| te file '" + filename + "'."; | | te file '" + filePath + "'."; | |
| fileHandle_ = HDF5Handle(createFile_(filename, mode), &H5Fclose, er | | fileHandle_ = HDF5HandleShared(createFile_(filePath, mode), &H5Fclo | |
| rorMessage.c_str()); | | se, errorMessage.c_str()); | |
| cGroupHandle_ = HDF5Handle(openCreateGroup_("/"), &H5Gclose, "HDF5F
ile.open(): Failed to open root group."); | | cGroupHandle_ = HDF5Handle(openCreateGroup_("/"), &H5Gclose, "HDF5F
ile.open(): Failed to open root group."); | |
|
| | | setReadOnly(mode == OpenReadOnly); | |
| } | | } | |
| | | | |
| /** \brief Close the current file. | | /** \brief Close the current file. | |
|
| */ | | */ | |
| void close() | | void close() | |
| { | | { | |
| bool success = cGroupHandle_.close() >= 0 && fileHandle_.close() >=
0; | | bool success = cGroupHandle_.close() >= 0 && fileHandle_.close() >=
0; | |
| vigra_postcondition(success, "HDF5File.close() failed."); | | vigra_postcondition(success, "HDF5File.close() failed."); | |
| } | | } | |
| | | | |
| /** \brief Change current group to "/". | | /** \brief Change current group to "/". | |
| */ | | */ | |
| inline void root() | | inline void root() | |
| { | | { | |
| std::string message = "HDF5File::root(): Could not open group '/'."
; | | std::string message = "HDF5File::root(): Could not open group '/'."
; | |
| cGroupHandle_ = HDF5Handle(H5Gopen(fileHandle_, "/", H5P_DEFAULT),&
H5Gclose,message.c_str()); | | cGroupHandle_ = HDF5Handle(H5Gopen(fileHandle_, "/", H5P_DEFAULT),&
H5Gclose,message.c_str()); | |
| } | | } | |
| | | | |
| /** \brief Change the current group. | | /** \brief Change the current group. | |
| Both absolute and relative group names are allowed. | | Both absolute and relative group names are allowed. | |
| */ | | */ | |
| inline void cd(std::string groupName) | | inline void cd(std::string groupName) | |
| { | | { | |
|
| std::string message = "HDF5File::cd(): Could not open group '" + gr | | cGroupHandle_ = getGroupHandle(groupName, "HDF5File::cd()"); | |
| oupName + "'.\n"; | | | |
| | | | |
| // make groupName clean | | | |
| groupName = get_absolute_path(groupName); | | | |
| | | | |
| if(groupName == "/") | | | |
| { | | | |
| cGroupHandle_ = HDF5Handle(openCreateGroup_("/"),&H5Gclose,mess | | | |
| age.c_str()); | | | |
| } | | | |
| else | | | |
| { | | | |
| vigra_precondition(H5Lexists(fileHandle_, groupName.c_str(), H5 | | | |
| P_DEFAULT) != 0, message); | | | |
| cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName),&H5Gclos | | | |
| e,message.c_str()); | | | |
| } | | | |
| } | | } | |
| | | | |
| /** \brief Change the current group to its parent group. | | /** \brief Change the current group to its parent group. | |
| Returns true if successful, false otherwise. If unsuccessful, | | Returns true if successful, false otherwise. If unsuccessful, | |
| the group will not change. | | the group will not change. | |
| */ | | */ | |
| inline bool cd_up() | | inline bool cd_up() | |
| { | | { | |
| std::string groupName = currentGroupName_(); | | std::string groupName = currentGroupName_(); | |
| | | | |
| | | | |
| skipping to change at line 708 | | skipping to change at line 1240 | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
| | | | |
| /** \brief Create a new group. | | /** \brief Create a new group. | |
| If the first character is a "/", the path will be interpreted
as absolute path, | | If the first character is a "/", the path will be interpreted
as absolute path, | |
| otherwise it will be interpreted as path relative to the curre
nt group. | | otherwise it will be interpreted as path relative to the curre
nt group. | |
| */ | | */ | |
| inline void mkdir(std::string groupName) | | inline void mkdir(std::string groupName) | |
| { | | { | |
|
| | | vigra_precondition(!isReadOnly(), | |
| | | "HDF5File::mkdir(): file is read-only."); | |
| | | | |
| std::string message = "HDF5File::mkdir(): Could not create group '"
+ groupName + "'.\n"; | | std::string message = "HDF5File::mkdir(): Could not create group '"
+ groupName + "'.\n"; | |
| | | | |
| // make groupName clean | | // make groupName clean | |
| groupName = get_absolute_path(groupName); | | groupName = get_absolute_path(groupName); | |
| | | | |
| HDF5Handle(openCreateGroup_(groupName.c_str()),&H5Gclose,message.c_
str()); | | HDF5Handle(openCreateGroup_(groupName.c_str()),&H5Gclose,message.c_
str()); | |
| } | | } | |
| | | | |
| /** \brief Change the current group; create it if necessary. | | /** \brief Change the current group; create it if necessary. | |
| If the first character is a "/", the path will be interpreted
as absolute path, | | If the first character is a "/", the path will be interpreted
as absolute path, | |
| otherwise it will be interpreted as path relative to the curre
nt group. | | otherwise it will be interpreted as path relative to the curre
nt group. | |
| */ | | */ | |
| inline void cd_mk(std::string groupName) | | inline void cd_mk(std::string groupName) | |
| { | | { | |
|
| | | vigra_precondition(!isReadOnly(), | |
| | | "HDF5File::cd_mk(): file is read-only."); | |
| | | | |
| std::string message = "HDF5File::cd_mk(): Could not create group '
" + groupName + "'."; | | std::string message = "HDF5File::cd_mk(): Could not create group '
" + groupName + "'."; | |
| | | | |
| // make groupName clean | | // make groupName clean | |
| groupName = get_absolute_path(groupName); | | groupName = get_absolute_path(groupName); | |
| | | | |
| cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName.c_str()),&H5G
close,message.c_str()); | | cGroupHandle_ = HDF5Handle(openCreateGroup_(groupName.c_str()),&H5G
close,message.c_str()); | |
| } | | } | |
| | | | |
| // helper function for the various ls() variants. | | // helper function for the various ls() variants. | |
| void ls_H5Literate(ls_closure & data) const | | void ls_H5Literate(ls_closure & data) const | |
| | | | |
| skipping to change at line 784 | | skipping to change at line 1322 | |
| return currentGroupName_(); | | return currentGroupName_(); | |
| } | | } | |
| | | | |
| /** \brief Get the name of the associated file. | | /** \brief Get the name of the associated file. | |
| */ | | */ | |
| inline std::string filename() const | | inline std::string filename() const | |
| { | | { | |
| return fileName_(); | | return fileName_(); | |
| } | | } | |
| | | | |
|
| | | /** \brief Check if given datasetName exists. | |
| | | */ | |
| | | inline bool existsDataset(std::string datasetName) const | |
| | | { | |
| | | // make datasetName clean | |
| | | datasetName = get_absolute_path(datasetName); | |
| | | return (H5Lexists(fileHandle_, datasetName.c_str(), H5P_DEFAULT) > | |
| | | 0); | |
| | | } | |
| | | | |
| /** \brief Get the number of dimensions of a certain dataset | | /** \brief Get the number of dimensions of a certain dataset | |
| If the first character is a "/", the path will be interpreted
as absolute path, | | If the first character is a "/", the path will be interpreted
as absolute path, | |
| otherwise it will be interpreted as path relative to the curre
nt group. | | otherwise it will be interpreted as path relative to the curre
nt group. | |
| */ | | */ | |
|
| inline hssize_t getDatasetDimensions(std::string datasetName) | | hssize_t getDatasetDimensions(std::string datasetName) const | |
| { | | { | |
|
| // make datasetName clean | | HDF5Handle datasetHandle = getDatasetHandle(datasetName); | |
| datasetName = get_absolute_path(datasetName); | | | |
| | | | |
|
| //Open dataset and dataspace | | return getDatasetDimensions_(datasetHandle); | |
| std::string errorMessage = "HDF5File::getDatasetDimensions(): Unabl | | } | |
| e to open dataset '" + datasetName + "'."; | | | |
| HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName | | | |
| ), &H5Dclose, errorMessage.c_str()); | | | |
| | | | |
|
| errorMessage = "HDF5File::getDatasetDimensions(): Unable to access | | hssize_t getDatasetDimensions_(hid_t dataset) const | |
| dataspace."; | | { | |
| HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose, | | std::string errorMessage = "HDF5File::getDatasetDimensions(): Unabl | |
| errorMessage.c_str()); | | e to access dataspace."; | |
| | | HDF5Handle dataspaceHandle(H5Dget_space(dataset), &H5Sclose, errorM | |
| | | essage.c_str()); | |
| | | | |
| //return dimension information | | //return dimension information | |
| return H5Sget_simple_extent_ndims(dataspaceHandle); | | return H5Sget_simple_extent_ndims(dataspaceHandle); | |
| } | | } | |
| | | | |
| /** \brief Get the shape of each dimension of a certain dataset. | | /** \brief Get the shape of each dimension of a certain dataset. | |
| | | | |
| Normally, this function is called after determining the dimensio
n of the | | Normally, this function is called after determining the dimensio
n of the | |
| dataset using \ref getDatasetDimensions(). | | dataset using \ref getDatasetDimensions(). | |
| If the first character is a "/", the path will be interpreted a
s absolute path, | | If the first character is a "/", the path will be interpreted a
s absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| | | | |
| Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | | Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | |
| Fortran-order, while HDF5 uses C-order. This function therefore
reverses the axis | | Fortran-order, while HDF5 uses C-order. This function therefore
reverses the axis | |
| order relative to the file contents. That is, when the axes in
the file are | | order relative to the file contents. That is, when the axes in
the file are | |
| ordered as 'z', 'y', 'x', this function will return the shape i
n the order | | ordered as 'z', 'y', 'x', this function will return the shape i
n the order | |
| 'x', 'y', 'z'. | | 'x', 'y', 'z'. | |
| */ | | */ | |
|
| inline ArrayVector<hsize_t> getDatasetShape(std::string datasetName) | | ArrayVector<hsize_t> getDatasetShape(std::string datasetName) const | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| //Open dataset and dataspace | | //Open dataset and dataspace | |
| std::string errorMessage = "HDF5File::getDatasetShape(): Unable to
open dataset '" + datasetName + "'."; | | std::string errorMessage = "HDF5File::getDatasetShape(): Unable to
open dataset '" + datasetName + "'."; | |
| HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName
), &H5Dclose, errorMessage.c_str()); | | HDF5Handle datasetHandle = HDF5Handle(getDatasetHandle_(datasetName
), &H5Dclose, errorMessage.c_str()); | |
| | | | |
| errorMessage = "HDF5File::getDatasetShape(): Unable to access datas
pace."; | | errorMessage = "HDF5File::getDatasetShape(): Unable to access datas
pace."; | |
| HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose,
errorMessage.c_str()); | | HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose,
errorMessage.c_str()); | |
| | | | |
| skipping to change at line 841 | | skipping to change at line 1388 | |
| | | | |
| ArrayVector<hsize_t> shape(dimensions); | | ArrayVector<hsize_t> shape(dimensions); | |
| ArrayVector<hsize_t> maxdims(dimensions); | | ArrayVector<hsize_t> maxdims(dimensions); | |
| H5Sget_simple_extent_dims(dataspaceHandle, shape.data(), maxdims.da
ta()); | | H5Sget_simple_extent_dims(dataspaceHandle, shape.data(), maxdims.da
ta()); | |
| | | | |
| // invert the dimensions to guarantee VIGRA-compatible order. | | // invert the dimensions to guarantee VIGRA-compatible order. | |
| std::reverse(shape.begin(), shape.end()); | | std::reverse(shape.begin(), shape.end()); | |
| return shape; | | return shape; | |
| } | | } | |
| | | | |
|
| | | /** Query the pixel type of the dataset. | |
| | | | |
| | | Possible values are: | |
| | | <DL> | |
| | | <DT>"INT8"<DD> 8-bit signed integer (unsigned char) | |
| | | <DT>"UINT8"<DD> 8-bit unsigned integer (unsigned char) | |
| | | <DT>"INT16"<DD> 16-bit signed integer (short) | |
| | | <DT>"UINT16"<DD> 16-bit unsigned integer (unsigned short) | |
| | | <DT>"INT32"<DD> 32-bit signed integer (long) | |
| | | <DT>"UINT32"<DD> 32-bit unsigned integer (unsigned long) | |
| | | <DT>"INT64"<DD> 64-bit signed integer (long long) | |
| | | <DT>"UINT64"<DD> 64-bit unsigned integer (unsigned long long) | |
| | | <DT>"FLOAT"<DD> 32-bit floating point (float) | |
| | | <DT>"DOUBLE"<DD> 64-bit floating point (double) | |
| | | <DT>"UNKNOWN"<DD> any other type | |
| | | </DL> | |
| | | */ | |
| | | std::string getDatasetType(std::string const & datasetName) const | |
| | | { | |
| | | HDF5Handle datasetHandle = getDatasetHandle(datasetName); | |
| | | | |
| | | hid_t datatype = H5Dget_type(datasetHandle); | |
| | | H5T_class_t dataclass = H5Tget_class(datatype); | |
| | | size_t datasize = H5Tget_size(datatype); | |
| | | H5T_sign_t datasign = H5Tget_sign(datatype); | |
| | | | |
| | | if(dataclass == H5T_FLOAT) | |
| | | { | |
| | | if(datasize == 4) | |
| | | return "FLOAT"; | |
| | | else if(datasize == 8) | |
| | | return "DOUBLE"; | |
| | | } | |
| | | else if(dataclass == H5T_INTEGER) | |
| | | { | |
| | | if(datasign == H5T_SGN_NONE) | |
| | | { | |
| | | if(datasize == 1) | |
| | | return "UINT8"; | |
| | | else if(datasize == 2) | |
| | | return "UINT16"; | |
| | | else if(datasize == 4) | |
| | | return "UINT32"; | |
| | | else if(datasize == 8) | |
| | | return "UINT64"; | |
| | | } | |
| | | else | |
| | | { | |
| | | if(datasize == 1) | |
| | | return "INT8"; | |
| | | else if(datasize == 2) | |
| | | return "INT16"; | |
| | | else if(datasize == 4) | |
| | | return "INT32"; | |
| | | else if(datasize == 8) | |
| | | return "INT64"; | |
| | | } | |
| | | } | |
| | | return "UNKNOWN"; | |
| | | } | |
| | | | |
| /** \brief Obtain the HDF5 handle of a dataset. | | /** \brief Obtain the HDF5 handle of a dataset. | |
| */ | | */ | |
|
| inline HDF5Handle getDatasetHandle(std::string dataset_name) | | HDF5Handle getDatasetHandle(std::string const & datasetName) const | |
| | | { | |
| | | std::string errorMessage = "HDF5File::getDatasetHandle(): Unable to | |
| | | open dataset '" + datasetName + "'."; | |
| | | return HDF5Handle(getDatasetHandle_(get_absolute_path(datasetName)) | |
| | | , &H5Dclose, errorMessage.c_str()); | |
| | | } | |
| | | | |
| | | /** \brief Obtain a shared HDF5 handle of a dataset. | |
| | | */ | |
| | | HDF5HandleShared getDatasetHandleShared(std::string const & datasetName | |
| | | ) const | |
| { | | { | |
|
| std::string errorMessage = "HDF5File::getDatasetHandle(): Unable to | | std::string errorMessage = "HDF5File::getDatasetHandle(): Unable to | |
| open dataset '" + dataset_name + "'."; | | open dataset '" + datasetName + "'."; | |
| return HDF5Handle(getDatasetHandle_(dataset_name), &H5Dclose, error | | return HDF5HandleShared(getDatasetHandle_(get_absolute_path(dataset | |
| Message.c_str()); | | Name)), &H5Dclose, errorMessage.c_str()); | |
| } | | } | |
| | | | |
|
| /** \brief Obtain the HDF5 handle of a group. | | /** \brief Obtain the HDF5 handle of a group (create the group if i
t doesn't exist). | |
| */ | | */ | |
|
| inline HDF5Handle getGroupHandle(std::string group_name) | | HDF5Handle getGroupHandle(std::string group_name, | |
| | | std::string function_name = "HDF5File::getGro | |
| | | upHandle()") | |
| { | | { | |
|
| std::string errorMessage = "HDF5File::getGroupHandle(): Group '" +
group_name + "' not found."; | | std::string errorMessage = function_name + ": Group '" + group_name
+ "' not found."; | |
| | | | |
| // make group_name clean | | // make group_name clean | |
| group_name = get_absolute_path(group_name); | | group_name = get_absolute_path(group_name); | |
| | | | |
| // group must exist | | // group must exist | |
|
| vigra_precondition(H5Lexists(fileHandle_, group_name.c_str(), H5P_D
EFAULT) == 1, | | vigra_precondition(group_name == "/" || H5Lexists(fileHandle_, grou
p_name.c_str(), H5P_DEFAULT) != 0, | |
| errorMessage.c_str()); | | errorMessage.c_str()); | |
| | | | |
| // open group and return group handle | | // open group and return group handle | |
| return HDF5Handle(openCreateGroup_(group_name), &H5Gclose, "Interna
l error"); | | return HDF5Handle(openCreateGroup_(group_name), &H5Gclose, "Interna
l error"); | |
| } | | } | |
| | | | |
|
| | | // helper function for the various listAttributes() variants. | |
| | | void ls_H5Aiterate(std::string const & group_or_dataset, ls_closure & d | |
| | | ata) const | |
| | | { | |
| | | H5O_type_t h5_type = get_object_type_(group_or_dataset); | |
| | | vigra_precondition(h5_type == H5O_TYPE_GROUP || h5_type == H5O_TYPE | |
| | | _DATASET, | |
| | | "HDF5File::listAttributes(): object \"" + group_or_dataset + "\ | |
| | | " is neither a group nor a dataset."); | |
| | | // get object handle | |
| | | HDF5Handle object_handle(h5_type == H5O_TYPE_GROUP | |
| | | ? const_cast<HDF5File*>(this)->openCre | |
| | | ateGroup_(group_or_dataset) | |
| | | : getDatasetHandle_(group_or_dataset), | |
| | | h5_type == H5O_TYPE_GROUP | |
| | | ? &H5Gclose | |
| | | : &H5Dclose, | |
| | | "HDF5File::listAttributes(): unable to ope | |
| | | n object."); | |
| | | hsize_t n = 0; | |
| | | H5Aiterate2(object_handle, H5_INDEX_NAME, H5_ITER_NATIVE, &n, | |
| | | HDF5_listAttributes_inserter_callback, static_cast<void | |
| | | *>(&data)); | |
| | | } | |
| | | | |
| | | /** \brief List the attribute names of the given group or dataset. | |
| | | | |
| | | If \a group_or_dataset is empty or <tt>"."</tt> (a dot), the co | |
| | | mmand | |
| | | refers to the current group of this file object. | |
| | | */ | |
| | | inline std::vector<std::string> listAttributes(std::string const & grou | |
| | | p_or_dataset) const | |
| | | { | |
| | | std::vector<std::string> list; | |
| | | lsOpData data(list); | |
| | | ls_H5Aiterate(group_or_dataset, data); | |
| | | return list; | |
| | | } | |
| | | | |
| | | /** \brief Insert the attribute names of the given group or dataset | |
| | | into the given | |
| | | \a container by calling <tt>container.insert(std::string | |
| | | )</tt>. | |
| | | | |
| | | If \a group_or_dataset is empty or <tt>"."</tt> (a dot), the co | |
| | | mmand | |
| | | refers to the current group of this file object. | |
| | | */ | |
| | | template<class Container> | |
| | | void listAttributes(std::string const & group_or_dataset, Container & c | |
| | | ontainer) const | |
| | | { | |
| | | ls_container_data<Container> data(container); | |
| | | ls_H5Aiterate(group_or_dataset, data); | |
| | | } | |
| | | | |
| /** \brief Obtain the HDF5 handle of a attribute. | | /** \brief Obtain the HDF5 handle of a attribute. | |
| */ | | */ | |
|
| inline HDF5Handle getAttributeHandle(std::string dataset_name, std::str
ing attribute_name) | | HDF5Handle getAttributeHandle(std::string dataset_name, std::string att
ribute_name) const | |
| { | | { | |
| std::string message = "HDF5File::getAttributeHandle(): Attribute '"
+ attribute_name + "' not found."; | | std::string message = "HDF5File::getAttributeHandle(): Attribute '"
+ attribute_name + "' not found."; | |
| return HDF5Handle(H5Aopen(getDatasetHandle(dataset_name), attribute
_name.c_str(), H5P_DEFAULT), | | return HDF5Handle(H5Aopen(getDatasetHandle(dataset_name), attribute
_name.c_str(), H5P_DEFAULT), | |
| &H5Aclose, message.c_str()); | | &H5Aclose, message.c_str()); | |
| } | | } | |
| | | | |
| /* Writing Attributes */ | | /* Writing Attributes */ | |
| | | | |
| /** \brief Write MultiArray Attributes. | | /** \brief Write MultiArray Attributes. | |
| * In contrast to datasets, subarray access, chunks and compressio
n are not available. | | * In contrast to datasets, subarray access, chunks and compressio
n are not available. | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void writeAttribute(std::string object_name, std::string attribu | | inline void writeAttribute(std::string object_name, | |
| te_name, const MultiArrayView<N, T, UnstridedArrayTag> & array) | | std::string attribute_name, | |
| | | const MultiArrayView<N, T, Stride> & array) | |
| { | | { | |
| // make object_name clean | | // make object_name clean | |
| object_name = get_absolute_path(object_name); | | object_name = get_absolute_path(object_name); | |
| | | | |
| write_attribute_(object_name, attribute_name, array, detail::getH5D
ataType<T>(), 1); | | write_attribute_(object_name, attribute_name, array, detail::getH5D
ataType<T>(), 1); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE, class Stride> | |
| inline void writeAttribute(std::string datasetName, std::string attribu | | inline void writeAttribute(std::string datasetName, | |
| teName, const MultiArrayView<N, TinyVector<T, SIZE>, UnstridedArrayTag> & a | | std::string attributeName, | |
| rray) | | const MultiArrayView<N, TinyVector<T, SIZE>, | |
| | | Stride> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), SIZE); | | write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), SIZE); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void writeAttribute(std::string datasetName, std::string attribu | | inline void writeAttribute(std::string datasetName, | |
| teName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | | std::string attributeName, | |
| | | const MultiArrayView<N, RGBValue<T>, Stride> | |
| | | & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), 3); | | write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), 3); | |
| } | | } | |
| | | | |
| /** \brief Write a single value. | | /** \brief Write a single value. | |
| Specialization of the write function for simple datatypes | | Specialization of the write function for simple datatypes | |
| */ | | */ | |
| | | | |
| skipping to change at line 961 | | skipping to change at line 1629 | |
| "object '" + object_name + "' " | | "object '" + object_name + "' " | |
| "not found."); | | "not found."); | |
| return exists != 0; | | return exists != 0; | |
| } | | } | |
| | | | |
| // Reading Attributes | | // Reading Attributes | |
| | | | |
| /** \brief Read MultiArray Attributes. | | /** \brief Read MultiArray Attributes. | |
| * In contrast to datasets, subarray access is not available. | | * In contrast to datasets, subarray access is not available. | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void readAttribute(std::string object_name, std::string attribut | | inline void readAttribute(std::string object_name, | |
| e_name, const MultiArrayView<N, T, UnstridedArrayTag> & array) | | std::string attribute_name, | |
| | | MultiArrayView<N, T, Stride> array) | |
| { | | { | |
| // make object_name clean | | // make object_name clean | |
| object_name = get_absolute_path(object_name); | | object_name = get_absolute_path(object_name); | |
| | | | |
| read_attribute_(object_name, attribute_name, array, detail::getH5Da
taType<T>(), 1); | | read_attribute_(object_name, attribute_name, array, detail::getH5Da
taType<T>(), 1); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE, class Stride> | |
| inline void readAttribute(std::string datasetName, std::string attribut | | inline void readAttribute(std::string datasetName, | |
| eName, const MultiArrayView<N, TinyVector<T, SIZE>, UnstridedArrayTag> & ar | | std::string attributeName, | |
| ray) | | MultiArrayView<N, TinyVector<T, SIZE>, Stride | |
| | | > array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<T>(), SIZE); | | read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<T>(), SIZE); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void readAttribute(std::string datasetName, std::string attribut | | inline void readAttribute(std::string datasetName, | |
| eName, const MultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | | std::string attributeName, | |
| | | MultiArrayView<N, RGBValue<T>, Stride> array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<T>(), 3); | | read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<T>(), 3); | |
| } | | } | |
| | | | |
| /** \brief Read a single value. | | /** \brief Read a single value. | |
| Specialization of the read function for simple datatypes | | Specialization of the read function for simple datatypes | |
| */ | | */ | |
| | | | |
| skipping to change at line 1029 | | skipping to change at line 1703 | |
| inline void readAttribute(std::string datasetName, std::string attribut
eName, std::string &data) | | inline void readAttribute(std::string datasetName, std::string attribut
eName, std::string &data) | |
| { readAtomicAttribute(datasetName,attributeName,data); } | | { readAtomicAttribute(datasetName,attributeName,data); } | |
| | | | |
| // Writing data | | // Writing data | |
| | | | |
| /** \brief Write multi arrays. | | /** \brief Write multi arrays. | |
| | | | |
| Chunks can be activated by setting | | Chunks can be activated by setting | |
| \code iChunkSize = size; //size \> 0 | | \code iChunkSize = size; //size \> 0 | |
| \endcode . | | \endcode . | |
|
| The chunks will be hypercubes with edge length size. | | The chunks will be hypercubes with edge length size. When <tt>i | |
| | | ChunkSize == 0</tt> | |
| | | (default), the behavior depends on the <tt>compression</tt> set | |
| | | ting: If no | |
| | | compression is requested, the data is written without chunking. | |
| | | Otherwise, | |
| | | chuning is required, and the chunk size is automatically select | |
| | | ed such that | |
| | | each chunk contains about 300k pixels. | |
| | | | |
| Compression can be activated by setting | | Compression can be activated by setting | |
| \code compression = parameter; // 0 \< parameter \<= 9 | | \code compression = parameter; // 0 \< parameter \<= 9 | |
| \endcode | | \endcode | |
| where 0 stands for no compression and 9 for maximum compression
. | | where 0 stands for no compression and 9 for maximum compression
. | |
| | | | |
| If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | | If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| | | | |
| Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | | Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | |
| Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray, | | Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray, | |
| whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed | | whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed | |
| upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'. | | upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'. | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void write(std::string datasetName, const MultiArrayView<N, T, U | | inline void write(std::string datasetName, | |
| nstridedArrayTag> & array, int iChunkSize = 0, int compression = 0) | | const MultiArrayView<N, T, Stride> & array, | |
| | | int iChunkSize = 0, int compression = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| typename MultiArrayShape<N>::type chunkSize; | | typename MultiArrayShape<N>::type chunkSize; | |
| for(unsigned int i = 0; i < N; i++){ | | for(unsigned int i = 0; i < N; i++){ | |
| chunkSize[i] = iChunkSize; | | chunkSize[i] = iChunkSize; | |
| } | | } | |
| write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
, compression); | | write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
, compression); | |
| } | | } | |
| | | | |
| skipping to change at line 1074 | | skipping to change at line 1754 | |
| where 0 stands for no compression and 9 for maximum compression
. | | where 0 stands for no compression and 9 for maximum compression
. | |
| | | | |
| If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | | If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| | | | |
| Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | | Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | |
| Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray, | | Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray, | |
| whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed | | whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed | |
| upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'. | | upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'. | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void write(std::string datasetName, const MultiArrayView<N, T, U | | inline void write(std::string datasetName, | |
| nstridedArrayTag> & array, typename MultiArrayShape<N>::type chunkSize, int | | const MultiArrayView<N, T, Stride> & array, | |
| compression = 0) | | typename MultiArrayShape<N>::type chunkSize, int comp | |
| | | ression = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
, compression); | | write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
, compression); | |
| } | | } | |
| | | | |
| /** \brief Write a multi array into a larger volume. | | /** \brief Write a multi array into a larger volume. | |
| blockOffset determines the position, where array is written. | | blockOffset determines the position, where array is written. | |
| | | | |
|
| Chunks can be activated by providing a MultiArrayShape as chunk | | | |
| Size. | | | |
| chunkSize must have equal dimension as array. | | | |
| | | | |
| Compression can be activated by setting | | | |
| \code compression = parameter; // 0 \< parameter \<= 9 | | | |
| \endcode | | | |
| where 0 stands for no compression and 9 for maximum compression | | | |
| . | | | |
| | | | |
| If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | | If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| | | | |
| Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | | Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | |
| Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray, | | Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray, | |
| whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed | | whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed | |
| upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'. | | upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'. | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void writeBlock(std::string datasetName, typename MultiArrayShap | | inline void writeBlock(std::string datasetName, | |
| e<N>::type blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & arr | | typename MultiArrayShape<N>::type blockOffset, | |
| ay) | | const MultiArrayView<N, T, Stride> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
|
| | | typedef detail::HDF5TypeTraits<T> TypeTraits; | |
| | | writeBlock_(datasetName, blockOffset, array, | |
| | | TypeTraits::getH5DataType(), TypeTraits::numberOfBands( | |
| | | )); | |
| | | } | |
| | | | |
|
| writeBlock_(datasetName, blockOffset, array, detail::getH5DataType< | | template<unsigned int N, class T, class Stride> | |
| T>(), 1); | | inline herr_t writeBlock(HDF5HandleShared dataset, | |
| | | typename MultiArrayShape<N>::type blockOffset, | |
| | | const MultiArrayView<N, T, Stride> & array) | |
| | | { | |
| | | typedef detail::HDF5TypeTraits<T> TypeTraits; | |
| | | return writeBlock_(dataset, blockOffset, array, | |
| | | TypeTraits::getH5DataType(), TypeTraits::numberO | |
| | | fBands()); | |
| } | | } | |
| | | | |
| // non-scalar (TinyVector) and unstrided multi arrays | | // non-scalar (TinyVector) and unstrided multi arrays | |
|
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE, class Stride> | |
| inline void write(std::string datasetName, const MultiArrayView<N, Tiny | | inline void write(std::string datasetName, | |
| Vector<T, SIZE>, UnstridedArrayTag> & array, int iChunkSize = 0, int compre | | const MultiArrayView<N, TinyVector<T, SIZE>, Stride> | |
| ssion = 0) | | & array, | |
| | | int iChunkSize = 0, int compression = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| typename MultiArrayShape<N>::type chunkSize; | | typename MultiArrayShape<N>::type chunkSize; | |
| for(int i = 0; i < N; i++){ | | for(int i = 0; i < N; i++){ | |
| chunkSize[i] = iChunkSize; | | chunkSize[i] = iChunkSize; | |
| } | | } | |
| write_(datasetName, array, detail::getH5DataType<T>(), SIZE, chunkS
ize, compression); | | write_(datasetName, array, detail::getH5DataType<T>(), SIZE, chunkS
ize, compression); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE, class Stride> | |
| inline void write(std::string datasetName, const MultiArrayView<N, Tiny | | inline void write(std::string datasetName, | |
| Vector<T, SIZE>, UnstridedArrayTag> & array, typename MultiArrayShape<N>::t | | const MultiArrayView<N, TinyVector<T, SIZE>, Stride> | |
| ype chunkSize, int compression = 0) | | & array, | |
| | | typename MultiArrayShape<N>::type chunkSize, int comp | |
| | | ression = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| write_(datasetName, array, detail::getH5DataType<T>(), SIZE, chunkS
ize, compression); | | write_(datasetName, array, detail::getH5DataType<T>(), SIZE, chunkS
ize, compression); | |
| } | | } | |
| | | | |
| /** \brief Write array vectors. | | /** \brief Write array vectors. | |
| | | | |
| Compression can be activated by setting | | Compression can be activated by setting | |
| | | | |
| skipping to change at line 1150 | | skipping to change at line 1841 | |
| | | | |
| If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | | If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
| void write(const std::string & datasetName, | | void write(const std::string & datasetName, | |
| const ArrayVectorView<T> & array, | | const ArrayVectorView<T> & array, | |
| int compression = 0) | | int compression = 0) | |
| { | | { | |
| // convert to a (trivial) MultiArrayView and forward. | | // convert to a (trivial) MultiArrayView and forward. | |
|
| MultiArrayShape<1>::type shape(array.size()); | | MultiArrayShape<1>::type shape(static_cast<MultiArrayIndex>(array.s
ize())); | |
| const MultiArrayView<1, T> m_array(shape, const_cast<T*>(array.data
())); | | const MultiArrayView<1, T> m_array(shape, const_cast<T*>(array.data
())); | |
| write(datasetName, m_array, compression); | | write(datasetName, m_array, compression); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T, int SIZE> | | | |
| inline void writeBlock(std::string datasetName, typename MultiArrayShap | | | |
| e<N>::type blockOffset, const MultiArrayView<N, TinyVector<T, SIZE>, Unstri | | | |
| dedArrayTag> & array) | | | |
| { | | | |
| // make datasetName clean | | | |
| datasetName = get_absolute_path(datasetName); | | | |
| | | | |
| writeBlock_(datasetName, blockOffset, array, detail::getH5DataType< | | | |
| T>(), SIZE); | | | |
| } | | | |
| | | | |
| // non-scalar (RGBValue) and unstrided multi arrays | | // non-scalar (RGBValue) and unstrided multi arrays | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void write(std::string datasetName, const MultiArrayView<N, RGBV | | inline void write(std::string datasetName, | |
| alue<T>, UnstridedArrayTag> & array, int iChunkSize = 0, int compression = | | const MultiArrayView<N, RGBValue<T>, Stride> & array, | |
| 0) | | int iChunkSize = 0, int compression = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| typename MultiArrayShape<N>::type chunkSize; | | typename MultiArrayShape<N>::type chunkSize; | |
| for(int i = 0; i < N; i++){ | | for(int i = 0; i < N; i++){ | |
| chunkSize[i] = iChunkSize; | | chunkSize[i] = iChunkSize; | |
| } | | } | |
| write_(datasetName, array, detail::getH5DataType<T>(), 3, chunkSize
, compression); | | write_(datasetName, array, detail::getH5DataType<T>(), 3, chunkSize
, compression); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void write(std::string datasetName, const MultiArrayView<N, RGBV | | inline void write(std::string datasetName, | |
| alue<T>, UnstridedArrayTag> & array, typename MultiArrayShape<N>::type chun | | const MultiArrayView<N, RGBValue<T>, Stride> & array, | |
| kSize, int compression = 0) | | typename MultiArrayShape<N>::type chunkSize, int comp | |
| | | ression = 0) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| write_(datasetName, array, detail::getH5DataType<T>(), 3, chunkSize
, compression); | | write_(datasetName, array, detail::getH5DataType<T>(), 3, chunkSize
, compression); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T> | | | |
| inline void writeBlock(std::string datasetName, typename MultiArrayShap | | | |
| e<N>::type blockOffset, const MultiArrayView<N, RGBValue<T>, UnstridedArray | | | |
| Tag> & array) | | | |
| { | | | |
| // make datasetName clean | | | |
| datasetName = get_absolute_path(datasetName); | | | |
| | | | |
| writeBlock_(datasetName, blockOffset, array, detail::getH5DataType< | | | |
| T>(), 3); | | | |
| } | | | |
| | | | |
| /** \brief Write a single value. | | /** \brief Write a single value. | |
| Specialization of the write function for simple datatypes | | Specialization of the write function for simple datatypes | |
| */ | | */ | |
| inline void write(std::string datasetName, char data) { writeAtomic(dat
asetName,data); } | | inline void write(std::string datasetName, char data) { writeAtomic(dat
asetName,data); } | |
| inline void write(std::string datasetName, signed char data) { writeAto
mic(datasetName,data); } | | inline void write(std::string datasetName, signed char data) { writeAto
mic(datasetName,data); } | |
| inline void write(std::string datasetName, signed short data) { writeAt
omic(datasetName,data); } | | inline void write(std::string datasetName, signed short data) { writeAt
omic(datasetName,data); } | |
| inline void write(std::string datasetName, signed int data) { writeAtom
ic(datasetName,data); } | | inline void write(std::string datasetName, signed int data) { writeAtom
ic(datasetName,data); } | |
| inline void write(std::string datasetName, signed long data) { writeAto
mic(datasetName,data); } | | inline void write(std::string datasetName, signed long data) { writeAto
mic(datasetName,data); } | |
| inline void write(std::string datasetName, signed long long data) { wri
teAtomic(datasetName,data); } | | inline void write(std::string datasetName, signed long long data) { wri
teAtomic(datasetName,data); } | |
| inline void write(std::string datasetName, unsigned char data) { writeA
tomic(datasetName,data); } | | inline void write(std::string datasetName, unsigned char data) { writeA
tomic(datasetName,data); } | |
| | | | |
| skipping to change at line 1227 | | skipping to change at line 1904 | |
| | | | |
| /** \brief Read data into a multi array. | | /** \brief Read data into a multi array. | |
| If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | | If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| | | | |
| Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | | Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | |
| Fortran-order, while HDF5 uses C-order. This means that a HDF5
dataset, | | Fortran-order, while HDF5 uses C-order. This means that a HDF5
dataset, | |
| whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or
der, is reversed | | whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or
der, is reversed | |
| upon reading into a MultiArrayView, i.e. in the array axis orde
r must be 'x', 'y', 'z'. | | upon reading into a MultiArrayView, i.e. in the array axis orde
r must be 'x', 'y', 'z'. | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void read(std::string datasetName, MultiArrayView<N, T, Unstride | | inline void read(std::string datasetName, MultiArrayView<N, T, Stride> | |
| dArrayTag> & array) | | array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), 1); | | read_(datasetName, array, detail::getH5DataType<T>(), 1); | |
| } | | } | |
| | | | |
| /** \brief Read data into a MultiArray. Resize MultiArray to the co
rrect size. | | /** \brief Read data into a MultiArray. Resize MultiArray to the co
rrect size. | |
| If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | | If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| | | | |
| Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | | Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | |
| Fortran-order, while HDF5 uses C-order. This means that a HDF5
dataset, | | Fortran-order, while HDF5 uses C-order. This means that a HDF5
dataset, | |
| whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or
der, is reversed | | whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or
der, is reversed | |
| upon reading into a MultiArray, i.e. in the array axis order wi
ll be 'x', 'y', 'z'. | | upon reading into a MultiArray, i.e. in the array axis order wi
ll be 'x', 'y', 'z'. | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Alloc> | |
| inline void readAndResize(std::string datasetName, MultiArray<N, T> & a | | inline void readAndResize(std::string datasetName, MultiArray<N, T, All | |
| rray) | | oc> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| // get dataset dimension | | // get dataset dimension | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
| | | | |
| // check if dimensions are correct | | // check if dimensions are correct | |
| vigra_precondition(N == MultiArrayIndex(dimshape.size()), // the ob
ject in the HDF5 file may have one additional dimension which we then inter
pret as the pixel type bands | | vigra_precondition(N == MultiArrayIndex(dimshape.size()), // the ob
ject in the HDF5 file may have one additional dimension which we then inter
pret as the pixel type bands | |
| "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | | "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | |
| | | | |
| // reshape target MultiArray | | // reshape target MultiArray | |
| typename MultiArrayShape<N>::type shape; | | typename MultiArrayShape<N>::type shape; | |
|
| for(int k=0; k < (int)dimshape.size(); ++k) | | for(int k=0; k < static_cast<int>(dimshape.size()); ++k) | |
| shape[k] = (MultiArrayIndex)dimshape[k]; | | shape[k] = static_cast<MultiArrayIndex>(dimshape[k]); | |
| array.reshape(shape); | | array.reshape(shape); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), 1); | | read_(datasetName, array, detail::getH5DataType<T>(), 1); | |
| } | | } | |
| | | | |
| /** \brief Read data into an array vector. | | /** \brief Read data into an array vector. | |
| If the first character of datasetName is a "/", the path will be
interpreted as absolute path, | | If the first character of datasetName is a "/", the path will be
interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the current
group. | | otherwise it will be interpreted as path relative to the current
group. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
|
| inline void read(const std::string & datasetName, ArrayVectorView<T> &
array) | | inline void read(const std::string & datasetName, ArrayVectorView<T> ar
ray) | |
| { | | { | |
| // convert to a (trivial) MultiArrayView and forward. | | // convert to a (trivial) MultiArrayView and forward. | |
| MultiArrayShape<1>::type shape(array.size()); | | MultiArrayShape<1>::type shape(array.size()); | |
| MultiArrayView<1, T> m_array(shape, (array.data())); | | MultiArrayView<1, T> m_array(shape, (array.data())); | |
| read(datasetName, m_array); | | read(datasetName, m_array); | |
| } | | } | |
| | | | |
| /** \brief Read data into an array vector. Resize the array vector
to the correct size. | | /** \brief Read data into an array vector. Resize the array vector
to the correct size. | |
| If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | | If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| | | | |
| skipping to change at line 1301 | | skipping to change at line 1978 | |
| // get dataset dimension | | // get dataset dimension | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
| | | | |
| // check if dimensions are correct | | // check if dimensions are correct | |
| vigra_precondition(1 == MultiArrayIndex(dimshape.size()), | | vigra_precondition(1 == MultiArrayIndex(dimshape.size()), | |
| "HDF5File::readAndResize(): Array dimension disagrees with Data
set dimension must equal one for vigra::ArrayVector."); | | "HDF5File::readAndResize(): Array dimension disagrees with Data
set dimension must equal one for vigra::ArrayVector."); | |
| | | | |
| // resize target array vector | | // resize target array vector | |
| array.resize((typename ArrayVector<T>::size_type)dimshape[0]); | | array.resize((typename ArrayVector<T>::size_type)dimshape[0]); | |
| // convert to a (trivial) MultiArrayView and forward. | | // convert to a (trivial) MultiArrayView and forward. | |
|
| MultiArrayShape<1>::type shape(array.size()); | | MultiArrayShape<1>::type shape(static_cast<MultiArrayIndex>(array.s
ize())); | |
| MultiArrayView<1, T> m_array(shape, (array.data())); | | MultiArrayView<1, T> m_array(shape, (array.data())); | |
| | | | |
| read_(datasetName, m_array, detail::getH5DataType<T>(), 1); | | read_(datasetName, m_array, detail::getH5DataType<T>(), 1); | |
| } | | } | |
| | | | |
| /** \brief Read a block of data into a multi array. | | /** \brief Read a block of data into a multi array. | |
| This function allows to read a small block out of a larger volu
me stored | | This function allows to read a small block out of a larger volu
me stored | |
| in an HDF5 dataset. | | in an HDF5 dataset. | |
| | | | |
| blockOffset determines the position of the block. | | blockOffset determines the position of the block. | |
| blockSize determines the size in each dimension of the block. | | blockSize determines the size in each dimension of the block. | |
| | | | |
| If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | | If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| | | | |
| Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | | Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | |
| Fortran-order, while HDF5 uses C-order. This means that a HDF5
dataset, | | Fortran-order, while HDF5 uses C-order. This means that a HDF5
dataset, | |
| whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or
der, is reversed | | whose indices represent the 'z'-, 'y'-, and 'x'-axis in that or
der, is reversed | |
| upon reading into a MultiArray, i.e. in the array axis order wi
ll be 'x', 'y', 'z'. | | upon reading into a MultiArray, i.e. in the array axis order wi
ll be 'x', 'y', 'z'. | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void readBlock(std::string datasetName, typename MultiArrayShape | | inline void readBlock(std::string datasetName, | |
| <N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA | | typename MultiArrayShape<N>::type blockOffset, | |
| rrayView<N, T, UnstridedArrayTag> & array) | | typename MultiArrayShape<N>::type blockShape, | |
| | | MultiArrayView<N, T, Stride> array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
|
| | | typedef detail::HDF5TypeTraits<T> TypeTraits; | |
| | | readBlock_(datasetName, blockOffset, blockShape, array, | |
| | | TypeTraits::getH5DataType(), TypeTraits::numberOfBands() | |
| | | ); | |
| | | } | |
| | | | |
|
| readBlock_(datasetName, blockOffset, blockShape, array, detail::get | | template<unsigned int N, class T, class Stride> | |
| H5DataType<T>(), 1); | | inline herr_t readBlock(HDF5HandleShared dataset, | |
| | | typename MultiArrayShape<N>::type blockOffset, | |
| | | typename MultiArrayShape<N>::type blockShape, | |
| | | MultiArrayView<N, T, Stride> array) | |
| | | { | |
| | | typedef detail::HDF5TypeTraits<T> TypeTraits; | |
| | | return readBlock_(dataset, blockOffset, blockShape, array, | |
| | | TypeTraits::getH5DataType(), TypeTraits::numberOf | |
| | | Bands()); | |
| } | | } | |
| | | | |
| // non-scalar (TinyVector) and unstrided target MultiArrayView | | // non-scalar (TinyVector) and unstrided target MultiArrayView | |
|
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE, class Stride> | |
| inline void read(std::string datasetName, MultiArrayView<N, TinyVector< | | inline void read(std::string datasetName, MultiArrayView<N, TinyVector< | |
| T, SIZE>, UnstridedArrayTag> & array) | | T, SIZE>, Stride> array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), SIZE); | | read_(datasetName, array, detail::getH5DataType<T>(), SIZE); | |
| } | | } | |
| | | | |
| // non-scalar (TinyVector) MultiArray | | // non-scalar (TinyVector) MultiArray | |
|
| template<unsigned int N, class T, int SIZE> | | template<unsigned int N, class T, int SIZE, class Alloc> | |
| inline void readAndResize(std::string datasetName, MultiArray<N, TinyVe | | inline void readAndResize(std::string datasetName, MultiArray<N, TinyVe | |
| ctor<T, SIZE> > & array) | | ctor<T, SIZE>, Alloc> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| // get dataset dimension | | // get dataset dimension | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
| | | | |
| // check if dimensions are correct | | // check if dimensions are correct | |
| vigra_precondition((N+1) == MultiArrayIndex(dimshape.size()) && | | vigra_precondition((N+1) == MultiArrayIndex(dimshape.size()) && | |
| SIZE == dimshape[0], // the object in the HDF5 f
ile must have one additional dimension which we interpret as the pixel type
bands | | SIZE == dimshape[0], // the object in the HDF5 f
ile must have one additional dimension which we interpret as the pixel type
bands | |
| "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | | "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | |
| | | | |
| // reshape target MultiArray | | // reshape target MultiArray | |
| typename MultiArrayShape<N>::type shape; | | typename MultiArrayShape<N>::type shape; | |
|
| for(int k=1; k < (int)dimshape.size(); ++k) | | for(int k=1; k < static_cast<int>(dimshape.size()); ++k) | |
| shape[k-1] = (MultiArrayIndex)dimshape[k]; | | shape[k-1] = static_cast<MultiArrayIndex>(dimshape[k]); | |
| array.reshape(shape); | | array.reshape(shape); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), SIZE); | | read_(datasetName, array, detail::getH5DataType<T>(), SIZE); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T, int SIZE> | | | |
| inline void readBlock(std::string datasetName, typename MultiArrayShape | | | |
| <N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA | | | |
| rrayView<N, TinyVector<T, SIZE>, UnstridedArrayTag> & array) | | | |
| { | | | |
| // make datasetName clean | | | |
| datasetName = get_absolute_path(datasetName); | | | |
| | | | |
| readBlock_(datasetName, blockOffset, blockShape, array, detail::get | | | |
| H5DataType<T>(), SIZE); | | | |
| } | | | |
| | | | |
| // non-scalar (RGBValue) and unstrided target MultiArrayView | | // non-scalar (RGBValue) and unstrided target MultiArrayView | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void read(std::string datasetName, MultiArrayView<N, RGBValue<T> | | inline void read(std::string datasetName, MultiArrayView<N, RGBValue<T> | |
| , UnstridedArrayTag> & array) | | , Stride> array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), 3); | | read_(datasetName, array, detail::getH5DataType<T>(), 3); | |
| } | | } | |
| | | | |
| // non-scalar (RGBValue) MultiArray | | // non-scalar (RGBValue) MultiArray | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Alloc> | |
| inline void readAndResize(std::string datasetName, MultiArray<N, RGBVal | | inline void readAndResize(std::string datasetName, MultiArray<N, RGBVal | |
| ue<T> > & array) | | ue<T>, Alloc> & array) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| // get dataset dimension | | // get dataset dimension | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
| | | | |
| // check if dimensions are correct | | // check if dimensions are correct | |
| vigra_precondition((N+1) == MultiArrayIndex(dimshape.size()) && | | vigra_precondition((N+1) == MultiArrayIndex(dimshape.size()) && | |
| 3 == dimshape[0], // the object in the HDF5 file
must have one additional dimension which we interpret as the pixel type ba
nds | | 3 == dimshape[0], // the object in the HDF5 file
must have one additional dimension which we interpret as the pixel type ba
nds | |
| "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | | "HDF5File::readAndResize(): Array dimension disagrees with data
set dimension."); | |
| | | | |
| // reshape target MultiArray | | // reshape target MultiArray | |
| typename MultiArrayShape<N>::type shape; | | typename MultiArrayShape<N>::type shape; | |
|
| for(int k=1; k < (int)dimshape.size(); ++k) | | for(int k=1; k < static_cast<int>(dimshape.size()); ++k) | |
| shape[k-1] = (MultiArrayIndex)dimshape[k]; | | shape[k-1] = static_cast<MultiArrayIndex>(dimshape[k]); | |
| array.reshape(shape); | | array.reshape(shape); | |
| | | | |
| read_(datasetName, array, detail::getH5DataType<T>(), 3); | | read_(datasetName, array, detail::getH5DataType<T>(), 3); | |
| } | | } | |
| | | | |
|
| template<unsigned int N, class T> | | | |
| inline void readBlock(std::string datasetName, typename MultiArrayShape | | | |
| <N>::type blockOffset, typename MultiArrayShape<N>::type blockShape, MultiA | | | |
| rrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | | | |
| { | | | |
| // make datasetName clean | | | |
| datasetName = get_absolute_path(datasetName); | | | |
| | | | |
| readBlock_(datasetName, blockOffset, blockShape, array, detail::get | | | |
| H5DataType<T>(), 3); | | | |
| } | | | |
| | | | |
| /** \brief Read a single value. | | /** \brief Read a single value. | |
| Specialization of the read function for simple datatypes | | Specialization of the read function for simple datatypes | |
| */ | | */ | |
| inline void read(std::string datasetName, char &data) { readAtomic(data
setName,data); } | | inline void read(std::string datasetName, char &data) { readAtomic(data
setName,data); } | |
| inline void read(std::string datasetName, signed char &data) { readAtom
ic(datasetName,data); } | | inline void read(std::string datasetName, signed char &data) { readAtom
ic(datasetName,data); } | |
| inline void read(std::string datasetName, signed short &data) { readAto
mic(datasetName,data); } | | inline void read(std::string datasetName, signed short &data) { readAto
mic(datasetName,data); } | |
| inline void read(std::string datasetName, signed int &data) { readAtomi
c(datasetName,data); } | | inline void read(std::string datasetName, signed int &data) { readAtomi
c(datasetName,data); } | |
| inline void read(std::string datasetName, signed long &data) { readAtom
ic(datasetName,data); } | | inline void read(std::string datasetName, signed long &data) { readAtom
ic(datasetName,data); } | |
| inline void read(std::string datasetName, signed long long &data) { rea
dAtomic(datasetName,data); } | | inline void read(std::string datasetName, signed long long &data) { rea
dAtomic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned char &data) { readAt
omic(datasetName,data); } | | inline void read(std::string datasetName, unsigned char &data) { readAt
omic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned short &data) { readA
tomic(datasetName,data); } | | inline void read(std::string datasetName, unsigned short &data) { readA
tomic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned int &data) { readAto
mic(datasetName,data); } | | inline void read(std::string datasetName, unsigned int &data) { readAto
mic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned long &data) { readAt
omic(datasetName,data); } | | inline void read(std::string datasetName, unsigned long &data) { readAt
omic(datasetName,data); } | |
| inline void read(std::string datasetName, unsigned long long &data) { r
eadAtomic(datasetName,data); } | | inline void read(std::string datasetName, unsigned long long &data) { r
eadAtomic(datasetName,data); } | |
| inline void read(std::string datasetName, float &data) { readAtomic(dat
asetName,data); } | | inline void read(std::string datasetName, float &data) { readAtomic(dat
asetName,data); } | |
| inline void read(std::string datasetName, double &data) { readAtomic(da
tasetName,data); } | | inline void read(std::string datasetName, double &data) { readAtomic(da
tasetName,data); } | |
| inline void read(std::string datasetName, long double &data) { readAtom
ic(datasetName,data); } | | inline void read(std::string datasetName, long double &data) { readAtom
ic(datasetName,data); } | |
| inline void read(std::string datasetName, std::string &data) { readAtom
ic(datasetName,data); } | | inline void read(std::string datasetName, std::string &data) { readAtom
ic(datasetName,data); } | |
| | | | |
| /** \brief Create a new dataset. | | /** \brief Create a new dataset. | |
|
| This function can be used to create a dataset filled with a def
ault value, | | This function can be used to create a dataset filled with a def
ault value \a init, | |
| for example before writing data into it using \ref writeBlock()
. | | for example before writing data into it using \ref writeBlock()
. | |
|
| Attention: only atomic datatypes are provided. For spectral dat | | | |
| a, add an | | | |
| dimension (case RGB: add one dimension of size 3). | | | |
| | | | |
| shape determines the dimension and the size of the dataset. | | shape determines the dimension and the size of the dataset. | |
| | | | |
| Chunks can be activated by providing a MultiArrayShape as chunk
Size. | | Chunks can be activated by providing a MultiArrayShape as chunk
Size. | |
| chunkSize must have equal dimension as array. | | chunkSize must have equal dimension as array. | |
| | | | |
| Compression can be activated by setting | | Compression can be activated by setting | |
| \code compression = parameter; // 0 \< parameter \<= 9 | | \code compression = parameter; // 0 \< parameter \<= 9 | |
| \endcode | | \endcode | |
|
| where 0 stands for no compression and 9 for maximum compression | | where 0 stands for no compression and 9 for maximum compression | |
| . | | . If | |
| | | a non-zero compression level is specified, but the chunk size i | |
| | | s zero, | |
| | | a default chunk size will be chosen (compression always require | |
| | | s chunks). | |
| | | | |
| If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | | If the first character of datasetName is a "/", the path will b
e interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the curren
t group. | | otherwise it will be interpreted as path relative to the curren
t group. | |
| | | | |
| Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | | Note that the memory order between VIGRA and HDF5 files differs
: VIGRA uses | |
| Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray, | | Fortran-order, while HDF5 uses C-order. This means that a VIGRA
MultiArray, | |
| whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed | | whose indices represent the 'x'-, 'y'-, and 'z'-axis in that or
der, is reversed | |
| upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'. | | upon writing to an HDF5 file, i.e. in the file the axis order i
s 'z', 'y', 'x'. | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<int N, class T> | |
| inline void createDataset(std::string datasetName, | | HDF5HandleShared | |
| typename MultiArrayShape<N>::type shape, | | createDataset(std::string datasetName, | |
| T init = T(), | | TinyVector<MultiArrayIndex, N> const & shape, | |
| int iChunkSize = 0, | | typename detail::HDF5TypeTraits<T>::value_type init = | |
| int compressionParameter = 0) | | typename detail::HDF5T | |
| { | | ypeTraits<T>::value_type(), | |
| // make datasetName clean | | #ifdef _MSC_VER | |
| datasetName = get_absolute_path(datasetName); | | TinyVector<MultiArrayIndex, N> const & chunkSize = TinyVe | |
| | | ctor<MultiArrayIndex, N>(), | |
| | | #else | |
| | | TinyVector<MultiArrayIndex, N> const & chunkSize = (TinyV | |
| | | ector<MultiArrayIndex, N>()), | |
| | | #endif | |
| | | int compressionParameter = 0); | |
| | | | |
|
| | | // for backwards compatibility | |
| | | template<int N, class T> | |
| | | HDF5HandleShared | |
| | | createDataset(std::string datasetName, | |
| | | TinyVector<MultiArrayIndex, N> const & shape, | |
| | | T init, | |
| | | int iChunkSize, | |
| | | int compressionParameter = 0) | |
| | | { | |
| typename MultiArrayShape<N>::type chunkSize; | | typename MultiArrayShape<N>::type chunkSize; | |
| for(int i = 0; i < N; i++){ | | for(int i = 0; i < N; i++){ | |
| chunkSize[i] = iChunkSize; | | chunkSize[i] = iChunkSize; | |
| } | | } | |
|
| createDataset<N,T>(datasetName, shape, init, chunkSize, compression | | return this->template createDataset<N, T>(datasetName, shape, init, | |
| Parameter); | | chunkSize, compressionPar | |
| } | | ameter); | |
| | | | |
| template<unsigned int N, class T> | | | |
| inline void createDataset(std::string datasetName, | | | |
| typename MultiArrayShape<N>::type shape, | | | |
| T init, | | | |
| typename MultiArrayShape<N>::type chunkSize, | | | |
| int compressionParameter = 0) | | | |
| { | | | |
| // make datasetName clean | | | |
| datasetName = get_absolute_path(datasetName); | | | |
| | | | |
| std::string groupname = SplitString(datasetName).first(); | | | |
| std::string setname = SplitString(datasetName).last(); | | | |
| | | | |
| hid_t parent = openCreateGroup_(groupname); | | | |
| | | | |
| // delete the dataset if it already exists | | | |
| deleteDataset_(parent, setname); | | | |
| | | | |
| // create dataspace | | | |
| // add an extra dimension in case that the data is non-scalar | | | |
| HDF5Handle dataspaceHandle; | | | |
| | | | |
| // invert dimensions to guarantee c-order | | | |
| hsize_t shape_inv[N]; | | | |
| for(unsigned int k=0; k<N; ++k) | | | |
| shape_inv[N-1-k] = shape[k]; | | | |
| | | | |
| // create dataspace | | | |
| dataspaceHandle = HDF5Handle(H5Screate_simple(N, shape_inv, NULL), | | | |
| &H5Sclose, "HDF5File::createDataset(): | | | |
| unable to create dataspace for scalar data."); | | | |
| | | | |
| // set fill value | | | |
| HDF5Handle plist ( H5Pcreate(H5P_DATASET_CREATE), &H5Pclose, "HDF5F | | | |
| ile::createDataset(): unable to create property list." ); | | | |
| H5Pset_fill_value(plist,detail::getH5DataType<T>(), &init); | | | |
| | | | |
| // turn off time tagging of datasets by default. | | | |
| H5Pset_obj_track_times(plist, track_time); | | | |
| | | | |
| // enable chunks | | | |
| if(chunkSize[0] > 0) | | | |
| { | | | |
| hsize_t cSize [N]; | | | |
| for(int i = 0; i<N; i++) | | | |
| { | | | |
| cSize[i] = chunkSize[N-1-i]; | | | |
| } | | | |
| H5Pset_chunk (plist, N, cSize); | | | |
| } | | | |
| | | | |
| // enable compression | | | |
| if(compressionParameter > 0) | | | |
| { | | | |
| H5Pset_deflate(plist, compressionParameter); | | | |
| } | | | |
| | | | |
| //create the dataset. | | | |
| HDF5Handle datasetHandle ( H5Dcreate(parent, setname.c_str(), detai | | | |
| l::getH5DataType<T>(), dataspaceHandle, H5P_DEFAULT, plist, H5P_DEFAULT), | | | |
| &H5Dclose, "HDF5File::createDataset(): un | | | |
| able to create dataset."); | | | |
| if(parent != cGroupHandle_) | | | |
| H5Gclose(parent); | | | |
| } | | } | |
| | | | |
| /** \brief Immediately write all data to disk | | /** \brief Immediately write all data to disk | |
| */ | | */ | |
| inline void flushToDisk() | | inline void flushToDisk() | |
| { | | { | |
| H5Fflush(fileHandle_, H5F_SCOPE_GLOBAL); | | H5Fflush(fileHandle_, H5F_SCOPE_GLOBAL); | |
| } | | } | |
| | | | |
| private: | | private: | |
| | | | |
| skipping to change at line 1563 | | skipping to change at line 2188 | |
| * For example, "/path/to/some/file" will be split (delimiter = "/
") into | | * For example, "/path/to/some/file" will be split (delimiter = "/
") into | |
| * first() = "/path/to/some" and last() = "file". | | * first() = "/path/to/some" and last() = "file". | |
| */ | | */ | |
| class SplitString: public std::string { | | class SplitString: public std::string { | |
| public: | | public: | |
| SplitString(std::string &sstring): std::string(sstring) {}; | | SplitString(std::string &sstring): std::string(sstring) {}; | |
| | | | |
| // return the part of the string before the delimiter | | // return the part of the string before the delimiter | |
| std::string first(char delimiter = '/') | | std::string first(char delimiter = '/') | |
| { | | { | |
|
| size_t last = find_last_of(delimiter); | | size_t lastPos = find_last_of(delimiter); | |
| if(last == std::string::npos) // delimiter not found --> no fir | | if(lastPos == std::string::npos) // delimiter not found --> no | |
| st | | first | |
| return ""; | | return ""; | |
| | | | |
|
| return std::string(begin(), begin()+last+1); | | return std::string(begin(), begin()+lastPos+1); | |
| } | | } | |
| | | | |
| // return the part of the string after the delimiter | | // return the part of the string after the delimiter | |
| std::string last(char delimiter = '/') | | std::string last(char delimiter = '/') | |
| { | | { | |
|
| size_t last = find_last_of(delimiter); | | size_t lastPos = find_last_of(delimiter); | |
| if(last == std::string::npos) // delimiter not found --> only l | | if(lastPos == std::string::npos) // delimiter not found --> onl | |
| ast | | y last | |
| return std::string(*this); | | return std::string(*this); | |
|
| return std::string(begin()+last+1, end()); | | return std::string(begin()+lastPos+1, end()); | |
| } | | } | |
| }; | | }; | |
| | | | |
|
| | | template <class Shape> | |
| | | ArrayVector<hsize_t> | |
| | | defineChunks(Shape chunks, Shape const & shape, int numBands, int compr | |
| | | ession = 0) | |
| | | { | |
| | | if(prod(chunks) > 0) | |
| | | { | |
| | | ArrayVector<hsize_t> res(chunks.begin(), chunks.end()); | |
| | | if(numBands > 1) | |
| | | res.insert(res.begin(), static_cast<hsize_t>(numBands)); | |
| | | return res; | |
| | | } | |
| | | else if(compression > 0) | |
| | | { | |
| | | // set default chunks to enable compression | |
| | | chunks = min(detail::ChunkShape<Shape::static_size>::defaultSha | |
| | | pe(), shape); | |
| | | ArrayVector<hsize_t> res(chunks.begin(), chunks.end()); | |
| | | if(numBands > 1) | |
| | | res.insert(res.begin(), static_cast<hsize_t>(numBands)); | |
| | | return res; | |
| | | } | |
| | | else | |
| | | { | |
| | | return ArrayVector<hsize_t>(); | |
| | | } | |
| | | } | |
| | | | |
| public: | | public: | |
| | | | |
| /** \brief takes any path and converts it into an absolute path | | /** \brief takes any path and converts it into an absolute path | |
| in the current file. | | in the current file. | |
| | | | |
| Elements like "." and ".." are treated as expected. | | Elements like "." and ".." are treated as expected. | |
| Links are not supported or resolved. | | Links are not supported or resolved. | |
| */ | | */ | |
| inline std::string get_absolute_path(std::string path) const { | | inline std::string get_absolute_path(std::string path) const { | |
| // check for empty input or "." and return the current folder | | // check for empty input or "." and return the current folder | |
| | | | |
| skipping to change at line 1684 | | skipping to change at line 2335 | |
| */ | | */ | |
| inline std::string fileName_() const | | inline std::string fileName_() const | |
| { | | { | |
| int len = H5Fget_name(fileHandle_,NULL,1000); | | int len = H5Fget_name(fileHandle_,NULL,1000); | |
| ArrayVector<char> name (len+1,0); | | ArrayVector<char> name (len+1,0); | |
| H5Fget_name(fileHandle_,name.begin(),len+1); | | H5Fget_name(fileHandle_,name.begin(),len+1); | |
| | | | |
| return std::string(name.begin()); | | return std::string(name.begin()); | |
| } | | } | |
| | | | |
|
| /* create an empty file and open is | | /* create an empty file or open an existing one | |
| */ | | */ | |
| inline hid_t createFile_(std::string filePath, OpenMode mode = Open) | | inline hid_t createFile_(std::string filePath, OpenMode mode = Open) | |
| { | | { | |
| // try to open file | | // try to open file | |
| FILE * pFile; | | FILE * pFile; | |
| pFile = fopen ( filePath.c_str(), "r" ); | | pFile = fopen ( filePath.c_str(), "r" ); | |
| hid_t fileId; | | hid_t fileId; | |
| | | | |
| // check if opening was successful (= file exists) | | // check if opening was successful (= file exists) | |
| if ( pFile == NULL ) | | if ( pFile == NULL ) | |
| { | | { | |
|
| | | vigra_precondition(mode != OpenReadOnly, | |
| | | "HDF5File::open(): cannot open non-existing file in read-on | |
| | | ly mode."); | |
| fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT
, H5P_DEFAULT); | | fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT
, H5P_DEFAULT); | |
| } | | } | |
|
| else if(mode == Open) | | | |
| { | | | |
| fclose( pFile ); | | | |
| fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDWR, H5P_DEFAULT); | | | |
| } | | | |
| else if(mode == OpenReadOnly) { | | | |
| fclose( pFile ); | | | |
| fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT) | | | |
| ; | | | |
| } | | | |
| else | | else | |
| { | | { | |
| fclose(pFile); | | fclose(pFile); | |
|
| std::remove(filePath.c_str()); | | if(mode == OpenReadOnly) | |
| fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT | | { | |
| , H5P_DEFAULT); | | fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDONLY, H5P_DEFA | |
| | | ULT); | |
| | | } | |
| | | else if(mode == New) | |
| | | { | |
| | | std::remove(filePath.c_str()); | |
| | | fileId = H5Fcreate(filePath.c_str(), H5F_ACC_TRUNC, H5P_DEF | |
| | | AULT, H5P_DEFAULT); | |
| | | } | |
| | | else | |
| | | { | |
| | | fileId = H5Fopen(filePath.c_str(), H5F_ACC_RDWR, H5P_DEFAUL | |
| | | T); | |
| | | } | |
| } | | } | |
| return fileId; | | return fileId; | |
| } | | } | |
| | | | |
|
| /* open a group and subgroups. Create if necessary. | | /* \brief Open a group. | |
| | | | |
| | | A negative value is returned when the group does not exist or wh | |
| | | en opening | |
| | | fails for other reasons. | |
| */ | | */ | |
|
| inline hid_t openCreateGroup_(std::string groupName) | | hid_t openGroup_(std::string groupName) const | |
| | | { | |
| | | return const_cast<HDF5File *>(this)->openCreateGroup_(groupName, fa | |
| | | lse); | |
| | | } | |
| | | | |
| | | /* \brief Open or create a group. | |
| | | | |
| | | If \a create is <tt>true</tt> and the group does not exist, it w | |
| | | ill be created, | |
| | | including all necessary parent groups. If group creation fails, | |
| | | a negative | |
| | | value is returned. Likewise, a negative value is returned when \ | |
| | | a create | |
| | | is <tt>false</tt> and the group does not exist or when opening o | |
| | | f the group | |
| | | fails for other reasons. | |
| | | */ | |
| | | hid_t openCreateGroup_(std::string groupName, bool create = true) | |
| { | | { | |
| // make groupName clean | | // make groupName clean | |
| groupName = get_absolute_path(groupName); | | groupName = get_absolute_path(groupName); | |
| | | | |
| // open root group | | // open root group | |
| hid_t parent = H5Gopen(fileHandle_, "/", H5P_DEFAULT); | | hid_t parent = H5Gopen(fileHandle_, "/", H5P_DEFAULT); | |
| if(groupName == "/") | | if(groupName == "/") | |
| { | | { | |
| return parent; | | return parent; | |
| } | | } | |
| | | | |
| skipping to change at line 1748 | | skipping to change at line 2419 | |
| | | | |
| // open or create subgroups one by one | | // open or create subgroups one by one | |
| std::string::size_type begin = 0, end = groupName.find('/'); | | std::string::size_type begin = 0, end = groupName.find('/'); | |
| while (end != std::string::npos) | | while (end != std::string::npos) | |
| { | | { | |
| std::string group(groupName.begin()+begin, groupName.begin()+en
d); | | std::string group(groupName.begin()+begin, groupName.begin()+en
d); | |
| hid_t prevParent = parent; | | hid_t prevParent = parent; | |
| | | | |
| if(H5LTfind_dataset(parent, group.c_str()) == 0) | | if(H5LTfind_dataset(parent, group.c_str()) == 0) | |
| { | | { | |
|
| parent = H5Gcreate(prevParent, group.c_str(), H5P_DEFAULT, | | if(create) | |
| H5P_DEFAULT, H5P_DEFAULT); | | parent = H5Gcreate(prevParent, group.c_str(), H5P_DEFAU | |
| } else { | | LT, H5P_DEFAULT, H5P_DEFAULT); | |
| | | else | |
| | | parent = -1; | |
| | | } | |
| | | else | |
| | | { | |
| parent = H5Gopen(prevParent, group.c_str(), H5P_DEFAULT); | | parent = H5Gopen(prevParent, group.c_str(), H5P_DEFAULT); | |
| } | | } | |
| H5Gclose(prevParent); | | H5Gclose(prevParent); | |
| | | | |
| if(parent < 0) | | if(parent < 0) | |
| { | | { | |
| return parent; | | return parent; | |
| } | | } | |
| begin = end + 1; | | begin = end + 1; | |
| end = groupName.find('/', begin); | | end = groupName.find('/', begin); | |
| | | | |
| skipping to change at line 1790 | | skipping to change at line 2466 | |
| if(H5Ldelete(parent, datasetName.c_str(), H5P_DEFAULT ) < 0) | | if(H5Ldelete(parent, datasetName.c_str(), H5P_DEFAULT ) < 0) | |
| { | | { | |
| vigra_postcondition(false, "HDF5File::deleteDataset_(): Una
ble to delete existing data."); | | vigra_postcondition(false, "HDF5File::deleteDataset_(): Una
ble to delete existing data."); | |
| } | | } | |
| #endif | | #endif | |
| } | | } | |
| } | | } | |
| | | | |
| /* get the handle of a dataset specified by a string | | /* get the handle of a dataset specified by a string | |
| */ | | */ | |
|
| inline hid_t getDatasetHandle_(std::string datasetName) | | hid_t getDatasetHandle_(std::string datasetName) const | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| std::string groupname = SplitString(datasetName).first(); | | std::string groupname = SplitString(datasetName).first(); | |
| std::string setname = SplitString(datasetName).last(); | | std::string setname = SplitString(datasetName).last(); | |
| | | | |
| if(H5Lexists(fileHandle_, datasetName.c_str(), H5P_DEFAULT) <= 0) | | if(H5Lexists(fileHandle_, datasetName.c_str(), H5P_DEFAULT) <= 0) | |
| { | | { | |
| std::cerr << "HDF5File::getDatasetHandle_(): Dataset '" << data
setName << "' does not exist.\n"; | | std::cerr << "HDF5File::getDatasetHandle_(): Dataset '" << data
setName << "' does not exist.\n"; | |
| return -1; | | return -1; | |
| } | | } | |
| | | | |
| // Open parent group | | // Open parent group | |
|
| HDF5Handle groupHandle(openCreateGroup_(groupname), &H5Gclose, "Int
ernal error"); | | HDF5Handle groupHandle(openGroup_(groupname), &H5Gclose, "HDF5File:
:getDatasetHandle_(): Internal error"); | |
| | | | |
| return H5Dopen(groupHandle, setname.c_str(), H5P_DEFAULT); | | return H5Dopen(groupHandle, setname.c_str(), H5P_DEFAULT); | |
| } | | } | |
| | | | |
| /* get the type of an object specified by a string | | /* get the type of an object specified by a string | |
| */ | | */ | |
|
| H5O_type_t get_object_type_(std::string name) | | H5O_type_t get_object_type_(std::string name) const | |
| { | | { | |
| name = get_absolute_path(name); | | name = get_absolute_path(name); | |
| std::string group_name = SplitString(name).first(); | | std::string group_name = SplitString(name).first(); | |
| std::string object_name = SplitString(name).last(); | | std::string object_name = SplitString(name).last(); | |
| if (!object_name.size()) | | if (!object_name.size()) | |
| return H5O_TYPE_GROUP; | | return H5O_TYPE_GROUP; | |
| | | | |
| htri_t exists = H5Lexists(fileHandle_, name.c_str(), H5P_DEFAULT); | | htri_t exists = H5Lexists(fileHandle_, name.c_str(), H5P_DEFAULT); | |
| vigra_precondition(exists > 0, "HDF5File::get_object_type_(): " | | vigra_precondition(exists > 0, "HDF5File::get_object_type_(): " | |
| "object \"" + name + "\" " | | "object \"" + name + "\" " | |
| "not found."); | | "not found."); | |
| // open parent group | | // open parent group | |
|
| HDF5Handle group_handle(openCreateGroup_(group_name), &H5Gclose, "I
nternal error"); | | HDF5Handle group_handle(openGroup_(group_name), &H5Gclose, "Interna
l error"); | |
| return HDF5_get_type(group_handle, name.c_str()); | | return HDF5_get_type(group_handle, name.c_str()); | |
| } | | } | |
| | | | |
| /* low-level write function to write vigra MultiArray data as an at
tribute | | /* low-level write function to write vigra MultiArray data as an at
tribute | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| void write_attribute_(std::string name, const std::string & attribute_n | | void write_attribute_(std::string name, | |
| ame, | | const std::string & attribute_name, | |
| const MultiArrayView<N, T, UnstridedArrayTag> & a | | const MultiArrayView<N, T, Stride> & array, | |
| rray, | | | |
| const hid_t datatype, | | const hid_t datatype, | |
|
| const int numBandsOfType) | | const int numBandsOfType); | |
| { | | | |
| // shape of the array. Add one dimension, if array contains non-sca | | | |
| lars. | | | |
| ArrayVector<hsize_t> shape(array.shape().begin(), array.shape().end | | | |
| ()); | | | |
| std::reverse(shape.begin(), shape.end()); | | | |
| if(numBandsOfType > 1) | | | |
| shape.push_back(numBandsOfType); | | | |
| | | | |
| HDF5Handle dataspace(H5Screate_simple(shape.size(), | | | |
| shape.begin(), NULL), | | | |
| &H5Sclose, "HDF5File::writeAttribute(): Can no | | | |
| t" | | | |
| " create dataspace."); | | | |
| | | | |
| std::string errorMessage ("HDF5File::writeAttribute(): can not find | | | |
| " | | | |
| "object '" + name + "'."); | | | |
| | | | |
| H5O_type_t h5_type = get_object_type_(name); | | | |
| bool is_group = h5_type == H5O_TYPE_GROUP; | | | |
| if (!is_group && h5_type != H5O_TYPE_DATASET) | | | |
| vigra_precondition(0, "HDF5File::writeAttribute(): object \"" | | | |
| + name + "\" is neither a group nor a " | | | |
| "dataset."); | | | |
| // get parent object handle | | | |
| HDF5Handle object_handle(is_group | | | |
| ? openCreateGroup_(name) | | | |
| : getDatasetHandle_(name), | | | |
| is_group | | | |
| ? &H5Gclose | | | |
| : &H5Dclose, | | | |
| errorMessage.c_str()); | | | |
| // create / open attribute | | | |
| bool exists = existsAttribute(name, attribute_name); | | | |
| HDF5Handle attributeHandle(exists | | | |
| ? H5Aopen(object_handle, | | | |
| attribute_name.c_str(), | | | |
| H5P_DEFAULT) | | | |
| : H5Acreate(object_handle, | | | |
| attribute_name.c_str(), data | | | |
| type, | | | |
| dataspace, H5P_DEFAULT, | | | |
| H5P_DEFAULT), | | | |
| &H5Aclose, | | | |
| "HDF5File::writeAttribute(): Can not cre | | | |
| ate" | | | |
| " attribute."); | | | |
| | | | |
| // Write the data to the HDF5 object | | | |
| H5Awrite(attributeHandle, datatype, array.data()); | | | |
| } | | | |
| | | | |
| /* Write single value attribute | | /* Write single value attribute | |
| This function allows to write data of atomic datatypes (int, lon
g, double) | | This function allows to write data of atomic datatypes (int, lon
g, double) | |
| as an attribute in the HDF5 file. So it is not necessary to crea
te a MultiArray | | as an attribute in the HDF5 file. So it is not necessary to crea
te a MultiArray | |
| of size 1 to write a single number. | | of size 1 to write a single number. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
| inline void writeAtomicAttribute(std::string datasetName, std::string a
ttributeName, const T data) | | inline void writeAtomicAttribute(std::string datasetName, std::string a
ttributeName, const T data) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| typename MultiArrayShape<1>::type chunkSize; | | typename MultiArrayShape<1>::type chunkSize; | |
| chunkSize[0] = 0; | | chunkSize[0] = 0; | |
| MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | |
| array[0] = data; | | array[0] = data; | |
| write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), 1); | | write_attribute_(datasetName, attributeName, array, detail::getH5Da
taType<T>(), 1); | |
| } | | } | |
| | | | |
|
| /* low-level read function to write vigra MultiArray data from attr
ibutes | | /* low-level read function to read vigra MultiArray data from attri
butes | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void read_attribute_(std::string datasetName, std::string attrib | | void read_attribute_(std::string datasetName, | |
| uteName, MultiArrayView<N, T, UnstridedArrayTag> array, const hid_t datatyp | | std::string attributeName, | |
| e, const int numBandsOfType) | | MultiArrayView<N, T, Stride> array, | |
| { | | const hid_t datatype, const int numBandsOfType); | |
| std::string dataset_path = get_absolute_path(datasetName); | | | |
| // open Attribute handle | | | |
| std::string message = "Error: could not get handle for attribute '" | | | |
| +attributeName+"'' of object '"+dataset_path+"'."; | | | |
| HDF5Handle attr_handle (H5Aopen_by_name(fileHandle_,dataset_path.c_ | | | |
| str(),attributeName.c_str(),H5P_DEFAULT,H5P_DEFAULT),&H5Aclose, message.c_s | | | |
| tr()); | | | |
| | | | |
| // get Attribute dataspace | | | |
| message = "Error: could not get dataspace for attribute '"+attribut | | | |
| eName+"'' of object '"+dataset_path+"'."; | | | |
| HDF5Handle attr_dataspace_handle (H5Aget_space(attr_handle),&H5Sclo | | | |
| se,message.c_str()); | | | |
| | | | |
| // obtain Attribute shape | | | |
| int dims = H5Sget_simple_extent_ndims(attr_dataspace_handle); | | | |
| ArrayVector<hsize_t> dimshape(dims); | | | |
| H5Sget_simple_extent_dims(attr_dataspace_handle, dimshape.data(), N | | | |
| ULL); | | | |
| | | | |
| // invert the dimensions to guarantee VIGRA-compatible order | | | |
| std::reverse(dimshape.begin(), dimshape.end()); | | | |
| | | | |
| int offset = (numBandsOfType > 1) | | | |
| ? 1 | | | |
| : 0; | | | |
| message = "Error: Array dimension disagrees with dataset dimension. | | | |
| "; | | | |
| // the object in the HDF5 file may have one additional dimension wh | | | |
| ich we then interpret as the pixel type bands | | | |
| vigra_precondition((N + offset) == MultiArrayIndex(dims), message); | | | |
| | | | |
| typename MultiArrayShape<N>::type shape; | | | |
| for(int k=offset; k < (int)dimshape.size(); ++k) | | | |
| shape[k-offset] = (MultiArrayIndex)dimshape[k]; | | | |
| | | | |
| message = "Error: Array shape disagrees with dataset shape"; | | | |
| vigra_precondition(shape == array.shape(), message); | | | |
| | | | |
| // simply read in the data as is | | | |
| H5Aread( attr_handle, datatype, array.data()); | | | |
| } | | | |
| | | | |
| /* Read a single value attribute. | | /* Read a single value attribute. | |
| This functions allows to read a single value attribute of atomic
datatype (int, long, double) | | This functions allows to read a single value attribute of atomic
datatype (int, long, double) | |
| from the HDF5 file. So it is not necessary to create a MultiArra
y | | from the HDF5 file. So it is not necessary to create a MultiArra
y | |
| of size 1 to read a single number. | | of size 1 to read a single number. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
| inline void readAtomicAttribute(std::string datasetName, std::string at
tributeName, T & data) | | inline void readAtomicAttribute(std::string datasetName, std::string at
tributeName, T & data) | |
| { | | { | |
| // make datasetName clean | | // make datasetName clean | |
| | | | |
| skipping to change at line 1969 | | skipping to change at line 2568 | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); | |
| read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<const char *>(), 1); | | read_attribute_(datasetName, attributeName, array, detail::getH5Dat
aType<const char *>(), 1); | |
| data = std::string(array[0]); | | data = std::string(array[0]); | |
| } | | } | |
| | | | |
| /* low-level write function to write vigra unstrided MultiArray dat
a | | /* low-level write function to write vigra unstrided MultiArray dat
a | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void write_(std::string &datasetName, | | void write_(std::string &datasetName, | |
| const MultiArrayView<N, T, UnstridedArrayTag> & arra | | const MultiArrayView<N, T, Stride> & array, | |
| y, | | | |
| const hid_t datatype, | | const hid_t datatype, | |
| const int numBandsOfType, | | const int numBandsOfType, | |
| typename MultiArrayShape<N>::type &chunkSize, | | typename MultiArrayShape<N>::type &chunkSize, | |
|
| int compressionParameter = 0) | | int compressionParameter = 0); | |
| { | | | |
| std::string groupname = SplitString(datasetName).first(); | | | |
| std::string setname = SplitString(datasetName).last(); | | | |
| | | | |
| // shape of the array. Add one dimension, if array contains non-sca | | | |
| lars. | | | |
| ArrayVector<hsize_t> shape(array.shape().begin(), array.shape().end | | | |
| ()); | | | |
| std::reverse(shape.begin(), shape.end()); | | | |
| | | | |
| if(numBandsOfType > 1) | | | |
| shape.push_back(numBandsOfType); | | | |
| | | | |
| HDF5Handle dataspace(H5Screate_simple(shape.size(), shape.begin(), | | | |
| NULL), &H5Sclose, | | | |
| "HDF5File::write(): Can not create dataspace." | | | |
| ); | | | |
| | | | |
| // create and open group: | | | |
| std::string errorMessage ("HDF5File::write(): can not create group | | | |
| '" + groupname + "'."); | | | |
| HDF5Handle groupHandle(openCreateGroup_(groupname), &H5Gclose, erro | | | |
| rMessage.c_str()); | | | |
| | | | |
| // delete dataset, if it already exists | | | |
| deleteDataset_(groupHandle, setname.c_str()); | | | |
| | | | |
| // set up properties list | | | |
| HDF5Handle plist(H5Pcreate(H5P_DATASET_CREATE), &H5Pclose, | | | |
| "HDF5File::write(): unable to create property list | | | |
| ." ); | | | |
| | | | |
| // turn off time tagging of datasets by default. | | | |
| H5Pset_obj_track_times(plist, track_time); | | | |
| | | | |
| // enable chunks | | | |
| if(chunkSize[0] > 0) | | | |
| { | | | |
| ArrayVector<hsize_t> cSize(chunkSize.begin(), chunkSize.end()); | | | |
| std::reverse(cSize.begin(), cSize.end()); | | | |
| if(numBandsOfType > 1) | | | |
| cSize.push_back(numBandsOfType); | | | |
| | | | |
| H5Pset_chunk (plist, cSize.size(), cSize.begin()); | | | |
| } | | | |
| | | | |
| // enable compression | | | |
| if(compressionParameter > 0) | | | |
| { | | | |
| H5Pset_deflate(plist, compressionParameter); | | | |
| } | | | |
| | | | |
| // create dataset | | | |
| HDF5Handle datasetHandle(H5Dcreate(groupHandle, setname.c_str(), da | | | |
| tatype, dataspace,H5P_DEFAULT, plist, H5P_DEFAULT), | | | |
| &H5Dclose, "HDF5File::write(): Can not cre | | | |
| ate dataset."); | | | |
| | | | |
| // Write the data to the HDF5 dataset as is | | | |
| herr_t write_status = H5Dwrite(datasetHandle, datatype, H5S_ALL, | | | |
| H5S_ALL, H5P_DEFAULT, array.data()); | | | |
| vigra_precondition(write_status >= 0, "HDF5File::write_(): write to | | | |
| " | | | |
| "dataset \"" + datasetName + "\" " | | | |
| "failed."); | | | |
| } | | | |
| | | | |
| /* Write single value as dataset. | | /* Write single value as dataset. | |
| This functions allows to write data of atomic datatypes (int, lo
ng, double) | | This functions allows to write data of atomic datatypes (int, lo
ng, double) | |
| as a dataset in the HDF5 file. So it is not necessary to create
a MultiArray | | as a dataset in the HDF5 file. So it is not necessary to create
a MultiArray | |
| of size 1 to write a single number. | | of size 1 to write a single number. | |
| | | | |
| If the first character of datasetName is a "/", the path will be
interpreted as absolute path, | | If the first character of datasetName is a "/", the path will be
interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the current
group. | | otherwise it will be interpreted as path relative to the current
group. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
| | | | |
| skipping to change at line 2056 | | skipping to change at line 2599 | |
| | | | |
| typename MultiArrayShape<1>::type chunkSize; | | typename MultiArrayShape<1>::type chunkSize; | |
| chunkSize[0] = 0; | | chunkSize[0] = 0; | |
| MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,T> array(MultiArrayShape<1>::type(1)); | |
| array[0] = data; | | array[0] = data; | |
| write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
,0); | | write_(datasetName, array, detail::getH5DataType<T>(), 1, chunkSize
,0); | |
| } | | } | |
| | | | |
| /* low-level read function to read vigra unstrided MultiArray data | | /* low-level read function to read vigra unstrided MultiArray data | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void read_(std::string datasetName, | | void read_(std::string datasetName, | |
| MultiArrayView<N, T, UnstridedArrayTag> array, | | MultiArrayView<N, T, Stride> array, | |
| const hid_t datatype, const int numBandsOfType) | | const hid_t datatype, const int numBandsOfType); | |
| { | | | |
| //Prepare to read without using HDF5ImportInfo | | | |
| ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | | | |
| | | | |
| std::string errorMessage ("HDF5File::read(): Unable to open dataset | | | |
| '" + datasetName + "'."); | | | |
| HDF5Handle datasetHandle(getDatasetHandle_(datasetName), &H5Dclose, | | | |
| errorMessage.c_str()); | | | |
| | | | |
| int offset = (numBandsOfType > 1) | | | |
| ? 1 | | | |
| : 0; | | | |
| | | | |
| vigra_precondition((N + offset ) == MultiArrayIndex(dimshape.size() | | | |
| ), // the object in the HDF5 file may have one additional dimension which w | | | |
| e then interpret as the pixel type bands | | | |
| "HDF5File::read(): Array dimension disagrees with dataset dimen | | | |
| sion."); | | | |
| | | | |
| typename MultiArrayShape<N>::type shape; | | | |
| for(int k=offset; k < (int)dimshape.size(); ++k) | | | |
| shape[k-offset] = (MultiArrayIndex)dimshape[k]; | | | |
| | | | |
| vigra_precondition(shape == array.shape(), | | | |
| "HDF5File::read(): Array shape disagrees with da | | | |
| taset shape."); | | | |
| if (offset) | | | |
| vigra_precondition(dimshape[0] == static_cast<hsize_t>(numBands | | | |
| OfType), | | | |
| "HDF5File::read(): Band count doesn't match | | | |
| destination array compound type."); | | | |
| | | | |
| // simply read in the data as is | | | |
| H5Dread( datasetHandle, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, ar | | | |
| ray.data() ); // .data() possible since void pointer! | | | |
| } | | | |
| | | | |
| /* Read a single value. | | /* Read a single value. | |
| This functions allows to read a single datum of atomic datatype
(int, long, double) | | This functions allows to read a single datum of atomic datatype
(int, long, double) | |
| from the HDF5 file. So it is not necessary to create a MultiArra
y | | from the HDF5 file. So it is not necessary to create a MultiArra
y | |
| of size 1 to read a single number. | | of size 1 to read a single number. | |
| | | | |
| If the first character of datasetName is a "/", the path will be
interpreted as absolute path, | | If the first character of datasetName is a "/", the path will be
interpreted as absolute path, | |
| otherwise it will be interpreted as path relative to the current
group. | | otherwise it will be interpreted as path relative to the current
group. | |
| */ | | */ | |
| template<class T> | | template<class T> | |
| | | | |
| skipping to change at line 2119 | | skipping to change at line 2635 | |
| // make datasetName clean | | // make datasetName clean | |
| datasetName = get_absolute_path(datasetName); | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); | | MultiArray<1,const char *> array(MultiArrayShape<1>::type(1)); | |
| read_(datasetName, array, detail::getH5DataType<const char *>(), 1)
; | | read_(datasetName, array, detail::getH5DataType<const char *>(), 1)
; | |
| data = std::string(array[0]); | | data = std::string(array[0]); | |
| } | | } | |
| | | | |
| /* low-level write function to write vigra unstrided MultiArray data
into a sub-block of a dataset | | /* low-level write function to write vigra unstrided MultiArray data
into a sub-block of a dataset | |
| */ | | */ | |
|
| template<unsigned int N, class T> | | template<unsigned int N, class T, class Stride> | |
| inline void writeBlock_(std::string datasetName, typename MultiArraySha | | void writeBlock_(std::string datasetName, | |
| pe<N>::type &blockOffset, const MultiArrayView<N, T, UnstridedArrayTag> & a | | typename MultiArrayShape<N>::type &blockOffset, | |
| rray, const hid_t datatype, const int numBandsOfType) | | const MultiArrayView<N, T, Stride> & array, | |
| | | const hid_t datatype, | |
| | | const int numBandsOfType) | |
| { | | { | |
| // open dataset if it exists | | // open dataset if it exists | |
| std::string errorMessage = "HDF5File::writeBlock(): Error opening d
ataset '" + datasetName + "'."; | | std::string errorMessage = "HDF5File::writeBlock(): Error opening d
ataset '" + datasetName + "'."; | |
|
| HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose | | HDF5HandleShared dataset(getDatasetHandle_(datasetName), &H5Dclose, | |
| , errorMessage.c_str()); | | errorMessage.c_str()); | |
| | | herr_t status = writeBlock_(dataset, blockOffset, array, datatype, | |
| | | numBandsOfType); | |
| | | vigra_postcondition(status >= 0, | |
| | | "HDF5File::writeBlock(): write to dataset '" + datasetName + "' | |
| | | via H5Dwrite() failed."); | |
| | | } | |
| | | | |
| | | /* low-level write function to write vigra unstrided MultiArray data | |
| | | into a | |
| | | sub-block of a dataset. Returns the result of the internal call | |
| | | to <tt>H5Dwrite()</tt>. | |
| | | */ | |
| | | template<unsigned int N, class T, class Stride> | |
| | | herr_t writeBlock_(HDF5HandleShared dataset, | |
| | | typename MultiArrayShape<N>::type &blockOffset, | |
| | | const MultiArrayView<N, T, Stride> & array, | |
| | | const hid_t datatype, | |
| | | const int numBandsOfType); | |
| | | | |
|
| // hyperslab parameters for position, size, ... | | /* low-level read function to read vigra unstrided MultiArray data | |
| hsize_t boffset [N]; | | from a sub-block of a dataset. | |
| hsize_t bshape [N]; | | | |
| hsize_t bones [N]; | | | |
| | | | |
|
| for(int i = 0; i < N; i++){ | | The array must have the same shape as the block. | |
| boffset[i] = blockOffset[N-1-i]; | | */ | |
| bshape[i] = array.size(N-1-i); | | template<unsigned int N, class T, class Stride> | |
| bones[i] = 1; | | void readBlock_(std::string datasetName, | |
| } | | typename MultiArrayShape<N>::type &blockOffset, | |
| | | typename MultiArrayShape<N>::type &blockShape, | |
| | | MultiArrayView<N, T, Stride> array, | |
| | | const hid_t datatype, const int numBandsOfType) | |
| | | { | |
| | | std::string errorMessage ("HDF5File::readBlock(): Unable to open da | |
| | | taset '" + datasetName + "'."); | |
| | | HDF5HandleShared dataset(getDatasetHandle_(datasetName), &H5Dclose, | |
| | | errorMessage.c_str()); | |
| | | herr_t status = readBlock_(dataset, blockOffset, blockShape, array, | |
| | | datatype, numBandsOfType); | |
| | | vigra_postcondition(status >= 0, | |
| | | "HDF5File::readBlock(): read from dataset '" + datasetName + "' | |
| | | via H5Dread() failed."); | |
| | | } | |
| | | | |
| | | /* low-level read function to read vigra unstrided MultiArray data | |
| | | from a sub-block of a dataset. | |
| | | | |
| | | The array must have the same shape as the block. Returns the res | |
| | | ult of the internal call | |
| | | to <tt>H5Dread()</tt>. | |
| | | */ | |
| | | template<unsigned int N, class T, class Stride> | |
| | | herr_t readBlock_(HDF5HandleShared dataset, | |
| | | typename MultiArrayShape<N>::type &blockOffset, | |
| | | typename MultiArrayShape<N>::type &blockShape, | |
| | | MultiArrayView<N, T, Stride> array, | |
| | | const hid_t datatype, const int numBandsOfType); | |
| | | }; /* class HDF5File */ | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | template<int N, class T> | |
| | | HDF5HandleShared | |
| | | HDF5File::createDataset(std::string datasetName, | |
| | | TinyVector<MultiArrayIndex, N> const & shape, | |
| | | typename detail::HDF5TypeTraits<T>::value_type init | |
| | | , | |
| | | TinyVector<MultiArrayIndex, N> const & chunkSize, | |
| | | int compressionParameter) | |
| | | { | |
| | | vigra_precondition(!isReadOnly(), | |
| | | "HDF5File::createDataset(): file is read-only."); | |
| | | | |
| | | // make datasetName clean | |
| | | datasetName = get_absolute_path(datasetName); | |
| | | | |
| | | std::string groupname = SplitString(datasetName).first(); | |
| | | std::string setname = SplitString(datasetName).last(); | |
| | | | |
|
| // create a target dataspace in memory with the shape of the desire | | hid_t parent = openCreateGroup_(groupname); | |
| d block | | | |
| HDF5Handle memspace_handle (H5Screate_simple(N,bshape,NULL),&H5Sclo | | | |
| se,"Unable to get origin dataspace"); | | | |
| | | | |
|
| // get file dataspace and select the desired block | | // delete the dataset if it already exists | |
| HDF5Handle dataspaceHandle (H5Dget_space(datasetHandle),&H5Sclose," | | deleteDataset_(parent, setname); | |
| Unable to create target dataspace"); | | | |
| H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones | | | |
| , bones, bshape); | | | |
| | | | |
|
| // Write the data to the HDF5 dataset as is | | // invert dimensions to guarantee c-order | |
| H5Dwrite( datasetHandle, datatype, memspace_handle, dataspaceHandle | | // add an extra dimension in case that the data is non-scalar | |
| , H5P_DEFAULT, array.data()); // .data() possible since void pointer! | | typedef detail::HDF5TypeTraits<T> TypeTraits; | |
| | | ArrayVector<hsize_t> shape_inv; | |
| | | if(TypeTraits::numberOfBands() > 1) | |
| | | { | |
| | | shape_inv.resize(N+1); | |
| | | shape_inv[N] = TypeTraits::numberOfBands(); | |
| | | } | |
| | | else | |
| | | { | |
| | | shape_inv.resize(N); | |
| } | | } | |
|
| | | for(int k=0; k<N; ++k) | |
| | | shape_inv[N-1-k] = shape[k]; | |
| | | | |
|
| /* low-level read function to read vigra unstrided MultiArray data | | // create dataspace | |
| from a sub-block of a dataset | | HDF5Handle | |
| */ | | dataspaceHandle = HDF5Handle(H5Screate_simple(shape_inv.size(), shape_i | |
| template<unsigned int N, class T> | | nv.data(), NULL), | |
| inline void readBlock_(std::string datasetName, typename MultiArrayShap | | &H5Sclose, "HDF5File::createDataset(): unab | |
| e<N>::type &blockOffset, typename MultiArrayShape<N>::type &blockShape, Mul | | le to create dataspace for scalar data."); | |
| tiArrayView<N, T, UnstridedArrayTag> &array, const hid_t datatype, const in | | | |
| t numBandsOfType) | | // set fill value | |
| | | HDF5Handle plist ( H5Pcreate(H5P_DATASET_CREATE), &H5Pclose, "HDF5File: | |
| | | :createDataset(): unable to create property list." ); | |
| | | H5Pset_fill_value(plist, TypeTraits::getH5DataType(), &init); | |
| | | | |
| | | // turn off time tagging of datasets by default. | |
| | | H5Pset_obj_track_times(plist, track_time); | |
| | | | |
| | | // enable chunks | |
| | | ArrayVector<hsize_t> chunks(defineChunks(chunkSize, shape, TypeTraits:: | |
| | | numberOfBands(), compressionParameter)); | |
| | | if(chunks.size() > 0) | |
| { | | { | |
|
| //Prepare to read without using HDF5ImportInfo | | std::reverse(chunks.begin(), chunks.end()); | |
| //ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName) ; | | H5Pset_chunk (plist, chunks.size(), chunks.begin()); | |
| hssize_t dimensions = getDatasetDimensions(datasetName); | | } | |
| | | | |
|
| std::string errorMessage ("HDF5File::readBlock(): Unable to open da | | // enable compression | |
| taset '" + datasetName + "'."); | | if(compressionParameter > 0) | |
| HDF5Handle datasetHandle (getDatasetHandle_(datasetName), &H5Dclose | | { | |
| , errorMessage.c_str()); | | H5Pset_deflate(plist, compressionParameter); | |
| | | } | |
| | | | |
|
| int offset = (numBandsOfType > 1) | | //create the dataset. | |
| ? 1 | | HDF5HandleShared datasetHandle(H5Dcreate(parent, setname.c_str(), | |
| : 0; | | TypeTraits::getH5DataType(), | |
| | | dataspaceHandle, H5P_DEFAULT, | |
| vigra_precondition(( (N + offset ) == MultiArrayIndex(dimensions)) | | plist, H5P_DEFAULT), | |
| , // the object in the HDF5 file may have one additional dimension which we | | &H5Dclose, | |
| then interpret as the pixel type bands | | "HDF5File::createDataset(): unable to cr | |
| "readHDF5_block(): Array dimension disagrees with data dimensio | | eate dataset."); | |
| n."); | | if(parent != cGroupHandle_) | |
| | | H5Gclose(parent); | |
| vigra_precondition(blockShape == array.shape(), | | | |
| "readHDF5_block(): Array shape disagrees with block size."); | | | |
| | | | |
| // hyperslab parameters for position, size, ... | | | |
| hsize_t boffset [N]; | | | |
| hsize_t bshape [N]; | | | |
| hsize_t bones [N]; | | | |
| | | | |
|
| for(int i = 0; i < N; i++){ | | return datasetHandle; | |
| // vigra and hdf5 use different indexing | | } | |
| boffset[i] = blockOffset[N-1-i]; | | | |
| //bshape[i] = blockShape[i]; | | /********************************************************************/ | |
| bshape[i] = blockShape[N-1-i]; | | | |
| //boffset[i] = blockOffset[N-1-i]; | | template<unsigned int N, class T, class Stride> | |
| bones[i] = 1; | | void HDF5File::write_(std::string &datasetName, | |
| } | | const MultiArrayView<N, T, Stride> & array, | |
| | | const hid_t datatype, | |
| // create a target dataspace in memory with the shape of the desire | | const int numBandsOfType, | |
| d block | | typename MultiArrayShape<N>::type &chunkSize, | |
| HDF5Handle memspace_handle(H5Screate_simple(N,bshape,NULL),&H5Sclos | | int compressionParameter) | |
| e, | | { | |
| "Unable to create target dataspace"); | | vigra_precondition(!isReadOnly(), | |
| | | "HDF5File::write(): file is read-only."); | |
| // get file dataspace and select the desired block | | | |
| HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle),&H5Sclose, | | std::string groupname = SplitString(datasetName).first(); | |
| "Unable to get dataspace"); | | std::string setname = SplitString(datasetName).last(); | |
| H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, boffset, bones | | | |
| , bones, bshape); | | // shape of the array. Add one dimension, if array contains non-scalars | |
| | | . | |
| | | ArrayVector<hsize_t> shape(array.shape().begin(), array.shape().end()); | |
| | | std::reverse(shape.begin(), shape.end()); | |
| | | | |
| | | if(numBandsOfType > 1) | |
| | | shape.push_back(numBandsOfType); | |
| | | | |
| | | HDF5Handle dataspace(H5Screate_simple(shape.size(), shape.begin(), NULL | |
| | | ), &H5Sclose, | |
| | | "HDF5File::write(): Can not create dataspace."); | |
| | | | |
|
| // now read the data | | // create and open group: | |
| H5Dread( datasetHandle, datatype, memspace_handle, dataspaceHandle, | | std::string errorMessage ("HDF5File::write(): can not create group '" + | |
| H5P_DEFAULT, array.data() ); // .data() possible since void pointer! | | groupname + "'."); | |
| | | HDF5Handle groupHandle(openCreateGroup_(groupname), &H5Gclose, errorMes | |
| | | sage.c_str()); | |
| | | | |
| | | // delete dataset, if it already exists | |
| | | deleteDataset_(groupHandle, setname.c_str()); | |
| | | | |
| | | // set up properties list | |
| | | HDF5Handle plist(H5Pcreate(H5P_DATASET_CREATE), &H5Pclose, | |
| | | "HDF5File::write(): unable to create property list." ) | |
| | | ; | |
| | | | |
| | | // turn off time tagging of datasets by default. | |
| | | H5Pset_obj_track_times(plist, track_time); | |
| | | | |
| | | // enable chunks | |
| | | ArrayVector<hsize_t> chunks(defineChunks(chunkSize, array.shape(), numB | |
| | | andsOfType, compressionParameter)); | |
| | | if(chunks.size() > 0) | |
| | | { | |
| | | std::reverse(chunks.begin(), chunks.end()); | |
| | | H5Pset_chunk (plist, chunks.size(), chunks.begin()); | |
| } | | } | |
| | | | |
|
| }; /* class HDF5File */ | | // enable compression | |
| | | if(compressionParameter > 0) | |
| | | { | |
| | | H5Pset_deflate(plist, compressionParameter); | |
| | | } | |
| | | | |
|
| namespace detail { | | // create dataset | |
| | | HDF5Handle datasetHandle(H5Dcreate(groupHandle, setname.c_str(), dataty | |
| | | pe, dataspace,H5P_DEFAULT, plist, H5P_DEFAULT), | |
| | | &H5Dclose, "HDF5File::write(): Can not create | |
| | | dataset."); | |
| | | | |
| | | herr_t status = 0; | |
| | | if(array.isUnstrided()) | |
| | | { | |
| | | // Write the data directly from the array data buffer | |
| | | status = H5Dwrite(datasetHandle, datatype, H5S_ALL, H5S_ALL, H5P_DE | |
| | | FAULT, array.data()); | |
| | | } | |
| | | else | |
| | | { | |
| | | // otherwise, we need an intermediate buffer | |
| | | // FIXME: right now, the buffer has the same size as the array to b | |
| | | e read | |
| | | // incomplete code for better solutions is below | |
| | | // MultiArray<N, T> buffer(array); | |
| | | // status = H5Dwrite(datasetHandle, datatype, H5S_ALL, H5S_ALL, H5P | |
| | | _DEFAULT, buffer.data()); | |
| | | | |
| | | int offset = numBandsOfType > 1 ? 1 : 0; | |
| | | std::reverse(shape.begin(), shape.end()); | |
| | | if(chunks.size() > 0) | |
| | | { | |
| | | // if the file is chunked, we use a buffer that matches the chu | |
| | | nk size. | |
| | | std::reverse(chunks.begin(), chunks.end()); | |
| | | } | |
| | | else | |
| | | { | |
| | | // otherwise, we compute a suitable chunk size. | |
| | | ArrayVector<hsize_t>(shape.size(), 1).swap(chunks); | |
| | | chunks[0] = numBandsOfType; | |
| | | MultiArrayIndex prod = 1; | |
| | | for(unsigned int k=0; k<N; ++k) | |
| | | { | |
| | | chunks[k+offset] = array.shape(k); | |
| | | prod *= array.shape(k); | |
| | | if(prod > 300000) | |
| | | break; | |
| | | } | |
| | | } | |
| | | | |
| | | ArrayVector<hsize_t> null(shape.size(), 0), | |
| | | start(shape.size(), 0), | |
| | | count(shape.size(), 1); | |
| | | | |
| | | count[N-1-offset] = numBandsOfType; | |
| | | | |
| | | typedef typename MultiArrayShape<N>::type Shape; | |
| | | Shape chunkCount, chunkMaxShape; | |
| | | for(unsigned int k=offset; k<chunks.size(); ++k) | |
| | | { | |
| | | chunkMaxShape[k-offset] = chunks[k]; | |
| | | chunkCount[k-offset] = static_cast<MultiArrayIndex>(std::ceil(d | |
| | | ouble(shape[k]) / chunks[k])); | |
| | | } | |
| | | | |
| | | typename CoupledIteratorType<N>::type chunkIter = createCoupledIter | |
| | | ator(chunkCount), | |
| | | chunkEnd = chunkIter.getEndI | |
| | | terator(); | |
| | | for(; chunkIter != chunkEnd; ++chunkIter) | |
| | | { | |
| | | Shape chunkStart(chunkIter.point() * chunkMaxShape), | |
| | | chunkStop(min(chunkStart + chunkMaxShape, array.shape())) | |
| | | ; | |
| | | MultiArray<N, T> buffer(array.subarray(chunkStart, chunkStop)); | |
| | | | |
| | | for(unsigned int k=0; k<N; ++k) | |
| | | { | |
| | | start[N-1-k] = chunkStart[k]; | |
| | | count[N-1-k] = buffer.shape(k); | |
| | | } | |
| | | if(offset == 1) | |
| | | { | |
| | | start[N] = 0; | |
| | | count[N] = numBandsOfType; | |
| | | } | |
| | | HDF5Handle filespace(H5Dget_space(datasetHandle), | |
| | | &H5Sclose, "HDF5File::write(): unable to c | |
| | | reate hyperslabs."); | |
| | | status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start.d | |
| | | ata(), NULL, count.data(), NULL); | |
| | | if(status < 0) | |
| | | break; | |
| | | | |
| | | HDF5Handle dataspace2(H5Screate_simple(count.size(), count.data | |
| | | (), NULL), | |
| | | &H5Sclose, "HDF5File::write(): unable to c | |
| | | reate hyperslabs."); | |
| | | status = H5Sselect_hyperslab(dataspace2, H5S_SELECT_SET, null.d | |
| | | ata(), NULL, count.data(), NULL); | |
| | | if(status < 0) | |
| | | break; | |
| | | | |
| | | status = H5Dwrite(datasetHandle, datatype, dataspace2, filespac | |
| | | e, H5P_DEFAULT, buffer.data()); | |
| | | if(status < 0) | |
| | | break; | |
| | | } | |
| | | } | |
| | | vigra_postcondition(status >= 0, | |
| | | "HDF5File::write(): write to dataset '" + datasetName + "' via H5Dw | |
| | | rite() failed."); | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | template<unsigned int N, class T, class Stride> | |
| | | herr_t HDF5File::writeBlock_(HDF5HandleShared datasetHandle, | |
| | | typename MultiArrayShape<N>::type &blockOffset | |
| | | , | |
| | | const MultiArrayView<N, T, Stride> & array, | |
| | | const hid_t datatype, | |
| | | const int numBandsOfType) | |
| | | { | |
| | | vigra_precondition(!isReadOnly(), | |
| | | "HDF5File::writeBlock(): file is read-only."); | |
| | | | |
| | | ArrayVector<hsize_t> boffset, bshape, bones(N+1, 1); | |
| | | hssize_t dimensions = getDatasetDimensions_(datasetHandle); | |
| | | if(numBandsOfType > 1) | |
| | | { | |
| | | vigra_precondition(N+1 == dimensions, | |
| | | "HDF5File::readBlock(): Array dimension disagrees with data dim | |
| | | ension."); | |
| | | bshape.resize(N+1); | |
| | | boffset.resize(N+1); | |
| | | bshape[N] = numBandsOfType; | |
| | | boffset[N] = 0; | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(N == dimensions, | |
| | | "HDF5File::readBlock(): Array dimension disagrees with data dim | |
| | | ension."); | |
| | | bshape.resize(N); | |
| | | boffset.resize(N); | |
| | | } | |
| | | | |
| | | for(int i = 0; i < N; ++i) | |
| | | { | |
| | | // vigra and hdf5 use different indexing | |
| | | bshape[N-1-i] = array.shape(i); | |
| | | boffset[N-1-i] = blockOffset[i]; | |
| | | } | |
| | | | |
|
| template <class Shape> | | // create a target dataspace in memory with the shape of the desired bl | |
| inline void | | ock | |
| selectHyperslabs(HDF5Handle & mid1, HDF5Handle & mid2, Shape const & shape, | | HDF5Handle memspace_handle (H5Screate_simple(bshape.size(), bshape.data | |
| int & counter, const int elements, const int numBandsOfType) | | (), NULL), | |
| { | | &H5Sclose, | |
| // select hyperslab in HDF5 file | | "Unable to get origin dataspace"); | |
| hsize_t shapeHDF5[2]; | | | |
| shapeHDF5[0] = 1; | | // get file dataspace and select the desired block | |
| shapeHDF5[1] = elements; | | HDF5Handle dataspaceHandle (H5Dget_space(datasetHandle),&H5Sclose,"Unab | |
| hsize_t startHDF5[2]; | | le to create target dataspace"); | |
| startHDF5[0] = 0; | | H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, | |
| startHDF5[1] = counter * numBandsOfType * shape[0]; // we have to reser | | boffset.data(), bones.data(), bones.data(), bshape. | |
| ve space for the pixel type channel(s) | | data()); | |
| hsize_t strideHDF5[2]; | | | |
| strideHDF5[0] = 1; | | herr_t status = 0; | |
| strideHDF5[1] = 1; | | if(array.isUnstrided()) | |
| hsize_t countHDF5[2]; | | { | |
| countHDF5[0] = 1; | | // when the array is unstrided, we can read the data directly from | |
| countHDF5[1] = numBandsOfType * shape[0]; | | the array buffer | |
| hsize_t blockHDF5[2]; | | status = H5Dwrite( datasetHandle, datatype, memspace_handle, datasp | |
| blockHDF5[0] = 1; | | aceHandle, H5P_DEFAULT, array.data()); | |
| blockHDF5[1] = 1; | | } | |
| mid1 = HDF5Handle(H5Screate_simple(2, shapeHDF5, NULL), | | else | |
| &H5Sclose, "unable to create hyperslabs."); | | { | |
| H5Sselect_hyperslab(mid1, H5S_SELECT_SET, startHDF5, strideHDF5, countH | | // otherwise, we must copy the data into an unstrided extra buffer | |
| DF5, blockHDF5); | | MultiArray<N, T> buffer(array); | |
| // select hyperslab in input data object | | status = H5Dwrite( datasetHandle, datatype, memspace_handle, datasp | |
| hsize_t shapeData[2]; | | aceHandle, H5P_DEFAULT, buffer.data()); | |
| shapeData[0] = 1; | | } | |
| shapeData[1] = numBandsOfType * shape[0]; | | return status; | |
| hsize_t startData[2]; | | } | |
| startData[0] = 0; | | | |
| startData[1] = 0; | | /********************************************************************/ | |
| hsize_t strideData[2]; | | | |
| strideData[0] = 1; | | template<unsigned int N, class T, class Stride> | |
| strideData[1] = 1; | | void HDF5File::write_attribute_(std::string name, | |
| hsize_t countData[2]; | | const std::string & attribute_name, | |
| countData[0] = 1; | | const MultiArrayView<N, T, Stride> & array, | |
| countData[1] = numBandsOfType * shape[0]; | | const hid_t datatype, | |
| hsize_t blockData[2]; | | const int numBandsOfType) | |
| blockData[0] = 1; | | { | |
| blockData[1] = 1; | | vigra_precondition(!isReadOnly(), | |
| mid2 = HDF5Handle(H5Screate_simple(2, shapeData, NULL), | | "HDF5File::writeAttribute(): file is read-only."); | |
| &H5Sclose, "unable to create hyperslabs."); | | | |
| H5Sselect_hyperslab(mid2, H5S_SELECT_SET, startData, strideData, countD | | // shape of the array. Add one dimension, if array contains non-scalars | |
| ata, blockData); | | . | |
| } | | ArrayVector<hsize_t> shape(array.shape().begin(), array.shape().end()); | |
| | | std::reverse(shape.begin(), shape.end()); | |
| template <class DestIterator, class Shape, class T> | | if(numBandsOfType > 1) | |
| inline void | | shape.push_back(numBandsOfType); | |
| readHDF5Impl(DestIterator d, Shape const & shape, const hid_t dataset_id, c | | | |
| onst hid_t datatype, ArrayVector<T> & buffer, int & counter, const int elem | | HDF5Handle dataspace(H5Screate_simple(shape.size(), | |
| ents, const int numBandsOfType, MetaInt<0>) | | shape.begin(), NULL), | |
| { | | &H5Sclose, "HDF5File::writeAttribute(): Can not" | |
| HDF5Handle mid1, mid2; | | " create dataspace."); | |
| | | | |
| // select hyperslabs | | std::string errorMessage ("HDF5File::writeAttribute(): can not find " | |
| selectHyperslabs(mid1, mid2, shape, counter, elements, numBandsOfType); | | "object '" + name + "'."); | |
| | | | |
| // read from hdf5 | | H5O_type_t h5_type = get_object_type_(name); | |
| herr_t read_status = H5Dread(dataset_id, datatype, mid2, mid1, H5P_DEFA | | bool is_group = h5_type == H5O_TYPE_GROUP; | |
| ULT, buffer.data()); | | if (!is_group && h5_type != H5O_TYPE_DATASET) | |
| vigra_precondition(read_status >= 0, "readHDF5Impl(): read from dataset | | vigra_precondition(0, "HDF5File::writeAttribute(): object \"" | |
| failed."); | | + name + "\" is neither a group nor a " | |
| | | "dataset."); | |
| // increase counter | | // get parent object handle | |
| counter++; | | HDF5Handle object_handle(is_group | |
| | | ? openCreateGroup_(name) | |
| //std::cout << "numBandsOfType: " << numBandsOfType << std::endl; | | : getDatasetHandle_(name), | |
| DestIterator dend = d + shape[0]; | | is_group | |
| int k = 0; | | ? &H5Gclose | |
| for(; d < dend; ++d, k++) | | : &H5Dclose, | |
| { | | errorMessage.c_str()); | |
| *d = buffer[k]; | | // create / open attribute | |
| //std::cout << buffer[k] << "| "; | | bool exists = existsAttribute(name, attribute_name); | |
| } | | HDF5Handle attributeHandle(exists | |
| } | | ? H5Aopen(object_handle, | |
| | | attribute_name.c_str(), | |
| template <class DestIterator, class Shape, class T, int N> | | H5P_DEFAULT) | |
| void | | : H5Acreate(object_handle, | |
| readHDF5Impl(DestIterator d, Shape const & shape, const hid_t dataset_id, c | | attribute_name.c_str(), datatype | |
| onst hid_t datatype, ArrayVector<T> & buffer, int & counter, const int elem | | , | |
| ents, const int numBandsOfType, MetaInt<N>) | | dataspace, H5P_DEFAULT, | |
| | | H5P_DEFAULT), | |
| | | &H5Aclose, | |
| | | "HDF5File::writeAttribute(): Can not create" | |
| | | " attribute."); | |
| | | herr_t status = 0; | |
| | | if(array.isUnstrided()) | |
| | | { | |
| | | // write the data directly from the array data buffer | |
| | | status = H5Awrite(attributeHandle, datatype, array.data()); | |
| | | } | |
| | | else | |
| | | { | |
| | | // write the data via an unstrided copy | |
| | | // (we assume that attributes are small arrays, so that the wasted | |
| | | memory is uncritical) | |
| | | MultiArray<N, T> buffer(array); | |
| | | status = H5Awrite(attributeHandle, datatype, buffer.data()); | |
| | | } | |
| | | vigra_postcondition(status >= 0, | |
| | | "HDF5File::writeAttribute(): write to attribute '" + attribute_name | |
| | | + "' via H5Awrite() failed."); | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | template<unsigned int N, class T, class Stride> | |
| | | void HDF5File::read_(std::string datasetName, | |
| | | MultiArrayView<N, T, Stride> array, | |
| | | const hid_t datatype, const int numBandsOfType) | |
| { | | { | |
|
| DestIterator dend = d + shape[N]; | | //Prepare to read without using HDF5ImportInfo | |
| for(; d < dend; ++d) | | ArrayVector<hsize_t> dimshape = getDatasetShape(datasetName); | |
| | | | |
| | | std::string errorMessage ("HDF5File::read(): Unable to open dataset '" | |
| | | + datasetName + "'."); | |
| | | HDF5Handle datasetHandle(getDatasetHandle_(datasetName), &H5Dclose, err | |
| | | orMessage.c_str()); | |
| | | | |
| | | // the object in the HDF5 file may have one additional dimension which | |
| | | we | |
| | | // interprete as the pixel type's bands | |
| | | int offset = (numBandsOfType > 1) | |
| | | ? 1 | |
| | | : 0; | |
| | | | |
| | | vigra_precondition(MultiArrayIndex(N + offset) == MultiArrayIndex(dimsh | |
| | | ape.size()), | |
| | | "HDF5File::read(): Array dimension disagrees with dataset dimension | |
| | | ."); | |
| | | | |
| | | typename MultiArrayShape<N>::type shape; | |
| | | for(int k=offset; k < (int)dimshape.size(); ++k) | |
| | | shape[k-offset] = (MultiArrayIndex)dimshape[k]; | |
| | | | |
| | | vigra_precondition(shape == array.shape(), | |
| | | "HDF5File::read(): Array shape disagrees with datase | |
| | | t shape."); | |
| | | if (offset) | |
| | | vigra_precondition(dimshape[0] == static_cast<hsize_t>(numBandsOfTy | |
| | | pe), | |
| | | "HDF5File::read(): Band count doesn't match dest | |
| | | ination array compound type."); | |
| | | | |
| | | herr_t status = 0; | |
| | | if(array.isUnstrided()) | |
| { | | { | |
|
| readHDF5Impl(d.begin(), shape, dataset_id, datatype, buffer, counte | | // when the array is unstrided, we can read the data directly into | |
| r, elements, numBandsOfType, MetaInt<N-1>()); | | the array buffer | |
| | | status = H5Dread(datasetHandle, datatype, H5S_ALL, H5S_ALL, H5P_DEF | |
| | | AULT, array.data() ); | |
| } | | } | |
|
| | | else | |
| | | { | |
| | | // otherwise, we need an intermediate buffer | |
| | | | |
| | | ArrayVector<hsize_t> null(dimshape.size(), 0), | |
| | | chunks(dimshape.size(), 1), | |
| | | start(dimshape.size(), 0), | |
| | | count(dimshape.size(), 1); | |
| | | | |
| | | HDF5Handle properties(H5Dget_create_plist(datasetHandle), | |
| | | &H5Pclose, "HDF5File::read(): failed to get pr | |
| | | operty list"); | |
| | | if(H5D_CHUNKED == H5Pget_layout(properties)) | |
| | | { | |
| | | // if the file is chunked, we use a buffer that matches the chu | |
| | | nk size. | |
| | | H5Pget_chunk(properties, static_cast<int>(chunks.size()), chunk | |
| | | s.data()); | |
| | | std::reverse(chunks.begin(), chunks.end()); | |
| | | } | |
| | | else | |
| | | { | |
| | | // otherwise, we compute a suitable chunk size. | |
| | | chunks[0] = numBandsOfType; | |
| | | MultiArrayIndex prod = 1; | |
| | | for(unsigned int k=0; k<N; ++k) | |
| | | { | |
| | | chunks[k+offset] = array.shape(k); | |
| | | prod *= array.shape(k); | |
| | | if(prod > 300000) | |
| | | break; | |
| | | } | |
| | | } | |
| | | | |
| | | count[N-1-offset] = static_cast<hsize_t>(numBandsOfType); | |
| | | | |
| | | typedef typename MultiArrayShape<N>::type Shape; | |
| | | Shape chunkCount, chunkMaxShape; | |
| | | for(unsigned int k=offset; k<chunks.size(); ++k) | |
| | | { | |
| | | chunkMaxShape[k-offset] = chunks[k]; | |
| | | chunkCount[k-offset] = (MultiArrayIndex)std::ceil(double(dimsha | |
| | | pe[k]) / chunks[k]); | |
| | | } | |
| | | | |
| | | typename CoupledIteratorType<N>::type chunkIter = createCoupledIter | |
| | | ator(chunkCount), | |
| | | chunkEnd = chunkIter.getEndI | |
| | | terator(); | |
| | | for(; chunkIter != chunkEnd; ++chunkIter) | |
| | | { | |
| | | Shape chunkStart(chunkIter.point() * chunkMaxShape), | |
| | | chunkStop(min(chunkStart + chunkMaxShape, array.shape())) | |
| | | ; | |
| | | MultiArray<N, T> buffer(chunkStop - chunkStart); | |
| | | | |
| | | for(unsigned int k=0; k<N; ++k) | |
| | | { | |
| | | start[N-1-k] = chunkStart[k]; | |
| | | count[N-1-k] = buffer.shape(k); | |
| | | } | |
| | | if(offset == 1) | |
| | | { | |
| | | start[N] = 0; | |
| | | count[N] = numBandsOfType; | |
| | | } | |
| | | HDF5Handle filespace(H5Dget_space(datasetHandle), | |
| | | &H5Sclose, "HDF5File::read(): unable to cr | |
| | | eate hyperslabs."); | |
| | | status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, start.d | |
| | | ata(), NULL, count.data(), NULL); | |
| | | if(status < 0) | |
| | | break; | |
| | | | |
| | | HDF5Handle dataspace(H5Screate_simple(count.size(), count.data( | |
| | | ), NULL), | |
| | | &H5Sclose, "HDF5File::read(): unable to cr | |
| | | eate hyperslabs."); | |
| | | status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, null.da | |
| | | ta(), NULL, count.data(), NULL); | |
| | | if(status < 0) | |
| | | break; | |
| | | | |
| | | status = H5Dread(datasetHandle, datatype, dataspace, filespace, | |
| | | H5P_DEFAULT, buffer.data()); | |
| | | if(status < 0) | |
| | | break; | |
| | | | |
| | | array.subarray(chunkStart, chunkStop) = buffer; | |
| | | } | |
| | | } | |
| | | vigra_postcondition(status >= 0, | |
| | | "HDF5File::read(): read from dataset '" + datasetName + "' via H5Dr | |
| | | ead() failed."); | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | template<unsigned int N, class T, class Stride> | |
| | | herr_t HDF5File::readBlock_(HDF5HandleShared datasetHandle, | |
| | | typename MultiArrayShape<N>::type &blockOffset, | |
| | | typename MultiArrayShape<N>::type &blockShape, | |
| | | MultiArrayView<N, T, Stride> array, | |
| | | const hid_t datatype, const int numBandsOfType) | |
| | | { | |
| | | vigra_precondition(blockShape == array.shape(), | |
| | | "HDF5File::readBlock(): Array shape disagrees with block size."); | |
| | | | |
| | | ArrayVector<hsize_t> boffset, bshape, bones(N+1, 1); | |
| | | hssize_t dimensions = getDatasetDimensions_(datasetHandle); | |
| | | if(numBandsOfType > 1) | |
| | | { | |
| | | vigra_precondition(N+1 == dimensions, | |
| | | "HDF5File::readBlock(): Array dimension disagrees with data dim | |
| | | ension."); | |
| | | bshape.resize(N+1); | |
| | | boffset.resize(N+1); | |
| | | bshape[N] = numBandsOfType; | |
| | | boffset[N] = 0; | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(N == dimensions, | |
| | | "HDF5File::readBlock(): Array dimension disagrees with data dim | |
| | | ension."); | |
| | | bshape.resize(N); | |
| | | boffset.resize(N); | |
| | | } | |
| | | | |
| | | for(int i = 0; i < N; ++i) | |
| | | { | |
| | | // vigra and hdf5 use different indexing | |
| | | bshape[N-1-i] = blockShape[i]; | |
| | | boffset[N-1-i] = blockOffset[i]; | |
| | | } | |
| | | | |
| | | // create a target dataspace in memory with the shape of the desired bl | |
| | | ock | |
| | | HDF5Handle memspace_handle(H5Screate_simple(bshape.size(), bshape.data( | |
| | | ), NULL), | |
| | | &H5Sclose, | |
| | | "Unable to create target dataspace"); | |
| | | | |
| | | // get file dataspace and select the desired block | |
| | | HDF5Handle dataspaceHandle(H5Dget_space(datasetHandle), &H5Sclose, | |
| | | "Unable to get dataspace"); | |
| | | H5Sselect_hyperslab(dataspaceHandle, H5S_SELECT_SET, | |
| | | boffset.data(), bones.data(), bones.data(), bshape. | |
| | | data()); | |
| | | | |
| | | herr_t status = 0; | |
| | | if(array.isUnstrided()) | |
| | | { | |
| | | // when the array is unstrided, we can read the data directly into | |
| | | the array buffer | |
| | | status = H5Dread( datasetHandle, datatype, memspace_handle, dataspa | |
| | | ceHandle, H5P_DEFAULT, array.data()); | |
| | | } | |
| | | else | |
| | | { | |
| | | // otherwise, we need an unstrided extra buffer ... | |
| | | MultiArray<N, T> buffer(array.shape()); | |
| | | status = H5Dread( datasetHandle, datatype, memspace_handle, dataspa | |
| | | ceHandle, H5P_DEFAULT, buffer.data()); | |
| | | // ... and must copy the values | |
| | | if(status >= 0) | |
| | | array = buffer; | |
| | | } | |
| | | return status; | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | template<unsigned int N, class T, class Stride> | |
| | | void HDF5File::read_attribute_(std::string datasetName, | |
| | | std::string attributeName, | |
| | | MultiArrayView<N, T, Stride> array, | |
| | | const hid_t datatype, const int numBandsOfTy | |
| | | pe) | |
| | | { | |
| | | std::string dataset_path = get_absolute_path(datasetName); | |
| | | // open Attribute handle | |
| | | std::string message = "HDF5File::readAttribute(): could not get handle | |
| | | for attribute '"+attributeName+"'' of object '"+dataset_path+"'."; | |
| | | HDF5Handle attr_handle (H5Aopen_by_name(fileHandle_,dataset_path.c_str( | |
| | | ),attributeName.c_str(),H5P_DEFAULT,H5P_DEFAULT),&H5Aclose, message.c_str() | |
| | | ); | |
| | | | |
| | | // get Attribute dataspace | |
| | | message = "HDF5File::readAttribute(): could not get dataspace for attri | |
| | | bute '"+attributeName+"'' of object '"+dataset_path+"'."; | |
| | | HDF5Handle attr_dataspace_handle (H5Aget_space(attr_handle),&H5Sclose,m | |
| | | essage.c_str()); | |
| | | | |
| | | // obtain Attribute shape | |
| | | int raw_dims = H5Sget_simple_extent_ndims(attr_dataspace_handle); | |
| | | int dims = std::max(raw_dims, 1); // scalar attributes may be stored wi | |
| | | th raw_dims==0 | |
| | | ArrayVector<hsize_t> dimshape(dims); | |
| | | if(raw_dims > 0) | |
| | | H5Sget_simple_extent_dims(attr_dataspace_handle, dimshape.data(), N | |
| | | ULL); | |
| | | else | |
| | | dimshape[0] = 1; | |
| | | | |
| | | // invert the dimensions to guarantee VIGRA-compatible order | |
| | | std::reverse(dimshape.begin(), dimshape.end()); | |
| | | | |
| | | int offset = (numBandsOfType > 1) | |
| | | ? 1 | |
| | | : 0; | |
| | | message = "HDF5File::readAttribute(): Array dimension disagrees with da | |
| | | taset dimension."; | |
| | | // the object in the HDF5 file may have one additional dimension which | |
| | | we then interpret as the pixel type bands | |
| | | vigra_precondition(MultiArrayIndex(N + offset) == MultiArrayIndex(dims) | |
| | | , message); | |
| | | | |
| | | for(int k=offset; k < (int)dimshape.size(); ++k) | |
| | | vigra_precondition(array.shape()[k-offset] == (MultiArrayIndex)dims | |
| | | hape[k], | |
| | | "HDF5File::readAttribute(): Array shape disagree | |
| | | s with dataset shape"); | |
| | | | |
| | | herr_t status = 0; | |
| | | if(array.isUnstrided()) | |
| | | { | |
| | | // when the array is unstrided, we can read the data directly into | |
| | | the array buffer | |
| | | status = H5Aread( attr_handle, datatype, array.data()); | |
| | | } | |
| | | else | |
| | | { | |
| | | // otherwise, we need an unstrided extra buffer ... | |
| | | // (we assume that attributes are small arrays, so that the wasted | |
| | | memory is uncritical) | |
| | | MultiArray<N, T> buffer(array.shape()); | |
| | | status = H5Aread( attr_handle, datatype, buffer.data() ); | |
| | | // ... and must copy the values | |
| | | if(status >= 0) | |
| | | array = buffer; | |
| | | } | |
| | | vigra_postcondition(status >= 0, | |
| | | "HDF5File::readAttribute(): read from attribute '" + attributeName | |
| | | + "' via H5Aread() failed."); | |
| } | | } | |
| | | | |
|
| } // namespace detail | | /********************************************************************/ | |
| | | | |
| /** \brief Read the data specified by the given \ref vigra::HDF5ImportInfo
object | | /** \brief Read the data specified by the given \ref vigra::HDF5ImportInfo
object | |
| and write the into the given 'array'. | | and write the into the given 'array'. | |
| | | | |
| The array must have the correct number of dimensions and shape for the
dataset | | The array must have the correct number of dimensions and shape for the
dataset | |
| represented by 'info'. When the element type of 'array' differs from th
e stored element | | represented by 'info'. When the element type of 'array' differs from th
e stored element | |
| type, HDF5 will convert the type on the fly (except when the HDF5 versi
on is 1.6 or below, | | type, HDF5 will convert the type on the fly (except when the HDF5 versi
on is 1.6 or below, | |
| in which case an error will result). Multi-channel element types (i.e.
\ref vigra::RGBValue, | | in which case an error will result). Multi-channel element types (i.e.
\ref vigra::RGBValue, | |
| \ref vigra::TinyVector, and \ref vigra::FFTWComplex) are recognized and
handled correctly. | | \ref vigra::TinyVector, and \ref vigra::FFTWComplex) are recognized and
handled correctly. | |
| | | | |
| | | | |
| skipping to change at line 2321 | | skipping to change at line 3336 | |
| vigra_precondition(info.numDimensions() == 3, "Dataset must be 3-dimens
ional."); | | vigra_precondition(info.numDimensions() == 3, "Dataset must be 3-dimens
ional."); | |
| | | | |
| MultiArrayShape<3>::type shape(info.shape().begin()); | | MultiArrayShape<3>::type shape(info.shape().begin()); | |
| MultiArray<3, int> array(shape); | | MultiArray<3, int> array(shape); | |
| | | | |
| readHDF5(info, array); | | readHDF5(info, array); | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void readHDF5) | | doxygen_overloaded_function(template <...> void readHDF5) | |
| | | | |
|
| // scalar and unstrided target multi array | | template<unsigned int N, class T, class StrideTag> | |
| template<unsigned int N, class T> | | inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, Strid | |
| inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, Unstr | | eTag> array) | |
| idedArrayTag> array) // scalar | | | |
| { | | | |
| readHDF5(info, array, detail::getH5DataType<T>(), 1); | | | |
| } | | | |
| | | | |
| // non-scalar (TinyVector) and unstrided target multi array | | | |
| template<unsigned int N, class T, int SIZE> | | | |
| inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, TinyVect | | | |
| or<T, SIZE>, UnstridedArrayTag> array) | | | |
| { | | | |
| readHDF5(info, array, detail::getH5DataType<T>(), SIZE); | | | |
| } | | | |
| | | | |
| // non-scalar (RGBValue) and unstrided target multi array | | | |
| template<unsigned int N, class T> | | | |
| inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, RGBValue | | | |
| <T>, UnstridedArrayTag> array) | | | |
| { | | | |
| readHDF5(info, array, detail::getH5DataType<T>(), 3); | | | |
| } | | | |
| | | | |
| // non-scalar (FFTWComplex) and unstrided target multi array | | | |
| template<unsigned int N, class T> | | | |
| inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, FFTWComp | | | |
| lex<T>, UnstridedArrayTag> array) | | | |
| { | | | |
| readHDF5(info, array, detail::getH5DataType<T>(), 2); | | | |
| } | | | |
| | | | |
| // unstrided target multi array | | | |
| template<unsigned int N, class T> | | | |
| void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, UnstridedArr | | | |
| ayTag> array, const hid_t datatype, const int numBandsOfType) | | | |
| { | | | |
| int offset = (numBandsOfType > 1); | | | |
| | | | |
| //std::cout << "offset: " << offset << ", N: " << N << ", dims: " << in | | | |
| fo.numDimensions() << std::endl; | | | |
| vigra_precondition(( (N + offset ) == info.numDimensions()), // the obj | | | |
| ect in the HDF5 file may have one additional dimension which we then interp | | | |
| ret as the pixel type bands | | | |
| "readHDF5(): Array dimension disagrees with HDF5ImportInfo.numDimen | | | |
| sions()."); | | | |
| | | | |
| typename MultiArrayShape<N>::type shape; | | | |
| for(int k=offset; k<info.numDimensions(); ++k) { | | | |
| shape[k-offset] = info.shapeOfDimension(k); | | | |
| } | | | |
| | | | |
| vigra_precondition(shape == array.shape(), | | | |
| "readHDF5(): Array shape disagrees with HDF5ImportInfo."); | | | |
| | | | |
| // simply read in the data as is | | | |
| H5Dread( info.getDatasetHandle(), datatype, H5S_ALL, H5S_ALL, H5P_DEFAU | | | |
| LT, array.data() ); // .data() possible since void pointer! | | | |
| } | | | |
| | | | |
| // scalar and strided target multi array | | | |
| template<unsigned int N, class T> | | | |
| inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, Strid | | | |
| edArrayTag> array) // scalar | | | |
| { | | { | |
|
| readHDF5(info, array, detail::getH5DataType<T>(), 1); | | readHDF5(info, array, 0, 0); // last two arguments are not used | |
| } | | } | |
| | | | |
|
| // non-scalar (TinyVector) and strided target multi array | | template<unsigned int N, class T, class StrideTag> | |
| template<unsigned int N, class T, int SIZE> | | void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, StrideTag> a | |
| inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, TinyVect | | rray, const hid_t datatype, const int numBandsOfType) | |
| or<T, SIZE>, StridedArrayTag> array) | | | |
| { | | { | |
|
| readHDF5(info, array, detail::getH5DataType<T>(), SIZE); | | HDF5File file(info.getFilePath(), HDF5File::OpenReadOnly); | |
| } | | file.read(info.getPathInFile(), array); | |
| | | file.close(); | |
| // non-scalar (RGBValue) and strided target multi array | | | |
| template<unsigned int N, class T> | | | |
| inline void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, RGBValue | | | |
| <T>, StridedArrayTag> array) | | | |
| { | | | |
| readHDF5(info, array, detail::getH5DataType<T>(), 3); | | | |
| } | | | |
| | | | |
| // strided target multi array | | | |
| template<unsigned int N, class T> | | | |
| void readHDF5(const HDF5ImportInfo &info, MultiArrayView<N, T, StridedArray | | | |
| Tag> array, const hid_t datatype, const int numBandsOfType) | | | |
| { | | | |
| int offset = (numBandsOfType > 1); | | | |
| | | | |
| //std::cout << "offset: " << offset << ", N: " << N << ", dims: " << in | | | |
| fo.numDimensions() << std::endl; | | | |
| vigra_precondition(( (N + offset ) == info.numDimensions()), // the obj | | | |
| ect in the HDF5 file may have one additional dimension which we then interp | | | |
| ret as the pixel type bands | | | |
| "readHDF5(): Array dimension disagrees with HDF5ImportInfo.numDimen | | | |
| sions()."); | | | |
| | | | |
| typename MultiArrayShape<N>::type shape; | | | |
| for(int k=offset; k<info.numDimensions(); ++k) { | | | |
| shape[k-offset] = info.shapeOfDimension(k); | | | |
| } | | | |
| | | | |
| vigra_precondition(shape == array.shape(), | | | |
| "readHDF5(): Array shape disagrees with HDF5ImportInfo."); | | | |
| | | | |
| //Get the data | | | |
| int counter = 0; | | | |
| int elements = numBandsOfType; | | | |
| for(unsigned int i=0;i<N;++i) | | | |
| elements *= shape[i]; | | | |
| ArrayVector<T> buffer(shape[0]); | | | |
| detail::readHDF5Impl(array.traverser_begin(), shape, info.getDatasetHan | | | |
| dle(), datatype, buffer, counter, elements, numBandsOfType, vigra::MetaInt< | | | |
| N-1>()); | | | |
| } | | } | |
| | | | |
| inline hid_t openGroup(hid_t parent, std::string group_name) | | inline hid_t openGroup(hid_t parent, std::string group_name) | |
| { | | { | |
| //std::cout << group_name << std::endl; | | //std::cout << group_name << std::endl; | |
| size_t last_slash = group_name.find_last_of('/'); | | size_t last_slash = group_name.find_last_of('/'); | |
| if (last_slash == std::string::npos || last_slash != group_name.size()
- 1) | | if (last_slash == std::string::npos || last_slash != group_name.size()
- 1) | |
| group_name = group_name + '/'; | | group_name = group_name + '/'; | |
| std::string::size_type begin = 0, end = group_name.find('/'); | | std::string::size_type begin = 0, end = group_name.find('/'); | |
| int ii = 0; | | int ii = 0; | |
| | | | |
| skipping to change at line 2579 | | skipping to change at line 3510 | |
| | | | |
| //alloc memory for dataset. | | //alloc memory for dataset. | |
| dataset_handle = HDF5Handle(H5Dcreate(group, | | dataset_handle = HDF5Handle(H5Dcreate(group, | |
| data_set_name.c_str(), | | data_set_name.c_str(), | |
| datatype, | | datatype, | |
| dataspace_handle, | | dataspace_handle, | |
| H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAU
LT), | | H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAU
LT), | |
| &H5Dclose, "createDataset(): unable to create
dataset."); | | &H5Dclose, "createDataset(): unable to create
dataset."); | |
| } | | } | |
| | | | |
|
| namespace detail { | | | |
| | | | |
| template <class DestIterator, class Shape, class T> | | | |
| inline void | | | |
| writeHDF5Impl(DestIterator d, Shape const & shape, const hid_t dataset_id, | | | |
| const hid_t datatype, ArrayVector<T> & buffer, int & counter, const int ele | | | |
| ments, const int numBandsOfType, MetaInt<0>) | | | |
| { | | | |
| DestIterator dend = d + (typename DestIterator::difference_type)shape[0 | | | |
| ]; | | | |
| int k = 0; | | | |
| //std::cout << "new:" << std::endl; | | | |
| for(; d < dend; ++d, k++) | | | |
| { | | | |
| buffer[k] = *d; | | | |
| //std::cout << buffer[k] << " "; | | | |
| } | | | |
| //std::cout << std::endl; | | | |
| HDF5Handle mid1, mid2; | | | |
| | | | |
| // select hyperslabs | | | |
| selectHyperslabs(mid1, mid2, shape, counter, elements, numBandsOfType); | | | |
| | | | |
| // write to hdf5 | | | |
| H5Dwrite(dataset_id, datatype, mid2, mid1, H5P_DEFAULT, buffer.data()); | | | |
| // increase counter | | | |
| counter++; | | | |
| } | | | |
| | | | |
| template <class DestIterator, class Shape, class T, int N> | | | |
| void | | | |
| writeHDF5Impl(DestIterator d, Shape const & shape, const hid_t dataset_id, | | | |
| const hid_t datatype, ArrayVector<T> & buffer, int & counter, const int ele | | | |
| ments, const int numBandsOfType, MetaInt<N>) | | | |
| { | | | |
| DestIterator dend = d + (typename DestIterator::difference_type)sha | | | |
| pe[N]; | | | |
| for(; d < dend; ++d) | | | |
| { | | | |
| writeHDF5Impl(d.begin(), shape, dataset_id, datatype, buffer, c | | | |
| ounter, elements, numBandsOfType, MetaInt<N-1>()); | | | |
| } | | | |
| } | | | |
| | | | |
| } // namespace detail | | | |
| | | | |
| /** \brief Store array data in an HDF5 file. | | /** \brief Store array data in an HDF5 file. | |
| | | | |
| The number of dimensions, shape and element type of the stored dataset
is automatically | | The number of dimensions, shape and element type of the stored dataset
is automatically | |
| determined from the properties of the given \a array. Strided arrays ar
e stored in an | | determined from the properties of the given \a array. Strided arrays ar
e stored in an | |
| unstrided way, i.e. in contiguous scan-order. Multi-channel element typ
es | | unstrided way, i.e. in contiguous scan-order. Multi-channel element typ
es | |
| (i.e. \ref vigra::RGBValue, \ref vigra::TinyVector and \ref vigra::FFTW
Complex) | | (i.e. \ref vigra::RGBValue, \ref vigra::TinyVector and \ref vigra::FFTW
Complex) | |
| are recognized and handled correctly | | are recognized and handled correctly | |
| (in particular, the will form the innermost dimension of the stored dat
aset). | | (in particular, the will form the innermost dimension of the stored dat
aset). | |
| \a pathInFile may contain '/'-separated group names, but must end with
the name | | \a pathInFile may contain '/'-separated group names, but must end with
the name | |
| of the dataset to be created. | | of the dataset to be created. | |
| | | | |
| skipping to change at line 2655 | | skipping to change at line 3547 | |
| \code | | \code | |
| MultiArrayShape<3>::type shape(100, 200, 20); | | MultiArrayShape<3>::type shape(100, 200, 20); | |
| MultiArray<3, int> array(shape); | | MultiArray<3, int> array(shape); | |
| ... // fill array with data | | ... // fill array with data | |
| | | | |
| writeHDF5("mydata.h5", "/group1/my_dataset", array); | | writeHDF5("mydata.h5", "/group1/my_dataset", array); | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void writeHDF5) | | doxygen_overloaded_function(template <...> void writeHDF5) | |
| | | | |
|
| // scalar and unstrided multi arrays | | template<unsigned int N, class T, class StrideTag> | |
| template<unsigned int N, class T> | | inline void writeHDF5(const char* filePath, const char* pathInFile, const M | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M | | ultiArrayView<N, T, StrideTag> & array) | |
| ultiArrayView<N, T, UnstridedArrayTag> & array) // scalar | | | |
| { | | { | |
|
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 1); | | //last two arguments are not used | |
| | | writeHDF5(filePath, pathInFile, array, 0, 0); | |
| } | | } | |
| | | | |
|
| // non-scalar (TinyVector) and unstrided multi arrays | | template<unsigned int N, class T, class StrideTag> | |
| template<unsigned int N, class T, int SIZE> | | void writeHDF5(const char* filePath, const char* pathInFile, const MultiArr | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M | | ayView<N, T, StrideTag> & array, const hid_t datatype, const int numBandsOf | |
| ultiArrayView<N, TinyVector<T, SIZE>, UnstridedArrayTag> & array) | | Type) | |
| { | | { | |
|
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), SIZE | | HDF5File file(filePath, HDF5File::Open); | |
| ); | | file.write(pathInFile, array); | |
| } | | file.close(); | |
| | | | |
| // non-scalar (RGBValue) and unstrided multi arrays | | | |
| template<unsigned int N, class T> | | | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M | | | |
| ultiArrayView<N, RGBValue<T>, UnstridedArrayTag> & array) | | | |
| { | | | |
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 3); | | | |
| } | | | |
| | | | |
| // non-scalar (FFTWComplex) and unstrided multi arrays | | | |
| template<unsigned int N, class T> | | | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M | | | |
| ultiArrayView<N, FFTWComplex<T>, UnstridedArrayTag> & array) | | | |
| { | | | |
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 2); | | | |
| } | | | |
| | | | |
| // unstrided multi arrays | | | |
| template<unsigned int N, class T> | | | |
| void writeHDF5(const char* filePath, const char* pathInFile, const MultiArr | | | |
| ayView<N, T, UnstridedArrayTag> & array, const hid_t datatype, const int nu | | | |
| mBandsOfType) | | | |
| { | | | |
| HDF5Handle file_handle; | | | |
| HDF5Handle dataset_handle; | | | |
| createDataset(filePath, pathInFile, array, datatype, numBandsOfType, fi | | | |
| le_handle, dataset_handle); | | | |
| | | | |
| // Write the data to the HDF5 dataset as is | | | |
| H5Dwrite( dataset_handle, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT, arra | | | |
| y.data()); // .data() possible since void pointer! | | | |
| | | | |
| H5Fflush(file_handle, H5F_SCOPE_GLOBAL); | | | |
| } | | | |
| | | | |
| // scalar and strided multi arrays | | | |
| template<unsigned int N, class T> | | | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M | | | |
| ultiArrayView<N, T, StridedArrayTag> & array) // scalar | | | |
| { | | | |
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 1); | | | |
| } | | | |
| | | | |
| // non-scalar (TinyVector) and strided multi arrays | | | |
| template<unsigned int N, class T, int SIZE> | | | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M | | | |
| ultiArrayView<N, TinyVector<T, SIZE>, StridedArrayTag> & array) | | | |
| { | | | |
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), SIZE | | | |
| ); | | | |
| } | | | |
| | | | |
| // non-scalar (RGBValue) and strided multi arrays | | | |
| template<unsigned int N, class T> | | | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M | | | |
| ultiArrayView<N, RGBValue<T>, StridedArrayTag> & array) | | | |
| { | | | |
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 3); | | | |
| } | | | |
| | | | |
| // non-scalar (FFTWComplex) and strided multi arrays | | | |
| template<unsigned int N, class T> | | | |
| inline void writeHDF5(const char* filePath, const char* pathInFile, const M | | | |
| ultiArrayView<N, FFTWComplex<T>, StridedArrayTag> & array) | | | |
| { | | | |
| writeHDF5(filePath, pathInFile, array, detail::getH5DataType<T>(), 2); | | | |
| } | | | |
| | | | |
| // strided multi arrays | | | |
| template<unsigned int N, class T> | | | |
| void writeHDF5(const char* filePath, const char* pathInFile, const MultiArr | | | |
| ayView<N, T, StridedArrayTag> & array, const hid_t datatype, const int numB | | | |
| andsOfType) | | | |
| { | | | |
| HDF5Handle file_handle; | | | |
| HDF5Handle dataset_handle; | | | |
| createDataset(filePath, pathInFile, array, datatype, numBandsOfType, fi | | | |
| le_handle, dataset_handle); | | | |
| | | | |
| vigra::TinyVector<int,N> shape; | | | |
| vigra::TinyVector<int,N> stride; | | | |
| int elements = numBandsOfType; | | | |
| for(unsigned int k=0; k<N; ++k) | | | |
| { | | | |
| shape[k] = array.shape(k); | | | |
| stride[k] = array.stride(k); | | | |
| elements *= (int)shape[k]; | | | |
| } | | | |
| int counter = 0; | | | |
| | | | |
| ArrayVector<T> buffer((int)array.shape(0)); | | | |
| detail::writeHDF5Impl(array.traverser_begin(), shape, dataset_handle, d | | | |
| atatype, buffer, counter, elements, numBandsOfType, vigra::MetaInt<N-1>()); | | | |
| | | | |
| H5Fflush(file_handle, H5F_SCOPE_GLOBAL); | | | |
| | | | |
| } | | } | |
| | | | |
| namespace detail | | namespace detail | |
| { | | { | |
| struct MaxSizeFnc | | struct MaxSizeFnc | |
| { | | { | |
| size_t size; | | size_t size; | |
| | | | |
| MaxSizeFnc() | | MaxSizeFnc() | |
| : size(0) | | : size(0) | |
| | | | |
End of changes. 160 change blocks. |
| 1052 lines changed or deleted | | 1906 lines changed or added | |
|
| inspectimage.hxx | | inspectimage.hxx | |
| | | | |
| skipping to change at line 47 | | skipping to change at line 47 | |
| #define VIGRA_INSPECTIMAGE_HXX | | #define VIGRA_INSPECTIMAGE_HXX | |
| | | | |
| #include <vector> | | #include <vector> | |
| #include <algorithm> | | #include <algorithm> | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "iteratortraits.hxx" | | #include "iteratortraits.hxx" | |
| #include "functortraits.hxx" | | #include "functortraits.hxx" | |
| #include "rgbvalue.hxx" | | #include "rgbvalue.hxx" | |
| #include "inspector_passes.hxx" | | #include "inspector_passes.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup InspectAlgo Algorithms to Inspect Images | | /** \addtogroup InspectAlgo Algorithms to Inspect Images | |
| | | | |
|
| Apply read-only functor to every pixel | | Collect information and statistics over all or selected pixels. | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* inspectLine */ | | /* inspectLine */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class Functor> | | template <class SrcIterator, class SrcAccessor, class Functor> | |
| | | | |
| skipping to change at line 124 | | skipping to change at line 125 | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* inspectImage */ | | /* inspectImage */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply read-only functor to every pixel in the image. | | /** \brief Apply read-only functor to every pixel in the image. | |
| | | | |
| This function can be used to collect statistics of the image etc. | | This function can be used to collect statistics of the image etc. | |
|
| The results must be stored in the functor, which serves as a return | | The results must be stored in the functor, which serves as a return val | |
| value. | | ue | |
| The function uses an accessor to access the pixel data. | | (and is therefore passed by reference). | |
| | | | |
| | | For many common statistics, the use of \ref vigra::acc::extractFeatures | |
| | | () in combination with | |
| | | \ref FeatureAccumulators is more convenient. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| template <class ImageIterator, class Accessor, class Functor> | | template <class T, class S, class Functor> | |
| void | | void | |
|
| inspectImage(ImageIterator upperleft, ImageIterator lowerright, | | inspectImage(MultiArrayView<2, T, S> const & img, | |
| Accessor a, Functor & f) | | Functor & f); | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedAPI{inspectImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class ImageIterator, class Accessor, class Functor> | |
| | | void | |
| | | inspectImage(ImageIterator upperleft, ImageIterator lowerright, Acc | |
| | | essor a, | |
| | | Functor & f) | |
| | | } | |
| | | \endcode | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class ImageIterator, class Accessor, class Functor> | | template <class ImageIterator, class Accessor, class Functor> | |
| void | | void | |
| inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, | | inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, | |
|
| Functor & f) | | Functor & f) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> img(width, height); | |
| | | ... // fill img | |
| | | | |
| | | // init functor | |
| | | FindMinMax<unsined char> minmax; | |
| | | | |
| | | inspectImage(img, minmax); | |
| | | | |
| | | cout << "Min: " << minmax.min << " Max: " << minmax.max; | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{inspectImage} | |
| | | \code | |
| // init functor | | // init functor | |
| vigra::BImage img; | | vigra::BImage img; | |
| | | | |
| vigra::FindMinMax<vigra::BImage::PixelType> minmax; | | vigra::FindMinMax<vigra::BImage::PixelType> minmax; | |
| | | | |
| vigra::inspectImage(srcImageRange(img), minmax); | | vigra::inspectImage(srcImageRange(img), minmax); | |
| | | | |
| cout << "Min: " << minmax.min << " Max: " << minmax.max; | | cout << "Min: " << minmax.min << " Max: " << minmax.max; | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| ConstImageIterator upperleft, lowerright; | | ConstImageIterator upperleft, lowerright; | |
| ConstImageIterator::row_iterator ix = upperleft.rowIterator(); | | ConstImageIterator::row_iterator ix = upperleft.rowIterator(); | |
| | | | |
| Accessor accessor; | | Accessor accessor; | |
| Functor functor; | | Functor functor; | |
| | | | |
| functor(accessor(ix)); // return not used | | functor(accessor(ix)); // return not used | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
|
| | | \see InspectFunctor, FeatureAccumulators | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void inspectImage) | | doxygen_overloaded_function(template <...> void inspectImage) | |
| | | | |
| template <class ImageIterator, class Accessor> | | template <class ImageIterator, class Accessor> | |
| struct inspectImage_binder | | struct inspectImage_binder | |
| { | | { | |
| ImageIterator upperleft; | | ImageIterator upperleft; | |
| ImageIterator lowerright; | | ImageIterator lowerright; | |
| Accessor a; | | Accessor a; | |
| | | | |
| | | | |
| skipping to change at line 213 | | skipping to change at line 239 | |
| template <class ImageIterator, class Accessor, class Functor> | | template <class ImageIterator, class Accessor, class Functor> | |
| void | | void | |
| inspectImage(ImageIterator upperleft, ImageIterator lowerright, | | inspectImage(ImageIterator upperleft, ImageIterator lowerright, | |
| Accessor a, Functor & f) | | Accessor a, Functor & f) | |
| { | | { | |
| inspectImage_binder<ImageIterator, Accessor> g(upperleft, lowerright, a
); | | inspectImage_binder<ImageIterator, Accessor> g(upperleft, lowerright, a
); | |
| detail::extra_passes_select(g, f); | | detail::extra_passes_select(g, f); | |
| } | | } | |
| | | | |
| template <class ImageIterator, class Accessor, class Functor> | | template <class ImageIterator, class Accessor, class Functor> | |
|
| inline | | inline void | |
| void | | | |
| inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, | | inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, | |
|
| Functor & f) | | Functor & f) | |
| { | | { | |
| inspectImage(img.first, img.second, img.third, f); | | inspectImage(img.first, img.second, img.third, f); | |
| } | | } | |
| | | | |
|
| | | template <class T, class S, class Functor> | |
| | | inline void | |
| | | inspectImage(MultiArrayView<2, T, S> const & img, | |
| | | Functor & f) | |
| | | { | |
| | | inspectImage(srcImageRange(img), f); | |
| | | } | |
| | | | |
| namespace functor | | namespace functor | |
| { | | { | |
| template <class T> class UnaryAnalyser; | | template <class T> class UnaryAnalyser; | |
| } | | } | |
| | | | |
| template <class ImageIterator, class Accessor, class Functor> | | template <class ImageIterator, class Accessor, class Functor> | |
| inline | | inline | |
| void | | void | |
| inspectImage(ImageIterator upperleft, ImageIterator lowerright, | | inspectImage(ImageIterator upperleft, ImageIterator lowerright, | |
| Accessor a, functor::UnaryAnalyser<Functor> const & f) | | Accessor a, functor::UnaryAnalyser<Functor> const & f) | |
| { | | { | |
| inspectImage(upperleft, lowerright, a, | | inspectImage(upperleft, lowerright, a, | |
| const_cast<functor::UnaryAnalyser<Functor> &>(f)); | | const_cast<functor::UnaryAnalyser<Functor> &>(f)); | |
| } | | } | |
| | | | |
| template <class ImageIterator, class Accessor, class Functor> | | template <class ImageIterator, class Accessor, class Functor> | |
|
| inline | | inline void | |
| void | | | |
| inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, | | inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, | |
|
| functor::UnaryAnalyser<Functor> const & f) | | functor::UnaryAnalyser<Functor> const & f) | |
| { | | { | |
| inspectImage(img.first, img.second, img.third, | | inspectImage(img.first, img.second, img.third, | |
| const_cast<functor::UnaryAnalyser<Functor> &>(f)); | | const_cast<functor::UnaryAnalyser<Functor> &>(f)); | |
| } | | } | |
| | | | |
|
| | | template <class T, class S, class Functor> | |
| | | inline void | |
| | | inspectImage(MultiArrayView<2, T, S> const & img, | |
| | | functor::UnaryAnalyser<Functor> const & f) | |
| | | { | |
| | | inspectImage(srcImageRange(img), | |
| | | const_cast<functor::UnaryAnalyser<Functor> &>(f)); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* inspectImageIf */ | | /* inspectImageIf */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply read-only functor to every pixel in the ROI. | | /** \brief Apply read-only functor to every pixel in the ROI. | |
| | | | |
|
| This function can be used to collect statistics of the roi etc. | | This function can be used to collect statistics of the ROI etc. | |
| The functor is called whenever the return value of the mask's | | The functor is called whenever the return value of the mask's | |
| accessor is not zero. | | accessor is not zero. | |
| The results must be stored in the functor, which serves as a return | | The results must be stored in the functor, which serves as a return | |
|
| value. | | value (and is therefore passed by reference. | |
| Accessors are used to access the pixel and mask data. | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T, class S, | |
| | | class TM, class SM, class Functor> | |
| | | void | |
| | | inspectImageIf(MultiArrayView<2, T, S> const & img, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | Functor & f); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{inspectImageIf} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class ImageIterator, class Accessor, | | template <class ImageIterator, class Accessor, | |
| class MaskImageIterator, class MaskAccessor, class Functo
r> | | class MaskImageIterator, class MaskAccessor, class Functo
r> | |
| void | | void | |
| inspectImageIf(ImageIterator upperleft, ImageIterator lowerright, | | inspectImageIf(ImageIterator upperleft, ImageIterator lowerright, | |
| MaskImageIterator mask_upperleft, MaskAccessor ma, | | MaskImageIterator mask_upperleft, MaskAccessor ma, | |
| Functor & f) | | Functor & f) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class ImageIterator, class Accessor, | | template <class ImageIterator, class Accessor, | |
| class MaskImageIterator, class MaskAccessor, class Functor> | | class MaskImageIterator, class MaskAccessor, class Functor> | |
| void | | void | |
| inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, | | inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, | |
| pair<MaskImageIterator, MaskAccessor> mask, | | pair<MaskImageIterator, MaskAccessor> mask, | |
| Functor & f) | | Functor & f) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, unsigned char> img(100, 100), | |
| | | mask(100, 100); | |
| | | ... // fill img and mask | |
| | | | |
| | | // init functor | |
| | | FindMinMax<unsigned char> minmax; | |
| | | | |
| | | inspectImageIf(img, mask, minmax); | |
| | | | |
| | | cout << "Min: " << minmax.min << " Max: " << minmax.max; | |
| | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{inspectImageIf} | |
| \code | | \code | |
| vigra::BImage img(100, 100); | | vigra::BImage img(100, 100); | |
| vigra::BImage mask(100, 100); | | vigra::BImage mask(100, 100); | |
| | | | |
| // init functor | | // init functor | |
| vigra::FindMinMax<vigra::BImage::PixelType> minmax; | | vigra::FindMinMax<vigra::BImage::PixelType> minmax; | |
| | | | |
| vigra::inspectImageIf(srcImageRange(img), | | vigra::inspectImageIf(srcImageRange(img), | |
| maskImage(mask), minmax); | | maskImage(mask), minmax); | |
| | | | |
| cout << "Min: " << minmax.min << " Max: " << minmax.max; | | cout << "Min: " << minmax.min << " Max: " << minmax.max; | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| ConstImageIterator upperleft, lowerright; | | ConstImageIterator upperleft, lowerright; | |
| MaskImageIterator mask_upperleft; | | MaskImageIterator mask_upperleft; | |
| ConstImageIterator::row_iterator ix = upperleft.rowIterator(); | | ConstImageIterator::row_iterator ix = upperleft.rowIterator(); | |
| MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator(); | | MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator(); | |
| | | | |
| Accessor accessor; | | Accessor accessor; | |
| MaskAccessor mask_accessor; | | MaskAccessor mask_accessor; | |
| | | | |
| Functor functor; | | Functor functor; | |
| | | | |
| if(mask_accessor(mx)) functor(accessor(ix)); | | if(mask_accessor(mx)) functor(accessor(ix)); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
|
| | | \see InspectFunctor, FeatureAccumulators | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void inspectImageIf) | | doxygen_overloaded_function(template <...> void inspectImageIf) | |
| | | | |
| template <class ImageIterator, class Accessor, | | template <class ImageIterator, class Accessor, | |
| class MaskImageIterator, class MaskAccessor> | | class MaskImageIterator, class MaskAccessor> | |
| struct inspectImageIf_binder | | struct inspectImageIf_binder | |
| { | | { | |
| ImageIterator upperleft; | | ImageIterator upperleft; | |
| ImageIterator lowerright; | | ImageIterator lowerright; | |
| Accessor a; | | Accessor a; | |
| | | | |
| skipping to change at line 370 | | skipping to change at line 436 | |
| Functor & f) | | Functor & f) | |
| { | | { | |
| inspectImageIf_binder<ImageIterator, Accessor, MaskImageIterator, | | inspectImageIf_binder<ImageIterator, Accessor, MaskImageIterator, | |
| MaskAcce
ssor> | | MaskAcce
ssor> | |
| g(upperleft, lowerright, a, mask_upperleft, ma); | | g(upperleft, lowerright, a, mask_upperleft, ma); | |
| detail::extra_passes_select(g, f); | | detail::extra_passes_select(g, f); | |
| } | | } | |
| | | | |
| template <class ImageIterator, class Accessor, | | template <class ImageIterator, class Accessor, | |
| class MaskImageIterator, class MaskAccessor, class Functor> | | class MaskImageIterator, class MaskAccessor, class Functor> | |
|
| inline | | | |
| void | | | |
| inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, | | | |
| pair<MaskImageIterator, MaskAccessor> mask, | | | |
| Functor & f) | | | |
| { | | | |
| inspectImageIf(img.first, img.second, img.third, | | | |
| mask.first, mask.second, f); | | | |
| } | | | |
| | | | |
| template <class ImageIterator, class Accessor, | | | |
| class MaskImageIterator, class MaskAccessor, class Functor> | | | |
| inline void | | inline void | |
| inspectImageIf(ImageIterator upperleft, | | inspectImageIf(ImageIterator upperleft, | |
| ImageIterator lowerright, Accessor a, | | ImageIterator lowerright, Accessor a, | |
| MaskImageIterator mask_upperleft, MaskAccessor ma, | | MaskImageIterator mask_upperleft, MaskAccessor ma, | |
| functor::UnaryAnalyser<Functor> const & f) | | functor::UnaryAnalyser<Functor> const & f) | |
| { | | { | |
| inspectImageIf(upperleft, lowerright, a, | | inspectImageIf(upperleft, lowerright, a, | |
| mask_upperleft, ma, const_cast<functor::UnaryAnalyser<Fu
nctor> &>(f)); | | mask_upperleft, ma, const_cast<functor::UnaryAnalyser<Fu
nctor> &>(f)); | |
| } | | } | |
| | | | |
| template <class ImageIterator, class Accessor, | | template <class ImageIterator, class Accessor, | |
|
| class MaskImageIterator, class MaskAccessor, class Functor> | | class MaskImageIterator, class MaskAccessor, class Functor> | |
| | | inline void | |
| | | inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, | |
| | | pair<MaskImageIterator, MaskAccessor> mask, | |
| | | Functor & f) | |
| | | { | |
| | | inspectImageIf(img.first, img.second, img.third, | |
| | | mask.first, mask.second, f); | |
| | | } | |
| | | | |
| | | template <class ImageIterator, class Accessor, | |
| | | class MaskImageIterator, class MaskAccessor, class Functor> | |
| inline void | | inline void | |
| inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, | | inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, | |
| pair<MaskImageIterator, MaskAccessor> mask, | | pair<MaskImageIterator, MaskAccessor> mask, | |
| functor::UnaryAnalyser<Functor> const & f) | | functor::UnaryAnalyser<Functor> const & f) | |
| { | | { | |
| inspectImageIf(img.first, img.second, img.third, | | inspectImageIf(img.first, img.second, img.third, | |
| mask.first, mask.second, const_cast<functor::UnaryAnalys
er<Functor> &>(f)); | | mask.first, mask.second, const_cast<functor::UnaryAnalys
er<Functor> &>(f)); | |
| } | | } | |
| | | | |
|
| | | template <class T, class S, | |
| | | class TM, class SM, class Functor> | |
| | | inline void | |
| | | inspectImageIf(MultiArrayView<2, T, S> const & img, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | Functor & f) | |
| | | { | |
| | | vigra_precondition(img.shape() == mask.shape(), | |
| | | "inspectImageIf(): shape mismatch between input and output."); | |
| | | inspectImageIf(srcImageRange(img), | |
| | | maskImage(mask), f); | |
| | | } | |
| | | | |
| | | template <class T, class S, | |
| | | class TM, class SM, class Functor> | |
| | | inline void | |
| | | inspectImageIf(MultiArrayView<2, T, S> const & img, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | functor::UnaryAnalyser<Functor> const & f) | |
| | | { | |
| | | inspectImageIf(srcImageRange(img), | |
| | | maskImage(mask), const_cast<functor::UnaryAnalyser<Funct | |
| | | or> &>(f)); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* inspectTwoImages */ | | /* inspectTwoImages */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply read-only functor to every pixel of both images. | | /** \brief Apply read-only functor to every pixel of both images. | |
| | | | |
| This function can be used to collect statistics for each region of a | | This function can be used to collect statistics for each region of a | |
| labeled image, especially in conjunction with | | labeled image, especially in conjunction with | |
| the \ref ArrayOfRegionStatistics functor. The results must be | | the \ref ArrayOfRegionStatistics functor. The results must be | |
| stored in the functor which serves as a return value. | | stored in the functor which serves as a return value. | |
|
| Accessors are used to access the pixel data. | | | |
| | | Note: For many common statistics, the use of \ref vigra::acc::extractFe | |
| | | atures() in combination | |
| | | with \ref FeatureAccumulators is more convenient. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | void | |
| | | inspectTwoImages(MultiArrayView<2, T1, S1> const & img1, | |
| | | MultiArrayView<2, T2, S2> const & img2, | |
| | | Functor & f); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{inspectTwoImages} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
| class ImageIterator2, class Accessor2, | | class ImageIterator2, class Accessor2, | |
| class Functor> | | class Functor> | |
| void | | void | |
| inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerrig
ht1, Accessor1 a1, | | inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerrig
ht1, Accessor1 a1, | |
| ImageIterator2 upperleft2, Accessor2 a2, | | ImageIterator2 upperleft2, Accessor2 a2, | |
| Functor & f) | | Functor & f) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
| class ImageIterator2, class Accessor2, | | class ImageIterator2, class Accessor2, | |
| class Functor> | | class Functor> | |
| void | | void | |
| inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1>
img1, | | inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1>
img1, | |
| pair<ImageIterator2, Accessor2> img2, | | pair<ImageIterator2, Accessor2> img2, | |
| Functor & f) | | Functor & f) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> image1(width, height), image2(width, heigh | |
| | | t); | |
| | | | |
| | | SomeStatisticsFunctor stats(...); // init functor | |
| | | | |
| | | inspectTwoImages(image1, image2, stats); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{inspectTwoImages} | |
| | | \code | |
| vigra::BImage image1; | | vigra::BImage image1; | |
| vigra::BImage image2; | | vigra::BImage image2; | |
| | | | |
| SomeStatisticsFunctor stats(...); // init functor | | SomeStatisticsFunctor stats(...); // init functor | |
| | | | |
| vigra::inspectTwoImages(srcImageRange(image1), srcImage(image2), | | vigra::inspectTwoImages(srcImageRange(image1), srcImage(image2), | |
| stats); | | stats); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| ImageIterator1 upperleft1, lowerright1; | | ImageIterator1 upperleft1, lowerright1; | |
| ImageIterator2 upperleft2; | | ImageIterator2 upperleft2; | |
| ImageIterator1::row_iterator ix1 = upperleft1.rowIterator(); | | ImageIterator1::row_iterator ix1 = upperleft1.rowIterator(); | |
| ImageIterator2::row_iterator ix2 = upperleft2.rowIterator(); | | ImageIterator2::row_iterator ix2 = upperleft2.rowIterator(); | |
| | | | |
| Accessor1 accessor1; | | Accessor1 accessor1; | |
| Accessor2 accessor2; | | Accessor2 accessor2; | |
| | | | |
| Functor functor; | | Functor functor; | |
| functor(accessor1(ix1), accessor2(ix2)); // return not used | | functor(accessor1(ix1), accessor2(ix2)); // return not used | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
|
| | | \see InspectFunctor, FeatureAccumulators | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void inspectTwoImages) | | doxygen_overloaded_function(template <...> void inspectTwoImages) | |
| | | | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
| class ImageIterator2, class Accessor2> | | class ImageIterator2, class Accessor2> | |
| struct inspectTwoImages_binder | | struct inspectTwoImages_binder | |
| { | | { | |
| ImageIterator1 upperleft1; | | ImageIterator1 upperleft1; | |
| ImageIterator1 lowerright1; | | ImageIterator1 lowerright1; | |
| Accessor1 a1; | | Accessor1 a1; | |
| | | | |
| skipping to change at line 523 | | skipping to change at line 636 | |
| ImageIterator2 upperleft2, Accessor2 a2, | | ImageIterator2 upperleft2, Accessor2 a2, | |
| Functor & f) | | Functor & f) | |
| { | | { | |
| inspectTwoImages_binder<ImageIterator1, Accessor1, | | inspectTwoImages_binder<ImageIterator1, Accessor1, | |
| ImageIterator2, Accessor2> | | ImageIterator2, Accessor2> | |
| g(upperleft1, lowerright1, a1, upperleft2, a2); | | g(upperleft1, lowerright1, a1, upperleft2, a2); | |
| detail::extra_passes_select(g, f); | | detail::extra_passes_select(g, f); | |
| } | | } | |
| | | | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
|
| class ImageIterator2, class Accessor2, | | | |
| class Functor> | | | |
| inline | | | |
| void | | | |
| inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, | | | |
| pair<ImageIterator2, Accessor2> img2, | | | |
| Functor & f) | | | |
| { | | | |
| inspectTwoImages(img1.first, img1.second, img1.third, | | | |
| img2.first, img2.second, f); | | | |
| } | | | |
| | | | |
| template <class ImageIterator1, class Accessor1, | | | |
| class ImageIterator2, class Accessor2, | | class ImageIterator2, class Accessor2, | |
| class Functor> | | class Functor> | |
| inline void | | inline void | |
| inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Acc
essor1 a1, | | inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Acc
essor1 a1, | |
| ImageIterator2 upperleft2, Accessor2 a2, | | ImageIterator2 upperleft2, Accessor2 a2, | |
| functor::UnaryAnalyser<Functor> const & f) | | functor::UnaryAnalyser<Functor> const & f) | |
| { | | { | |
| inspectTwoImages(upperleft1, lowerright1, a1, | | inspectTwoImages(upperleft1, lowerright1, a1, | |
| upperleft2, a2, const_cast<functor::UnaryAnalyser<Func
tor> &>(f)); | | upperleft2, a2, const_cast<functor::UnaryAnalyser<Func
tor> &>(f)); | |
| } | | } | |
| | | | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
|
| class ImageIterator2, class Accessor2, | | class ImageIterator2, class Accessor2, | |
| class Functor> | | class Functor> | |
| inline | | inline void | |
| void | | | |
| inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, | | inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, | |
|
| pair<ImageIterator2, Accessor2> img2, | | pair<ImageIterator2, Accessor2> img2, | |
| functor::UnaryAnalyser<Functor> const & f) | | Functor & f) | |
| | | { | |
| | | inspectTwoImages(img1.first, img1.second, img1.third, | |
| | | img2.first, img2.second, f); | |
| | | } | |
| | | | |
| | | template <class ImageIterator1, class Accessor1, | |
| | | class ImageIterator2, class Accessor2, | |
| | | class Functor> | |
| | | inline void | |
| | | inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, | |
| | | pair<ImageIterator2, Accessor2> img2, | |
| | | functor::UnaryAnalyser<Functor> const & f) | |
| { | | { | |
| inspectTwoImages(img1.first, img1.second, img1.third, | | inspectTwoImages(img1.first, img1.second, img1.third, | |
| img2.first, img2.second, const_cast<functor::UnaryAnal
yser<Functor> &>(f)); | | img2.first, img2.second, const_cast<functor::UnaryAnal
yser<Functor> &>(f)); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | inspectTwoImages(MultiArrayView<2, T1, S1> const & img1, | |
| | | MultiArrayView<2, T2, S2> const & img2, | |
| | | Functor & f) | |
| | | { | |
| | | vigra_precondition(img1.shape() == img2.shape(), | |
| | | "inspectTwoImages(): shape mismatch between input and output."); | |
| | | inspectTwoImages(srcImageRange(img1), | |
| | | srcImage(img2), | |
| | | f); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | inspectTwoImages(MultiArrayView<2, T1, S1> const & img1, | |
| | | MultiArrayView<2, T2, S2> const & img2, | |
| | | functor::UnaryAnalyser<Functor> const & f) | |
| | | { | |
| | | vigra_precondition(img1.shape() == img2.shape(), | |
| | | "inspectTwoImages(): shape mismatch between input and output."); | |
| | | inspectTwoImages(srcImageRange(img1), | |
| | | srcImage(img2), const_cast<functor::UnaryAnalyser<Func | |
| | | tor> &>(f)); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* inspectTwoImagesIf */ | | /* inspectTwoImagesIf */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply read-only functor to those pixels of both images where | | /** \brief Apply read-only functor to those pixels of both images where | |
| the mask image is non-zero. | | the mask image is non-zero. | |
| | | | |
| This function can be used to collect statistics for selected regions of
a | | This function can be used to collect statistics for selected regions of
a | |
| labeled image, especially in conjunction with | | labeled image, especially in conjunction with | |
| the \ref ArrayOfRegionStatistics functor. The results must be | | the \ref ArrayOfRegionStatistics functor. The results must be | |
| stored in the functor which serves as a return value. | | stored in the functor which serves as a return value. | |
|
| Accessors are used to access the pixel data. | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class TM, class SM, | |
| | | class Functor> | |
| | | void | |
| | | inspectTwoImagesIf(MultiArrayView<2, T1, S1> const & img1, | |
| | | MultiArrayView<2, T2, S2> const & img2, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | Functor & f); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{inspectTwoImagesIf} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
| class ImageIterator2, class Accessor2, | | class ImageIterator2, class Accessor2, | |
| class MaskImageIterator, class MaskAccessor, | | class MaskImageIterator, class MaskAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerr
ight1, Accessor1 a1, | | inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerr
ight1, Accessor1 a1, | |
| ImageIterator2 upperleft2, Accessor2 a2, | | ImageIterator2 upperleft2, Accessor2 a2, | |
| MaskImageIterator mupperleft, MaskAccessor mask, | | MaskImageIterator mupperleft, MaskAccessor mask, | |
| Functor & f) | | Functor & f) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
| class ImageIterator2, class Accessor2, | | class ImageIterator2, class Accessor2, | |
| class MaskImageIterator, class MaskAccessor, | | class MaskImageIterator, class MaskAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1
> img1, | | inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1
> img1, | |
| pair<ImageIterator2, Accessor2> img2, | | pair<ImageIterator2, Accessor2> img2, | |
| pair<MaskImageIterator, MaskAccessor> mimg, | | pair<MaskImageIterator, MaskAccessor> mimg, | |
| Functor & f) | | Functor & f) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, unsigned char> image1(width, height), image2(width, heigh | |
| | | t), | |
| | | maskimage(width, height); | |
| | | | |
| | | SomeStatisticsFunctor stats(...); // init functor | |
| | | | |
| | | inspectTwoImagesIf(image1, image2, maskimage, region_stats); | |
| | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{inspectTwoImagesIf} | |
| \code | | \code | |
| vigra::BImage image1; | | vigra::BImage image1; | |
| vigra::BImage image2; | | vigra::BImage image2; | |
| vigra::BImage maskimage; | | vigra::BImage maskimage; | |
| | | | |
| SomeStatisticsFunctor stats(...); // init functor | | SomeStatisticsFunctor stats(...); // init functor | |
| | | | |
| vigra::inspectTwoImagesIf(srcImageRange(image1), srcImage(image2), | | vigra::inspectTwoImagesIf(srcImageRange(image1), srcImage(image2), | |
| srcImage(maskimage), region_stats); | | srcImage(maskimage), region_stats); | |
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| ImageIterator1 upperleft1, lowerright1; | | ImageIterator1 upperleft1, lowerright1; | |
| ImageIterator2 upperleft2; | | ImageIterator2 upperleft2; | |
| MaskImageIterator upperleftm; | | MaskImageIterator upperleftm; | |
| ImageIterator1::row_iterator ix1 = upperleft1.rowIterator(); | | ImageIterator1::row_iterator ix1 = upperleft1.rowIterator(); | |
| ImageIterator2::row_iterator ix2 = upperleft2.rowIterator(); | | ImageIterator2::row_iterator ix2 = upperleft2.rowIterator(); | |
| MaskImageIterator::row_iterator mx = mupperleft.rowIterator(); | | MaskImageIterator::row_iterator mx = mupperleft.rowIterator(); | |
| | | | |
| Accessor1 accessor1; | | Accessor1 accessor1; | |
| Accessor2 accessor2; | | Accessor2 accessor2; | |
| MaskAccessor mask; | | MaskAccessor mask; | |
| | | | |
| Functor functor; | | Functor functor; | |
| if(mask(mx)) | | if(mask(mx)) | |
| functor(accessor1(ix1), accessor2(ix2)); | | functor(accessor1(ix1), accessor2(ix2)); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
|
| | | \see InspectFunctor, FeatureAccumulators | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void inspectTwoImagesIf) | | doxygen_overloaded_function(template <...> void inspectTwoImagesIf) | |
| | | | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
| class ImageIterator2, class Accessor2, | | class ImageIterator2, class Accessor2, | |
| class MaskImageIterator, class MaskAccessor> | | class MaskImageIterator, class MaskAccessor> | |
| struct inspectTwoImagesIf_binder | | struct inspectTwoImagesIf_binder | |
| { | | { | |
| ImageIterator1 upperleft1; | | ImageIterator1 upperleft1; | |
| ImageIterator1 lowerright1; | | ImageIterator1 lowerright1; | |
| | | | |
| skipping to change at line 703 | | skipping to change at line 868 | |
| ImageIterator2, Accessor2, | | ImageIterator2, Accessor2, | |
| MaskImageIterator, MaskAccessor> | | MaskImageIterator, MaskAccessor> | |
| g(upperleft1, lowerright1, a1, upperleft2, a2, mupperleft, mask); | | g(upperleft1, lowerright1, a1, upperleft2, a2, mupperleft, mask); | |
| detail::extra_passes_select(g, f); | | detail::extra_passes_select(g, f); | |
| } | | } | |
| | | | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
| class ImageIterator2, class Accessor2, | | class ImageIterator2, class Accessor2, | |
| class MaskImageIterator, class MaskAccessor, | | class MaskImageIterator, class MaskAccessor, | |
| class Functor> | | class Functor> | |
|
| inline | | | |
| void | | | |
| inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, | | | |
| pair<ImageIterator2, Accessor2> img2, | | | |
| pair<MaskImageIterator, MaskAccessor> m, | | | |
| Functor & f) | | | |
| { | | | |
| inspectTwoImagesIf(img1.first, img1.second, img1.third, | | | |
| img2.first, img2.second, | | | |
| m.first, m.second, | | | |
| f); | | | |
| } | | | |
| | | | |
| template <class ImageIterator1, class Accessor1, | | | |
| class ImageIterator2, class Accessor2, | | | |
| class MaskImageIterator, class MaskAccessor, | | | |
| class Functor> | | | |
| inline void | | inline void | |
| inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, A
ccessor1 a1, | | inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, A
ccessor1 a1, | |
| ImageIterator2 upperleft2, Accessor2 a2, | | ImageIterator2 upperleft2, Accessor2 a2, | |
| MaskImageIterator mupperleft, MaskAccessor mask, | | MaskImageIterator mupperleft, MaskAccessor mask, | |
| functor::UnaryAnalyser<Functor> const & f) | | functor::UnaryAnalyser<Functor> const & f) | |
| { | | { | |
| inspectTwoImagesIf(upperleft1, lowerright1, a1, | | inspectTwoImagesIf(upperleft1, lowerright1, a1, | |
| upperleft2, a2, | | upperleft2, a2, | |
| mupperleft, mask, | | mupperleft, mask, | |
| const_cast<functor::UnaryAnalyser<Functor> &>(f)); | | const_cast<functor::UnaryAnalyser<Functor> &>(f)); | |
| } | | } | |
| | | | |
| template <class ImageIterator1, class Accessor1, | | template <class ImageIterator1, class Accessor1, | |
| class ImageIterator2, class Accessor2, | | class ImageIterator2, class Accessor2, | |
| class MaskImageIterator, class MaskAccessor, | | class MaskImageIterator, class MaskAccessor, | |
| class Functor> | | class Functor> | |
|
| inline | | inline void | |
| void | | inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, | |
| | | pair<ImageIterator2, Accessor2> img2, | |
| | | pair<MaskImageIterator, MaskAccessor> m, | |
| | | Functor & f) | |
| | | { | |
| | | inspectTwoImagesIf(img1.first, img1.second, img1.third, | |
| | | img2.first, img2.second, | |
| | | m.first, m.second, | |
| | | f); | |
| | | } | |
| | | | |
| | | template <class ImageIterator1, class Accessor1, | |
| | | class ImageIterator2, class Accessor2, | |
| | | class MaskImageIterator, class MaskAccessor, | |
| | | class Functor> | |
| | | inline void | |
| inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, | | inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, | |
|
| pair<ImageIterator2, Accessor2> img2, | | pair<ImageIterator2, Accessor2> img2, | |
| pair<MaskImageIterator, MaskAccessor> m, | | pair<MaskImageIterator, MaskAccessor> m, | |
| functor::UnaryAnalyser<Functor> const & f) | | functor::UnaryAnalyser<Functor> const & f) | |
| { | | { | |
| inspectTwoImagesIf(img1.first, img1.second, img1.third, | | inspectTwoImagesIf(img1.first, img1.second, img1.third, | |
| img2.first, img2.second, | | img2.first, img2.second, | |
| m.first, m.second, | | m.first, m.second, | |
| const_cast<functor::UnaryAnalyser<Functor> &>(f)); | | const_cast<functor::UnaryAnalyser<Functor> &>(f)); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class TM, class SM, | |
| | | class Functor> | |
| | | inline void | |
| | | inspectTwoImagesIf(MultiArrayView<2, T1, S1> const & img1, | |
| | | MultiArrayView<2, T2, S2> const & img2, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | Functor & f) | |
| | | { | |
| | | vigra_precondition(img1.shape() == img2.shape() && img1.shape() == mask | |
| | | .shape(), | |
| | | "inspectTwoImagesIf(): shape mismatch between input and output."); | |
| | | inspectTwoImagesIf(srcImageRange(img1), | |
| | | srcImage(img2), | |
| | | maskImage(mask), | |
| | | f); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class TM, class SM, | |
| | | class Functor> | |
| | | inline void | |
| | | inspectTwoImagesIf(MultiArrayView<2, T1, S1> const & img1, | |
| | | MultiArrayView<2, T2, S2> const & img2, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | functor::UnaryAnalyser<Functor> const & f) | |
| | | { | |
| | | vigra_precondition(img1.shape() == img2.shape() && img1.shape() == mask | |
| | | .shape(), | |
| | | "inspectTwoImagesIf(): shape mismatch between input and output."); | |
| | | inspectTwoImagesIf(srcImageRange(img1), | |
| | | srcImage(img2), | |
| | | maskImage(mask), | |
| | | const_cast<functor::UnaryAnalyser<Functor> &>(f)); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| /** \addtogroup InspectFunctor Functors To Inspect Images | | /** \addtogroup InspectFunctor Functors To Inspect Images | |
| Functors which report image statistics | | Functors which report image statistics | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* FindMinMax */ | | /* FindMinMax */ | |
| | | | |
| skipping to change at line 775 | | skipping to change at line 974 | |
| These functors can also be used in conjunction with | | These functors can also be used in conjunction with | |
| \ref ArrayOfRegionStatistics to find the extremes of all regions in | | \ref ArrayOfRegionStatistics to find the extremes of all regions in | |
| a labeled image. | | a labeled image. | |
| | | | |
| <b> Traits defined:</b> | | <b> Traits defined:</b> | |
| | | | |
| <tt>FunctorTraits::isUnaryAnalyser</tt> is true (<tt>VigraTrueType</tt>
) | | <tt>FunctorTraits::isUnaryAnalyser</tt> is true (<tt>VigraTrueType</tt>
) | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BImage img; | | vigra::BImage img; | |
| | | | |
| vigra::FindMinMax<vigra::BImage::PixelType> minmax; // init functor | | vigra::FindMinMax<vigra::BImage::PixelType> minmax; // init functor | |
| | | | |
| vigra::inspectImage(srcImageRange(img), minmax); | | vigra::inspectImage(srcImageRange(img), minmax); | |
| | | | |
| cout << "Min: " << minmax.min << " Max: " << minmax.max; | | cout << "Min: " << minmax.min << " Max: " << minmax.max; | |
| | | | |
| | | | |
| skipping to change at line 918 | | skipping to change at line 1117 | |
| \ref ArrayOfRegionStatistics to find the sum of all regions in | | \ref ArrayOfRegionStatistics to find the sum of all regions in | |
| a labeled image, and with the reduce mode of transformMultiArray(). | | a labeled image, and with the reduce mode of transformMultiArray(). | |
| | | | |
| <b> Traits defined:</b> | | <b> Traits defined:</b> | |
| | | | |
| <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | | <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | |
| are true (<tt>VigraTrueType</tt>) | | are true (<tt>VigraTrueType</tt>) | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BImage img; | | vigra::BImage img; | |
| | | | |
| vigra::FindSum<vigra::BImage::PixelType> sum; // init functor | | vigra::FindSum<vigra::BImage::PixelType> sum; // init functor | |
| | | | |
| vigra::inspectImage(srcImageRange(img), sum); | | vigra::inspectImage(srcImageRange(img), sum); | |
| | | | |
| cout << "Sum: " << sum(); | | cout << "Sum: " << sum(); | |
| | | | |
| | | | |
| skipping to change at line 1019 | | skipping to change at line 1218 | |
| \ref ArrayOfRegionStatistics to find the average of all regions in | | \ref ArrayOfRegionStatistics to find the average of all regions in | |
| a labeled image. | | a labeled image. | |
| | | | |
| <b> Traits defined:</b> | | <b> Traits defined:</b> | |
| | | | |
| <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | | <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | |
| are true (<tt>VigraTrueType</tt>) | | are true (<tt>VigraTrueType</tt>) | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BImage img; | | vigra::BImage img; | |
| | | | |
| vigra::FindAverage<vigra::BImage::PixelType> average; // init functor | | vigra::FindAverage<vigra::BImage::PixelType> average; // init functor | |
| | | | |
| vigra::inspectImage(srcImageRange(img), average); | | vigra::inspectImage(srcImageRange(img), average); | |
| | | | |
| cout << "Average: " << average(); | | cout << "Average: " << average(); | |
| | | | |
| | | | |
| skipping to change at line 1167 | | skipping to change at line 1366 | |
| conjunction with \ref ArrayOfRegionStatistics to find the statistics of
all | | conjunction with \ref ArrayOfRegionStatistics to find the statistics of
all | |
| regions in a labeled image. | | regions in a labeled image. | |
| | | | |
| <b> Traits defined:</b> | | <b> Traits defined:</b> | |
| | | | |
| <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | | <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | |
| are true (<tt>VigraTrueType</tt>) | | are true (<tt>VigraTrueType</tt>) | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BImage img; | | vigra::BImage img; | |
| | | | |
| vigra::FindAverageAndVariance<vigra::BImage::PixelType> averageAndVaria
nce; // init functor | | vigra::FindAverageAndVariance<vigra::BImage::PixelType> averageAndVaria
nce; // init functor | |
| | | | |
| vigra::inspectImage(srcImageRange(img), averageAndVariance); | | vigra::inspectImage(srcImageRange(img), averageAndVariance); | |
| | | | |
| cout << "Average: " << averageAndVariance.average() << "\n"; | | cout << "Average: " << averageAndVariance.average() << "\n"; | |
| cout << "Standard deviation: " << sqrt(averageAndVariance.variance()) <
< "\n"; | | cout << "Standard deviation: " << sqrt(averageAndVariance.variance()) <
< "\n"; | |
| | | | |
| skipping to change at line 1345 | | skipping to change at line 1544 | |
| a labeled image. | | a labeled image. | |
| | | | |
| <b> Traits defined:</b> | | <b> Traits defined:</b> | |
| | | | |
| <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | | <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | |
| are true (<tt>VigraTrueType</tt>) | | are true (<tt>VigraTrueType</tt>) | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
|
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BImage img, mask; | | vigra::BImage img, mask; | |
| | | | |
| vigra::FindROISize<vigra::BImage::PixelType> roisize; // init functor | | vigra::FindROISize<vigra::BImage::PixelType> roisize; // init functor | |
| | | | |
| vigra::inspectImageIf(srcImageRange(img), srcImage(mask), roisize); | | vigra::inspectImageIf(srcImageRange(img), srcImage(mask), roisize); | |
| | | | |
| cout << "Size of ROI: " << roisize.count; | | cout << "Size of ROI: " << roisize.count; | |
| | | | |
| | | | |
| skipping to change at line 1454 | | skipping to change at line 1653 | |
| of all regions in a labeled image. | | of all regions in a labeled image. | |
| | | | |
| <b> Traits defined:</b> | | <b> Traits defined:</b> | |
| | | | |
| <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | | <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | |
| are true (<tt>VigraTrueType</tt>) | | are true (<tt>VigraTrueType</tt>) | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
|
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BImage img, mask; | | vigra::BImage img, mask; | |
| ... | | ... | |
| | | | |
| vigra::FindBoundingRectangle roiRect; // init functor | | vigra::FindBoundingRectangle roiRect; // init functor | |
| | | | |
| // Diff2D is used as the iterator for the source image. This | | // Diff2D is used as the iterator for the source image. This | |
| // simulates an image where each pixel value equals the pixel's | | // simulates an image where each pixel value equals the pixel's | |
| // coordinates. The image 'mask' determines the ROI. | | // coordinates. The image 'mask' determines the ROI. | |
| | | | |
| skipping to change at line 1600 | | skipping to change at line 1799 | |
| \ref ArrayOfRegionStatistics to realize a look-up table. | | \ref ArrayOfRegionStatistics to realize a look-up table. | |
| | | | |
| <b> Traits defined:</b> | | <b> Traits defined:</b> | |
| | | | |
| <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | | <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitia
lizer</tt> | |
| are true (<tt>VigraTrueType</tt>) | | are true (<tt>VigraTrueType</tt>) | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
|
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BImage img; | | vigra::BImage img; | |
| | | | |
| vigra::ArrayOfRegionStatistics<LastValueFunctor<unsigned char> > lut(25
5); | | vigra::ArrayOfRegionStatistics<LastValueFunctor<unsigned char> > lut(25
5); | |
| | | | |
| for(int i=0; i<256; ++i) | | for(int i=0; i<256; ++i) | |
| { | | { | |
| lut[i] = ...; // init look-up table | | lut[i] = ...; // init look-up table | |
| } | | } | |
| | | | |
| skipping to change at line 1696 | | skipping to change at line 1895 | |
| | | | |
| <b> Traits defined:</b> | | <b> Traits defined:</b> | |
| | | | |
| <tt>FunctorTraits::isUnaryAnalyser</tt>, <tt>FunctorTraits::isBinaryAna
lyser</tt> | | <tt>FunctorTraits::isUnaryAnalyser</tt>, <tt>FunctorTraits::isBinaryAna
lyser</tt> | |
| and <tt>FunctorTraits::isInitializer</tt> | | and <tt>FunctorTraits::isInitializer</tt> | |
| are true (<tt>VigraTrueType</tt>) | | are true (<tt>VigraTrueType</tt>) | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
|
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BImage img; | | vigra::BImage img; | |
| ... // fill the image | | ... // fill the image | |
| | | | |
| // create a functor to sum the elements of the image | | // create a functor to sum the elements of the image | |
| vigra::ReduceFunctor<std::plus<int>, int> sumElements(std::plus<int>, 0
); | | vigra::ReduceFunctor<std::plus<int>, int> sumElements(std::plus<int>, 0
); | |
| | | | |
| vigra::inspectImage(srcImageRange(img), sumElements); | | vigra::inspectImage(srcImageRange(img), sumElements); | |
| | | | |
| | | | |
| skipping to change at line 1830 | | skipping to change at line 2029 | |
| pixel's label. | | pixel's label. | |
| | | | |
| <b> Traits defined:</b> | | <b> Traits defined:</b> | |
| | | | |
| <tt>FunctorTraits::isBinaryAnalyser</tt> and <tt>FunctorTraits::isUnary
Functor</tt> | | <tt>FunctorTraits::isBinaryAnalyser</tt> and <tt>FunctorTraits::isUnary
Functor</tt> | |
| are true (<tt>VigraTrueType</tt>) | | are true (<tt>VigraTrueType</tt>) | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/inspectimage.hxx\><br> | | <b>\#include</b> \<vigra/inspectimage.hxx\><br> | |
|
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BImage img; | | vigra::BImage img; | |
| vigra::IImage labels; | | vigra::IImage labels; | |
| int max_label; | | int max_label; | |
| ... | | ... | |
| | | | |
| // init functor as an array of 'max_label' FindMinMax-Functors | | // init functor as an array of 'max_label' FindMinMax-Functors | |
| vigra::ArrayOfRegionStatistics<vigra::FindMinMax<vigra::BImage::PixelTy
pe> > | | vigra::ArrayOfRegionStatistics<vigra::FindMinMax<vigra::BImage::PixelTy
pe> > | |
| minmax(max_label); | | minmax(max_label); | |
| | | | |
End of changes. 75 change blocks. |
| 112 lines changed or deleted | | 321 lines changed or added | |
|
| labelimage.hxx | | labelimage.hxx | |
| | | | |
| skipping to change at line 45 | | skipping to change at line 45 | |
| | | | |
| #ifndef VIGRA_LABELIMAGE_HXX | | #ifndef VIGRA_LABELIMAGE_HXX | |
| #define VIGRA_LABELIMAGE_HXX | | #define VIGRA_LABELIMAGE_HXX | |
| | | | |
| #include <vector> | | #include <vector> | |
| #include <functional> | | #include <functional> | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "stdimage.hxx" | | #include "stdimage.hxx" | |
| #include "union_find.hxx" | | #include "union_find.hxx" | |
| #include "sized_int.hxx" | | #include "sized_int.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup Labeling Connected Components Labeling | | /** \addtogroup Labeling Connected Components Labeling | |
| The 2-dimensional connected components algorithms may use either 4 or
8 connectivity. | | The 2-dimensional connected components algorithms may use either 4 or
8 connectivity. | |
| By means of a functor the merge criterion can be defined arbitrarily. | | By means of a functor the merge criterion can be defined arbitrarily. | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* labelImage */ | | /* labelImage */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find the connected components of a segmented image. | | /** \brief Find the connected components of a segmented image. | |
| | | | |
|
| | | Connected components are defined as regions with uniform pixel | |
| | | values. Thus, <TT>T1</TT> either must be | |
| | | equality comparable, or a suitable EqualityFunctor must be | |
| | | provided that realizes the desired predicate. The | |
| | | destination's value type <tt>T2</tt> should be large enough to hold the | |
| | | labels | |
| | | without overflow. Region numbers will be a consecutive sequence | |
| | | starting with one and ending with the region number returned by | |
| | | the function (inclusive). The parameter '<TT>eight_neighbors</TT>' | |
| | | determines whether the regions should be 4-connected (false) or | |
| | | 8-connected (true). | |
| | | | |
| | | Return: the number of regions found (= largest region label) | |
| | | | |
| | | See \ref labelMultiArray() for a dimension-independent implementation o | |
| | | f | |
| | | connected components labelling. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class EqualityFunctor = std::equal_to<T1> > | |
| | | unsigned int | |
| | | labelImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | bool eight_neighbors, EqualityFunctor equal = EqualityFu | |
| | | nctor()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{labelImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| unsigned int labelImage(SrcIterator upperlefts, | | unsigned int labelImage(SrcIterator upperlefts, | |
| SrcIterator lowerrights, SrcAccessor sa, | | SrcIterator lowerrights, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| bool eight_neighbors); | | bool eight_neighbors); | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class EqualityFunctor> | | class EqualityFunctor> | |
| unsigned int labelImage(SrcIterator upperlefts, | | unsigned int labelImage(SrcIterator upperlefts, | |
| SrcIterator lowerrights, SrcAccessor sa, | | SrcIterator lowerrights, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| bool eight_neighbors, EqualityFunctor equal
); | | bool eight_neighbors, EqualityFunctor equal
); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| unsigned int labelImage(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | | unsigned int labelImage(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| bool eight_neighbors); | | bool eight_neighbors); | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class EqualityFunctor> | | class EqualityFunctor> | |
| unsigned int labelImage(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | | unsigned int labelImage(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| bool eight_neighbors, EqualityFunctor equal
) | | bool eight_neighbors, EqualityFunctor equal
) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| Connected components are defined as regions with uniform pixel | | | |
| values. Thus, <TT>SrcAccessor::value_type</TT> either must be | | | |
| equality comparable (first form), or an EqualityFunctor must be | | | |
| provided that realizes the desired predicate (second form). The | | | |
| destination's value type should be large enough to hold the labels | | | |
| without overflow. Region numbers will be a consecutive sequence | | | |
| starting with one and ending with the region number returned by | | | |
| the function (inclusive). The parameter '<TT>eight_neighbors</TT>' | | | |
| determines whether the regions should be 4-connected or | | | |
| 8-connected. The function uses accessors. | | | |
| | | | |
| Return: the number of regions found (= largest region label) | | | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/labelimage.hxx\><br> | | <b>\#include</b> \<vigra/labelimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h); | |
| | | MultiArray<2, unsigned int> labels(w,h); | |
| | | | |
| | | // threshold at 128 | |
| | | transformImage(src, src, Threshold<int, int>(128, 256, 0, 255)); | |
| | | | |
| | | // find 4-connected regions | |
| | | labelImage(src, labels, false); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{labelImage} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| vigra::IImage labels(w,h); | | vigra::IImage labels(w,h); | |
| | | | |
| // threshold at 128 | | // threshold at 128 | |
| vigra::transformImage(srcImageRange(src), destImage(src), | | vigra::transformImage(srcImageRange(src), destImage(src), | |
| vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType>
( | | vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType>
( | |
| 128, 256, 0, 255)); | | 128, 256, 0, 255)); | |
| | | | |
| // find 4-connected regions | | // find 4-connected regions | |
| vigra::labelImage(srcImageRange(src), destImage(labels), false); | | vigra::labelImage(srcImageRange(src), destImage(labels), false); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| u == u // first form | | u == u // first form | |
| | | | |
| EqualityFunctor equal; // second form | | EqualityFunctor equal; // second form | |
| equal(u, u) // second form | | equal(u, u) // second form | |
| | | | |
| int i; | | int i; | |
| dest_accessor.set(i, dest_upperleft); | | dest_accessor.set(i, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> unsigned int labelImage) | | doxygen_overloaded_function(template <...> unsigned int labelImage) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class EqualityFunctor> | | class EqualityFunctor> | |
| unsigned int labelImage(SrcIterator upperlefts, | | unsigned int labelImage(SrcIterator upperlefts, | |
| SrcIterator lowerrights, SrcAccessor sa, | | SrcIterator lowerrights, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| bool eight_neighbors, EqualityFunctor equal) | | bool eight_neighbors, EqualityFunctor equal) | |
| { | | { | |
| typedef typename DestAccessor::value_type LabelType; | | typedef typename DestAccessor::value_type LabelType; | |
| | | | |
| int w = lowerrights.x - upperlefts.x; | | int w = lowerrights.x - upperlefts.x; | |
| int h = lowerrights.y - upperlefts.y; | | int h = lowerrights.y - upperlefts.y; | |
| int x,y,i; | | int x,y,i; | |
| | | | |
|
| static const Diff2D neighbor[] = { | | const Diff2D neighbor[] = { | |
| Diff2D(-1,0), // left | | Diff2D(-1,0), // left | |
| Diff2D(-1,-1), // topleft | | Diff2D(-1,-1), // topleft | |
| Diff2D(0,-1), // top | | Diff2D(0,-1), // top | |
| Diff2D(1,-1) // topright | | Diff2D(1,-1) // topright | |
| }; | | }; | |
| | | | |
|
| static const int left = 0, /* unused: topleft = 1, */ top = 2, toprigh
t = 3; | | const int left = 0, /* unused: topleft = 1, */ top = 2, topright = 3; | |
| int step = eight_neighbors ? 1 : 2; | | int step = eight_neighbors ? 1 : 2; | |
| | | | |
| SrcIterator ys = upperlefts; | | SrcIterator ys = upperlefts; | |
| DestIterator yd = upperleftd; | | DestIterator yd = upperleftd; | |
| | | | |
|
| detail::UnionFindArray<LabelType> label; | | UnionFindArray<LabelType> label; | |
| | | | |
| // pass 1: scan image from upper left to lower right | | // pass 1: scan image from upper left to lower right | |
| // to find connected components | | // to find connected components | |
| | | | |
| // Each component will be represented by a tree of pixels. Each | | // Each component will be represented by a tree of pixels. Each | |
| // pixel contains the scan order address of its parent in the | | // pixel contains the scan order address of its parent in the | |
| // tree. In order for pass 2 to work correctly, the parent must | | // tree. In order for pass 2 to work correctly, the parent must | |
| // always have a smaller scan order address than the child. | | // always have a smaller scan order address than the child. | |
| // Therefore, we can merge trees only at their roots, because the | | // Therefore, we can merge trees only at their roots, because the | |
| // root of the combined tree must have the smallest scan order | | // root of the combined tree must have the smallest scan order | |
| | | | |
| skipping to change at line 215 | | skipping to change at line 243 | |
| | | | |
| for(x = 0; x != w; ++x, ++xs.x, ++xd.x) | | for(x = 0; x != w; ++x, ++xs.x, ++xd.x) | |
| { | | { | |
| int beginNeighbor = (x == 0) ? top : left; | | int beginNeighbor = (x == 0) ? top : left; | |
| if(x == w-1 && endNeighbor == topright) endNeighbor = top; | | if(x == w-1 && endNeighbor == topright) endNeighbor = top; | |
| | | | |
| for(i=beginNeighbor; i<=endNeighbor; i+=step) | | for(i=beginNeighbor; i<=endNeighbor; i+=step) | |
| { | | { | |
| if(equal(sa(xs), sa(xs, neighbor[i]))) | | if(equal(sa(xs), sa(xs, neighbor[i]))) | |
| { | | { | |
|
| LabelType neighborLabel = label.find(da(xd,neighbor[i])
); | | LabelType neighborIndex = label.findIndex(da(xd,neighbo
r[i])); | |
| | | | |
| for(int j=i+2; j<=endNeighbor; j+=step) | | for(int j=i+2; j<=endNeighbor; j+=step) | |
| { | | { | |
| if(equal(sa(xs), sa(xs, neighbor[j]))) | | if(equal(sa(xs), sa(xs, neighbor[j]))) | |
| { | | { | |
|
| neighborLabel = label.makeUnion(da(xd, neighbor
[j]), neighborLabel); | | neighborIndex = label.makeUnion(da(xd, neighbor
[j]), neighborIndex); | |
| break; | | break; | |
| } | | } | |
| } | | } | |
|
| da.set(neighborLabel, xd); | | da.set(neighborIndex, xd); | |
| break; | | break; | |
| } | | } | |
| | | | |
| } | | } | |
| if(i > endNeighbor) | | if(i > endNeighbor) | |
| { | | { | |
|
| da.set(label.makeNewLabel(), xd); | | da.set(label.makeNewIndex(), xd); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| // pass 2: assign one label to each region (tree) | | // pass 2: assign one label to each region (tree) | |
| // so that labels form a consecutive sequence 1, 2, ... | | // so that labels form a consecutive sequence 1, 2, ... | |
| unsigned int count = label.makeContiguous(); | | unsigned int count = label.makeContiguous(); | |
| | | | |
| yd = upperleftd; | | yd = upperleftd; | |
| for(y=0; y != h; ++y, ++yd.y) | | for(y=0; y != h; ++y, ++yd.y) | |
| { | | { | |
| typename DestIterator::row_iterator xd = yd.rowIterator(); | | typename DestIterator::row_iterator xd = yd.rowIterator(); | |
| for(x = 0; x != w; ++x, ++xd) | | for(x = 0; x != w; ++x, ++xd) | |
| { | | { | |
|
| da.set(label[da(xd)], xd); | | da.set(label.findLabel(da(xd)), xd); | |
| } | | } | |
| } | | } | |
| return count; | | return count; | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
|
| class DestIterator, class DestAccessor, | | | |
| class EqualityFunctor> | | | |
| inline | | | |
| unsigned int labelImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | | |
| pair<DestIterator, DestAccessor> dest, | | | |
| bool eight_neighbors, EqualityFunctor equal) | | | |
| { | | | |
| return labelImage(src.first, src.second, src.third, | | | |
| dest.first, dest.second, eight_neighbors, equal); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline | | inline | |
| unsigned int labelImage(SrcIterator upperlefts, | | unsigned int labelImage(SrcIterator upperlefts, | |
| SrcIterator lowerrights, SrcAccessor sa, | | SrcIterator lowerrights, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| bool eight_neighbors) | | bool eight_neighbors) | |
| { | | { | |
| return labelImage(upperlefts, lowerrights, sa, | | return labelImage(upperlefts, lowerrights, sa, | |
| upperleftd, da, eight_neighbors, | | upperleftd, da, eight_neighbors, | |
| std::equal_to<typename SrcAccessor::value_type>()); | | std::equal_to<typename SrcAccessor::value_type>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
|
| | | class DestIterator, class DestAccessor, | |
| | | class EqualityFunctor> | |
| | | inline unsigned int | |
| | | labelImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| | | pair<DestIterator, DestAccessor> dest, | |
| | | bool eight_neighbors, EqualityFunctor equal) | |
| | | { | |
| | | return labelImage(src.first, src.second, src.third, | |
| | | dest.first, dest.second, eight_neighbors, equal); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline unsigned int | |
| unsigned int labelImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | labelImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| bool eight_neighbors) | | bool eight_neighbors) | |
| { | | { | |
| return labelImage(src.first, src.second, src.third, | | return labelImage(src.first, src.second, src.third, | |
|
| dest.first, dest.second, eight_neighbors, | | dest.first, dest.second, eight_neighbors, | |
| std::equal_to<typename SrcAccessor::value_type>()); | | std::equal_to<typename SrcAccessor::value_type>()); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class EqualityFunctor> | |
| | | inline unsigned int | |
| | | labelImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | bool eight_neighbors, EqualityFunctor equal) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "labelImage(): shape mismatch between input and output."); | |
| | | return labelImage(srcImageRange(src), | |
| | | destImage(dest), eight_neighbors, equal); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline unsigned int | |
| | | labelImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | bool eight_neighbors) | |
| | | { | |
| | | return labelImage(srcImageRange(src), | |
| | | destImage(dest), eight_neighbors, | |
| | | std::equal_to<T1>()); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* labelImageWithBackground */ | | /* labelImageWithBackground */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find the connected components of a segmented image, | | /** \brief Find the connected components of a segmented image, | |
| excluding the background from labeling. | | excluding the background from labeling. | |
| | | | |
|
| | | This function works like \ref labelImage(), but considers all backgroun | |
| | | d pixels | |
| | | (i.e. pixels having the given '<TT>background_value</TT>') as a single | |
| | | region that | |
| | | is ignored when determining connected components and remains untouched | |
| | | in the | |
| | | destination image. Usually, you will zero-initialize the output image, | |
| | | so that | |
| | | the background gets label 0 (remember that actual region labels start a | |
| | | t one). | |
| | | | |
| | | Return: the number of non-background regions found (= largest region l | |
| | | abel) | |
| | | | |
| | | See \ref labelMultiArrayWithBackground() for a dimension-independent im | |
| | | plementation | |
| | | if this algorithm. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class ValueType, | |
| | | class EqualityFunctor = std::equal_to<T1> > | |
| | | unsigned int | |
| | | labelImageWithBackground(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | bool eight_neighbors, | |
| | | ValueType background_value, | |
| | | EqualityFunctor equal = EqualityFunctor()) | |
| | | ; | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{labelImageWithBackground} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class ValueType> | | class ValueType> | |
| int labelImageWithBackground(SrcIterator upperlefts, | | int labelImageWithBackground(SrcIterator upperlefts, | |
| SrcIterator lowerrights, SrcAccessor sa, | | SrcIterator lowerrights, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| bool eight_neighbors, | | bool eight_neighbors, | |
| ValueType background_value ); | | ValueType background_value ); | |
| | | | |
| skipping to change at line 323 | | skipping to change at line 405 | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class ValueType, class EqualityFunctor> | | class ValueType, class EqualityFunctor> | |
| int labelImageWithBackground(SrcIterator upperlefts, | | int labelImageWithBackground(SrcIterator upperlefts, | |
| SrcIterator lowerrights, SrcAccessor sa, | | SrcIterator lowerrights, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| bool eight_neighbors, | | bool eight_neighbors, | |
| ValueType background_value, EqualityFunctor equal); | | ValueType background_value, EqualityFunctor equal); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class ValueType> | | class ValueType> | |
| int labelImageWithBackground(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | | int labelImageWithBackground(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| bool eight_neighbors, | | bool eight_neighbors, | |
| ValueType background_value); | | ValueType background_value); | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class ValueType, class EqualityFunctor> | | class ValueType, class EqualityFunctor> | |
| int labelImageWithBackground(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | | int labelImageWithBackground(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| bool eight_neighbors, | | bool eight_neighbors, | |
| ValueType background_value, EqualityFu
nctor equal); | | ValueType background_value, EqualityFu
nctor equal); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| Connected components are defined as regions with uniform pixel | | | |
| values. Thus, <TT>SrcAccessor::value_type</TT> either must be | | | |
| equality comparable (first form), or an EqualityFunctor must be | | | |
| provided that realizes the desired predicate (second form). All | | | |
| pixel equal to the given '<TT>background_value</TT>' are ignored | | | |
| when determining connected components and remain untouched in the | | | |
| destination image and | | | |
| | | | |
| The destination's value type should be large enough to hold the | | | |
| labels without overflow. Region numbers will be a consecutive | | | |
| sequence starting with one and ending with the region number | | | |
| returned by the function (inclusive). The parameter | | | |
| '<TT>eight_neighbors</TT>' determines whether the regions should | | | |
| be 4-connected or 8-connected. The function uses accessors. | | | |
| | | | |
| Return: the number of regions found (= largest region label) | | | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/labelimage.hxx\><br> | | <b>\#include</b> \<vigra/labelimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h); | |
| | | MultiArray<2, unsigned int> labels(w,h); | |
| | | | |
| | | // threshold at 128 | |
| | | transformImage(src, src, Threshold<int, int>(128, 256, 0, 255)); | |
| | | | |
| | | // find 4-connected regions of foreground (= white pixels) only | |
| | | labelImageWithBackground(src, labels, false, 0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{labelImageWithBackground} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| vigra::IImage labels(w,h); | | vigra::IImage labels(w,h); | |
| | | | |
| // threshold at 128 | | // threshold at 128 | |
| vigra::transformImage(srcImageRange(src), destImage(src), | | vigra::transformImage(srcImageRange(src), destImage(src), | |
| vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType
>( | | vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType
>( | |
| 128, 256, 0, 255)); | | 128, 256, 0, 255)); | |
| | | | |
| // find 4-connected regions of foreground (= white pixels) only | | // find 4-connected regions of foreground (= white pixels) only | |
| vigra::labelImageWithBackground(srcImageRange(src), destImage(labels), | | vigra::labelImageWithBackground(srcImageRange(src), destImage(labels), | |
| false, 0); | | false, 0); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| ValueType background_value; | | ValueType background_value; | |
| | | | |
| u == u // first form | | u == u // first form | |
| u == background_value // first form | | u == background_value // first form | |
| | | | |
| EqualityFunctor equal; // second form | | EqualityFunctor equal; // second form | |
| equal(u, u) // second form | | equal(u, u) // second form | |
| equal(u, background_value) // second form | | equal(u, background_value) // second form | |
| | | | |
| int i; | | int i; | |
| dest_accessor.set(i, dest_upperleft); | | dest_accessor.set(i, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> unsigned int labelImageWithBackg
round) | | doxygen_overloaded_function(template <...> unsigned int labelImageWithBackg
round) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class ValueType, class EqualityFunctor> | | class ValueType, class EqualityFunctor> | |
| unsigned int labelImageWithBackground( | | unsigned int labelImageWithBackground( | |
| SrcIterator upperlefts, | | SrcIterator upperlefts, | |
| SrcIterator lowerrights, SrcAccessor sa, | | SrcIterator lowerrights, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| bool eight_neighbors, | | bool eight_neighbors, | |
| ValueType background_value, EqualityFunctor equal) | | ValueType background_value, EqualityFunctor equal) | |
| { | | { | |
| int w = lowerrights.x - upperlefts.x; | | int w = lowerrights.x - upperlefts.x; | |
| int h = lowerrights.y - upperlefts.y; | | int h = lowerrights.y - upperlefts.y; | |
| int x,y,i; | | int x,y,i; | |
| | | | |
|
| static const Diff2D neighbor[] = { | | const Diff2D neighbor[] = { | |
| Diff2D(-1,0), // left | | Diff2D(-1,0), // left | |
| Diff2D(-1,-1), // topleft | | Diff2D(-1,-1), // topleft | |
| Diff2D(0,-1), // top | | Diff2D(0,-1), // top | |
| Diff2D(1,-1) // topright | | Diff2D(1,-1) // topright | |
| }; | | }; | |
| | | | |
|
| static const int left = 0, /* unused: topleft = 1,*/ top = 2, topright
= 3; | | const int left = 0, /* unused: topleft = 1,*/ top = 2, topright = 3; | |
| int step = eight_neighbors ? 1 : 2; | | int step = eight_neighbors ? 1 : 2; | |
| | | | |
| SrcIterator ys(upperlefts); | | SrcIterator ys(upperlefts); | |
| SrcIterator xs(ys); | | SrcIterator xs(ys); | |
| | | | |
| // temporary image to store region labels | | // temporary image to store region labels | |
| typedef BasicImage<IntBiggest> TmpImage; | | typedef BasicImage<IntBiggest> TmpImage; | |
| TmpImage labelimage(w, h); | | TmpImage labelimage(w, h); | |
| TmpImage::ScanOrderIterator label = labelimage.begin(); | | TmpImage::ScanOrderIterator label = labelimage.begin(); | |
| TmpImage::Iterator yt = labelimage.upperLeft(); | | TmpImage::Iterator yt = labelimage.upperLeft(); | |
| | | | |
| skipping to change at line 466 | | skipping to change at line 541 | |
| } | | } | |
| else | | else | |
| { | | { | |
| int beginNeighbor = (x == 0) ? top : left; | | int beginNeighbor = (x == 0) ? top : left; | |
| if(x == w-1 && endNeighbor == topright) endNeighbor = top; | | if(x == w-1 && endNeighbor == topright) endNeighbor = top; | |
| | | | |
| for(i=beginNeighbor; i<=endNeighbor; i+=step) | | for(i=beginNeighbor; i<=endNeighbor; i+=step) | |
| { | | { | |
| if(equal(sa(xs), sa(xs, neighbor[i]))) | | if(equal(sa(xs), sa(xs, neighbor[i]))) | |
| { | | { | |
|
| IntBiggest neighborLabel = xt[neighbor[i]]; | | IntBiggest neighborIndex = xt[neighbor[i]]; | |
| | | | |
| for(int j=i+2; j<=endNeighbor; j+=step) | | for(int j=i+2; j<=endNeighbor; j+=step) | |
| { | | { | |
| if(equal(sa(xs), sa(xs, neighbor[j]))) | | if(equal(sa(xs), sa(xs, neighbor[j]))) | |
| { | | { | |
| IntBiggest neighborLabel1 = xt[neighbor[j]]
; | | IntBiggest neighborLabel1 = xt[neighbor[j]]
; | |
| | | | |
|
| if(neighborLabel != neighborLabel1) | | if(neighborIndex != neighborLabel1) | |
| { | | { | |
| // find roots of the region trees | | // find roots of the region trees | |
|
| while(neighborLabel != label[neighborLa
bel]) | | while(neighborIndex != label[neighborIn
dex]) | |
| { | | { | |
|
| neighborLabel = label[neighborLabel
]; | | neighborIndex = label[neighborIndex
]; | |
| } | | } | |
| while(neighborLabel1 != label[neighborL
abel1]) | | while(neighborLabel1 != label[neighborL
abel1]) | |
| { | | { | |
| neighborLabel1 = label[neighborLabe
l1]; | | neighborLabel1 = label[neighborLabe
l1]; | |
| } | | } | |
| | | | |
| // merge the trees | | // merge the trees | |
|
| if(neighborLabel1 < neighborLabel) | | if(neighborLabel1 < neighborIndex) | |
| { | | { | |
|
| label[neighborLabel] = neighborLabe | | label[neighborIndex] = neighborLabe | |
| l1; | | l1; | |
| neighborLabel = neighborLabel1; | | neighborIndex = neighborLabel1; | |
| } | | } | |
|
| else if(neighborLabel < neighborLabel1) | | else if(neighborIndex < neighborLabel1) | |
| { | | { | |
|
| label[neighborLabel1] = neighborLab
el; | | label[neighborLabel1] = neighborInd
ex; | |
| } | | } | |
| } | | } | |
| break; | | break; | |
| } | | } | |
| } | | } | |
|
| *xt = neighborLabel; | | *xt = neighborIndex; | |
| break; | | break; | |
| } | | } | |
| | | | |
| } | | } | |
| if(i > endNeighbor) | | if(i > endNeighbor) | |
| { | | { | |
| // new region | | // new region | |
| // The initial label of a new region equals the | | // The initial label of a new region equals the | |
| // scan order address of it's first pixel. | | // scan order address of it's first pixel. | |
| // This is essential for correct operation of the algor
ithm. | | // This is essential for correct operation of the algor
ithm. | |
| | | | |
| skipping to change at line 546 | | skipping to change at line 621 | |
| } | | } | |
| da.set(label[i]+1, xd); | | da.set(label[i]+1, xd); | |
| } | | } | |
| } | | } | |
| | | | |
| return count; | | return count; | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
|
| class ValueType, class EqualityFunctor> | | class ValueType> | |
| inline | | inline | |
| unsigned int labelImageWithBackground( | | unsigned int labelImageWithBackground( | |
|
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | SrcIterator upperlefts, | |
| pair<DestIterator, DestAccessor> dest, | | SrcIterator lowerrights, SrcAccessor sa, | |
| | | DestIterator upperleftd, DestAccessor da, | |
| bool eight_neighbors, | | bool eight_neighbors, | |
|
| ValueType background_value, EqualityFunctor equal) | | ValueType background_value) | |
| | | { | |
| | | return labelImageWithBackground(upperlefts, lowerrights, sa, | |
| | | upperleftd, da, | |
| | | eight_neighbors, background_value, | |
| | | std::equal_to<typename SrcAccessor::value_type> | |
| | | ()); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class ValueType, class EqualityFunctor> | |
| | | inline unsigned int | |
| | | labelImageWithBackground(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| | | pair<DestIterator, DestAccessor> dest, | |
| | | bool eight_neighbors, | |
| | | ValueType background_value, EqualityFunctor equal) | |
| { | | { | |
| return labelImageWithBackground(src.first, src.second, src.third, | | return labelImageWithBackground(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| eight_neighbors, background_value, equa
l); | | eight_neighbors, background_value, equa
l); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class ValueType> | | class ValueType> | |
|
| inline | | inline unsigned int | |
| unsigned int labelImageWithBackground( | | labelImageWithBackground(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | pair<DestIterator, DestAccessor> dest, | |
| pair<DestIterator, DestAccessor> dest, | | bool eight_neighbors, | |
| bool eight_neighbors, | | ValueType background_value) | |
| ValueType background_value) | | | |
| { | | { | |
| return labelImageWithBackground(src.first, src.second, src.third, | | return labelImageWithBackground(src.first, src.second, src.third, | |
|
| dest.first, dest.second, | | dest.first, dest.second, | |
| eight_neighbors, background_value, | | eight_neighbors, background_value, | |
| std::equal_to<typename SrcAccessor::value_type> | | std::equal_to<typename SrcAccessor::val | |
| ()); | | ue_type>()); | |
| } | | } | |
| | | | |
|
| template <class SrcIterator, class SrcAccessor, | | template <class T1, class S1, | |
| class DestIterator, class DestAccessor, | | class T2, class S2, | |
| | | class ValueType, class EqualityFunctor> | |
| | | inline unsigned int | |
| | | labelImageWithBackground(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | bool eight_neighbors, | |
| | | ValueType background_value, EqualityFunctor equal) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "labelImageWithBackground(): shape mismatch between input and outpu | |
| | | t."); | |
| | | return labelImageWithBackground(srcImageRange(src), | |
| | | destImage(dest), | |
| | | eight_neighbors, background_value, equa | |
| | | l); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| class ValueType> | | class ValueType> | |
|
| inline | | inline unsigned int | |
| unsigned int labelImageWithBackground( | | labelImageWithBackground(MultiArrayView<2, T1, S1> const & src, | |
| SrcIterator upperlefts, | | MultiArrayView<2, T2, S2> dest, | |
| SrcIterator lowerrights, SrcAccessor sa, | | bool eight_neighbors, | |
| DestIterator upperleftd, DestAccessor da, | | ValueType background_value) | |
| bool eight_neighbors, | | | |
| ValueType background_value) | | | |
| { | | { | |
|
| return labelImageWithBackground(upperlefts, lowerrights, sa, | | vigra_precondition(src.shape() == dest.shape(), | |
| upperleftd, da, | | "labelImageWithBackground(): shape mismatch between input and outpu | |
| eight_neighbors, background_value, | | t."); | |
| std::equal_to<typename SrcAccessor::value_type> | | return labelImageWithBackground(srcImageRange(src), | |
| ()); | | destImage(dest), | |
| | | eight_neighbors, background_value, | |
| | | std::equal_to<T1>()); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* regionImageToCrackEdgeImage */ | | /* regionImageToCrackEdgeImage */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
|
| /** \brief Transform a labeled image into a crack edge image. | | /** \brief Transform a labeled image into a crack edge (interpixel edge) im
age. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, class DestValue> | |
| | | void | |
| | | regionImageToCrackEdgeImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | DestValue edge_marker); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{regionImageToCrackEdgeImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| void regionImageToCrackEdgeImage( | | void regionImageToCrackEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| DestValue edge_marker) | | DestValue edge_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| void regionImageToCrackEdgeImage( | | void regionImageToCrackEdgeImage( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue edge_marker) | | DestValue edge_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
|
| This algorithm inserts border pixels (so called "crack edges") | | This algorithm inserts border pixels (so called "crack edges" or "inter
pixel edges") | |
| between regions in a labeled image like this (<TT>a</TT> and | | between regions in a labeled image like this (<TT>a</TT> and | |
| <TT>c</TT> are the original labels, and <TT>0</TT> is the value of | | <TT>c</TT> are the original labels, and <TT>0</TT> is the value of | |
| <TT>edge_marker</TT> and denotes the inserted edges): | | <TT>edge_marker</TT> and denotes the inserted edges): | |
| | | | |
| \code | | \code | |
| original image insert zero- and one-cells | | original image insert zero- and one-cells | |
| | | | |
| a 0 c c c | | a 0 c c c | |
| a c c a 0 0 0 c | | a c c a 0 0 0 c | |
| a a c => a a a 0 c | | a a c => a a a 0 c | |
| | | | |
| skipping to change at line 652 | | skipping to change at line 771 | |
| no background. Therefore, it is suitable as a post-processing | | no background. Therefore, it is suitable as a post-processing | |
| operation of \ref labelImage() or \ref seededRegionGrowing(). | | operation of \ref labelImage() or \ref seededRegionGrowing(). | |
| | | | |
| The destination image must be twice the size of the original | | The destination image must be twice the size of the original | |
| (precisely, <TT>(2*w-1)</TT> by <TT>(2*h-1)</TT> pixels). The | | (precisely, <TT>(2*w-1)</TT> by <TT>(2*h-1)</TT> pixels). The | |
| source value type (<TT>SrcAccessor::value-type</TT>) must be | | source value type (<TT>SrcAccessor::value-type</TT>) must be | |
| equality-comparable. | | equality-comparable. | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/labelimage.hxx\><br> | | <b>\#include</b> \<vigra/labelimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h); | |
| | | MultiArray<2, unsigned int> labels(w,h), | |
| | | cellgrid(2*w-1, 2*h-1); | |
| | | | |
| | | // threshold at 128 | |
| | | transformImage(src, src, Threshold<int, int>(128, 256, 0, 255)); | |
| | | | |
| | | // find 4-connected regions | |
| | | labelImage(src, labels, false); | |
| | | | |
| | | // create cell grid image, mark edges with 0 | |
| | | regionImageToCrackEdgeImage(labels, cellgrid, 0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{regionImageToCrackEdgeImage} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| vigra::IImage labels(w,h); | | vigra::IImage labels(w,h); | |
| vigra::IImage cellgrid(2*w-1, 2*h-1); | | vigra::IImage cellgrid(2*w-1, 2*h-1); | |
| | | | |
| // threshold at 128 | | // threshold at 128 | |
| vigra::transformImage(srcImageRange(src), destImage(src), | | vigra::transformImage(srcImageRange(src), destImage(src), | |
| vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType>
( | | vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType>
( | |
| 128, 256, 0, 255)); | | 128, 256, 0, 255)); | |
| | | | |
| // find 4-connected regions | | // find 4-connected regions | |
| vigra::labelImage(srcImageRange(src), destImage(labels), false); | | vigra::labelImage(srcImageRange(src), destImage(labels), false); | |
| | | | |
| // create cell grid image, mark edges with 0 | | // create cell grid image, mark edges with 0 | |
| vigra::regionImageToCrackEdgeImage(srcImageRange(labels), destImage(cel
lgrid), 0); | | vigra::regionImageToCrackEdgeImage(srcImageRange(labels), destImage(cel
lgrid), 0); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| ImageIterator src_upperleft, src_lowerright; | | ImageIterator src_upperleft, src_lowerright; | |
| ImageIterator dest_upperleft; | | ImageIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| u != u | | u != u | |
| | | | |
| DestValue edge_marker; | | DestValue edge_marker; | |
| dest_accessor.set(edge_marker, dest_upperleft); | | dest_accessor.set(edge_marker, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| The destination image must have twice the size of the source: | | The destination image must have twice the size of the source: | |
| \code | | \code | |
| w_dest = 2 * w_src - 1 | | w_dest = 2 * w_src - 1 | |
| h_dest = 2 * h_src - 1 | | h_dest = 2 * h_src - 1 | |
| \endcode | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void regionImageToCrackEdgeImage
) | | doxygen_overloaded_function(template <...> void regionImageToCrackEdgeImage
) | |
| | | | |
| skipping to change at line 710 | | skipping to change at line 844 | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| void regionImageToCrackEdgeImage( | | void regionImageToCrackEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| DestValue edge_marker) | | DestValue edge_marker) | |
| { | | { | |
| int w = slr.x - sul.x; | | int w = slr.x - sul.x; | |
| int h = slr.y - sul.y; | | int h = slr.y - sul.y; | |
| int x,y; | | int x,y; | |
| | | | |
|
| static const Diff2D right(1,0); | | const Diff2D right(1,0); | |
| static const Diff2D left(-1,0); | | const Diff2D left(-1,0); | |
| static const Diff2D bottomright(1,1); | | const Diff2D bottomright(1,1); | |
| static const Diff2D bottom(0,1); | | const Diff2D bottom(0,1); | |
| static const Diff2D top(0,-1); | | const Diff2D top(0,-1); | |
| | | | |
| SrcIterator iy = sul; | | SrcIterator iy = sul; | |
| DestIterator dy = dul; | | DestIterator dy = dul; | |
| | | | |
| for(y=0; y<h-1; ++y, ++iy.y, dy.y+=2) | | for(y=0; y<h-1; ++y, ++iy.y, dy.y+=2) | |
| { | | { | |
| SrcIterator ix = iy; | | SrcIterator ix = iy; | |
| DestIterator dx = dy; | | DestIterator dx = dy; | |
| | | | |
| for(x=0; x<w-1; ++x, ++ix.x, dx.x+=2) | | for(x=0; x<w-1; ++x, ++ix.x, dx.x+=2) | |
| | | | |
| skipping to change at line 778 | | skipping to change at line 912 | |
| } | | } | |
| else | | else | |
| { | | { | |
| da.set(sa(ix), dx, right); | | da.set(sa(ix), dx, right); | |
| } | | } | |
| } | | } | |
| da.set(sa(ix), dx); | | da.set(sa(ix), dx); | |
| | | | |
| dy = dul + Diff2D(1,1); | | dy = dul + Diff2D(1,1); | |
| | | | |
|
| | | const Diff2D dist[] = {right, top, left, bottom }; | |
| // find missing 0-cells | | // find missing 0-cells | |
| for(y=0; y<h-1; ++y, dy.y+=2) | | for(y=0; y<h-1; ++y, dy.y+=2) | |
| { | | { | |
| DestIterator dx = dy; | | DestIterator dx = dy; | |
| | | | |
| for(x=0; x<w-1; ++x, dx.x+=2) | | for(x=0; x<w-1; ++x, dx.x+=2) | |
| { | | { | |
|
| static const Diff2D dist[] = {right, top, left, bottom }; | | | |
| | | | |
| int i; | | int i; | |
| for(i=0; i<4; ++i) | | for(i=0; i<4; ++i) | |
| { | | { | |
| if(da(dx, dist[i]) == edge_marker) break; | | if(da(dx, dist[i]) == edge_marker) break; | |
| } | | } | |
| | | | |
| if(i < 4) da.set(edge_marker, dx); | | if(i < 4) da.set(edge_marker, dx); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
|
| inline | | inline void | |
| void regionImageToCrackEdgeImage( | | regionImageToCrackEdgeImage(triple<SrcIterator, SrcIterator, SrcAccessor> s | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | rc, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue edge_marker) | | DestValue edge_marker) | |
| { | | { | |
| regionImageToCrackEdgeImage(src.first, src.second, src.third, | | regionImageToCrackEdgeImage(src.first, src.second, src.third, | |
|
| dest.first, dest.second, | | dest.first, dest.second, | |
| edge_marker); | | edge_marker); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, class DestValue> | |
| | | inline void | |
| | | regionImageToCrackEdgeImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | DestValue edge_marker) | |
| | | { | |
| | | vigra_precondition(2*src.shape()-Shape2(1) == dest.shape(), | |
| | | "regionImageToCrackEdgeImage(): shape mismatch between input and ou | |
| | | tput."); | |
| | | regionImageToCrackEdgeImage(srcImageRange(src), | |
| | | destImage(dest), | |
| | | edge_marker); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* regionImageToEdgeImage */ | | /* regionImageToEdgeImage */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Transform a labeled image into an edge image. | | /** \brief Transform a labeled image into an edge image. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, class DestValue> | |
| | | void | |
| | | regionImageToEdgeImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | DestValue edge_marker); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{regionImageToEdgeImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| void regionImageToEdgeImage( | | void regionImageToEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| DestValue edge_marker) | | DestValue edge_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| void regionImageToEdgeImage( | | void regionImageToEdgeImage( | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue edge_marker) | | DestValue edge_marker) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| This algorithm marks all pixels with the given <TT>edge_marker</TT> | | This algorithm marks all pixels with the given <TT>edge_marker</TT> | |
| which belong to a different region (label) than their right or lower | | which belong to a different region (label) than their right or lower | |
| neighbors: | | neighbors: | |
| | | | |
| \code | | \code | |
| original image edges | | original image edges | |
| (assuming edge_marker == 1) | | (assuming edge_marker == 1) | |
| | | | |
| a c c 1 1 * | | a c c 1 1 * | |
| a a c => * 1 1 | | a a c => * 1 1 | |
| a a a * * * | | a a a * * * | |
| \endcode | | \endcode | |
| | | | |
| The non-edge pixels of the destination image will not be touched. | | The non-edge pixels of the destination image will not be touched. | |
|
| The source value type (<TT>SrcAccessor::value-type</TT>) must be | | The source value type <TT>T1</TT> must be | |
| equality-comparable. | | equality-comparable. | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/labelimage.hxx\><br> | | <b>\#include</b> \<vigra/labelimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w,h), | |
| | | edges(w,h); | |
| | | MultiArray<2, unsigned int> labels(w,h); | |
| | | | |
| | | edges = 255; // init background (non-edge) to 255 | |
| | | | |
| | | // threshold at 128 | |
| | | transformImage(src, src, Threshold<int, int>(128, 256, 0, 255)); | |
| | | | |
| | | // find 4-connected regions | |
| | | labelImage(src, labels, false); | |
| | | | |
| | | // create edge image, mark edges with 0 | |
| | | regionImageToEdgeImage(labels, edges, 0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{regionImageToEdgeImage} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| vigra::IImage labels(w,h); | | vigra::IImage labels(w,h); | |
| vigra::IImage edges(w, h); | | vigra::IImage edges(w, h); | |
| edges = 255; // init background (non-edge) to 255 | | edges = 255; // init background (non-edge) to 255 | |
| | | | |
| // threshold at 128 | | // threshold at 128 | |
| vigra::transformImage(srcImageRange(src), destImage(src), | | vigra::transformImage(srcImageRange(src), destImage(src), | |
| vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType>( | | vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType>( | |
| 128, 256, 0, 255)); | | 128, 256, 0, 255)); | |
| | | | |
| // find 4-connected regions | | // find 4-connected regions | |
| vigra::labelImage(srcImageRange(src), destImage(labels), false); | | vigra::labelImage(srcImageRange(src), destImage(labels), false); | |
| | | | |
| // create edge image, mark edges with 0 | | // create edge image, mark edges with 0 | |
| vigra::regionImageToEdgeImage(srcImageRange(labels), destImage(edges),
0); | | vigra::regionImageToEdgeImage(srcImageRange(labels), destImage(edges),
0); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| ImageIterator src_upperleft, src_lowerright; | | ImageIterator src_upperleft, src_lowerright; | |
| ImageIterator dest_upperleft; | | ImageIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| u != u | | u != u | |
| | | | |
| DestValue edge_marker; | | DestValue edge_marker; | |
| dest_accessor.set(edge_marker, dest_upperleft); | | dest_accessor.set(edge_marker, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void regionImageToEdgeImage) | | doxygen_overloaded_function(template <...> void regionImageToEdgeImage) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| void regionImageToEdgeImage( | | void regionImageToEdgeImage( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| DestValue edge_marker) | | DestValue edge_marker) | |
| { | | { | |
| int w = slr.x - sul.x; | | int w = slr.x - sul.x; | |
| int h = slr.y - sul.y; | | int h = slr.y - sul.y; | |
| int x,y; | | int x,y; | |
| | | | |
|
| static const Diff2D right(1,0); | | const Diff2D right(1,0); | |
| static const Diff2D left(-1,0); | | const Diff2D left(-1,0); | |
| static const Diff2D bottomright(1,1); | | const Diff2D bottomright(1,1); | |
| static const Diff2D bottom(0,1); | | const Diff2D bottom(0,1); | |
| static const Diff2D top(0,-1); | | const Diff2D top(0,-1); | |
| | | | |
| SrcIterator iy = sul; | | SrcIterator iy = sul; | |
| DestIterator dy = dul; | | DestIterator dy = dul; | |
| | | | |
| for(y=0; y<h-1; ++y, ++iy.y, ++dy.y) | | for(y=0; y<h-1; ++y, ++iy.y, ++dy.y) | |
| { | | { | |
| SrcIterator ix = iy; | | SrcIterator ix = iy; | |
| DestIterator dx = dy; | | DestIterator dx = dy; | |
| | | | |
| for(x=0; x<w-1; ++x, ++ix.x, ++dx.x) | | for(x=0; x<w-1; ++x, ++ix.x, ++dx.x) | |
| | | | |
| skipping to change at line 962 | | skipping to change at line 1137 | |
| { | | { | |
| if(sa(ix, right) != sa(ix)) | | if(sa(ix, right) != sa(ix)) | |
| { | | { | |
| da.set(edge_marker, dx); | | da.set(edge_marker, dx); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
|
| inline | | inline void | |
| void regionImageToEdgeImage( | | regionImageToEdgeImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | pair<DestIterator, DestAccessor> dest, | |
| pair<DestIterator, DestAccessor> dest, | | DestValue edge_marker) | |
| DestValue edge_marker) | | | |
| { | | { | |
| regionImageToEdgeImage(src.first, src.second, src.third, | | regionImageToEdgeImage(src.first, src.second, src.third, | |
|
| dest.first, dest.second, | | dest.first, dest.second, | |
| edge_marker); | | edge_marker); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, class DestValue> | |
| | | inline void | |
| | | regionImageToEdgeImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | DestValue edge_marker) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "regionImageToEdgeImage(): shape mismatch between input and output. | |
| | | "); | |
| | | regionImageToEdgeImage(srcImageRange(src), | |
| | | destImage(dest), | |
| | | edge_marker); | |
| } | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_LABELIMAGE_HXX | | #endif // VIGRA_LABELIMAGE_HXX | |
| | | | |
End of changes. 77 change blocks. |
| 149 lines changed or deleted | | 354 lines changed or added | |
|
| labelvolume.hxx | | labelvolume.hxx | |
| | | | |
| skipping to change at line 59 | | skipping to change at line 59 | |
| //@{ | | //@{ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* labelVolume */ | | /* labelVolume */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find the connected components of a segmented volume. | | /** \brief Find the connected components of a segmented volume. | |
| | | | |
|
| | | Connected components are defined as regions with uniform voxel | |
| | | values. Thus, <TT>T1</TT> either must be equality comparable, | |
| | | or an EqualityFunctor must be provided explicitly that realizes | |
| | | the desired equivalence predicate. The destination's value type | |
| | | <tt>T2</tt> should be large enough to hold the labels | |
| | | without overflow. Region numbers will be a consecutive sequence | |
| | | starting with one and ending with the region number returned by | |
| | | the function (inclusive). | |
| | | | |
| | | Return: the number of regions found (= largest region label) | |
| | | | |
| | | See \ref labelMultiArray() for a dimension-independent implementation o | |
| | | f | |
| | | connected components labelling. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 3D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood3D, | |
| | | class EqualityFunctor = std::equal_to<T1> > | |
| | | unsigned int | |
| | | labelVolume(MultiArrayView<3, T1, S1> const & source, | |
| | | MultiArrayView<3, T2, S2> dest, | |
| | | Neighborhood3D neighborhood3D, | |
| | | EqualityFunctor equal = EqualityFunctor()); | |
| | | | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{labelVolume} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood3D> | | class Neighborhood3D> | |
| unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, Src
Accessor sa, | | unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, Src
Accessor sa, | |
| DestIterator d_Iter, DestAccessor da, | | DestIterator d_Iter, DestAccessor da, | |
| Neighborhood3D neighborhood3D); | | Neighborhood3D neighborhood3D); | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood3D, class EqualityFunctor> | | class Neighborhood3D, class EqualityFunctor> | |
| unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, Src
Accessor sa, | | unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, Src
Accessor sa, | |
| DestIterator d_Iter, DestAccessor da, | | DestIterator d_Iter, DestAccessor da, | |
| Neighborhood3D neighborhood3D, EqualityFun
ctor equal); | | Neighborhood3D neighborhood3D, EqualityFun
ctor equal); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood3D> | | class Neighborhood3D> | |
| unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor>
src, | | unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor>
src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| Neighborhood3D neighborhood3D); | | Neighborhood3D neighborhood3D); | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood3D, class EqualityFunctor> | | class Neighborhood3D, class EqualityFunctor> | |
| unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor>
src, | | unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor>
src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| Neighborhood3D neighborhood3D, EqualityFun
ctor equal); | | Neighborhood3D neighborhood3D, EqualityFun
ctor equal); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use with 3D-Six-Neighborhood: | | use with 3D-Six-Neighborhood: | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| unsigned int labelVolumeSix(triple<SrcIterator, SrcShape, SrcAccess
or> src, | | unsigned int labelVolumeSix(triple<SrcIterator, SrcShape, SrcAccess
or> src, | |
| pair<DestIterator, DestAccessor> dest); | | pair<DestIterator, DestAccessor> dest); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| Connected components are defined as regions with uniform voxel | | | |
| values. Thus, <TT>SrcAccessor::value_type</TT> either must be | | | |
| equality comparable (first form), or an EqualityFunctor must be | | | |
| provided that realizes the desired predicate (second form). The | | | |
| destination's value type should be large enough to hold the labels | | | |
| without overflow. Region numbers will be a consecutive sequence | | | |
| starting with one and ending with the region number returned by | | | |
| the function (inclusive). | | | |
| | | | |
| Return: the number of regions found (= largest region label) | | | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/labelvolume.hxx\><br> | | <b>\#include</b> \<vigra/labelvolume.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | typedef MultiArray<3,int> IntVolume; | |
| | | IntVolume src(Shape3(w,h,d)); | |
| | | IntVolume dest(Shape3(w,h,d)); | |
| | | | |
| | | // find 6-connected regions | |
| | | int max_region_label = labelVolumeSix(src, dest); | |
| | | | |
| | | // find 26-connected regions | |
| | | int max_region_label = labelVolume(src, dest, NeighborCode3DTwentySix() | |
| | | ); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{labelVolume} | |
| | | \code | |
| typedef vigra::MultiArray<3,int> IntVolume; | | typedef vigra::MultiArray<3,int> IntVolume; | |
| IntVolume src(IntVolume::difference_type(w,h,d)); | | IntVolume src(IntVolume::difference_type(w,h,d)); | |
| IntVolume dest(IntVolume::difference_type(w,h,d)); | | IntVolume dest(IntVolume::difference_type(w,h,d)); | |
| | | | |
| // find 6-connected regions | | // find 6-connected regions | |
| int max_region_label = vigra::labelVolumeSix(srcMultiArrayRange(src), d
estMultiArray(dest)); | | int max_region_label = vigra::labelVolumeSix(srcMultiArrayRange(src), d
estMultiArray(dest)); | |
| | | | |
| // find 26-connected regions | | // find 26-connected regions | |
| int max_region_label = vigra::labelVolume(srcMultiArrayRange(src), dest
MultiArray(dest), NeighborCode3DTwentySix()); | | int max_region_label = vigra::labelVolume(srcMultiArrayRange(src), dest
MultiArray(dest), NeighborCode3DTwentySix()); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcIterator src_begin; | | SrcIterator src_begin; | |
| SrcShape shape; | | SrcShape shape; | |
| DestIterator dest_begin; | | DestIterator dest_begin; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_begin); | | SrcAccessor::value_type u = src_accessor(src_begin); | |
| | | | |
| u == u // first form | | u == u // first form | |
| | | | |
| EqualityFunctor equal; // second form | | EqualityFunctor equal; // second form | |
| equal(u, u) // second form | | equal(u, u) // second form | |
| | | | |
| int i; | | int i; | |
| dest_accessor.set(i, dest_begin); | | dest_accessor.set(i, dest_begin); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> unsigned int labelVolume) | | doxygen_overloaded_function(template <...> unsigned int labelVolume) | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
|
| class Neighborhood3D> | | | |
| unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor | | | |
| sa, | | | |
| DestIterator d_Iter, DestAccessor da, | | | |
| Neighborhood3D neighborhood3D) | | | |
| { | | | |
| return labelVolume(s_Iter, srcShape, sa, d_Iter, da, neighborhood3D | | | |
| , std::equal_to<typename SrcAccessor::value_type>()); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | | |
| class DestIterator, class DestAccessor, | | | |
| class Neighborhood3D> | | | |
| unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor> src, | | | |
| pair<DestIterator, DestAccessor> dest, | | | |
| Neighborhood3D neighborhood3D) | | | |
| { | | | |
| return labelVolume(src.first, src.second, src.third, dest.first, dest.s | | | |
| econd, neighborhood3D, std::equal_to<typename SrcAccessor::value_type>()); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | | |
| class DestIterator, class DestAccessor, | | | |
| class Neighborhood3D, class EqualityFunctor> | | | |
| unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor> src, | | | |
| pair<DestIterator, DestAccessor> dest, | | | |
| Neighborhood3D neighborhood3D, EqualityFunctor equ | | | |
| al) | | | |
| { | | | |
| return labelVolume(src.first, src.second, src.third, dest.first, dest.s | | | |
| econd, neighborhood3D, equal); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | | |
| class DestIterator, class DestAccessor, | | | |
| class Neighborhood3D, class EqualityFunctor> | | class Neighborhood3D, class EqualityFunctor> | |
| unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor
sa, | | unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor
sa, | |
| DestIterator d_Iter, DestAccessor da, | | DestIterator d_Iter, DestAccessor da, | |
| Neighborhood3D, EqualityFunctor equal) | | Neighborhood3D, EqualityFunctor equal) | |
| { | | { | |
| typedef typename DestAccessor::value_type LabelType; | | typedef typename DestAccessor::value_type LabelType; | |
| | | | |
| //basically needed for iteration and border-checks | | //basically needed for iteration and border-checks | |
| int w = srcShape[0], h = srcShape[1], d = srcShape[2]; | | int w = srcShape[0], h = srcShape[1], d = srcShape[2]; | |
| int x,y,z; | | int x,y,z; | |
| | | | |
| // temporary image to store region labels | | // temporary image to store region labels | |
|
| detail::UnionFindArray<LabelType> label; | | UnionFindArray<LabelType> label; | |
| | | | |
| //Declare traversers for all three dims at target | | //Declare traversers for all three dims at target | |
| SrcIterator zs = s_Iter; | | SrcIterator zs = s_Iter; | |
| DestIterator zd = d_Iter; | | DestIterator zd = d_Iter; | |
| | | | |
| // initialize the neighborhood traversers | | // initialize the neighborhood traversers | |
| NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast
); | | NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast
); | |
| ++nce; | | ++nce; | |
| // pass 1: scan image from upper left front to lower right back | | // pass 1: scan image from upper left front to lower right back | |
| // to find connected components | | // to find connected components | |
| | | | |
| skipping to change at line 245 | | skipping to change at line 245 | |
| SrcIterator ys(zs); | | SrcIterator ys(zs); | |
| DestIterator yd(zd); | | DestIterator yd(zd); | |
| | | | |
| for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1()) | | for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1()) | |
| { | | { | |
| SrcIterator xs(ys); | | SrcIterator xs(ys); | |
| DestIterator xd(yd); | | DestIterator xd(yd); | |
| | | | |
| for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0()) | | for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0()) | |
| { | | { | |
|
| LabelType currentLabel = label.nextFreeLabel(); | | LabelType currentIndex = label.nextFreeIndex(); | |
| | | | |
| //check whether there is a special border treatment to be u
sed or not | | //check whether there is a special border treatment to be u
sed or not | |
| AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h,
d); | | AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h,
d); | |
| | | | |
| //We are not at the border! | | //We are not at the border! | |
| if(atBorder == NotAtBorder) | | if(atBorder == NotAtBorder) | |
| { | | { | |
| NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::CausalFirst); | | NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::CausalFirst); | |
| | | | |
| do | | do | |
| { | | { | |
| // if colors are equal | | // if colors are equal | |
| if(equal(sa(xs), sa(xs, *nc))) | | if(equal(sa(xs), sa(xs, *nc))) | |
| { | | { | |
|
| currentLabel = label.makeUnion(label[da(xd,*nc)
], currentLabel); | | currentIndex = label.makeUnion(da(xd,*nc), curr
entIndex); | |
| } | | } | |
| ++nc; | | ++nc; | |
| } | | } | |
| while(nc!=nce); | | while(nc!=nce); | |
| } | | } | |
| else //we are at a border - handle this!! | | else //we are at a border - handle this!! | |
| { | | { | |
| NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::nearBorderDirectionsCausal(atBorder,0)); | | NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::nearBorderDirectionsCausal(atBorder,0)); | |
| int j=0; | | int j=0; | |
| while(nc.direction() != Neighborhood3D::Error) | | while(nc.direction() != Neighborhood3D::Error) | |
| { | | { | |
|
| /* | | int dummy = x+(*nc)[0]; // prevents an apparently | |
| SrcShape s(x,y,z), sn = s + *nc; | | incorrect optimization in gcc 4.8 | |
| | | if (dummy<0) | |
| if (sn[0]<0 || sn[0]>=w || sn[1]<0 || sn[1]>=h || s | | | |
| n[2]<0 || sn[2]>=d) | | | |
| { | | { | |
|
| std::cerr << "coordinate error at " << s << ", of | | std::cerr << "internal error " << dummy << std: | |
| fset " << *nc << ", index " << (nc).direction() << " at border " << | | :endl; | |
| | | | |
| atBorder << std::endl; | | | |
| | | | |
| } | | } | |
|
| */ | | | |
| // colors equal??? | | // colors equal??? | |
| if(equal(sa(xs), sa(xs, *nc))) | | if(equal(sa(xs), sa(xs, *nc))) | |
| { | | { | |
|
| currentLabel = label.makeUnion(label[da(xd,*nc)
], currentLabel); | | currentIndex = label.makeUnion(da(xd,*nc), curr
entIndex); | |
| } | | } | |
| nc.turnTo(Neighborhood3D::nearBorderDirectionsCausa
l(atBorder,++j)); | | nc.turnTo(Neighborhood3D::nearBorderDirectionsCausa
l(atBorder,++j)); | |
| } | | } | |
| } | | } | |
|
| da.set(label.finalizeLabel(currentLabel), xd); | | da.set(label.finalizeIndex(currentIndex), xd); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| LabelType count = label.makeContiguous(); | | LabelType count = label.makeContiguous(); | |
| | | | |
| // pass 2: assign one label to each region (tree) | | // pass 2: assign one label to each region (tree) | |
| // so that labels form a consecutive sequence 1, 2, ... | | // so that labels form a consecutive sequence 1, 2, ... | |
| zd = d_Iter; | | zd = d_Iter; | |
| for(z=0; z != d; ++z, ++zd.dim2()) | | for(z=0; z != d; ++z, ++zd.dim2()) | |
| { | | { | |
| DestIterator yd(zd); | | DestIterator yd(zd); | |
| | | | |
| for(y=0; y != h; ++y, ++yd.dim1()) | | for(y=0; y != h; ++y, ++yd.dim1()) | |
| { | | { | |
| DestIterator xd(yd); | | DestIterator xd(yd); | |
| | | | |
| for(x = 0; x != w; ++x, ++xd.dim0()) | | for(x = 0; x != w; ++x, ++xd.dim0()) | |
| { | | { | |
|
| da.set(label[da(xd)], xd); | | da.set(label.findLabel(da(xd)), xd); | |
| } | | } | |
| } | | } | |
| } | | } | |
| return count; | | return count; | |
| } | | } | |
| | | | |
|
| | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood3D> | |
| | | unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor | |
| | | sa, | |
| | | DestIterator d_Iter, DestAccessor da, | |
| | | Neighborhood3D neighborhood3D) | |
| | | { | |
| | | return labelVolume(s_Iter, srcShape, sa, d_Iter, da, neighborhood3D | |
| | | , std::equal_to<typename SrcAccessor::value_type>()); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood3D> | |
| | | unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor> src, | |
| | | pair<DestIterator, DestAccessor> dest, | |
| | | Neighborhood3D neighborhood3D) | |
| | | { | |
| | | return labelVolume(src.first, src.second, src.third, dest.first, dest.s | |
| | | econd, neighborhood3D, std::equal_to<typename SrcAccessor::value_type>()); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood3D, class EqualityFunctor> | |
| | | unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor> src, | |
| | | pair<DestIterator, DestAccessor> dest, | |
| | | Neighborhood3D neighborhood3D, EqualityFunctor equ | |
| | | al) | |
| | | { | |
| | | return labelVolume(src.first, src.second, src.third, dest.first, dest.s | |
| | | econd, neighborhood3D, equal); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood3D, class EqualityFunctor> | |
| | | inline unsigned int | |
| | | labelVolume(MultiArrayView<3, T1, S1> const & source, | |
| | | MultiArrayView<3, T2, S2> dest, | |
| | | Neighborhood3D neighborhood3D, | |
| | | EqualityFunctor equal) | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "labelVolume(): shape mismatch between input and output."); | |
| | | return labelVolume(srcMultiArrayRange(source), destMultiArray(dest), ne | |
| | | ighborhood3D, equal); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood3D> | |
| | | inline unsigned int | |
| | | labelVolume(MultiArrayView<3, T1, S1> const & source, | |
| | | MultiArrayView<3, T2, S2> dest, | |
| | | Neighborhood3D neighborhood3D) | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "labelVolume(): shape mismatch between input and output."); | |
| | | return labelVolume(srcMultiArrayRange(source), destMultiArray(dest), ne | |
| | | ighborhood3D, std::equal_to<T1>()); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* labelVolumeSix */ | | /* labelVolumeSix */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find the connected components of a segmented volume | | /** \brief Find the connected components of a segmented volume | |
| using the 6-neighborhood. | | using the 6-neighborhood. | |
| | | | |
| See \ref labelVolume() for detailed documentation. | | See \ref labelVolume() for detailed documentation. | |
| | | | |
| */ | | */ | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| unsigned int labelVolumeSix(triple<SrcIterator, SrcShape, SrcAccessor> src, | | unsigned int labelVolumeSix(triple<SrcIterator, SrcShape, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest) | | pair<DestIterator, DestAccessor> dest) | |
| { | | { | |
| return labelVolume(src.first, src.second, src.third, dest.first, dest.s
econd, NeighborCode3DSix(), std::equal_to<typename SrcAccessor::value_type>
()); | | return labelVolume(src.first, src.second, src.third, dest.first, dest.s
econd, NeighborCode3DSix(), std::equal_to<typename SrcAccessor::value_type>
()); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | unsigned int labelVolumeSix(MultiArrayView<3, T1, S1> const & source, | |
| | | MultiArrayView<3, T2, S2> dest) | |
| | | { | |
| | | return labelVolume(srcMultiArrayRange(source), destMultiArray(dest), | |
| | | NeighborCode3DSix(), std::equal_to<T1>()); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* labelVolumeWithBackground */ | | /* labelVolumeWithBackground */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find the connected components of a segmented volume, | | /** \brief Find the connected components of a segmented volume, | |
| excluding the background from labeling. | | excluding the background from labeling. | |
| | | | |
|
| | | This function works like \ref labelVolume(), but considers all backgrou | |
| | | nd voxels | |
| | | (i.e. voxels having the given '<TT>background_value</TT>') as a single | |
| | | region that | |
| | | is ignored when determining connected components and remains untouched | |
| | | in the | |
| | | destination array. Usually, you will zero-initialize the output array, | |
| | | so that | |
| | | the background gets label 0 (remember that actual region labels start a | |
| | | t one). | |
| | | | |
| | | Return: the number of regions found (= largest region label) | |
| | | | |
| | | See \ref labelMultiArrayWithBackground() for a dimension-independent im | |
| | | plementation | |
| | | if this algorithm. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 3D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood3D, | |
| | | class ValueType, | |
| | | class EqualityFunctor = std::equalt_to<T1> > | |
| | | unsigned int | |
| | | labelVolumeWithBackground(MultiArrayView<3, T1, S1> const & source, | |
| | | MultiArrayView<3, T2, S2> dest, | |
| | | Neighborhood3D neighborhood3D, | |
| | | ValueType backgroundValue, | |
| | | EqualityFunctor equal = EqualityFunctor() | |
| | | ); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{labelVolumeWithBackground} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood3D, class ValueType> | | class Neighborhood3D, class ValueType> | |
| unsigned int labelVolumeWithBackground( SrcIterator s_Iter, SrcS
hape srcShape, SrcAccessor sa, | | unsigned int labelVolumeWithBackground( SrcIterator s_Iter, SrcS
hape srcShape, SrcAccessor sa, | |
| DestIterator d_It
er, DestAccessor da, | | DestIterator d_It
er, DestAccessor da, | |
| Neighborhood3D ne
ighborhood3D, ValueType background_value); | | Neighborhood3D ne
ighborhood3D, ValueType background_value); | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood3D, class ValueType, class Equa
lityFunctor> | | class Neighborhood3D, class ValueType, class Equa
lityFunctor> | |
| unsigned int labelVolumeWithBackground( SrcIterator s_Iter, SrcS
hape srcShape, SrcAccessor sa, | | unsigned int labelVolumeWithBackground( SrcIterator s_Iter, SrcS
hape srcShape, SrcAccessor sa, | |
| DestIterator d_
Iter, DestAccessor da, | | DestIterator d_
Iter, DestAccessor da, | |
| Neighborhood3D ne
ighborhood3D, ValueType background_value, | | Neighborhood3D ne
ighborhood3D, ValueType background_value, | |
| EqualityFunctor
equal); | | EqualityFunctor
equal); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood3D, class ValueType> | | class Neighborhood3D, class ValueType> | |
| unsigned int labelVolumeWithBackground( triple<SrcIterator, SrcS
hape, SrcAccessor> src, | | unsigned int labelVolumeWithBackground( triple<SrcIterator, SrcS
hape, SrcAccessor> src, | |
| pair<DestIterator
, DestAccessor> dest, | | pair<DestIterator
, DestAccessor> dest, | |
| Neighborhood3D ne
ighborhood3D, ValueType background_value); | | Neighborhood3D ne
ighborhood3D, ValueType background_value); | |
| | | | |
| skipping to change at line 391 | | skipping to change at line 480 | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood3D, class ValueType, class Equa
lityFunctor> | | class Neighborhood3D, class ValueType, class Equa
lityFunctor> | |
| unsigned int labelVolumeWithBackground( triple<SrcIterator, SrcS
hape, SrcAccessor> src, | | unsigned int labelVolumeWithBackground( triple<SrcIterator, SrcS
hape, SrcAccessor> src, | |
| pair<DestIterator,
DestAccessor> dest, | | pair<DestIterator,
DestAccessor> dest, | |
| Neighborhood3D neig
hborhood3D, ValueType background_value, | | Neighborhood3D neig
hborhood3D, ValueType background_value, | |
| EqualityFunctor equ
al); | | EqualityFunctor equ
al); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| Connected components are defined as regions with uniform voxel | | | |
| values. Thus, <TT>SrcAccessor::value_type</TT> either must be | | | |
| equality comparable (first form), or an EqualityFunctor must be | | | |
| provided that realizes the desired predicate (second form). All | | | |
| voxel equal to the given '<TT>background_value</TT>' are ignored | | | |
| when determining connected components and remain untouched in the | | | |
| destination volume. | | | |
| | | | |
| The destination's value type should be large enough to hold the | | | |
| labels without overflow. Region numbers will be a consecutive | | | |
| sequence starting with one and ending with the region number | | | |
| returned by the function (inclusive). | | | |
| | | | |
| Return: the number of regions found (= largest region label) | | | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/labelvolume.hxx\><br> | | <b>\#include</b> \<vigra/labelvolume.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| typedef vigra::MultiArray<3,int> IntVolume; | | typedef vigra::MultiArray<3,int> IntVolume; | |
|
| | | | |
| | | IntVolume src(Shape3(w,h,d)); | |
| | | IntVolume dest(Shape3(w,h,d)); | |
| | | | |
| | | // find 6-connected regions | |
| | | int max_region_label = labelVolumeWithBackground(src, dest, NeighborCod | |
| | | e3DSix(), 0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{labelVolumeWithBackground} | |
| | | \code | |
| | | typedef vigra::MultiArray<3,int> IntVolume; | |
| IntVolume src(IntVolume::difference_type(w,h,d)); | | IntVolume src(IntVolume::difference_type(w,h,d)); | |
| IntVolume dest(IntVolume::difference_type(w,h,d)); | | IntVolume dest(IntVolume::difference_type(w,h,d)); | |
| | | | |
| // find 6-connected regions | | // find 6-connected regions | |
| int max_region_label = vigra::labelVolumeWithBackground( | | int max_region_label = vigra::labelVolumeWithBackground( | |
| srcMultiArrayRange(src), destMultiArray(dest), NeighborCode3DSix(), 0); | | srcMultiArrayRange(src), destMultiArray(dest), NeighborCode3DSix(), 0); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcIterator src_begin; | | SrcIterator src_begin; | |
| SrcShape shape; | | SrcShape shape; | |
| DestIterator dest_begin; | | DestIterator dest_begin; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_begin); | | SrcAccessor::value_type u = src_accessor(src_begin); | |
| | | | |
| u == u // first form | | u == u // first form | |
| | | | |
| EqualityFunctor equal; // second form | | EqualityFunctor equal; // second form | |
| equal(u, u) // second form | | equal(u, u) // second form | |
| | | | |
| int i; | | int i; | |
| dest_accessor.set(i, dest_begin); | | dest_accessor.set(i, dest_begin); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> unsigned int labelVolumeWithBack
ground) | | doxygen_overloaded_function(template <...> unsigned int labelVolumeWithBack
ground) | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood3D, | | class Neighborhood3D, | |
|
| class ValueType> | | | |
| unsigned int labelVolumeWithBackground(SrcIterator s_Iter, SrcShape srcShap | | | |
| e, SrcAccessor sa, | | | |
| DestIterator d_Iter, DestAccessor da | | | |
| , | | | |
| Neighborhood3D neighborhood3D, Value | | | |
| Type backgroundValue) | | | |
| { | | | |
| return labelVolumeWithBackground(s_Iter, srcShape, sa, d_Iter, da, neig | | | |
| hborhood3D, backgroundValue, std::equal_to<typename SrcAccessor::value_type | | | |
| >()); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | | |
| class DestIterator, class DestAccessor, | | | |
| class Neighborhood3D, | | | |
| class ValueType> | | | |
| unsigned int labelVolumeWithBackground(triple<SrcIterator, SrcShape, SrcAcc | | | |
| essor> src, | | | |
| pair<DestIterator, DestAccessor> des | | | |
| t, | | | |
| Neighborhood3D neighborhood3D, Value | | | |
| Type backgroundValue) | | | |
| { | | | |
| return labelVolumeWithBackground(src.first, src.second, src.third, dest | | | |
| .first, dest.second, neighborhood3D, backgroundValue, std::equal_to<typenam | | | |
| e SrcAccessor::value_type>()); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | | |
| class DestIterator, class DestAccessor, | | | |
| class Neighborhood3D, | | | |
| class ValueType, class EqualityFunctor> | | | |
| unsigned int labelVolumeWithBackground(triple<SrcIterator, SrcShape, SrcAcc | | | |
| essor> src, | | | |
| pair<DestIterator, DestAccessor> des | | | |
| t, | | | |
| Neighborhood3D neighborhood3D, Value | | | |
| Type backgroundValue, EqualityFunctor equal) | | | |
| { | | | |
| return labelVolumeWithBackground(src.first, src.second, src.third, dest | | | |
| .first, dest.second, neighborhood3D, backgroundValue, equal); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor,class SrcShape, | | | |
| class DestIterator, class DestAccessor, | | | |
| class Neighborhood3D, | | | |
| class ValueType, class EqualityFunctor> | | class ValueType, class EqualityFunctor> | |
| unsigned int labelVolumeWithBackground(SrcIterator s_Iter, SrcShape srcShap
e, SrcAccessor sa, | | unsigned int labelVolumeWithBackground(SrcIterator s_Iter, SrcShape srcShap
e, SrcAccessor sa, | |
| DestIterator d_Iter, DestAccessor da
, | | DestIterator d_Iter, DestAccessor da
, | |
| Neighborhood3D, | | Neighborhood3D, | |
| ValueType backgroundValue, EqualityF
unctor equal) | | ValueType backgroundValue, EqualityF
unctor equal) | |
| { | | { | |
| typedef typename DestAccessor::value_type LabelType; | | typedef typename DestAccessor::value_type LabelType; | |
| | | | |
| //basically needed for iteration and border-checks | | //basically needed for iteration and border-checks | |
| int w = srcShape[0], h = srcShape[1], d = srcShape[2]; | | int w = srcShape[0], h = srcShape[1], d = srcShape[2]; | |
| int x,y,z; | | int x,y,z; | |
| | | | |
| // temporary image to store region labels | | // temporary image to store region labels | |
|
| detail::UnionFindArray<LabelType> label; | | UnionFindArray<LabelType> label; | |
| | | | |
| //Declare traversers for all three dims at target | | //Declare traversers for all three dims at target | |
| SrcIterator zs = s_Iter; | | SrcIterator zs = s_Iter; | |
| DestIterator zd = d_Iter; | | DestIterator zd = d_Iter; | |
| | | | |
| // initialize the neighborhood traversers | | // initialize the neighborhood traversers | |
| NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast
); | | NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast
); | |
| ++nce; | | ++nce; | |
| // pass 1: scan image from upper left front to lower right back | | // pass 1: scan image from upper left front to lower right back | |
| // to find connected components | | // to find connected components | |
| | | | |
| skipping to change at line 531 | | skipping to change at line 582 | |
| | | | |
| for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1()) | | for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1()) | |
| { | | { | |
| SrcIterator xs(ys); | | SrcIterator xs(ys); | |
| DestIterator xd(yd); | | DestIterator xd(yd); | |
| | | | |
| for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0()) | | for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0()) | |
| { | | { | |
| if(equal(sa(xs), backgroundValue)) | | if(equal(sa(xs), backgroundValue)) | |
| { | | { | |
|
| da.set(label[0], xd); | | //da.set(label.getIndex(0), xd); | |
| | | da.set(0, xd); | |
| continue; | | continue; | |
| } | | } | |
| | | | |
|
| LabelType currentLabel = label.nextFreeLabel(); | | LabelType currentIndex = label.nextFreeIndex(); | |
| | | | |
| //check whether there is a special border treatment to be u
sed or not | | //check whether there is a special border treatment to be u
sed or not | |
| AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h,
d); | | AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h,
d); | |
| | | | |
| //We are not at the border! | | //We are not at the border! | |
| if(atBorder == NotAtBorder) | | if(atBorder == NotAtBorder) | |
| { | | { | |
| NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::CausalFirst); | | NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::CausalFirst); | |
| | | | |
| do | | do | |
| { | | { | |
| // if colors are equal | | // if colors are equal | |
| if(equal(sa(xs), sa(xs, *nc))) | | if(equal(sa(xs), sa(xs, *nc))) | |
| { | | { | |
|
| currentLabel = label.makeUnion(label[da(xd,*nc)
], currentLabel); | | currentIndex = label.makeUnion(da(xd,*nc), curr
entIndex); | |
| } | | } | |
| ++nc; | | ++nc; | |
| } | | } | |
| while(nc!=nce); | | while(nc!=nce); | |
| } | | } | |
| else //we are at a border - handle this!! | | else //we are at a border - handle this!! | |
| { | | { | |
| NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::nearBorderDirectionsCausal(atBorder,0)); | | NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhoo
d3D::nearBorderDirectionsCausal(atBorder,0)); | |
| int j=0; | | int j=0; | |
| while(nc.direction() != Neighborhood3D::Error) | | while(nc.direction() != Neighborhood3D::Error) | |
| { | | { | |
|
| | | int dummy = x+(*nc)[0]; // prevents an apparently | |
| | | incorrect optimization in gcc 4.8 | |
| | | if (dummy<0) | |
| | | { | |
| | | std::cerr << "internal error " << dummy << std: | |
| | | :endl; | |
| | | } | |
| // colors equal??? | | // colors equal??? | |
| if(equal(sa(xs), sa(xs, *nc))) | | if(equal(sa(xs), sa(xs, *nc))) | |
| { | | { | |
|
| currentLabel = label.makeUnion(label[da(xd,*nc)
], currentLabel); | | currentIndex = label.makeUnion(da(xd,*nc), curr
entIndex); | |
| } | | } | |
| nc.turnTo(Neighborhood3D::nearBorderDirectionsCausa
l(atBorder,++j)); | | nc.turnTo(Neighborhood3D::nearBorderDirectionsCausa
l(atBorder,++j)); | |
| } | | } | |
| } | | } | |
|
| da.set(label.finalizeLabel(currentLabel), xd); | | da.set(label.finalizeIndex(currentIndex), xd); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| LabelType count = label.makeContiguous(); | | LabelType count = label.makeContiguous(); | |
| | | | |
| // pass 2: assign one label to each region (tree) | | // pass 2: assign one label to each region (tree) | |
| // so that labels form a consecutive sequence 1, 2, ... | | // so that labels form a consecutive sequence 1, 2, ... | |
| zd = d_Iter; | | zd = d_Iter; | |
| for(z=0; z != d; ++z, ++zd.dim2()) | | for(z=0; z != d; ++z, ++zd.dim2()) | |
| { | | { | |
| DestIterator yd(zd); | | DestIterator yd(zd); | |
| | | | |
| for(y=0; y != h; ++y, ++yd.dim1()) | | for(y=0; y != h; ++y, ++yd.dim1()) | |
| { | | { | |
| DestIterator xd(yd); | | DestIterator xd(yd); | |
| | | | |
| for(x = 0; x != w; ++x, ++xd.dim0()) | | for(x = 0; x != w; ++x, ++xd.dim0()) | |
| { | | { | |
|
| da.set(label[da(xd)], xd); | | da.set(label.findLabel(da(xd)), xd); | |
| } | | } | |
| } | | } | |
| } | | } | |
| return count; | | return count; | |
| } | | } | |
| | | | |
|
| | | template <class SrcIterator, class SrcAccessor,class SrcShape, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood3D, | |
| | | class ValueType> | |
| | | inline unsigned int | |
| | | labelVolumeWithBackground(SrcIterator s_Iter, SrcShape srcShape, SrcAccesso | |
| | | r sa, | |
| | | DestIterator d_Iter, DestAccessor da, | |
| | | Neighborhood3D neighborhood3D, ValueType backgrou | |
| | | ndValue) | |
| | | { | |
| | | return labelVolumeWithBackground(s_Iter, srcShape, sa, d_Iter, da, neig | |
| | | hborhood3D, backgroundValue, std::equal_to<typename SrcAccessor::value_type | |
| | | >()); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood3D, | |
| | | class ValueType, | |
| | | class EqualityFunctor> | |
| | | inline unsigned int | |
| | | labelVolumeWithBackground(triple<SrcIterator, SrcShape, SrcAccessor> src, | |
| | | pair<DestIterator, DestAccessor> dest, | |
| | | Neighborhood3D neighborhood3D, ValueType backgrou | |
| | | ndValue, EqualityFunctor equal) | |
| | | { | |
| | | return labelVolumeWithBackground(src.first, src.second, src.third, dest | |
| | | .first, dest.second, neighborhood3D, backgroundValue, equal); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood3D, | |
| | | class ValueType> | |
| | | inline unsigned int | |
| | | labelVolumeWithBackground(triple<SrcIterator, SrcShape, SrcAccessor> src, | |
| | | pair<DestIterator, DestAccessor> dest, | |
| | | Neighborhood3D neighborhood3D, ValueType backgrou | |
| | | ndValue) | |
| | | { | |
| | | return labelVolumeWithBackground(src.first, src.second, src.third, dest | |
| | | .first, dest.second, | |
| | | neighborhood3D, backgroundValue, std:: | |
| | | equal_to<typename SrcAccessor::value_type>()); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood3D, | |
| | | class ValueType, | |
| | | class EqualityFunctor> | |
| | | inline unsigned int | |
| | | labelVolumeWithBackground(MultiArrayView<3, T1, S1> const & source, | |
| | | MultiArrayView<3, T2, S2> dest, | |
| | | Neighborhood3D neighborhood3D, | |
| | | ValueType backgroundValue, | |
| | | EqualityFunctor equal) | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "labelVolumeWithBackground(): shape mismatch between input and outp | |
| | | ut."); | |
| | | return labelVolumeWithBackground(srcMultiArrayRange(source), destMultiA | |
| | | rray(dest), | |
| | | neighborhood3D, backgroundValue, equal | |
| | | ); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood3D, | |
| | | class ValueType> | |
| | | inline unsigned int | |
| | | labelVolumeWithBackground(MultiArrayView<3, T1, S1> const & source, | |
| | | MultiArrayView<3, T2, S2> dest, | |
| | | Neighborhood3D neighborhood3D, | |
| | | ValueType backgroundValue) | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "labelVolumeWithBackground(): shape mismatch between input and outp | |
| | | ut."); | |
| | | return labelVolumeWithBackground(srcMultiArrayRange(source), destMultiA | |
| | | rray(dest), | |
| | | neighborhood3D, backgroundValue, | |
| | | std::equal_to<T1>()); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } //end of namespace vigra | | } //end of namespace vigra | |
| | | | |
| #endif //VIGRA_LABELVOLUME_HXX | | #endif //VIGRA_LABELVOLUME_HXX | |
| | | | |
End of changes. 39 change blocks. |
| 143 lines changed or deleted | | 286 lines changed or added | |
|
| linear_solve.hxx | | linear_solve.hxx | |
| | | | |
| skipping to change at line 163 | | skipping to change at line 163 | |
| { | | { | |
| typedef typename Matrix<T>::difference_type Shape; | | typedef typename Matrix<T>::difference_type Shape; | |
| | | | |
| const MultiArrayIndex m = rowCount(r); | | const MultiArrayIndex m = rowCount(r); | |
| const MultiArrayIndex n = columnCount(r); | | const MultiArrayIndex n = columnCount(r); | |
| const MultiArrayIndex rhsCount = columnCount(rhs); | | const MultiArrayIndex rhsCount = columnCount(rhs); | |
| vigra_precondition(m == rowCount(rhs), | | vigra_precondition(m == rowCount(rhs), | |
| "qrGivensStepImpl(): Matrix shape mismatch."); | | "qrGivensStepImpl(): Matrix shape mismatch."); | |
| | | | |
| Matrix<T> givens(2,2); | | Matrix<T> givens(2,2); | |
|
| for(int k=m-1; k>(int)i; --k) | | for(int k=m-1; k>static_cast<int>(i); --k) | |
| { | | { | |
| if(!givensReflectionMatrix(r(k-1,i), r(k,i), givens)) | | if(!givensReflectionMatrix(r(k-1,i), r(k,i), givens)) | |
| continue; // r(k,i) was already zero | | continue; // r(k,i) was already zero | |
| | | | |
| r(k-1,i) = givens(0,0)*r(k-1,i) + givens(0,1)*r(k,i); | | r(k-1,i) = givens(0,0)*r(k-1,i) + givens(0,1)*r(k,i); | |
| r(k,i) = 0.0; | | r(k,i) = 0.0; | |
| | | | |
| r.subarray(Shape(k-1,i+1), Shape(k+1,n)) = givens*r.subarray(Shape(
k-1,i+1), Shape(k+1,n)); | | r.subarray(Shape(k-1,i+1), Shape(k+1,n)) = givens*r.subarray(Shape(
k-1,i+1), Shape(k+1,n)); | |
| rhs.subarray(Shape(k-1,0), Shape(k+1,rhsCount)) = givens*rhs.subarr
ay(Shape(k-1,0), Shape(k+1,rhsCount)); | | rhs.subarray(Shape(k-1,0), Shape(k+1,rhsCount)) = givens*rhs.subarr
ay(Shape(k-1,0), Shape(k+1,rhsCount)); | |
| } | | } | |
| | | | |
| skipping to change at line 247 | | skipping to change at line 247 | |
| | | | |
| if(j == i) | | if(j == i) | |
| return; | | return; | |
| if(j < i) | | if(j < i) | |
| std::swap(j,i); | | std::swap(j,i); | |
| | | | |
| columnVector(r, i).swapData(columnVector(r, j)); | | columnVector(r, i).swapData(columnVector(r, j)); | |
| std::swap(permutation[i], permutation[j]); | | std::swap(permutation[i], permutation[j]); | |
| | | | |
| Matrix<T> givens(2,2); | | Matrix<T> givens(2,2); | |
|
| for(int k=m-1; k>(int)i; --k) | | for(int k=m-1; k>static_cast<int>(i); --k) | |
| { | | { | |
| if(!givensReflectionMatrix(r(k-1,i), r(k,i), givens)) | | if(!givensReflectionMatrix(r(k-1,i), r(k,i), givens)) | |
| continue; // r(k,i) was already zero | | continue; // r(k,i) was already zero | |
| | | | |
| r(k-1,i) = givens(0,0)*r(k-1,i) + givens(0,1)*r(k,i); | | r(k-1,i) = givens(0,0)*r(k-1,i) + givens(0,1)*r(k,i); | |
| r(k,i) = 0.0; | | r(k,i) = 0.0; | |
| | | | |
| r.subarray(Shape(k-1,i+1), Shape(k+1,n)) = givens*r.subarray(Shape(
k-1,i+1), Shape(k+1,n)); | | r.subarray(Shape(k-1,i+1), Shape(k+1,n)) = givens*r.subarray(Shape(
k-1,i+1), Shape(k+1,n)); | |
| rhs.subarray(Shape(k-1,0), Shape(k+1,rhsCount)) = givens*rhs.subarr
ay(Shape(k-1,0), Shape(k+1,rhsCount)); | | rhs.subarray(Shape(k-1,0), Shape(k+1,rhsCount)) = givens*rhs.subarr
ay(Shape(k-1,0), Shape(k+1,rhsCount)); | |
| } | | } | |
| | | | |
| skipping to change at line 391 | | skipping to change at line 391 | |
| | | | |
| MultiArrayIndex n = rowCount(newColumn) - 1; | | MultiArrayIndex n = rowCount(newColumn) - 1; | |
| | | | |
| T gamma = newColumn(n,0); | | T gamma = newColumn(n,0); | |
| if(gamma == 0.0) | | if(gamma == 0.0) | |
| { | | { | |
| v = 0.0; | | v = 0.0; | |
| return; | | return; | |
| } | | } | |
| | | | |
|
| T yv = dot(columnVector(newColumn, Shape(0,0),n), columnVector(z, Shape | | T yv = dot(columnVector(newColumn, Shape(0,0), static_cast<int>(n)), | |
| (0,0),n)); | | columnVector(z, Shape(0,0), static_cast<int>(n))); | |
| // use atan2 as it is robust against overflow/underflow | | // use atan2 as it is robust against overflow/underflow | |
| T t = 0.5*std::atan2(T(-2.0*yv), T(squaredNorm(gamma / v) + squaredNorm
(yv) - 1.0)), | | T t = 0.5*std::atan2(T(-2.0*yv), T(squaredNorm(gamma / v) + squaredNorm
(yv) - 1.0)), | |
| s = std::sin(t), | | s = std::sin(t), | |
| c = std::cos(t); | | c = std::cos(t); | |
|
| columnVector(z, Shape(0,0),n) *= c; | | columnVector(z, Shape(0,0), static_cast<int>(n)) *= c; | |
| z(n,0) = (s - c*yv) / gamma; | | z(n,0) = (s - c*yv) / gamma; | |
| v *= norm(gamma) / hypot(c*gamma, v*(s - c*yv)); | | v *= norm(gamma) / hypot(c*gamma, v*(s - c*yv)); | |
| } | | } | |
| | | | |
| // QR algorithm with optional column pivoting | | // QR algorithm with optional column pivoting | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| unsigned int | | unsigned int | |
| qrTransformToTriangularImpl(MultiArrayView<2, T, C1> & r, MultiArrayView<2,
T, C2> & rhs, MultiArrayView<2, T, C3> & householder, | | qrTransformToTriangularImpl(MultiArrayView<2, T, C1> & r, MultiArrayView<2,
T, C2> & rhs, MultiArrayView<2, T, C3> & householder, | |
| ArrayVector<MultiArrayIndex> & permutation, dou
ble epsilon) | | ArrayVector<MultiArrayIndex> & permutation, dou
ble epsilon) | |
| { | | { | |
| | | | |
| skipping to change at line 428 | | skipping to change at line 429 | |
| const MultiArrayIndex rhsCount = columnCount(rhs); | | const MultiArrayIndex rhsCount = columnCount(rhs); | |
| bool transformRHS = rhsCount > 0; | | bool transformRHS = rhsCount > 0; | |
| vigra_precondition(!transformRHS || m == rowCount(rhs), | | vigra_precondition(!transformRHS || m == rowCount(rhs), | |
| "qrTransformToTriangularImpl(): RHS matrix shape mis
match."); | | "qrTransformToTriangularImpl(): RHS matrix shape mis
match."); | |
| | | | |
| bool storeHouseholderSteps = columnCount(householder) > 0; | | bool storeHouseholderSteps = columnCount(householder) > 0; | |
| vigra_precondition(!storeHouseholderSteps || r.shape() == householder.s
hape(), | | vigra_precondition(!storeHouseholderSteps || r.shape() == householder.s
hape(), | |
| "qrTransformToTriangularImpl(): Householder matrix s
hape mismatch."); | | "qrTransformToTriangularImpl(): Householder matrix s
hape mismatch."); | |
| | | | |
| bool pivoting = permutation.size() > 0; | | bool pivoting = permutation.size() > 0; | |
|
| vigra_precondition(!pivoting || n == (MultiArrayIndex)permutation.size(
), | | vigra_precondition(!pivoting || n == static_cast<MultiArrayIndex>(permu
tation.size()), | |
| "qrTransformToTriangularImpl(): Permutation array si
ze mismatch."); | | "qrTransformToTriangularImpl(): Permutation array si
ze mismatch."); | |
| | | | |
| if(n == 0) | | if(n == 0) | |
| return 0; // trivial solution | | return 0; // trivial solution | |
| | | | |
| Matrix<SNType> columnSquaredNorms; | | Matrix<SNType> columnSquaredNorms; | |
| if(pivoting) | | if(pivoting) | |
| { | | { | |
| columnSquaredNorms.reshape(Shape(1,n)); | | columnSquaredNorms.reshape(Shape(1,n)); | |
| for(MultiArrayIndex k=0; k<n; ++k) | | for(MultiArrayIndex k=0; k<n; ++k) | |
| | | | |
| skipping to change at line 483 | | skipping to change at line 484 | |
| zmin(0,0) = 1.0 / r(0,0); | | zmin(0,0) = 1.0 / r(0,0); | |
| } | | } | |
| | | | |
| for(MultiArrayIndex k=1; k<maxRank; ++k) | | for(MultiArrayIndex k=1; k<maxRank; ++k) | |
| { | | { | |
| if(pivoting) | | if(pivoting) | |
| { | | { | |
| for(MultiArrayIndex l=k; l<n; ++l) | | for(MultiArrayIndex l=k; l<n; ++l) | |
| columnSquaredNorms[l] -= squaredNorm(r(k, l)); | | columnSquaredNorms[l] -= squaredNorm(r(k, l)); | |
| int pivot = k + argMax(rowVector(columnSquaredNorms, Shape(0,k)
, n)); | | int pivot = k + argMax(rowVector(columnSquaredNorms, Shape(0,k)
, n)); | |
|
| if(pivot != (int)k) | | if(pivot != static_cast<int>(k)) | |
| { | | { | |
| columnVector(r, k).swapData(columnVector(r, pivot)); | | columnVector(r, k).swapData(columnVector(r, pivot)); | |
| std::swap(columnSquaredNorms[k], columnSquaredNorms[pivot])
; | | std::swap(columnSquaredNorms[k], columnSquaredNorms[pivot])
; | |
| std::swap(permutation[k], permutation[pivot]); | | std::swap(permutation[k], permutation[pivot]); | |
| } | | } | |
| } | | } | |
| | | | |
| qrHouseholderStepImpl(k, r, rhs, householder); | | qrHouseholderStepImpl(k, r, rhs, householder); | |
| | | | |
| if(simpleSingularValueApproximation) | | if(simpleSingularValueApproximation) | |
| | | | |
| skipping to change at line 519 | | skipping to change at line 520 | |
| #endif | | #endif | |
| | | | |
| if(epsilon == 0.0) | | if(epsilon == 0.0) | |
| tolerance = m*maxApproxSingularValue*NumericTraits<T>::epsilon(
); | | tolerance = m*maxApproxSingularValue*NumericTraits<T>::epsilon(
); | |
| | | | |
| if(minApproxSingularValue > tolerance) | | if(minApproxSingularValue > tolerance) | |
| ++rank; | | ++rank; | |
| else | | else | |
| pivoting = false; // matrix doesn't have full rank, triangulize
the rest without pivoting | | pivoting = false; // matrix doesn't have full rank, triangulize
the rest without pivoting | |
| } | | } | |
|
| return (unsigned int)rank; | | return static_cast<unsigned int>(rank); | |
| } | | } | |
| | | | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| unsigned int | | unsigned int | |
| qrTransformToUpperTriangular(MultiArrayView<2, T, C1> & r, MultiArrayView<2
, T, C2> & rhs, | | qrTransformToUpperTriangular(MultiArrayView<2, T, C1> & r, MultiArrayView<2
, T, C2> & rhs, | |
| ArrayVector<MultiArrayIndex> & permutation, do
uble epsilon = 0.0) | | ArrayVector<MultiArrayIndex> & permutation, do
uble epsilon = 0.0) | |
| { | | { | |
| Matrix<T> dontStoreHouseholderVectors; // intentionally empty | | Matrix<T> dontStoreHouseholderVectors; // intentionally empty | |
| return qrTransformToTriangularImpl(r, rhs, dontStoreHouseholderVectors,
permutation, epsilon); | | return qrTransformToTriangularImpl(r, rhs, dontStoreHouseholderVectors,
permutation, epsilon); | |
| } | | } | |
| | | | |
| // QR algorithm with optional row pivoting | | // QR algorithm with optional row pivoting | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| unsigned int | | unsigned int | |
| qrTransformToLowerTriangular(MultiArrayView<2, T, C1> & r, MultiArrayView<2
, T, C2> & rhs, MultiArrayView<2, T, C3> & householderMatrix, | | qrTransformToLowerTriangular(MultiArrayView<2, T, C1> & r, MultiArrayView<2
, T, C2> & rhs, MultiArrayView<2, T, C3> & householderMatrix, | |
| double epsilon = 0.0) | | double epsilon = 0.0) | |
| { | | { | |
|
| ArrayVector<MultiArrayIndex> permutation((unsigned int)rowCount(rhs)); | | ArrayVector<MultiArrayIndex> permutation(static_cast<unsigned int>(rowC | |
| for(MultiArrayIndex k=0; k<(MultiArrayIndex)permutation.size(); ++k) | | ount(rhs))); | |
| | | for(MultiArrayIndex k=0; k<static_cast<MultiArrayIndex>(permutation.siz | |
| | | e()); ++k) | |
| permutation[k] = k; | | permutation[k] = k; | |
| Matrix<T> dontTransformRHS; // intentionally empty | | Matrix<T> dontTransformRHS; // intentionally empty | |
| MultiArrayView<2, T, StridedArrayTag> rt = transpose(r), | | MultiArrayView<2, T, StridedArrayTag> rt = transpose(r), | |
| ht = transpose(householderMatrix)
; | | ht = transpose(householderMatrix)
; | |
| unsigned int rank = qrTransformToTriangularImpl(rt, dontTransformRHS, h
t, permutation, epsilon); | | unsigned int rank = qrTransformToTriangularImpl(rt, dontTransformRHS, h
t, permutation, epsilon); | |
| | | | |
| // apply row permutation to RHS | | // apply row permutation to RHS | |
| Matrix<T> tempRHS(rhs); | | Matrix<T> tempRHS(rhs); | |
|
| for(MultiArrayIndex k=0; k<(MultiArrayIndex)permutation.size(); ++k) | | for(MultiArrayIndex k=0; k<static_cast<MultiArrayIndex>(permutation.siz
e()); ++k) | |
| rowVector(rhs, k) = rowVector(tempRHS, permutation[k]); | | rowVector(rhs, k) = rowVector(tempRHS, permutation[k]); | |
| return rank; | | return rank; | |
| } | | } | |
| | | | |
| // QR algorithm without column pivoting | | // QR algorithm without column pivoting | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline bool | | inline bool | |
| qrTransformToUpperTriangular(MultiArrayView<2, T, C1> & r, MultiArrayView<2
, T, C2> & rhs, | | qrTransformToUpperTriangular(MultiArrayView<2, T, C1> & r, MultiArrayView<2
, T, C2> & rhs, | |
| double epsilon = 0.0) | | double epsilon = 0.0) | |
| { | | { | |
| ArrayVector<MultiArrayIndex> noPivoting; // intentionally empty | | ArrayVector<MultiArrayIndex> noPivoting; // intentionally empty | |
| | | | |
| return (qrTransformToUpperTriangular(r, rhs, noPivoting, epsilon) == | | return (qrTransformToUpperTriangular(r, rhs, noPivoting, epsilon) == | |
|
| (unsigned int)columnCount(r)); | | static_cast<unsigned int>(columnCount(r))); | |
| } | | } | |
| | | | |
| // QR algorithm without row pivoting | | // QR algorithm without row pivoting | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline bool | | inline bool | |
| qrTransformToLowerTriangular(MultiArrayView<2, T, C1> & r, MultiArrayView<2
, T, C2> & householder, | | qrTransformToLowerTriangular(MultiArrayView<2, T, C1> & r, MultiArrayView<2
, T, C2> & householder, | |
| double epsilon = 0.0) | | double epsilon = 0.0) | |
| { | | { | |
| Matrix<T> noPivoting; // intentionally empty | | Matrix<T> noPivoting; // intentionally empty | |
| | | | |
| return (qrTransformToLowerTriangular(r, noPivoting, householder, epsilo
n) == | | return (qrTransformToLowerTriangular(r, noPivoting, householder, epsilo
n) == | |
|
| (unsigned int)rowCount(r)); | | static_cast<unsigned int>(rowCount(r))); | |
| } | | } | |
| | | | |
| // restore ordering of result vector elements after QR solution with column
pivoting | | // restore ordering of result vector elements after QR solution with column
pivoting | |
| template <class T, class C1, class C2, class Permutation> | | template <class T, class C1, class C2, class Permutation> | |
| void inverseRowPermutation(MultiArrayView<2, T, C1> &permuted, MultiArrayVi
ew<2, T, C2> &res, | | void inverseRowPermutation(MultiArrayView<2, T, C1> &permuted, MultiArrayVi
ew<2, T, C2> &res, | |
| Permutation const & permutation) | | Permutation const & permutation) | |
| { | | { | |
| for(MultiArrayIndex k=0; k<columnCount(permuted); ++k) | | for(MultiArrayIndex k=0; k<columnCount(permuted); ++k) | |
| for(MultiArrayIndex l=0; l<rowCount(permuted); ++l) | | for(MultiArrayIndex l=0; l<rowCount(permuted); ++l) | |
| res(permutation[l], k) = permuted(l,k); | | res(permutation[l], k) = permuted(l,k); | |
| | | | |
| skipping to change at line 632 | | skipping to change at line 633 | |
| vigra_precondition(n == rowCount(res), | | vigra_precondition(n == rowCount(res), | |
| "linearSolveQR(): Mismatch between column count of coefficient m
atrix and row count of solution."); | | "linearSolveQR(): Mismatch between column count of coefficient m
atrix and row count of solution."); | |
| vigra_precondition(epsilon >= 0.0, | | vigra_precondition(epsilon >= 0.0, | |
| "linearSolveQR(): 'epsilon' must be non-negative."); | | "linearSolveQR(): 'epsilon' must be non-negative."); | |
| | | | |
| if(m < n) | | if(m < n) | |
| { | | { | |
| // minimum norm solution of underdetermined system | | // minimum norm solution of underdetermined system | |
| Matrix<T> householderMatrix(n, m); | | Matrix<T> householderMatrix(n, m); | |
| MultiArrayView<2, T, StridedArrayTag> ht = transpose(householderMat
rix); | | MultiArrayView<2, T, StridedArrayTag> ht = transpose(householderMat
rix); | |
|
| rank = (MultiArrayIndex)detail::qrTransformToLowerTriangular(A, b,
ht, epsilon); | | rank = static_cast<MultiArrayIndex>(detail::qrTransformToLowerTrian
gular(A, b, ht, epsilon)); | |
| res.subarray(Shape(rank,0), Shape(n, rhsCount)).init(NumericTraits<
T>::zero()); | | res.subarray(Shape(rank,0), Shape(n, rhsCount)).init(NumericTraits<
T>::zero()); | |
| if(rank < m) | | if(rank < m) | |
| { | | { | |
| // system is also rank-deficient => compute minimum norm least
squares solution | | // system is also rank-deficient => compute minimum norm least
squares solution | |
| MultiArrayView<2, T, C1> Asub = A.subarray(ul, Shape(m,rank)); | | MultiArrayView<2, T, C1> Asub = A.subarray(ul, Shape(m,rank)); | |
| detail::qrTransformToUpperTriangular(Asub, b, epsilon); | | detail::qrTransformToUpperTriangular(Asub, b, epsilon); | |
| linearSolveUpperTriangular(A.subarray(ul, Shape(rank,rank)), | | linearSolveUpperTriangular(A.subarray(ul, Shape(rank,rank)), | |
| b.subarray(ul, Shape(rank,rhsCount))
, | | b.subarray(ul, Shape(rank,rhsCount))
, | |
| res.subarray(ul, Shape(rank, rhsCoun
t))); | | res.subarray(ul, Shape(rank, rhsCoun
t))); | |
| } | | } | |
| | | | |
| skipping to change at line 655 | | skipping to change at line 656 | |
| // system has full rank => compute minimum norm solution | | // system has full rank => compute minimum norm solution | |
| linearSolveLowerTriangular(A.subarray(ul, Shape(rank,rank)), | | linearSolveLowerTriangular(A.subarray(ul, Shape(rank,rank)), | |
| b.subarray(ul, Shape(rank, rhsCount)
), | | b.subarray(ul, Shape(rank, rhsCount)
), | |
| res.subarray(ul, Shape(rank, rhsCoun
t))); | | res.subarray(ul, Shape(rank, rhsCoun
t))); | |
| } | | } | |
| detail::applyHouseholderColumnReflections(householderMatrix.subarra
y(ul, Shape(n, rank)), res); | | detail::applyHouseholderColumnReflections(householderMatrix.subarra
y(ul, Shape(n, rank)), res); | |
| } | | } | |
| else | | else | |
| { | | { | |
| // solution of well-determined or overdetermined system | | // solution of well-determined or overdetermined system | |
|
| ArrayVector<MultiArrayIndex> permutation((unsigned int)n); | | ArrayVector<MultiArrayIndex> permutation(static_cast<unsigned int>(
n)); | |
| for(MultiArrayIndex k=0; k<n; ++k) | | for(MultiArrayIndex k=0; k<n; ++k) | |
| permutation[k] = k; | | permutation[k] = k; | |
| | | | |
|
| rank = (MultiArrayIndex)detail::qrTransformToUpperTriangular(A, b,
permutation, epsilon); | | rank = static_cast<MultiArrayIndex>(detail::qrTransformToUpperTrian
gular(A, b, permutation, epsilon)); | |
| | | | |
| Matrix<T> permutedSolution(n, rhsCount); | | Matrix<T> permutedSolution(n, rhsCount); | |
| if(rank < n) | | if(rank < n) | |
| { | | { | |
| // system is rank-deficient => compute minimum norm solution | | // system is rank-deficient => compute minimum norm solution | |
| Matrix<T> householderMatrix(n, rank); | | Matrix<T> householderMatrix(n, rank); | |
| MultiArrayView<2, T, StridedArrayTag> ht = transpose(householde
rMatrix); | | MultiArrayView<2, T, StridedArrayTag> ht = transpose(householde
rMatrix); | |
| MultiArrayView<2, T, C1> Asub = A.subarray(ul, Shape(rank,n)); | | MultiArrayView<2, T, C1> Asub = A.subarray(ul, Shape(rank,n)); | |
| detail::qrTransformToLowerTriangular(Asub, ht, epsilon); | | detail::qrTransformToLowerTriangular(Asub, ht, epsilon); | |
| linearSolveLowerTriangular(A.subarray(ul, Shape(rank,rank)), | | linearSolveLowerTriangular(A.subarray(ul, Shape(rank,rank)), | |
| | | | |
| skipping to change at line 683 | | skipping to change at line 684 | |
| } | | } | |
| else | | else | |
| { | | { | |
| // system has full rank => compute exact or least squares solut
ion | | // system has full rank => compute exact or least squares solut
ion | |
| linearSolveUpperTriangular(A.subarray(ul, Shape(rank,rank)), | | linearSolveUpperTriangular(A.subarray(ul, Shape(rank,rank)), | |
| b.subarray(ul, Shape(rank,rhsCount))
, | | b.subarray(ul, Shape(rank,rhsCount))
, | |
| permutedSolution); | | permutedSolution); | |
| } | | } | |
| detail::inverseRowPermutation(permutedSolution, res, permutation); | | detail::inverseRowPermutation(permutedSolution, res, permutation); | |
| } | | } | |
|
| return (unsigned int)rank; | | return static_cast<unsigned int>(rank); | |
| } | | } | |
| | | | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| unsigned int linearSolveQR(MultiArrayView<2, T, C1> const & A, MultiArrayVi
ew<2, T, C2> const & b, | | unsigned int linearSolveQR(MultiArrayView<2, T, C1> const & A, MultiArrayVi
ew<2, T, C2> const & b, | |
| MultiArrayView<2, T, C3> & res) | | MultiArrayView<2, T, C3> & res) | |
| { | | { | |
| Matrix<T> r(A), rhs(b); | | Matrix<T> r(A), rhs(b); | |
| return linearSolveQRReplace(r, rhs, res); | | return linearSolveQRReplace(r, rhs, res); | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 711 | | skipping to change at line 712 | |
| /** Create the inverse or pseudo-inverse of matrix \a v. | | /** Create the inverse or pseudo-inverse of matrix \a v. | |
| | | | |
| If the matrix \a v is square, \a res must have the same shape and w
ill contain the | | If the matrix \a v is square, \a res must have the same shape and w
ill contain the | |
| inverse of \a v. If \a v is rectangular, \a res must have the trans
posed shape | | inverse of \a v. If \a v is rectangular, \a res must have the trans
posed shape | |
| of \a v. The inverse is then computed in the least-squares | | of \a v. The inverse is then computed in the least-squares | |
| sense, i.e. \a res will be the pseudo-inverse (Moore-Penrose invers
e). | | sense, i.e. \a res will be the pseudo-inverse (Moore-Penrose invers
e). | |
| The function returns <tt>true</tt> upon success, and <tt>false</tt>
if \a v | | The function returns <tt>true</tt> upon success, and <tt>false</tt>
if \a v | |
| is not invertible (has not full rank). The inverse is computed by m
eans of QR | | is not invertible (has not full rank). The inverse is computed by m
eans of QR | |
| decomposition. This function can be applied in-place. | | decomposition. This function can be applied in-place. | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| bool inverse(const MultiArrayView<2, T, C1> &v, MultiArrayView<2, T, C2> &r
es) | | bool inverse(const MultiArrayView<2, T, C1> &v, MultiArrayView<2, T, C2> &r
es) | |
| { | | { | |
| typedef typename MultiArrayShape<2>::type Shape; | | typedef typename MultiArrayShape<2>::type Shape; | |
| | | | |
| const MultiArrayIndex n = columnCount(v); | | const MultiArrayIndex n = columnCount(v); | |
| const MultiArrayIndex m = rowCount(v); | | const MultiArrayIndex m = rowCount(v); | |
| vigra_precondition(n == rowCount(res) && m == columnCount(res), | | vigra_precondition(n == rowCount(res) && m == columnCount(res), | |
| | | | |
| skipping to change at line 765 | | skipping to change at line 766 | |
| is not invertible, <tt>vigra::PreconditionViolation</tt> exception
is thrown. | | is not invertible, <tt>vigra::PreconditionViolation</tt> exception
is thrown. | |
| Usage: | | Usage: | |
| | | | |
| \code | | \code | |
| vigra::Matrix<double> v(n, n); | | vigra::Matrix<double> v(n, n); | |
| v = ...; | | v = ...; | |
| | | | |
| vigra::Matrix<double> m = inverse(v); | | vigra::Matrix<double> m = inverse(v); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| TemporaryMatrix<T> inverse(const MultiArrayView<2, T, C> &v) | | TemporaryMatrix<T> inverse(const MultiArrayView<2, T, C> &v) | |
| { | | { | |
| TemporaryMatrix<T> ret(columnCount(v), rowCount(v)); // transpose shap
e | | TemporaryMatrix<T> ret(columnCount(v), rowCount(v)); // transpose shap
e | |
| vigra_precondition(inverse(v, ret), | | vigra_precondition(inverse(v, ret), | |
| "inverse(): matrix is not invertible."); | | "inverse(): matrix is not invertible."); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| skipping to change at line 808 | | skipping to change at line 809 | |
| \a method must be one of the following: | | \a method must be one of the following: | |
| <DL> | | <DL> | |
| <DT>"Cholesky"<DD> Compute the solution by means of Cholesky decomp
osition. This | | <DT>"Cholesky"<DD> Compute the solution by means of Cholesky decomp
osition. This | |
| method is faster than "LU", but requires the mat
rix \a a | | method is faster than "LU", but requires the mat
rix \a a | |
| to be symmetric positive definite. If this is | | to be symmetric positive definite. If this is | |
| not the case, a <tt>ContractViolation</tt> excep
tion is thrown. | | not the case, a <tt>ContractViolation</tt> excep
tion is thrown. | |
| | | | |
| <DT>"LU"<DD> (default) Compute the solution by means of LU decompos
ition. | | <DT>"LU"<DD> (default) Compute the solution by means of LU decompos
ition. | |
| </DL> | | </DL> | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1> | | template <class T, class C1> | |
| T determinant(MultiArrayView<2, T, C1> const & a, std::string method = "LU"
) | | T determinant(MultiArrayView<2, T, C1> const & a, std::string method = "LU"
) | |
| { | | { | |
| MultiArrayIndex n = columnCount(a); | | MultiArrayIndex n = columnCount(a); | |
| vigra_precondition(rowCount(a) == n, | | vigra_precondition(rowCount(a) == n, | |
| "determinant(): Square matrix required."); | | "determinant(): Square matrix required."); | |
| | | | |
| method = tolower(method); | | method = tolower(method); | |
| | | | |
| skipping to change at line 851 | | skipping to change at line 852 | |
| vigra_precondition(false, "determinant(): Unknown solution method."
); | | vigra_precondition(false, "determinant(): Unknown solution method."
); | |
| } | | } | |
| return T(); | | return T(); | |
| } | | } | |
| | | | |
| /** Compute the logarithm of the determinant of a symmetric positive de
finite matrix. | | /** Compute the logarithm of the determinant of a symmetric positive de
finite matrix. | |
| | | | |
| This is useful to avoid multiplication of very large numbers in big
matrices. | | This is useful to avoid multiplication of very large numbers in big
matrices. | |
| It is implemented by means of Cholesky decomposition. | | It is implemented by means of Cholesky decomposition. | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1> | | template <class T, class C1> | |
| T logDeterminant(MultiArrayView<2, T, C1> const & a) | | T logDeterminant(MultiArrayView<2, T, C1> const & a) | |
| { | | { | |
| MultiArrayIndex n = columnCount(a); | | MultiArrayIndex n = columnCount(a); | |
| vigra_precondition(rowCount(a) == n, | | vigra_precondition(rowCount(a) == n, | |
| "logDeterminant(): Square matrix required."); | | "logDeterminant(): Square matrix required."); | |
| if(n == 1) | | if(n == 1) | |
| { | | { | |
| | | | |
| skipping to change at line 899 | | skipping to change at line 900 | |
| triangular matrix, such that (up to round-off errors): | | triangular matrix, such that (up to round-off errors): | |
| | | | |
| \code | | \code | |
| A == L * transpose(L); | | A == L * transpose(L); | |
| \endcode | | \endcode | |
| | | | |
| This implementation cannot be applied in-place, i.e. <tt>&L == &A</
tt> is an error. | | This implementation cannot be applied in-place, i.e. <tt>&L == &A</
tt> is an error. | |
| If \a A is not symmetric, a <tt>ContractViolation</tt> exception is
thrown. If it | | If \a A is not symmetric, a <tt>ContractViolation</tt> exception is
thrown. If it | |
| is not positive definite, the function returns <tt>false</tt>. | | is not positive definite, the function returns <tt>false</tt>. | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| bool choleskyDecomposition(MultiArrayView<2, T, C1> const & A, | | bool choleskyDecomposition(MultiArrayView<2, T, C1> const & A, | |
| MultiArrayView<2, T, C2> &L) | | MultiArrayView<2, T, C2> &L) | |
| { | | { | |
| MultiArrayIndex n = columnCount(A); | | MultiArrayIndex n = columnCount(A); | |
| vigra_precondition(rowCount(A) == n, | | vigra_precondition(rowCount(A) == n, | |
| "choleskyDecomposition(): Input matrix must be squar
e."); | | "choleskyDecomposition(): Input matrix must be squar
e."); | |
| vigra_precondition(n == columnCount(L) && n == rowCount(L), | | vigra_precondition(n == columnCount(L) && n == rowCount(L), | |
| | | | |
| skipping to change at line 954 | | skipping to change at line 955 | |
| (up to round-off errors): | | (up to round-off errors): | |
| | | | |
| \code | | \code | |
| a == q * r; | | a == q * r; | |
| \endcode | | \endcode | |
| | | | |
| If \a a doesn't have full rank, the function returns <tt>false</tt>
. | | If \a a doesn't have full rank, the function returns <tt>false</tt>
. | |
| The decomposition is computed by householder transformations. It ca
n be applied in-place, | | The decomposition is computed by householder transformations. It ca
n be applied in-place, | |
| i.e. <tt>&a == &q</tt> or <tt>&a == &r</tt> are allowed. | | i.e. <tt>&a == &q</tt> or <tt>&a == &r</tt> are allowed. | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| bool qrDecomposition(MultiArrayView<2, T, C1> const & a, | | bool qrDecomposition(MultiArrayView<2, T, C1> const & a, | |
| MultiArrayView<2, T, C2> &q, MultiArrayView<2, T, C3>
&r, | | MultiArrayView<2, T, C2> &q, MultiArrayView<2, T, C3>
&r, | |
| double epsilon = 0.0) | | double epsilon = 0.0) | |
| { | | { | |
| const MultiArrayIndex m = rowCount(a); | | const MultiArrayIndex m = rowCount(a); | |
| const MultiArrayIndex n = columnCount(a); | | const MultiArrayIndex n = columnCount(a); | |
| vigra_precondition(n == columnCount(r) && m == rowCount(r) && | | vigra_precondition(n == columnCount(r) && m == rowCount(r) && | |
| m == columnCount(q) && m == rowCount(q), | | m == columnCount(q) && m == rowCount(q), | |
| "qrDecomposition(): Matrix shape mismatch."); | | "qrDecomposition(): Matrix shape mismatch."); | |
| | | | |
| q = identityMatrix<T>(m); | | q = identityMatrix<T>(m); | |
| MultiArrayView<2,T, StridedArrayTag> tq = transpose(q); | | MultiArrayView<2,T, StridedArrayTag> tq = transpose(q); | |
| r = a; | | r = a; | |
| ArrayVector<MultiArrayIndex> noPivoting; // intentionally empty | | ArrayVector<MultiArrayIndex> noPivoting; // intentionally empty | |
|
| return ((MultiArrayIndex)detail::qrTransformToUpperTriangular(r, tq, no
Pivoting, epsilon) == std::min(m,n)); | | return (static_cast<MultiArrayIndex>(detail::qrTransformToUpperTriangul
ar(r, tq, noPivoting, epsilon) == std::min(m,n))); | |
| } | | } | |
| | | | |
| /** Deprecated, use \ref linearSolveUpperTriangular(). | | /** Deprecated, use \ref linearSolveUpperTriangular(). | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| inline | | inline | |
| bool reverseElimination(const MultiArrayView<2, T, C1> &r, const MultiArray
View<2, T, C2> &b, | | bool reverseElimination(const MultiArrayView<2, T, C1> &r, const MultiArray
View<2, T, C2> &b, | |
| MultiArrayView<2, T, C3> x) | | MultiArrayView<2, T, C3> x) | |
| { | | { | |
| return linearSolveUpperTriangular(r, b, x); | | return linearSolveUpperTriangular(r, b, x); | |
| | | | |
| skipping to change at line 1006 | | skipping to change at line 1007 | |
| columns of \a b. This implementation can be applied in-place, i.e.
<tt>&b == &x</tt> is allowed. | | columns of \a b. This implementation can be applied in-place, i.e.
<tt>&b == &x</tt> is allowed. | |
| The following size requirements apply: | | The following size requirements apply: | |
| | | | |
| \code | | \code | |
| rowCount(r) == columnCount(r); | | rowCount(r) == columnCount(r); | |
| rowCount(r) == rowCount(b); | | rowCount(r) == rowCount(b); | |
| columnCount(r) == rowCount(x); | | columnCount(r) == rowCount(x); | |
| columnCount(b) == columnCount(x); | | columnCount(b) == columnCount(x); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| bool linearSolveUpperTriangular(const MultiArrayView<2, T, C1> &r, const Mu
ltiArrayView<2, T, C2> &b, | | bool linearSolveUpperTriangular(const MultiArrayView<2, T, C1> &r, const Mu
ltiArrayView<2, T, C2> &b, | |
| MultiArrayView<2, T, C3> x) | | MultiArrayView<2, T, C3> x) | |
| { | | { | |
|
| typedef MultiArrayShape<2>::type Shape; | | | |
| MultiArrayIndex m = rowCount(r); | | MultiArrayIndex m = rowCount(r); | |
| MultiArrayIndex rhsCount = columnCount(b); | | MultiArrayIndex rhsCount = columnCount(b); | |
| vigra_precondition(m == columnCount(r), | | vigra_precondition(m == columnCount(r), | |
| "linearSolveUpperTriangular(): square coefficient matrix required."
); | | "linearSolveUpperTriangular(): square coefficient matrix required."
); | |
| vigra_precondition(m == rowCount(b) && m == rowCount(x) && rhsCount ==
columnCount(x), | | vigra_precondition(m == rowCount(b) && m == rowCount(x) && rhsCount ==
columnCount(x), | |
| "linearSolveUpperTriangular(): matrix shape mismatch."); | | "linearSolveUpperTriangular(): matrix shape mismatch."); | |
| | | | |
| for(MultiArrayIndex k = 0; k < rhsCount; ++k) | | for(MultiArrayIndex k = 0; k < rhsCount; ++k) | |
| { | | { | |
| for(int i=m-1; i>=0; --i) | | for(int i=m-1; i>=0; --i) | |
| | | | |
| skipping to change at line 1057 | | skipping to change at line 1057 | |
| columns of \a b. This implementation can be applied in-place, i.e.
<tt>&b == &x</tt> is allowed. | | columns of \a b. This implementation can be applied in-place, i.e.
<tt>&b == &x</tt> is allowed. | |
| The following size requirements apply: | | The following size requirements apply: | |
| | | | |
| \code | | \code | |
| rowCount(l) == columnCount(l); | | rowCount(l) == columnCount(l); | |
| rowCount(l) == rowCount(b); | | rowCount(l) == rowCount(b); | |
| columnCount(l) == rowCount(x); | | columnCount(l) == rowCount(x); | |
| columnCount(b) == columnCount(x); | | columnCount(b) == columnCount(x); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| bool linearSolveLowerTriangular(const MultiArrayView<2, T, C1> &l, const Mu
ltiArrayView<2, T, C2> &b, | | bool linearSolveLowerTriangular(const MultiArrayView<2, T, C1> &l, const Mu
ltiArrayView<2, T, C2> &b, | |
| MultiArrayView<2, T, C3> x) | | MultiArrayView<2, T, C3> x) | |
| { | | { | |
| MultiArrayIndex m = columnCount(l); | | MultiArrayIndex m = columnCount(l); | |
| MultiArrayIndex n = columnCount(b); | | MultiArrayIndex n = columnCount(b); | |
| vigra_precondition(m == rowCount(l), | | vigra_precondition(m == rowCount(l), | |
| "linearSolveLowerTriangular(): square coefficient matrix required."
); | | "linearSolveLowerTriangular(): square coefficient matrix required."
); | |
| | | | |
| skipping to change at line 1105 | | skipping to change at line 1105 | |
| columns of \a b. This implementation can be applied in-place, i.e.
<tt>&b == &x</tt> is allowed. | | columns of \a b. This implementation can be applied in-place, i.e.
<tt>&b == &x</tt> is allowed. | |
| The following size requirements apply: | | The following size requirements apply: | |
| | | | |
| \code | | \code | |
| rowCount(L) == columnCount(L); | | rowCount(L) == columnCount(L); | |
| rowCount(L) == rowCount(b); | | rowCount(L) == rowCount(b); | |
| columnCount(L) == rowCount(x); | | columnCount(L) == rowCount(x); | |
| columnCount(b) == columnCount(x); | | columnCount(b) == columnCount(x); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| inline | | inline | |
|
| void choleskySolve(MultiArrayView<2, T, C1> & L, MultiArrayView<2, T, C2> c
onst & b, MultiArrayView<2, T, C3> & x) | | void choleskySolve(MultiArrayView<2, T, C1> const & L, MultiArrayView<2, T,
C2> const & b, MultiArrayView<2, T, C3> & x) | |
| { | | { | |
| /* Solve L * y = b */ | | /* Solve L * y = b */ | |
| linearSolveLowerTriangular(L, b, x); | | linearSolveLowerTriangular(L, b, x); | |
| /* Solve L^T * x = y */ | | /* Solve L^T * x = y */ | |
| linearSolveUpperTriangular(transpose(L), x, x); | | linearSolveUpperTriangular(transpose(L), x, x); | |
| } | | } | |
| | | | |
| /** Solve a linear system. | | /** Solve a linear system. | |
| | | | |
|
| | | <b> Declarations:</b> | |
| | | | |
| | | \code | |
| | | // use MultiArrayViews for input and output | |
| | | template <class T, class C1, class C2, class C3> | |
| | | bool linearSolve(MultiArrayView<2, T, C1> const & A, | |
| | | MultiArrayView<2, T, C2> const & b, | |
| | | MultiArrayView<2, T, C3> res, | |
| | | std::string method = "QR"); | |
| | | | |
| | | // use TinyVector for RHS and result | |
| | | template <class T, class C1, int N> | |
| | | bool linearSolve(MultiArrayView<2, T, C1> const & A, | |
| | | TinyVector<T, N> const & b, | |
| | | TinyVector<T, N> & res, | |
| | | std::string method = "QR"); | |
| | | \endcode | |
| | | | |
| \a A is the coefficient matrix, and the column vectors | | \a A is the coefficient matrix, and the column vectors | |
| in \a b are the right-hand sides of the equation (so, several equat
ions | | in \a b are the right-hand sides of the equation (so, several equat
ions | |
| with the same coefficients can be solved in one go). The result is
returned | | with the same coefficients can be solved in one go). The result is
returned | |
| in \a res, whose columns contain the solutions for the correspondin
g | | in \a res, whose columns contain the solutions for the correspondin
g | |
| columns of \a b. The number of columns of \a A must equal the numbe
r of rows of | | columns of \a b. The number of columns of \a A must equal the numbe
r of rows of | |
| both \a b and \a res, and the number of columns of \a b and \a res
must match. | | both \a b and \a res, and the number of columns of \a b and \a res
must match. | |
|
| | | If right-hand-side and result are specified as TinyVector, the numb | |
| | | er of columns | |
| | | of \a A must equal N. | |
| | | | |
| \a method must be one of the following: | | \a method must be one of the following: | |
| <DL> | | <DL> | |
| <DT>"Cholesky"<DD> Compute the solution by means of Cholesky decomp
osition. The | | <DT>"Cholesky"<DD> Compute the solution by means of Cholesky decomp
osition. The | |
| coefficient matrix \a A must by symmetric positi
ve definite. If | | coefficient matrix \a A must by symmetric positi
ve definite. If | |
| this is not the case, the function returns <tt>f
alse</tt>. | | this is not the case, the function returns <tt>f
alse</tt>. | |
| | | | |
| <DT>"QR"<DD> (default) Compute the solution by means of QR decompos
ition. The | | <DT>"QR"<DD> (default) Compute the solution by means of QR decompos
ition. The | |
| coefficient matrix \a A can be square or rectang
ular. In the latter case, | | coefficient matrix \a A can be square or rectang
ular. In the latter case, | |
| it must have more rows than columns, and the sol
ution will be computed in the | | it must have more rows than columns, and the sol
ution will be computed in the | |
| | | | |
| skipping to change at line 1164 | | skipping to change at line 1184 | |
| (provided they have the required shapes). | | (provided they have the required shapes). | |
| | | | |
| The following size requirements apply: | | The following size requirements apply: | |
| | | | |
| \code | | \code | |
| rowCount(r) == rowCount(b); | | rowCount(r) == rowCount(b); | |
| columnCount(r) == rowCount(x); | | columnCount(r) == rowCount(x); | |
| columnCount(b) == columnCount(x); | | columnCount(b) == columnCount(x); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | | <b>\#include</b> \<vigra/linear_solve.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
|
| | | doxygen_overloaded_function(template <...> bool linearSolve) | |
| | | | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
|
| bool linearSolve(const MultiArrayView<2, T, C1> &A, const MultiArrayView<2, | | bool linearSolve(MultiArrayView<2, T, C1> const & A, | |
| T, C2> &b, | | MultiArrayView<2, T, C2> const & b, | |
| MultiArrayView<2, T, C3> & res, std::string method = "QR") | | MultiArrayView<2, T, C3> res, | |
| | | std::string method = "QR") | |
| { | | { | |
|
| typedef typename Matrix<T>::difference_type Shape; | | | |
| typedef typename Matrix<T>::view_type SubMatrix; | | | |
| | | | |
| const MultiArrayIndex n = columnCount(A); | | const MultiArrayIndex n = columnCount(A); | |
| const MultiArrayIndex m = rowCount(A); | | const MultiArrayIndex m = rowCount(A); | |
| | | | |
| vigra_precondition(n <= m, | | vigra_precondition(n <= m, | |
| "linearSolve(): Coefficient matrix A must have at least as many row
s as columns."); | | "linearSolve(): Coefficient matrix A must have at least as many row
s as columns."); | |
| vigra_precondition(n == rowCount(res) && | | vigra_precondition(n == rowCount(res) && | |
| m == rowCount(b) && columnCount(b) == columnCount(re
s), | | m == rowCount(b) && columnCount(b) == columnCount(re
s), | |
| "linearSolve(): matrix shape mismatch."); | | "linearSolve(): matrix shape mismatch."); | |
| | | | |
| method = tolower(method); | | method = tolower(method); | |
| | | | |
| skipping to change at line 1196 | | skipping to change at line 1217 | |
| { | | { | |
| vigra_precondition(columnCount(A) == rowCount(A), | | vigra_precondition(columnCount(A) == rowCount(A), | |
| "linearSolve(): Cholesky method requires square coefficient mat
rix."); | | "linearSolve(): Cholesky method requires square coefficient mat
rix."); | |
| Matrix<T> L(A.shape()); | | Matrix<T> L(A.shape()); | |
| if(!choleskyDecomposition(A, L)) | | if(!choleskyDecomposition(A, L)) | |
| return false; // false if A wasn't symmetric positive definite | | return false; // false if A wasn't symmetric positive definite | |
| choleskySolve(L, b, res); | | choleskySolve(L, b, res); | |
| } | | } | |
| else if(method == "qr") | | else if(method == "qr") | |
| { | | { | |
|
| return (MultiArrayIndex)linearSolveQR(A, b, res) == n; | | return static_cast<MultiArrayIndex>(linearSolveQR(A, b, res)) == n; | |
| } | | } | |
| else if(method == "ne") | | else if(method == "ne") | |
| { | | { | |
| return linearSolve(transpose(A)*A, transpose(A)*b, res, "Cholesky")
; | | return linearSolve(transpose(A)*A, transpose(A)*b, res, "Cholesky")
; | |
| } | | } | |
| else if(method == "svd") | | else if(method == "svd") | |
| { | | { | |
| MultiArrayIndex rhsCount = columnCount(b); | | MultiArrayIndex rhsCount = columnCount(b); | |
| Matrix<T> u(A.shape()), s(n, 1), v(n, n); | | Matrix<T> u(A.shape()), s(n, 1), v(n, n); | |
| | | | |
|
| MultiArrayIndex rank = (MultiArrayIndex)singularValueDecomposition(
A, u, s, v); | | MultiArrayIndex rank = static_cast<MultiArrayIndex>(singularValueDe
composition(A, u, s, v)); | |
| | | | |
| Matrix<T> t = transpose(u)*b; | | Matrix<T> t = transpose(u)*b; | |
| for(MultiArrayIndex l=0; l<rhsCount; ++l) | | for(MultiArrayIndex l=0; l<rhsCount; ++l) | |
| { | | { | |
| for(MultiArrayIndex k=0; k<rank; ++k) | | for(MultiArrayIndex k=0; k<rank; ++k) | |
| t(k,l) /= s(k,0); | | t(k,l) /= s(k,0); | |
| for(MultiArrayIndex k=rank; k<n; ++k) | | for(MultiArrayIndex k=rank; k<n; ++k) | |
| t(k,l) = NumericTraits<T>::zero(); | | t(k,l) = NumericTraits<T>::zero(); | |
| } | | } | |
| res = v*t; | | res = v*t; | |
| | | | |
| return (rank == n); | | return (rank == n); | |
| } | | } | |
| else | | else | |
| { | | { | |
| vigra_precondition(false, "linearSolve(): Unknown solution method."
); | | vigra_precondition(false, "linearSolve(): Unknown solution method."
); | |
| } | | } | |
| return true; | | return true; | |
| } | | } | |
| | | | |
|
| | | template <class T, class C1, int N> | |
| | | bool linearSolve(MultiArrayView<2, T, C1> const & A, | |
| | | TinyVector<T, N> const & b, | |
| | | TinyVector<T, N> & res, | |
| | | std::string method = "QR") | |
| | | { | |
| | | Shape2 shape(N, 1); | |
| | | return linearSolve(A, MultiArrayView<2, T>(shape, b.data()), MultiArray | |
| | | View<2, T>(shape, res.data()), method); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace linalg | | } // namespace linalg | |
| | | | |
| using linalg::inverse; | | using linalg::inverse; | |
| using linalg::determinant; | | using linalg::determinant; | |
| using linalg::logDeterminant; | | using linalg::logDeterminant; | |
| using linalg::linearSolve; | | using linalg::linearSolve; | |
| using linalg::choleskySolve; | | using linalg::choleskySolve; | |
| using linalg::choleskyDecomposition; | | using linalg::choleskyDecomposition; | |
| | | | |
End of changes. 36 change blocks. |
| 48 lines changed or deleted | | 81 lines changed or added | |
|
| localminmax.hxx | | localminmax.hxx | |
| | | | |
| skipping to change at line 48 | | skipping to change at line 48 | |
| | | | |
| #include <vector> | | #include <vector> | |
| #include <functional> | | #include <functional> | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "stdimage.hxx" | | #include "stdimage.hxx" | |
| #include "initimage.hxx" | | #include "initimage.hxx" | |
| #include "labelimage.hxx" | | #include "labelimage.hxx" | |
| #include "labelvolume.hxx" | | #include "labelvolume.hxx" | |
| #include "pixelneighborhood.hxx" | | #include "pixelneighborhood.hxx" | |
| #include "voxelneighborhood.hxx" | | #include "voxelneighborhood.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra | | namespace vigra | |
| { | | { | |
| | | | |
| /** \addtogroup LocalMinMax Local Minima and Maxima | | /** \addtogroup LocalMinMax Local Minima and Maxima | |
| | | | |
| Detect local minima and maxima in a gray level image, | | Detect local minima and maxima in a gray level image, | |
| including extremal plateaus larger than 1 pixel | | including extremal plateaus larger than 1 pixel | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| skipping to change at line 195 | | skipping to change at line 196 | |
| bool allowExtremaAtBorder = false) | | bool allowExtremaAtBorder = false) | |
| { | | { | |
| int w = shp[0]; | | int w = shp[0]; | |
| int h = shp[1]; | | int h = shp[1]; | |
| int d = shp[2]; | | int d = shp[2]; | |
| | | | |
| int x, y, z; | | int x, y, z; | |
| | | | |
| if (allowExtremaAtBorder) | | if (allowExtremaAtBorder) | |
| { | | { | |
|
| throw std::runtime_error("not implemented!"); | | throw std::runtime_error("Not implemented (use localMinima() or loc | |
| /* | | alMaxima() instead)."); | |
| SrcIterator is = sul; | | | |
| DestIterator id = dul; | | | |
| | | | |
| for(x=0; x<w; ++x, ++is.x, ++id.x) | | | |
| { | | | |
| if(isLocalExtremum(is, sa, neighborhood, threshold, compare, | | | |
| isAtImageBorder(x, 0, w, h))) | | | |
| da.set(marker, id); | | | |
| } | | | |
| | | | |
| is = sul + Diff2D(0,1); | | | |
| id = dul + Diff2D(0,1); | | | |
| | | | |
| for(y=1; y<h-1; ++y, ++is.y, ++id.y) | | | |
| { | | | |
| if(isLocalExtremum(is, sa, neighborhood, threshold, compare, | | | |
| isAtImageBorder(0, y, w, h))) | | | |
| da.set(marker, id); | | | |
| } | | | |
| | | | |
| is = sul + Diff2D(w-1,1); | | | |
| id = dul + Diff2D(w-1,1); | | | |
| | | | |
| for(y=1; y<h-1; ++y, ++is.y, ++id.y) | | | |
| { | | | |
| if(isLocalExtremum(is, sa, neighborhood, threshold, compare, | | | |
| isAtImageBorder(w-1, y, w, h))) | | | |
| da.set(marker, id); | | | |
| } | | | |
| | | | |
| is = sul + Diff2D(0,h-1); | | | |
| id = dul + Diff2D(0,h-1); | | | |
| | | | |
| for(x=0; x<w; ++x, ++is.x, ++id.x) | | | |
| { | | | |
| if(isLocalExtremum(is, sa, neighborhood, threshold, compare, | | | |
| isAtImageBorder(x, h-1, w, h))) | | | |
| da.set(marker, id); | | | |
| } | | | |
| */ | | | |
| } | | } | |
| | | | |
| w -= 2; | | w -= 2; | |
| h -= 2; | | h -= 2; | |
| d -= 2; | | d -= 2; | |
| sul.dim0() += 1; | | sul.dim0() += 1; | |
| sul.dim1() += 1; | | sul.dim1() += 1; | |
| sul.dim2() += 1; | | sul.dim2() += 1; | |
| dul += Diff3D(1, 1, 1); | | dul += Diff3D(1, 1, 1); | |
| | | | |
| | | | |
| skipping to change at line 512 | | skipping to change at line 472 | |
| | | | |
| for (x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0(), ++xl.dim0()) | | for (x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0(), ++xl.dim0()) | |
| { | | { | |
| if(isExtremum[*xl]) | | if(isExtremum[*xl]) | |
| da.set(marker, xd); | | da.set(marker, xd); | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
|
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor, class DestValue, | | | |
| class Neighborhood, class Compare, class Equal> | | | |
| void | | | |
| extendedLocalMinMaxOld(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | | |
| DestIterator dul, DestAccessor da, DestValue marker, | | | |
| Neighborhood /*neighborhood*/, | | | |
| Compare compare, Equal equal, | | | |
| typename SrcAccessor::value_type threshold, | | | |
| bool allowExtremaAtBorder = false) | | | |
| { | | | |
| typedef typename SrcAccessor::value_type SrcType; | | | |
| | | | |
| int w = slr.x - sul.x; | | | |
| int h = slr.y - sul.y; | | | |
| | | | |
| int i,x,y; | | | |
| | | | |
| BasicImage<int> labels(w,h); | | | |
| | | | |
| int number_of_regions = | | | |
| labelImage(sul, slr, sa, labels.upperLeft(), labels.accessor(), | | | |
| (Neighborhood::DirectionCount == 8), equal); | | | |
| | | | |
| // assume that a region is a extremum until the opposite is proved | | | |
| std::vector<unsigned char> isExtremum(number_of_regions+1, (unsigned ch | | | |
| ar)1); | | | |
| | | | |
| BasicImage<int>::traverser ly = labels.upperLeft(); | | | |
| | | | |
| for(y=0; y<h; ++y, ++sul.y, ++ly.y) | | | |
| { | | | |
| SrcIterator sx = sul; | | | |
| BasicImage<int>::traverser lx(ly); | | | |
| | | | |
| for(x=0; x<w; ++x, ++sx.x, ++lx.x) | | | |
| { | | | |
| int lab = *lx; | | | |
| SrcType v = sa(sx); | | | |
| if(x == 0 || y == 0 || x == w-1 || y == h-1 || !compare(v, thre | | | |
| shold)) | | | |
| { | | | |
| // mark all regions that touch the image border as non-extr | | | |
| emum | | | |
| // likewise for all pixels that don't exceed the threshold | | | |
| isExtremum[lab] = 0; | | | |
| continue; | | | |
| } | | | |
| | | | |
| NeighborhoodCirculator<SrcIterator, Neighborhood> sc(sx); | | | |
| NeighborhoodCirculator<BasicImage<int>::traverser, Neighborhood | | | |
| > lc(lx); | | | |
| for(i=0; i<Neighborhood::DirectionCount; ++i, ++sc, ++lc) | | | |
| { | | | |
| if(lab != *lc && compare(sa(sc),v)) | | | |
| isExtremum[lab] = 0; | | | |
| } | | | |
| | | | |
| } | | | |
| } | | | |
| | | | |
| ly = labels.upperLeft(); | | | |
| for(y=0; y<h; ++y, ++dul.y, ++ly.y) | | | |
| { | | | |
| DestIterator xd = dul; | | | |
| BasicImage<int>::Iterator lx(ly); | | | |
| | | | |
| for(x=0; x<w; ++x, ++xd.x, ++lx.x) | | | |
| { | | | |
| if(isExtremum[*lx]) | | | |
| da.set(marker, xd); | | | |
| } | | | |
| } | | | |
| } | | | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| /** \brief Options object for localMinima() and localMaxima(). | | /** \brief Options object for localMinima() and localMaxima(). | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/localminmax.hxx\><br> | | <b>\#include</b> \<vigra/localminmax.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| vigra::BImage src(w,h), minima(w,h); | | MultiArray<2, unsigned char> src(w,h), minima(w,h); | |
| ... // fill src | | ... // fill src | |
| | | | |
| // use 4-neighborhood, allow minima at the image border, | | // use 4-neighborhood, allow minima at the image border, | |
| // and discard those where the gray value is not below 5 | | // and discard those where the gray value is not below 5 | |
|
| vigra::localMinima(srcImageRange(src), destImage(minima), | | localMinima(src, minima, | |
| vigra::LocalMinmaxOptions().neighborhood(4).allowAtB | | LocalMinmaxOptions().neighborhood(4).allowAtBorder().thresh | |
| order().threshold(5)); | | old(5)); | |
| | | | |
| \endcode | | \endcode | |
| */ | | */ | |
| class LocalMinmaxOptions | | class LocalMinmaxOptions | |
| { | | { | |
| public: | | public: | |
| double marker, thresh; | | double marker, thresh; | |
| int neigh; | | int neigh; | |
| bool use_threshold, allow_at_border, allow_plateaus; | | bool use_threshold, allow_at_border, allow_plateaus; | |
| | | | |
| | | | |
| skipping to change at line 629 | | skipping to change at line 518 | |
| use_threshold(false), | | use_threshold(false), | |
| allow_at_border(false), | | allow_at_border(false), | |
| allow_plateaus(false) | | allow_plateaus(false) | |
| {} | | {} | |
| | | | |
| /**\brief Use the given neighborhood. | | /**\brief Use the given neighborhood. | |
| | | | |
| The value '0' indicates direct neighborhood (i.e. 4-neighborhoo
d | | The value '0' indicates direct neighborhood (i.e. 4-neighborhoo
d | |
| in 2D, 6-neighborhood in 3D, 2*N neighborhood in N-D), the valu
e '1' | | in 2D, 6-neighborhood in 3D, 2*N neighborhood in N-D), the valu
e '1' | |
| indicates indirect neighborhood (i.e. 8-neighborhood in 2D, | | indicates indirect neighborhood (i.e. 8-neighborhood in 2D, | |
|
| 26-neighborhood in 3D, 3<sup>N</sup>-1 neighborhood in N-D). Th | | 26-neighborhood in 3D, 3<sup>N</sup>-1 neighborhood in N-D). Th | |
| e specific number | | e appropriate | |
| of neighbors for the desired dimension can also be used. | | number of neighbors for the desired dimension and the constants | |
| | | <tt>DirectNeighborhood</tt> and <tt>IndirectNeighborhood</tt> c | |
| | | an be used as well. | |
| | | | |
| Default: 1 (indirect neighborhood) | | Default: 1 (indirect neighborhood) | |
| */ | | */ | |
| LocalMinmaxOptions & neighborhood(unsigned int n) | | LocalMinmaxOptions & neighborhood(unsigned int n) | |
| { | | { | |
| neigh = n; | | neigh = n; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| | | LocalMinmaxOptions & neighborhood(NeighborhoodType n) | |
| | | { | |
| | | neigh = n; | |
| | | return *this; | |
| | | } | |
| | | | |
| /**\brief Mark extrema in the destination image with the given valu
e. | | /**\brief Mark extrema in the destination image with the given valu
e. | |
| | | | |
| Default: 1 | | Default: 1 | |
| */ | | */ | |
| LocalMinmaxOptions & markWith(double m) | | LocalMinmaxOptions & markWith(double m) | |
| { | | { | |
| marker = m; | | marker = m; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 696 | | skipping to change at line 592 | |
| }; | | }; | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* localMinima */ | | /* localMinima */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find local minima in an image or multi-dimensional array. | | /** \brief Find local minima in an image or multi-dimensional array. | |
| | | | |
|
| Note: the function is not yet implemented for arbitrary dimensional | | | |
| arrays, but see \ref localMinima3D() for 3D. | | | |
| | | | |
| By default, minima are defined as points which are not | | By default, minima are defined as points which are not | |
| at the array border and whose value is lower than the value | | at the array border and whose value is lower than the value | |
| of all indirect neighbors (i.e. 8-neighbors in 2D, | | of all indirect neighbors (i.e. 8-neighbors in 2D, | |
| 26-neighbors in 3D, 3<sup>N</sup>-1 neighbors in N-D). | | 26-neighbors in 3D, 3<sup>N</sup>-1 neighbors in N-D). | |
| The detected points will be marked | | The detected points will be marked | |
| with the default value 1 in the destination array. | | with the default value 1 in the destination array. | |
| | | | |
| The defaults can be overridden in various ways by providing | | The defaults can be overridden in various ways by providing | |
| \ref LocalMinmaxOptions : you can switch to the direct neighborhood | | \ref LocalMinmaxOptions : you can switch to the direct neighborhood | |
| (i.e. 4-neighborhood in 2D, 6-neighborhood in 3D, 2*N neighborhood | | (i.e. 4-neighborhood in 2D, 6-neighborhood in 3D, 2*N neighborhood | |
| | | | |
| skipping to change at line 733 | | skipping to change at line 626 | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <unsigned int N, class T1, class C1, class T2, class C2> | | template <unsigned int N, class T1, class C1, class T2, class C2> | |
| void | | void | |
| localMinima(MultiArrayView<N, T1, C1> src, | | localMinima(MultiArrayView<N, T1, C1> src, | |
| MultiArrayView<N, T2, C2> dest, | | MultiArrayView<N, T2, C2> dest, | |
| LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | | LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
|
| pass image iterators explicitly: | | \deprecatedAPI{localMinima} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | | LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | | LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/localminmax.hxx\><br> | | <b>\#include</b> \<vigra/localminmax.hxx\><br> | |
| <b>\#include</b> \<vigra/multi_localminmax.hxx\><br> | | <b>\#include</b> \<vigra/multi_localminmax.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| // 3D examples using MultiArray | | // 3D examples (other dimensions work likewise) | |
| vigra::MultiArrayShape<3>::type shape(w,h,d); | | Shape3 shape(w,h,d); | |
| vigra::MultiArray<3, unsigned char> src(shape), minima(shape); | | MultiArray<3, unsigned char> src(shape), minima(shape); | |
| ... // fill src | | ... // fill src | |
| | | | |
| // use default parameterisation | | // use default parameterisation | |
|
| vigra::localMinima(src, minima); | | localMinima(src, minima); | |
| | | | |
| // reset destination image | | // reset destination image | |
| minima = 0; | | minima = 0; | |
| | | | |
|
| // use 6-neighborhood and allow minima at the image border | | // use direct neighborhood (i.e. 6-neighborhood since we are in 3D) | |
| vigra::localMinima(src, minima, | | // and allow minima at the image border | |
| vigra::LocalMinmaxOptions().neighborhood(6).allowAtB | | localMinima(src, minima, | |
| order()); | | LocalMinmaxOptions().neighborhood(0).allowAtBorder()); | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{localMinima} | |
| \code | | \code | |
| // 2D examples using BasicImage | | // 2D examples using BasicImage | |
|
| vigra::BImage src(w,h), minima(w,h); | | BImage src(w,h), minima(w,h); | |
| ... // fill src | | ... // fill src | |
| | | | |
| // use default parameterisation | | // use default parameterisation | |
|
| vigra::localMinima(srcImageRange(src), destImage(minima)); | | localMinima(srcImageRange(src), destImage(minima)); | |
| | | | |
| // reset destination image | | // reset destination image | |
| minima = 0; | | minima = 0; | |
| | | | |
| // use 4-neighborhood and allow minima at the image border | | // use 4-neighborhood and allow minima at the image border | |
|
| vigra::localMinima(srcImageRange(src), destImage(minima), | | localMinima(srcImageRange(src), destImage(minima), | |
| vigra::LocalMinmaxOptions().neighborhood(4).allowAtB | | LocalMinmaxOptions().neighborhood(4).allowAtBorder() | |
| order()); | | ); | |
| | | | |
| // reset destination image | | // reset destination image | |
| minima = 0; | | minima = 0; | |
| | | | |
| // allow extended minima (minimal plateaus) and use value '255' as a ma
rker | | // allow extended minima (minimal plateaus) and use value '255' as a ma
rker | |
|
| vigra::localMinima(srcImageRange(src), destImage(minima), | | localMinima(srcImageRange(src), destImage(minima), | |
| vigra::LocalMinmaxOptions().allowPlateaus().markWith | | LocalMinmaxOptions().allowPlateaus().markWith(255)); | |
| (255)); | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcIterator src_upperleft, src_lowerright; | | SrcIterator src_upperleft, src_lowerright; | |
| DestIterator dest_upperleft; | | DestIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| u < u | | u < u | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void localMinima) | | doxygen_overloaded_function(template <...> void localMinima) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| LocalMinmaxOptions const & options = LocalMinmaxOptions()) | | LocalMinmaxOptions const & options = LocalMinmaxOptions()) | |
| { | | { | |
| | | | |
| skipping to change at line 961 | | skipping to change at line 856 | |
| /**************************************************************************
/ | | /**************************************************************************
/ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* localMinima3D */ | | /* localMinima3D */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find local minima in a 3D multi array. | | /** \brief Find local minima in a 3D multi array. | |
| | | | |
|
| By default, minima are defined as points which are not | | Deprecated, use localMinima() instead. | |
| at the array border and whose value is lower than the value | | | |
| of all indirect neighbors. | | | |
| The detected points will be marked. See localMinima() for more details. | | | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void localMinima3D) | | doxygen_overloaded_function(template <...> void localMinima3D) | |
| | | | |
| template<class SrcIterator, class SrcAccessor, class SrcShape, | | template<class SrcIterator, class SrcAccessor, class SrcShape, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| inline void | | inline void | |
| localMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa, | | localMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| DestValue marker, | | DestValue marker, | |
| | | | |
| skipping to change at line 1014 | | skipping to change at line 906 | |
| | | | |
| template<class SrcIterator, class SrcShape, class SrcAccessor, | | template<class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| inline void | | inline void | |
| localMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src, | | localMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue marker, | | DestValue marker, | |
| NeighborCode3DSix neighborhood) | | NeighborCode3DSix neighborhood) | |
| { | | { | |
| localMinima3D(src.first, src.second, src.third, dest.first, dest.second
, | | localMinima3D(src.first, src.second, src.third, dest.first, dest.second
, | |
|
| marker, neighborhood); | | marker, neighborhood); | |
| } | | } | |
| | | | |
| template<class SrcIterator, class SrcShape, class SrcAccessor, | | template<class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| inline void | | inline void | |
| localMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src, | | localMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue marker, | | DestValue marker, | |
| NeighborCode3DTwentySix neighborhood) | | NeighborCode3DTwentySix neighborhood) | |
| { | | { | |
| localMinima3D(src.first, src.second, src.third, dest.first, dest.second
, | | localMinima3D(src.first, src.second, src.third, dest.first, dest.second
, | |
|
| marker, neighborhood); | | marker, neighborhood); | |
| | | } | |
| | | | |
| | | template<class T1, class S1, | |
| | | class T2, class S2, | |
| | | class DestValue, | |
| | | class Neighborhood> | |
| | | inline void | |
| | | localMinima3D(MultiArrayView<3, T1, S1> const & src, | |
| | | MultiArrayView<3, T2, S2> dest, | |
| | | DestValue marker, | |
| | | Neighborhood neighborhood) | |
| | | { | |
| | | localMinima3D(srcMultiArrayRange(src), destMultiArray(dest), | |
| | | marker, neighborhood); | |
| | | } | |
| | | | |
| | | template<class T1, class S1, | |
| | | class T2, class S2, | |
| | | class DestValue> | |
| | | inline void | |
| | | localMinima3D(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | DestValue marker) | |
| | | { | |
| | | localMinima3D(srcMultiArrayRange(src), destMultiArray(dest), | |
| | | marker, NeighborCode3DSix()); | |
| } | | } | |
| | | | |
| /**************************************************************************
/ | | /**************************************************************************
/ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* localMaxima */ | | /* localMaxima */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find local maxima in an image or multi-dimensional array. | | /** \brief Find local maxima in an image or multi-dimensional array. | |
| | | | |
|
| Note: the function is not yet implemented for arbitrary dimensional | | | |
| arrays, but see \ref localMaxima3D() for 3D. | | | |
| | | | |
| By default, maxima are defined as points which are not | | By default, maxima are defined as points which are not | |
| at the array border and whose value is higher than the value | | at the array border and whose value is higher than the value | |
| of all indirect neighbors (i.e. 8-neighbors in 2D, | | of all indirect neighbors (i.e. 8-neighbors in 2D, | |
| 26-neighbors in 3D, 3<sup>N</sup>-1 neighbors in N-D). | | 26-neighbors in 3D, 3<sup>N</sup>-1 neighbors in N-D). | |
| The detected points will be marked | | The detected points will be marked | |
| with the default value 1 in the destination array. | | with the default value 1 in the destination array. | |
| | | | |
| The defaults can be overridden in various ways by providing | | The defaults can be overridden in various ways by providing | |
| \ref LocalMinmaxOptions : you can switch to the direct neighborhood | | \ref LocalMinmaxOptions : you can switch to the direct neighborhood | |
| (i.e. 4-neighborhood in 2D, 6-neighborhood in 3D, 2*N neighborhood | | (i.e. 4-neighborhood in 2D, 6-neighborhood in 3D, 2*N neighborhood | |
| | | | |
| skipping to change at line 1076 | | skipping to change at line 991 | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <unsigned int N, class T1, class C1, class T2, class C2> | | template <unsigned int N, class T1, class C1, class T2, class C2> | |
| void | | void | |
| localMaxima(MultiArrayView<N, T1, C1> src, | | localMaxima(MultiArrayView<N, T1, C1> src, | |
| MultiArrayView<N, T2, C2> dest, | | MultiArrayView<N, T2, C2> dest, | |
| LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | | LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
|
| pass image iterators explicitly: | | \deprecatedAPI{localMaxima} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | | LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | | LocalMinmaxOptions const & options = LocalMinmaxOptions
()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/localminmax.hxx\><br> | | <b>\#include</b> \<vigra/localminmax.hxx\><br> | |
| <b>\#include</b> \<vigra/multi_localminmax.hxx\><br> | | <b>\#include</b> \<vigra/multi_localminmax.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| // 3D examples using MultiArray | | // 3D examples (other dimensions work likewise) | |
| vigra::MultiArrayShape<3>::type shape(w,h,d); | | Shape3 shape(w,h,d); | |
| vigra::MultiArray<3, unsigned char> src(shape), maxima(shape); | | MultiArray<3, unsigned char> src(shape), maxima(shape); | |
| ... // fill src | | ... // fill src | |
| | | | |
| // use default parameterisation | | // use default parameterisation | |
|
| vigra::localMaxima(src, maxima); | | localMaxima(src, maxima); | |
| | | | |
| // reset destination image | | // reset destination image | |
| maxima = 0; | | maxima = 0; | |
| | | | |
|
| // use 6-neighborhood and allow maxima at the image border | | // use direct neighborhood (i.e. 6-neighborhood sine we are in 3D) | |
| vigra::localMaxima(src, maxima, | | // and allow maxima at the image border | |
| vigra::LocalMinmaxOptions().neighborhood(6).allowAtB | | localMaxima(src, maxima, | |
| order()); | | LocalMinmaxOptions().neighborhood(0).allowAtBorder()); | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{localMaxima} | |
| \code | | \code | |
| // 2D examples using BasicImage | | // 2D examples using BasicImage | |
|
| vigra::BImage src(w,h), maxima(w,h); | | BImage src(w,h), maxima(w,h); | |
| ... // fill src | | ... // fill src | |
| | | | |
| // use default parameterisation | | // use default parameterisation | |
|
| vigra::localMaxima(srcImageRange(src), destImage(maxima)); | | localMaxima(srcImageRange(src), destImage(maxima)); | |
| | | | |
| // reset destination image | | // reset destination image | |
| maxima = 0; | | maxima = 0; | |
| | | | |
| // use 4-neighborhood and allow maxima at the image border | | // use 4-neighborhood and allow maxima at the image border | |
|
| vigra::localMaxima(srcImageRange(src), destImage(maxima), | | localMaxima(srcImageRange(src), destImage(maxima), | |
| vigra::LocalMinmaxOptions().neighborhood(4).allowAtB | | LocalMinmaxOptions().neighborhood(4).allowAtBorder() | |
| order()); | | ); | |
| | | | |
| // reset destination image | | // reset destination image | |
| maxima = 0; | | maxima = 0; | |
| | | | |
| // allow extended maxima (maximal plateaus) and use value '255' as a ma
rker | | // allow extended maxima (maximal plateaus) and use value '255' as a ma
rker | |
|
| vigra::localMaxima(srcImageRange(src), destImage(maxima), | | localMaxima(srcImageRange(src), destImage(maxima), | |
| vigra::LocalMinmaxOptions().allowPlateaus().markWith | | LocalMinmaxOptions().allowPlateaus().markWith(255)); | |
| (255)); | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcIterator src_upperleft, src_lowerright; | | SrcIterator src_upperleft, src_lowerright; | |
| DestIterator dest_upperleft; | | DestIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| u < u | | u < u | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void localMaxima) | | doxygen_overloaded_function(template <...> void localMaxima) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| LocalMinmaxOptions const & options = LocalMinmaxOptions()) | | LocalMinmaxOptions const & options = LocalMinmaxOptions()) | |
| { | | { | |
| | | | |
| skipping to change at line 1303 | | skipping to change at line 1220 | |
| /**************************************************************************
/ | | /**************************************************************************
/ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* localMaxima3D */ | | /* localMaxima3D */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find local maxima in a 3D multi array. | | /** \brief Find local maxima in a 3D multi array. | |
| | | | |
|
| By default, maxima are defined as points which are not | | Deprecated, use \ref localMaxima() instead. | |
| at the array border and whose value is higher than the value | | | |
| of all indirect neighbors. | | | |
| The detected points will be marked as specified. See localMaxima() for mor | | | |
| details. | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void localMaxima3D) | | doxygen_overloaded_function(template <...> void localMaxima3D) | |
| | | | |
| template<class SrcIterator, class SrcShape, class SrcAccessor, | | template<class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| inline void | | inline void | |
| localMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa, | | localMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| DestValue marker, | | DestValue marker, | |
| NeighborCode3DSix neighborhood) | | NeighborCode3DSix neighborhood) | |
| | | | |
| skipping to change at line 1351 | | skipping to change at line 1265 | |
| DestValue marker, | | DestValue marker, | |
| NeighborCode3DTwentySix neighborhood) | | NeighborCode3DTwentySix neighborhood) | |
| { | | { | |
| localMaxima3D(src.first, src.second, src.third, dest.first, dest.second
, | | localMaxima3D(src.first, src.second, src.third, dest.first, dest.second
, | |
| marker, neighborhood); | | marker, neighborhood); | |
| } | | } | |
| | | | |
| template<class SrcIterator, class SrcShape, class SrcAccessor, | | template<class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| inline void | | inline void | |
|
| localMaxima3D(vigra::triple<SrcIterator, SrcShape, SrcAccessor> src, | | localMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> src, | |
| std::pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue marker) | | DestValue marker) | |
| { | | { | |
| localMaxima3D(src.first, src.second, src.third, dest.first, dest.second
, | | localMaxima3D(src.first, src.second, src.third, dest.first, dest.second
, | |
| marker, NeighborCode3DSix()); | | marker, NeighborCode3DSix()); | |
| } | | } | |
| | | | |
| template<class SrcIterator, class SrcShape, class SrcAccessor, | | template<class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class DestValue> | | class DestIterator, class DestAccessor, class DestValue> | |
| inline void | | inline void | |
| localMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> src, | | localMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue marker, | | DestValue marker, | |
| NeighborCode3DSix neighborhood) | | NeighborCode3DSix neighborhood) | |
| { | | { | |
| localMaxima3D(src.first, src.second, src.third, dest.first, dest.second
, | | localMaxima3D(src.first, src.second, src.third, dest.first, dest.second
, | |
| marker, neighborhood); | | marker, neighborhood); | |
| } | | } | |
| | | | |
|
| | | template<class T1, class S1, | |
| | | class T2, class S2, | |
| | | class DestValue, | |
| | | class Neighborhood> | |
| | | inline void | |
| | | localMaxima3D(MultiArrayView<3, T1, S1> const & src, | |
| | | MultiArrayView<3, T2, S2> dest, | |
| | | DestValue marker, | |
| | | Neighborhood neighborhood) | |
| | | { | |
| | | localMaxima3D(srcMultiArrayRange(src), destMultiArray(dest), | |
| | | marker, neighborhood); | |
| | | } | |
| | | | |
| | | template<class T1, class S1, | |
| | | class T2, class S2, | |
| | | class DestValue> | |
| | | inline void | |
| | | localMaxima3D(MultiArrayView<3, T1, S1> const & src, | |
| | | MultiArrayView<3, T2, S2> dest, | |
| | | DestValue marker) | |
| | | { | |
| | | localMaxima3D(srcMultiArrayRange(src), destMultiArray(dest), | |
| | | marker, NeighborCode3DSix()); | |
| | | } | |
| | | | |
| /**************************************************************************
/ | | /**************************************************************************
/ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* extendedLocalMinima */ | | /* extendedLocalMinima */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
|
| /** \brief Find local minimal regions in an image or volume. | | /** \brief Find local minimal regions (plateaus) in an array. | |
| | | | |
|
| Note: the function is not yet implemented for arbitrary dimensional | | This function is only needed when you want to pass a non-standard equal | |
| arrays, but see \ref extendedLocalMinima3D() for 3D. | | ity | |
| | | predicate via <tt>EqualityFunctor</tt>. Otherwise (i.e. when equality | |
| This function finds regions of uniform pixel value | | is defined by the '==' operator of the source value type <tt>T1</tt>), | |
| whose neighboring regions are all have smaller values | | you can simply call \ref localMinima() with the option | |
| (minimal plateaus of arbitrary size). By default, the pixels | | <tt>LocalMinmaxOptions::allowPlateaus()</tt>. | |
| in a plateau have exactly identical values. By passing an <tt>EqualityF | | | |
| unctor</tt> | | This function finds regions of uniform pixel values | |
| with tolerance, one can allow for plateaus that are not quite constant | | whose neighboring regions all have larger values, i.e. it finds minimal | |
| (this is often necessary with float pixel values). Pass | | plateaus of arbitrary size (including size 1). The <tt>EqualityFunctor< | |
| \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode | | /tt> | |
| to determine the neighborhood where pixel values are compared. | | determines when pixels are considered equal, so that one can allow | |
| | | for plateaus that are not quite constant (this is often necessary | |
| Minimal regions are | | with float pixel values). Otherwise, the functionality is identical to | |
| marked in the destination image with the given marker value | | \ref localMinima(). | |
| (default is 1), all other destination pixels remain unchanged. | | | |
| <TT>SrcAccessor::value_type</TT> must be equality-comparable and | | | |
| less-comparable. A pixel or region touching the image border will | | | |
| never be marked as minimum or minimal plateau. Use localMinima() with t | | | |
| he | | | |
| appropriate options if you need that functionality. Likewise if you wan | | | |
| t to | | | |
| apply a threshold onl the fly. In fact, all functionality | | | |
| except for 'equality with tolerance' can be accessed via that function | | | |
| in | | | |
| a more readable way, so localMinima() should be preferred. | | | |
| The function uses accessors. | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| use 3-dimensional arrays: | | use arbitrary-dimensional arrays: | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| template <class T1, class C1, class T2, class C2, | | template <unsigned int N, class T1, class S1, | |
| class Neighborhood> | | class T2, class S2, | |
| void | | class EqualityFunctor> | |
| extendedLocalMinima(MultiArrayView<3, T1, C1> src, | | unsigned int | |
| MultiArrayView<3, T2, C2> dest, | | extendedLocalMinima(MultiArrayView<N, T1, S1> const & src, | |
| LocalMinmaxOptions const & options = LocalMinma | | MultiArrayView<N, T2, S2> dest, | |
| xOptions()); | | EqualityFunctor const & equal, | |
| | | LocalMinmaxOptions options = LocalMinmaxOptions | |
| | | ()); | |
| \endcode | | \endcode | |
| | | | |
|
| pass image iterators explicitly: | | \deprecatedAPI{extendedLocalMinima} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class DestValue = DestAccessor::value_type, | | class DestValue = DestAccessor::value_type, | |
| class Neighborhood = EightNeighborCode, | | class Neighborhood = EightNeighborCode, | |
| class EqualityFunctor = std::equal_to<typename SrcAssesso
r::value_type> > | | class EqualityFunctor = std::equal_to<typename SrcAssesso
r::value_type> > | |
| void | | void | |
| extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor s
a, | | extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor s
a, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| DestValue marker = NumericTraits<DestValue>::on
e(), | | DestValue marker = NumericTraits<DestValue>::on
e(), | |
| Neighborhood neighborhood = EightNeighborCode()
, | | Neighborhood neighborhood = EightNeighborCode()
, | |
| EqualityFunctor equal = EqualityFunctor()); | | EqualityFunctor equal = EqualityFunctor()); | |
|
| | | | |
| | | template<class SrcIterator, class SrcShape, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood = NeighborCode3DSix, | |
| | | class EqualityFunctor = std::equal_to<typename SrcAssessor | |
| | | ::value_type> > | |
| | | void | |
| | | extendedLocalMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa | |
| | | , | |
| | | DestIterator dul, DestAccessor da, | |
| | | typename DestAccessor::value_type marker, | |
| | | Neighborhood neighborhood = Neighborhood(), | |
| | | EqualityFunctor equal = EqualityFunctor()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class DestValue = DestAccessor::value_type, | | class DestValue = DestAccessor::value_type, | |
| class Neighborhood = EightNeighborCode, | | class Neighborhood = EightNeighborCode, | |
| class EqualityFunctor = std::equal_to<typename SrcAssesso
r::value_type> > | | class EqualityFunctor = std::equal_to<typename SrcAssesso
r::value_type> > | |
| void | | void | |
| extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | | extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue marker = NumericTraits<DestValue>::on
e(), | | DestValue marker = NumericTraits<DestValue>::on
e(), | |
| Neighborhood neighborhood = EightNeighborCode()
, | | Neighborhood neighborhood = EightNeighborCode()
, | |
| EqualityFunctor equal = EqualityFunctor()); | | EqualityFunctor equal = EqualityFunctor()); | |
|
| | | | |
| | | template<class SrcIterator, class SrcAccessor, class SrcShape, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood> | |
| | | void | |
| | | extendedLocalMinima3D(triple<SrcIterator, SrcShape, SrcAccessor> sr | |
| | | c, | |
| | | pair<DestIterator, DestAccessor> dest, | |
| | | typename DestAccessor::value_type marker, | |
| | | Neighborhood neighborhood); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/localminmax.hxx\><br> | | <b>\#include</b> \<vigra/localminmax.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | // define an equality functor | |
| | | template <class T> | |
| | | struct EqualWithToleranceFunctor | |
| | | { | |
| | | EqualWithToleranceFunctor(T tolerance) | |
| | | : t(tolerance) | |
| | | {} | |
| | | | |
|
| | | bool operator()(T l, T r) const | |
| | | { | |
| | | return abs(l-r) <= t; | |
| | | } | |
| | | | |
| | | T t; | |
| | | }; | |
| | | | |
| | | MultiArray<2, unsigned char> src(w,h), minima(w,h); | |
| | | | |
| | | // allow plateaus | |
| | | localMinima(src, minima, LocalMinmaxOptions().allowPlateaus()); | |
| | | | |
| | | // reset result image | |
| | | minima.init(0); | |
| | | // allow plateaus with tolerance (grayvalues may differ by one) | |
| | | extendedLocalMinima(src, minima, EqualWithToleranceFunctor<unsigned cha | |
| | | r>(1)); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{extendedLocalMinima} | |
| | | \code | |
| // optional: define an equality functor | | // optional: define an equality functor | |
| template <class T> | | template <class T> | |
| struct EqualWithToleranceFunctor | | struct EqualWithToleranceFunctor | |
| { | | { | |
| EqualWithToleranceFunctor(T tolerance) | | EqualWithToleranceFunctor(T tolerance) | |
| : t(tolerance) | | : t(tolerance) | |
| {} | | {} | |
| | | | |
| bool operator()(T l, T r) const | | bool operator()(T l, T r) const | |
| { | | { | |
|
| return vigra::abs(l-r) <= t; | | return abs(l-r) <= t; | |
| } | | } | |
| | | | |
| T t; | | T t; | |
| }; | | }; | |
| | | | |
|
| vigra::BImage src(w,h), minima(w,h); | | BImage src(w,h), minima(w,h); | |
| | | | |
| // init destiniation image | | // init destiniation image | |
| minima.init(0); | | minima.init(0); | |
| | | | |
|
| vigra::extendedLocalMinima(srcImageRange(src), destImage(minima)); | | extendedLocalMinima(srcImageRange(src), destImage(minima)); | |
| | | | |
| // allow plateaus with tolerance | | // allow plateaus with tolerance | |
| minima.init(0); | | minima.init(0); | |
|
| vigra::extendedLocalMinima(srcImageRange(src), destImage(minima), 1.0, | | extendedLocalMinima(srcImageRange(src), destImage(minima), 1.0, | |
| | | FourNeighborCode(), | |
| EqualWithToleranceFunctor<unsigned char>(1))
; | | EqualWithToleranceFunctor<unsigned char>(1))
; | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| EqualityFunctor equal; | | EqualityFunctor equal; | |
| u == u | | u == u | |
| equal(u, u); | | equal(u, u); | |
| u < u | | u < u | |
| | | | |
| DestValue marker; | | DestValue marker; | |
| dest_accessor.set(marker, dest_upperleft); | | dest_accessor.set(marker, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void extendedLocalMinima) | | doxygen_overloaded_function(template <...> void extendedLocalMinima) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood, class EqualityFunctor> | | class Neighborhood, class EqualityFunctor> | |
| inline void | | inline void | |
| extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| typename DestAccessor::value_type marker, | | typename DestAccessor::value_type marker, | |
| | | | |
| skipping to change at line 1550 | | skipping to change at line 1530 | |
| marker, neighborhood, std::equal_to<SrcType>()); | | marker, neighborhood, std::equal_to<SrcType>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| typename DestAccessor::value_type marker) | | typename DestAccessor::value_type marker) | |
| { | | { | |
|
| typedef typename SrcAccessor::value_type SrcType; | | | |
| | | | |
| extendedLocalMinima(sul, slr, sa, dul, da, | | extendedLocalMinima(sul, slr, sa, dul, da, | |
| marker, EightNeighborCode()); | | marker, EightNeighborCode()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da) | | DestIterator dul, DestAccessor da) | |
| { | | { | |
| | | | |
| skipping to change at line 1622 | | skipping to change at line 1600 | |
| /**************************************************************************
/ | | /**************************************************************************
/ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* extendedLocalMinima3D */ | | /* extendedLocalMinima3D */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find local minimal regions in a volume. | | /** \brief Find local minimal regions in a volume. | |
| | | | |
|
| This function finds regions of uniform pixel value | | See \ref extendedLocalMinima(). | |
| whose neighboring regions are all have smaller values | | | |
| (minimal plateaus of arbitrary size). By default, the pixels | | | |
| in a plateau have exactly identical values. By passing an <tt>EqualityFunc | | | |
| tor</tt> | | | |
| with tolerance, one can allow for plateaus that are not quite constant | | | |
| (this is often necessary with float pixel values). Pass the neighborhood | | | |
| where pixel values are compared. See extendedLocalMinima() for more detail | | | |
| s. | | | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void extendedLocalMinima3D) | | doxygen_overloaded_function(template <...> void extendedLocalMinima3D) | |
| | | | |
| template<class SrcIterator, class SrcShape, class SrcAccessor, | | template<class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class Neighborhood, | | class DestIterator, class DestAccessor, class Neighborhood, | |
| class EqualityFunctor> | | class EqualityFunctor> | |
| inline void | | inline void | |
| extendedLocalMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa, | | extendedLocalMinima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| | | | |
| skipping to change at line 1696 | | skipping to change at line 1668 | |
| } | | } | |
| | | | |
| /**************************************************************************
/ | | /**************************************************************************
/ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* extendedLocalMaxima */ | | /* extendedLocalMaxima */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
|
| /** \brief Find local maximal regions in an image or volume. | | /** \brief Find local maximal regions in an array. | |
| | | | |
| Note: the function is not yet implemented for arbitrary dimensional | | | |
| arrays, but see \ref extendedLocalMaxima3D() for 3D. | | | |
| | | | |
|
| This function finds regions of uniform pixel value | | This function is only needed when you want to pass a non-standard equal | |
| whose neighboring regions are all have smaller values | | ity | |
| (maximal plateaus of arbitrary size). By default, the pixels | | predicate via <tt>EqualityFunctor</tt>. Otherwise (i.e. when equality | |
| in a plateau have exactly identical values. By passing an <tt>EqualityF | | is defined by the '==' operator of the source value type <tt>T1</tt>), | |
| unctor</tt> | | you can simply call \ref localMaxima() with the option | |
| with tolerance, one can allow for plateaus that are not quite constant | | <tt>LocalMinmaxOptions::allowPlateaus()</tt>. | |
| (this is often necessary with float pixel values). Pass | | | |
| \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode | | This function finds regions of uniform pixel values | |
| to determine the neighborhood where pixel values are compared. | | whose neighboring regions all have smaller values, i.e. it finds maxima | |
| | | l | |
| Maximal regions are | | plateaus of arbitrary size (including size 1). The <tt>EqualityFunctor< | |
| marked in the destination image with the given marker value | | /tt> | |
| (default is 1), all other destination pixels remain unchanged. | | determines when pixels are considered equal, so that one can allow | |
| <TT>SrcAccessor::value_type</TT> must be equality-comparable and | | for plateaus that are not quite constant (this is often necessary | |
| less-comparable. A pixel or region touching the image border will | | with float pixel values). Otherwise, the functionality is identical to | |
| never be marked as maximum or maximal plateau. Use localMaxima() with t | | \ref localMaxima(). | |
| he | | | |
| appropriate options if you need that functionality. Likewise if you wan | | | |
| t to | | | |
| apply a threshold onl the fly. In fact, all functionality | | | |
| except for 'equality with tolerance' can be accessed via that function | | | |
| in | | | |
| a more readable way, so localMaxima() should be preferred. | | | |
| The function uses accessors. | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| use 3-dimensional arrays: | | use arbitrary-dimensional arrays: | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| template <class T1, class C1, class T2, class C2, | | template <unsigned int N, class T1, class S1, | |
| class Neighborhood> | | class T2, class S2> | |
| void | | unsigned int // return number of maxima | |
| extendedLocalMaxima(MultiArrayView<3, T1, C1> src, | | extendedLocalMaxima(MultiArrayView<N, T1, S1> const & src, | |
| MultiArrayView<3, T2, C2> dest, | | MultiArrayView<N, T2, S2> dest, | |
| LocalMinmaxOptions const & options = LocalMinma | | LocalMinmaxOptions options = LocalMinmaxOptions | |
| xOptions()); | | ()); | |
| \endcode | | \endcode | |
| | | | |
|
| pass image iterators explicitly: | | \deprecatedAPI{extendedLocalMaxima} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class DestValue = DestAccessor::value_type, | | class DestValue = DestAccessor::value_type, | |
| class Neighborhood = EightNeighborCode, | | class Neighborhood = EightNeighborCode, | |
| class EqualityFunctor = std::equal_to<typename SrcAssesso
r::value_type> > | | class EqualityFunctor = std::equal_to<typename SrcAssesso
r::value_type> > | |
| void | | void | |
| extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor s
a, | | extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor s
a, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| DestValue marker = NumericTraits<DestValue>::on
e(), | | DestValue marker = NumericTraits<DestValue>::on
e(), | |
| Neighborhood neighborhood = EightNeighborCode()
, | | Neighborhood neighborhood = EightNeighborCode()
, | |
| EqualityFunctor equal = EqualityFunctor()) | | EqualityFunctor equal = EqualityFunctor()) | |
|
| | | | |
| | | template<class SrcIterator, class SrcShape, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood = NeighborCode3DSix, | |
| | | class EqualityFunctor = std::equal_to<typename SrcAssessor | |
| | | ::value_type> > | |
| | | void | |
| | | extendedLocalMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa | |
| | | , | |
| | | DestIterator dul, DestAccessor da, | |
| | | typename DestAccessor::value_type marker, | |
| | | Neighborhood neighborhood = Neighborhood(), | |
| | | EqualityFunctor equal = EqualityFunctor()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class DestValue = DestAccessor::value_type, | | class DestValue = DestAccessor::value_type, | |
| class Neighborhood = EightNeighborCode, | | class Neighborhood = EightNeighborCode, | |
| class EqualityFunctor = std::equal_to<typename SrcAssesso
r::value_type> > | | class EqualityFunctor = std::equal_to<typename SrcAssesso
r::value_type> > | |
| void | | void | |
| extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | | extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| DestValue marker = NumericTraits<DestValue>::on
e(), | | DestValue marker = NumericTraits<DestValue>::on
e(), | |
| Neighborhood neighborhood = EightNeighborCode()
, | | Neighborhood neighborhood = EightNeighborCode()
, | |
| EqualityFunctor equal = EqualityFunctor()) | | EqualityFunctor equal = EqualityFunctor()) | |
|
| | | | |
| | | template<class SrcIterator, class SrcAccessor, class SrcShape, | |
| | | class DestIterator, class DestAccessor, | |
| | | class Neighborhood> | |
| | | void | |
| | | extendedLocalMaxima3D(triple<SrcIterator, SrcShape, SrcAccessor> sr | |
| | | c, | |
| | | pair<DestIterator, DestAccessor> dest, | |
| | | typename DestAccessor::value_type marker, | |
| | | Neighborhood neighborhood); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/localminmax.hxx\><br> | | <b>\#include</b> \<vigra/localminmax.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | // define an equality functor | |
| | | template <class T> | |
| | | struct EqualWithToleranceFunctor | |
| | | { | |
| | | EqualWithToleranceFunctor(T tolerance) | |
| | | : t(tolerance) | |
| | | {} | |
| | | | |
| | | bool operator()(T l, T r) const | |
| | | { | |
| | | return abs(l-r) <= t; | |
| | | } | |
| | | | |
| | | T t; | |
| | | }; | |
| | | | |
| | | MultiArray<2, unsigned char> src(w,h), maxima(w,h); | |
| | | | |
| | | // allow plateaus | |
| | | localMaxima(src, maxima, LocalMinmaxOptions().allowPlateaus()); | |
| | | | |
| | | // reset result image | |
| | | maxima.init(0); | |
| | | // allow plateaus with tolerance (grayvalues may differ by one) | |
| | | extendedLocalMaxima(src, maxima, EqualWithToleranceFunctor<unsigned cha | |
| | | r>(1)); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{extendedLocalMaxima} | |
| | | \code | |
| | | | |
| // optional: define an equality functor | | // optional: define an equality functor | |
| template <class T> | | template <class T> | |
| struct EqualWithToleranceFunctor | | struct EqualWithToleranceFunctor | |
| { | | { | |
| EqualWithToleranceFunctor(T tolerance) | | EqualWithToleranceFunctor(T tolerance) | |
| : t(tolerance) | | : t(tolerance) | |
| {} | | {} | |
| | | | |
| bool operator()(T l, T r) const | | bool operator()(T l, T r) const | |
| { | | { | |
|
| return vigra::abs(l-r) <= t; | | return abs(l-r) <= t; | |
| } | | } | |
| | | | |
| T t; | | T t; | |
| }; | | }; | |
| | | | |
|
| vigra::BImage src(w,h), maxima(w,h); | | BImage src(w,h), maxima(w,h); | |
| | | | |
| // init destiniation image | | // init destiniation image | |
| maxima.init(0); | | maxima.init(0); | |
| | | | |
|
| vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima)); | | extendedLocalMaxima(srcImageRange(src), destImage(maxima)); | |
| | | | |
| // allow plateaus with tolerance | | // allow plateaus with tolerance | |
| maxima.init(0); | | maxima.init(0); | |
|
| vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima), 1.0, | | extendedLocalMaxima(srcImageRange(src), destImage(maxima), 1.0, | |
| | | FourNeighborCode(), | |
| EqualWithToleranceFunctor<unsigned char>(1))
; | | EqualWithToleranceFunctor<unsigned char>(1))
; | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft; | | DestImageIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| SrcAccessor::value_type u = src_accessor(src_upperleft); | | SrcAccessor::value_type u = src_accessor(src_upperleft); | |
| | | | |
| EqualityFunctor equal; | | EqualityFunctor equal; | |
| u == u | | u == u | |
| equal(u, u); | | equal(u, u); | |
| u < u | | u < u | |
| | | | |
| DestValue marker; | | DestValue marker; | |
| dest_accessor.set(marker, dest_upperleft); | | dest_accessor.set(marker, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void extendedLocalMaxima) | | doxygen_overloaded_function(template <...> void extendedLocalMaxima) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood, class EqualityFunctor> | | class Neighborhood, class EqualityFunctor> | |
| inline void | | inline void | |
| extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| typename DestAccessor::value_type marker, | | typename DestAccessor::value_type marker, | |
| | | | |
| skipping to change at line 1867 | | skipping to change at line 1878 | |
| marker, neighborhood, std::equal_to<SrcType>()); | | marker, neighborhood, std::equal_to<SrcType>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| typename DestAccessor::value_type marker) | | typename DestAccessor::value_type marker) | |
| { | | { | |
|
| typedef typename SrcAccessor::value_type SrcType; | | | |
| | | | |
| extendedLocalMaxima(sul, slr, sa, dul, da, | | extendedLocalMaxima(sul, slr, sa, dul, da, | |
| marker, EightNeighborCode()); | | marker, EightNeighborCode()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | | extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da) | | DestIterator dul, DestAccessor da) | |
| { | | { | |
| | | | |
| skipping to change at line 1937 | | skipping to change at line 1946 | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* extendedLocalMaxima3D */ | | /* extendedLocalMaxima3D */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Find local maximal regions in 3D multi array. | | /** \brief Find local maximal regions in 3D multi array. | |
| | | | |
|
| This function finds regions of uniform pixel value | | See \ref extendedLocalMaxima(). | |
| whose neighboring regions are all have smaller values | | | |
| (maximal plateaus of arbitrary size). By default, the pixels | | | |
| in a plateau have exactly identical values. By passing an <tt>EqualityFunc | | | |
| tor</tt> | | | |
| with tolerance, one can allow for plateaus that are not quite constant | | | |
| (this is often necessary with float pixel values). Pass | | | |
| the neighborhood where pixel values are compared. See extendedLocalMaxima( | | | |
| ) for more details. | | | |
| */ | | */ | |
| | | | |
| doxygen_overloaded_function(template <...> void extendedLocalMaxima3D) | | doxygen_overloaded_function(template <...> void extendedLocalMaxima3D) | |
| | | | |
| template<class SrcIterator, class SrcShape, class SrcAccessor, | | template<class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class Neighborhood, | | class DestIterator, class DestAccessor, class Neighborhood, | |
| class EqualityFunctor> | | class EqualityFunctor> | |
| inline void | | inline void | |
| extendedLocalMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa, | | extendedLocalMaxima3D(SrcIterator sul, SrcShape slr, SrcAccessor sa, | |
| DestIterator dul, DestAccessor da, | | DestIterator dul, DestAccessor da, | |
| | | | |
End of changes. 85 change blocks. |
| 299 lines changed or deleted | | 296 lines changed or added | |
|
| mathutil.hxx | | mathutil.hxx | |
| | | | |
| skipping to change at line 53 | | skipping to change at line 53 | |
| #include <cmath> | | #include <cmath> | |
| #include <cstdlib> | | #include <cstdlib> | |
| #include <complex> | | #include <complex> | |
| #include "config.hxx" | | #include "config.hxx" | |
| #include "error.hxx" | | #include "error.hxx" | |
| #include "tuple.hxx" | | #include "tuple.hxx" | |
| #include "sized_int.hxx" | | #include "sized_int.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "algorithm.hxx" | | #include "algorithm.hxx" | |
| | | | |
|
| /*! \page MathConstants Mathematical Constants | | /** \page MathConstants Mathematical Constants | |
| | | | |
| <TT>M_PI, M_SQRT2 etc.</TT> | | <TT>M_PI, M_SQRT2 etc.</TT> | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\> | | <b>\#include</b> \<vigra/mathutil.hxx\> | |
| | | | |
| Since mathematical constants such as <TT>M_PI</TT> and <TT>M_SQRT2</TT> | | Since mathematical constants such as <TT>M_PI</TT> and <TT>M_SQRT2</TT> | |
| are not officially standardized, we provide definitions here for those | | are not officially standardized, we provide definitions here for those | |
| compilers that don't support them. | | compilers that don't support them. | |
| | | | |
| \code | | \code | |
| | | | |
| skipping to change at line 109 | | skipping to change at line 109 | |
| #endif | | #endif | |
| | | | |
| #ifndef M_PI_4 | | #ifndef M_PI_4 | |
| # define M_PI_4 0.78539816339744830962 | | # define M_PI_4 0.78539816339744830962 | |
| #endif | | #endif | |
| | | | |
| #ifndef M_SQRT2 | | #ifndef M_SQRT2 | |
| # define M_SQRT2 1.41421356237309504880 | | # define M_SQRT2 1.41421356237309504880 | |
| #endif | | #endif | |
| | | | |
|
| | | #ifndef M_E | |
| | | # define M_E 2.71828182845904523536 | |
| | | #endif | |
| | | | |
| #ifndef M_EULER_GAMMA | | #ifndef M_EULER_GAMMA | |
| # define M_EULER_GAMMA 0.5772156649015329 | | # define M_EULER_GAMMA 0.5772156649015329 | |
| #endif | | #endif | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup MathFunctions Mathematical Functions | | /** \addtogroup MathFunctions Mathematical Functions | |
| | | | |
| Useful mathematical functions and functors. | | Useful mathematical functions and functors. | |
| */ | | */ | |
| | | | |
| skipping to change at line 158 | | skipping to change at line 162 | |
| | | | |
| VIGRA_DEFINE_MISSING_ABS(signed char) | | VIGRA_DEFINE_MISSING_ABS(signed char) | |
| VIGRA_DEFINE_MISSING_ABS(signed short) | | VIGRA_DEFINE_MISSING_ABS(signed short) | |
| | | | |
| #if defined(_MSC_VER) && _MSC_VER < 1600 | | #if defined(_MSC_VER) && _MSC_VER < 1600 | |
| VIGRA_DEFINE_MISSING_ABS(signed long long) | | VIGRA_DEFINE_MISSING_ABS(signed long long) | |
| #endif | | #endif | |
| | | | |
| #undef VIGRA_DEFINE_MISSING_ABS | | #undef VIGRA_DEFINE_MISSING_ABS | |
| | | | |
|
| | | #ifndef _MSC_VER | |
| | | | |
| | | using std::isinf; | |
| | | using std::isnan; | |
| | | | |
| | | #else | |
| | | | |
| | | template <class REAL> | |
| | | inline bool isinf(REAL v) | |
| | | { | |
| | | return _finite(v) == 0; | |
| | | } | |
| | | | |
| | | template <class REAL> | |
| | | inline bool isnan(REAL v) | |
| | | { | |
| | | return _isnan(v) != 0; | |
| | | } | |
| | | | |
| | | #endif | |
| | | | |
| // scalar dot is needed for generic functions that should work with | | // scalar dot is needed for generic functions that should work with | |
| // scalars and vectors alike | | // scalars and vectors alike | |
| | | | |
| #define VIGRA_DEFINE_SCALAR_DOT(T) \ | | #define VIGRA_DEFINE_SCALAR_DOT(T) \ | |
| inline NumericTraits<T>::Promote dot(T l, T r) { return l*r; } | | inline NumericTraits<T>::Promote dot(T l, T r) { return l*r; } | |
| | | | |
| VIGRA_DEFINE_SCALAR_DOT(unsigned char) | | VIGRA_DEFINE_SCALAR_DOT(unsigned char) | |
| VIGRA_DEFINE_SCALAR_DOT(unsigned short) | | VIGRA_DEFINE_SCALAR_DOT(unsigned short) | |
| VIGRA_DEFINE_SCALAR_DOT(unsigned int) | | VIGRA_DEFINE_SCALAR_DOT(unsigned int) | |
| VIGRA_DEFINE_SCALAR_DOT(unsigned long) | | VIGRA_DEFINE_SCALAR_DOT(unsigned long) | |
| | | | |
| skipping to change at line 194 | | skipping to change at line 219 | |
| inline float pow(float v, double e) | | inline float pow(float v, double e) | |
| { | | { | |
| return std::pow(v, (float)e); | | return std::pow(v, (float)e); | |
| } | | } | |
| | | | |
| inline long double pow(long double v, double e) | | inline long double pow(long double v, double e) | |
| { | | { | |
| return std::pow(v, (long double)e); | | return std::pow(v, (long double)e); | |
| } | | } | |
| | | | |
|
| /*! The rounding function. | | /** \brief The rounding function. | |
| | | | |
| Defined for all floating point types. Rounds towards the nearest in
teger | | Defined for all floating point types. Rounds towards the nearest in
teger | |
| such that <tt>abs(round(t)) == round(abs(t))</tt> for all <tt>t</tt
>. | | such that <tt>abs(round(t)) == round(abs(t))</tt> for all <tt>t</tt
>. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| #ifdef DOXYGEN // only for documentation | | #ifdef DOXYGEN // only for documentation | |
| REAL round(REAL v); | | REAL round(REAL v); | |
| #endif | | #endif | |
| | | | |
| skipping to change at line 227 | | skipping to change at line 252 | |
| : ceil(t - 0.5); | | : ceil(t - 0.5); | |
| } | | } | |
| | | | |
| inline long double round(long double t) | | inline long double round(long double t) | |
| { | | { | |
| return t >= 0.0 | | return t >= 0.0 | |
| ? floor(t + 0.5) | | ? floor(t + 0.5) | |
| : ceil(t - 0.5); | | : ceil(t - 0.5); | |
| } | | } | |
| | | | |
|
| /*! Round and cast to integer. | | /** \brief Round and cast to integer. | |
| | | | |
| Rounds to the nearest integer like round(), but casts the result to | | Rounds to the nearest integer like round(), but casts the result to | |
| <tt>int</tt> (this will be faster and is usually needed anyway). | | <tt>int</tt> (this will be faster and is usually needed anyway). | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline int roundi(double t) | | inline int roundi(double t) | |
| { | | { | |
| return t >= 0.0 | | return t >= 0.0 | |
| ? int(t + 0.5) | | ? int(t + 0.5) | |
| : int(t - 0.5); | | : int(t - 0.5); | |
| } | | } | |
| | | | |
|
| /*! Round up to the nearest power of 2. | | /** \brief Round up to the nearest power of 2. | |
| | | | |
| Efficient algorithm for finding the smallest power of 2 which is no
t smaller than \a x | | Efficient algorithm for finding the smallest power of 2 which is no
t smaller than \a x | |
| (function clp2() from Henry Warren: "Hacker's Delight", Addison-Wes
ley, 2003, | | (function clp2() from Henry Warren: "Hacker's Delight", Addison-Wes
ley, 2003, | |
| see http://www.hackersdelight.org/). | | see http://www.hackersdelight.org/). | |
| If \a x > 2^31, the function will return 0 because integer arithmet
ic is defined modulo 2^32. | | If \a x > 2^31, the function will return 0 because integer arithmet
ic is defined modulo 2^32. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline UInt32 ceilPower2(UInt32 x) | | inline UInt32 ceilPower2(UInt32 x) | |
| | | | |
| skipping to change at line 265 | | skipping to change at line 290 | |
| | | | |
| x = x - 1; | | x = x - 1; | |
| x = x | (x >> 1); | | x = x | (x >> 1); | |
| x = x | (x >> 2); | | x = x | (x >> 2); | |
| x = x | (x >> 4); | | x = x | (x >> 4); | |
| x = x | (x >> 8); | | x = x | (x >> 8); | |
| x = x | (x >>16); | | x = x | (x >>16); | |
| return x + 1; | | return x + 1; | |
| } | | } | |
| | | | |
|
| /*! Round down to the nearest power of 2. | | /** \brief Round down to the nearest power of 2. | |
| | | | |
| Efficient algorithm for finding the largest power of 2 which is not
greater than \a x | | Efficient algorithm for finding the largest power of 2 which is not
greater than \a x | |
| (function flp2() from Henry Warren: "Hacker's Delight", Addison-Wes
ley, 2003, | | (function flp2() from Henry Warren: "Hacker's Delight", Addison-Wes
ley, 2003, | |
| see http://www.hackersdelight.org/). | | see http://www.hackersdelight.org/). | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline UInt32 floorPower2(UInt32 x) | | inline UInt32 floorPower2(UInt32 x) | |
| { | | { | |
| | | | |
| skipping to change at line 287 | | skipping to change at line 312 | |
| x = x | (x >> 2); | | x = x | (x >> 2); | |
| x = x | (x >> 4); | | x = x | (x >> 4); | |
| x = x | (x >> 8); | | x = x | (x >> 8); | |
| x = x | (x >>16); | | x = x | (x >>16); | |
| return x - (x >> 1); | | return x - (x >> 1); | |
| } | | } | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| template <class T> | | template <class T> | |
|
| class IntLog2 | | struct IntLog2 | |
| { | | { | |
|
| public: | | | |
| static Int32 table[64]; | | static Int32 table[64]; | |
| }; | | }; | |
| | | | |
| template <class T> | | template <class T> | |
| Int32 IntLog2<T>::table[64] = { | | Int32 IntLog2<T>::table[64] = { | |
| -1, 0, -1, 15, -1, 1, 28, -1, 16, -1, -1, -1, 2, 21, | | -1, 0, -1, 15, -1, 1, 28, -1, 16, -1, -1, -1, 2, 21, | |
| 29, -1, -1, -1, 19, 17, 10, -1, 12, -1, -1, 3, -1, 6, | | 29, -1, -1, -1, 19, 17, 10, -1, 12, -1, -1, 3, -1, 6, | |
| -1, 22, 30, -1, 14, -1, 27, -1, -1, -1, 20, -1, 18, 9
, | | -1, 22, 30, -1, 14, -1, 27, -1, -1, -1, 20, -1, 18, 9
, | |
| 11, -1, 5, -1, -1, 13, 26, -1, -1, 8, -1, 4, -1, 25, | | 11, -1, 5, -1, -1, 13, 26, -1, -1, 8, -1, 4, -1, 25, | |
| -1, 7, 24, -1, 23, -1, 31, -1}; | | -1, 7, 24, -1, 23, -1, 31, -1}; | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! Compute the base-2 logarithm of an integer. | | /** \brief Compute the base-2 logarithm of an integer. | |
| | | | |
| Returns the position of the left-most 1-bit in the given number \a
x, or | | Returns the position of the left-most 1-bit in the given number \a
x, or | |
| -1 if \a x == 0. That is, | | -1 if \a x == 0. That is, | |
| | | | |
| \code | | \code | |
| assert(k >= 0 && k < 32 && log2i(1 << k) == k); | | assert(k >= 0 && k < 32 && log2i(1 << k) == k); | |
| \endcode | | \endcode | |
| | | | |
| The function uses Robert Harley's algorithm to determine the number
of leading zeros | | The function uses Robert Harley's algorithm to determine the number
of leading zeros | |
| in \a x (algorithm nlz10() at http://www.hackersdelight.org/). But
note that the functions | | in \a x (algorithm nlz10() at http://www.hackersdelight.org/). But
note that the functions | |
| | | | |
| skipping to change at line 331 | | skipping to change at line 355 | |
| // Propagate leftmost 1-bit to the right. | | // Propagate leftmost 1-bit to the right. | |
| x = x | (x >> 1); | | x = x | (x >> 1); | |
| x = x | (x >> 2); | | x = x | (x >> 2); | |
| x = x | (x >> 4); | | x = x | (x >> 4); | |
| x = x | (x >> 8); | | x = x | (x >> 8); | |
| x = x | (x >>16); | | x = x | (x >>16); | |
| x = x*0x06EB14F9; // Multiplier is 7*255**3. | | x = x*0x06EB14F9; // Multiplier is 7*255**3. | |
| return detail::IntLog2<Int32>::table[x >> 26]; | | return detail::IntLog2<Int32>::table[x >> 26]; | |
| } | | } | |
| | | | |
|
| /*! The square function. | | /** \brief The square function. | |
| | | | |
| <tt>sq(x) = x*x</tt> is needed so often that it makes sense to defi
ne it as a function. | | <tt>sq(x) = x*x</tt> is needed so often that it makes sense to defi
ne it as a function. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T> | | template <class T> | |
| inline | | inline | |
| typename NumericTraits<T>::Promote sq(T t) | | typename NumericTraits<T>::Promote sq(T t) | |
| { | | { | |
| | | | |
| skipping to change at line 371 | | skipping to change at line 395 | |
| static V call(const V & x) | | static V call(const V & x) | |
| { | | { | |
| return n / 2 | | return n / 2 | |
| ? cond_mult<V, n & 1>::call(x, power_static<V, n / 2>::call(x *
x)) | | ? cond_mult<V, n & 1>::call(x, power_static<V, n / 2>::call(x *
x)) | |
| : n & 1 ? x : V(); | | : n & 1 ? x : V(); | |
| } | | } | |
| }; | | }; | |
| template <class V> | | template <class V> | |
| struct power_static<V, 0> | | struct power_static<V, 0> | |
| { | | { | |
|
| static V call(const V & x) | | static V call(const V & /* x */) | |
| { | | { | |
| return V(1); | | return V(1); | |
| } | | } | |
| }; | | }; | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! Exponentiation to a positive integer power by squaring. | | /** \brief Exponentiation to a positive integer power by squaring. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <unsigned n, class V> | | template <unsigned n, class V> | |
| inline V power(const V & x) | | inline V power(const V & x) | |
| { | | { | |
| return detail::power_static<V, n>::call(x); | | return detail::power_static<V, n>::call(x); | |
| } | | } | |
| //doxygen_overloaded_function(template <unsigned n, class V> power(const V
& x)) | | //doxygen_overloaded_function(template <unsigned n, class V> power(const V
& x)) | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| template <class T> | | template <class T> | |
|
| class IntSquareRoot | | struct IntSquareRoot | |
| { | | { | |
|
| public: | | | |
| static UInt32 sqq_table[]; | | static UInt32 sqq_table[]; | |
| static UInt32 exec(UInt32 v); | | static UInt32 exec(UInt32 v); | |
| }; | | }; | |
| | | | |
| template <class T> | | template <class T> | |
| UInt32 IntSquareRoot<T>::sqq_table[] = { | | UInt32 IntSquareRoot<T>::sqq_table[] = { | |
| 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55,
57, | | 0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55,
57, | |
| 59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81,
83, | | 59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81,
83, | |
| 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 1
02, | | 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 1
02, | |
| 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 1
18, | | 103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 1
18, | |
| | | | |
| skipping to change at line 490 | | skipping to change at line 513 | |
| if (xn * xn > x) /* Correct rounding if necessary */ | | if (xn * xn > x) /* Correct rounding if necessary */ | |
| xn--; | | xn--; | |
| | | | |
| return xn; | | return xn; | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| using VIGRA_CSTD::sqrt; | | using VIGRA_CSTD::sqrt; | |
| | | | |
|
| /*! Signed integer square root. | | /** \brief Signed integer square root. | |
| | | | |
| Useful for fast fixed-point computations. | | Useful for fast fixed-point computations. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline Int32 sqrti(Int32 v) | | inline Int32 sqrti(Int32 v) | |
| { | | { | |
| if(v < 0) | | if(v < 0) | |
| throw std::domain_error("sqrti(Int32): negative argument."); | | throw std::domain_error("sqrti(Int32): negative argument."); | |
| return (Int32)detail::IntSquareRoot<UInt32>::exec((UInt32)v); | | return (Int32)detail::IntSquareRoot<UInt32>::exec((UInt32)v); | |
| } | | } | |
| | | | |
|
| /*! Unsigned integer square root. | | /** \brief Unsigned integer square root. | |
| | | | |
| Useful for fast fixed-point computations. | | Useful for fast fixed-point computations. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline UInt32 sqrti(UInt32 v) | | inline UInt32 sqrti(UInt32 v) | |
| { | | { | |
| return detail::IntSquareRoot<UInt32>::exec(v); | | return detail::IntSquareRoot<UInt32>::exec(v); | |
| } | | } | |
| | | | |
| #ifdef VIGRA_NO_HYPOT | | #ifdef VIGRA_NO_HYPOT | |
|
| /*! Compute the Euclidean distance (length of the hypotenuse of a right
-angled triangle). | | /** \brief Compute the Euclidean distance (length of the hypotenuse of
a right-angled triangle). | |
| | | | |
| The hypot() function returns the sqrt(a*a + b*b). | | The hypot() function returns the sqrt(a*a + b*b). | |
| It is implemented in a way that minimizes round-off error. | | It is implemented in a way that minimizes round-off error. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline double hypot(double a, double b) | | inline double hypot(double a, double b) | |
| { | | { | |
| double absa = VIGRA_CSTD::fabs(a), absb = VIGRA_CSTD::fabs(b); | | double absa = VIGRA_CSTD::fabs(a), absb = VIGRA_CSTD::fabs(b); | |
| | | | |
| skipping to change at line 542 | | skipping to change at line 565 | |
| ? 0.0 | | ? 0.0 | |
| : absb * VIGRA_CSTD::sqrt(1.0 + sq(absa/absb)); | | : absb * VIGRA_CSTD::sqrt(1.0 + sq(absa/absb)); | |
| } | | } | |
| | | | |
| #else | | #else | |
| | | | |
| using ::hypot; | | using ::hypot; | |
| | | | |
| #endif | | #endif | |
| | | | |
|
| /*! The sign function. | | /** \brief The sign function. | |
| | | | |
| Returns 1, 0, or -1 depending on the sign of \a t, but with the sam
e type as \a t. | | Returns 1, 0, or -1 depending on the sign of \a t, but with the sam
e type as \a t. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T> | | template <class T> | |
| inline T sign(T t) | | inline T sign(T t) | |
| { | | { | |
| return t > NumericTraits<T>::zero() | | return t > NumericTraits<T>::zero() | |
| ? NumericTraits<T>::one() | | ? NumericTraits<T>::one() | |
| : t < NumericTraits<T>::zero() | | : t < NumericTraits<T>::zero() | |
| ? -NumericTraits<T>::one() | | ? -NumericTraits<T>::one() | |
| : NumericTraits<T>::zero(); | | : NumericTraits<T>::zero(); | |
| } | | } | |
| | | | |
|
| /*! The integer sign function. | | /** \brief The integer sign function. | |
| | | | |
| Returns 1, 0, or -1 depending on the sign of \a t, converted to int
. | | Returns 1, 0, or -1 depending on the sign of \a t, converted to int
. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T> | | template <class T> | |
| inline int signi(T t) | | inline int signi(T t) | |
| { | | { | |
| return t > NumericTraits<T>::zero() | | return t > NumericTraits<T>::zero() | |
| ? 1 | | ? 1 | |
| : t < NumericTraits<T>::zero() | | : t < NumericTraits<T>::zero() | |
| ? -1 | | ? -1 | |
| : 0; | | : 0; | |
| } | | } | |
| | | | |
|
| /*! The binary sign function. | | /** \brief The binary sign function. | |
| | | | |
| Transfers the sign of \a t2 to \a t1. | | Transfers the sign of \a t2 to \a t1. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| inline T1 sign(T1 t1, T2 t2) | | inline T1 sign(T1 t1, T2 t2) | |
| { | | { | |
| return t2 >= NumericTraits<T2>::zero() | | return t2 >= NumericTraits<T2>::zero() | |
| ? abs(t1) | | ? abs(t1) | |
| : -abs(t1); | | : -abs(t1); | |
| } | | } | |
| | | | |
| #ifdef DOXYGEN // only for documentation | | #ifdef DOXYGEN // only for documentation | |
|
| /*! Check if an integer is even. | | /** \brief Check if an integer is even. | |
| | | | |
| Defined for all integral types. | | Defined for all integral types. | |
| */ | | */ | |
| bool even(int t); | | bool even(int t); | |
| | | | |
|
| /*! Check if an integer is odd. | | /** \brief Check if an integer is odd. | |
| | | | |
| Defined for all integral types. | | Defined for all integral types. | |
| */ | | */ | |
| bool odd(int t); | | bool odd(int t); | |
| | | | |
| #endif | | #endif | |
| | | | |
| #define VIGRA_DEFINE_ODD_EVEN(T) \ | | #define VIGRA_DEFINE_ODD_EVEN(T) \ | |
| inline bool even(T t) { return (t&1) == 0; } \ | | inline bool even(T t) { return (t&1) == 0; } \ | |
| inline bool odd(T t) { return (t&1) == 1; } | | inline bool odd(T t) { return (t&1) == 1; } | |
| | | | |
| skipping to change at line 652 | | skipping to change at line 675 | |
| #undef VIGRA_DEFINE_NORM | | #undef VIGRA_DEFINE_NORM | |
| | | | |
| template <class T> | | template <class T> | |
| inline typename NormTraits<std::complex<T> >::SquaredNormType | | inline typename NormTraits<std::complex<T> >::SquaredNormType | |
| squaredNorm(std::complex<T> const & t) | | squaredNorm(std::complex<T> const & t) | |
| { | | { | |
| return sq(t.real()) + sq(t.imag()); | | return sq(t.real()) + sq(t.imag()); | |
| } | | } | |
| | | | |
| #ifdef DOXYGEN // only for documentation | | #ifdef DOXYGEN // only for documentation | |
|
| /*! The squared norm of a numerical object. | | /** \brief The squared norm of a numerical object. | |
| | | | |
|
| For scalar types: equals <tt>vigra::sq(t)</tt><br>. | | <ul> | |
| For vectorial types: equals <tt>vigra::dot(t, t)</tt><br>. | | <li>For scalar types: equals <tt>vigra::sq(t)</tt>. | |
| For complex types: equals <tt>vigra::sq(t.real()) + vigra::sq(t.ima | | <li>For vectorial types (including TinyVector): equals <tt>vigra::d | |
| g())</tt><br>. | | ot(t, t)</tt>. | |
| For matrix types: results in the squared Frobenius norm (sum of squ | | <li>For complex number types: equals <tt>vigra::sq(t.real()) + vigr | |
| ares of the matrix elements). | | a::sq(t.imag())</tt>. | |
| | | <li>For array and matrix types: results in the squared Frobenius no | |
| | | rm (sum of squares of the matrix elements). | |
| | | </ul> | |
| */ | | */ | |
| NormTraits<T>::SquaredNormType squaredNorm(T const & t); | | NormTraits<T>::SquaredNormType squaredNorm(T const & t); | |
| | | | |
| #endif | | #endif | |
| | | | |
|
| /*! The norm of a numerical object. | | /** \brief The norm of a numerical object. | |
| | | | |
| For scalar types: implemented as <tt>abs(t)</tt><br> | | For scalar types: implemented as <tt>abs(t)</tt><br> | |
| otherwise: implemented as <tt>sqrt(squaredNorm(t))</tt>. | | otherwise: implemented as <tt>sqrt(squaredNorm(t))</tt>. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T> | | template <class T> | |
| inline typename NormTraits<T>::NormType | | inline typename NormTraits<T>::NormType | |
| norm(T const & t) | | norm(T const & t) | |
| { | | { | |
| typedef typename NormTraits<T>::SquaredNormType SNT; | | typedef typename NormTraits<T>::SquaredNormType SNT; | |
| return sqrt(static_cast<typename SquareRootTraits<SNT>::SquareRootArgum
ent>(squaredNorm(t))); | | return sqrt(static_cast<typename SquareRootTraits<SNT>::SquareRootArgum
ent>(squaredNorm(t))); | |
| } | | } | |
| | | | |
|
| /*! Compute the eigenvalues of a 2x2 real symmetric matrix. | | /** \brief Compute the eigenvalues of a 2x2 real symmetric matrix. | |
| | | | |
| This uses the analytical eigenvalue formula | | This uses the analytical eigenvalue formula | |
| \f[ | | \f[ | |
| \lambda_{1,2} = \frac{1}{2}\left(a_{00} + a_{11} \pm \sqrt{(a_{0
0} - a_{11})^2 + 4 a_{01}^2}\right) | | \lambda_{1,2} = \frac{1}{2}\left(a_{00} + a_{11} \pm \sqrt{(a_{0
0} - a_{11})^2 + 4 a_{01}^2}\right) | |
| \f] | | \f] | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T> | | template <class T> | |
| void symmetric2x2Eigenvalues(T a00, T a01, T a11, T * r0, T * r1) | | void symmetric2x2Eigenvalues(T a00, T a01, T a11, T * r0, T * r1) | |
| { | | { | |
| double d = hypot(a00 - a11, 2.0*a01); | | double d = hypot(a00 - a11, 2.0*a01); | |
| *r0 = static_cast<T>(0.5*(a00 + a11 + d)); | | *r0 = static_cast<T>(0.5*(a00 + a11 + d)); | |
| *r1 = static_cast<T>(0.5*(a00 + a11 - d)); | | *r1 = static_cast<T>(0.5*(a00 + a11 - d)); | |
| if(*r0 < *r1) | | if(*r0 < *r1) | |
| std::swap(*r0, *r1); | | std::swap(*r0, *r1); | |
| } | | } | |
| | | | |
|
| /*! Compute the eigenvalues of a 3x3 real symmetric matrix. | | /** \brief Compute the eigenvalues of a 3x3 real symmetric matrix. | |
| | | | |
| This uses a numerically stable version of the analytical eigenvalue
formula according to | | This uses a numerically stable version of the analytical eigenvalue
formula according to | |
| <p> | | <p> | |
| David Eberly: <a href="http://www.geometrictools.com/Documentation/
EigenSymmetric3x3.pdf"> | | David Eberly: <a href="http://www.geometrictools.com/Documentation/
EigenSymmetric3x3.pdf"> | |
|
| <em>"Eigensystems for 3 × 3 Symmetric Matrices (Revisited)"</em></a
>, Geometric Tools Documentation, 2006 | | <em>"Eigensystems for 3 × 3 Symmetric Matrices (Revisited)"</em></
a>, Geometric Tools Documentation, 2006 | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T> | | template <class T> | |
| void symmetric3x3Eigenvalues(T a00, T a01, T a02, T a11, T a12, T a22, | | void symmetric3x3Eigenvalues(T a00, T a01, T a02, T a11, T a12, T a22, | |
| T * r0, T * r1, T * r2) | | T * r0, T * r1, T * r2) | |
| { | | { | |
|
| static double inv3 = 1.0 / 3.0, root3 = std::sqrt(3.0); | | double inv3 = 1.0 / 3.0, root3 = std::sqrt(3.0); | |
| | | | |
| double c0 = a00*a11*a22 + 2.0*a01*a02*a12 - a00*a12*a12 - a11*a02*a02 -
a22*a01*a01; | | double c0 = a00*a11*a22 + 2.0*a01*a02*a12 - a00*a12*a12 - a11*a02*a02 -
a22*a01*a01; | |
| double c1 = a00*a11 - a01*a01 + a00*a22 - a02*a02 + a11*a22 - a12*a12; | | double c1 = a00*a11 - a01*a01 + a00*a22 - a02*a02 + a11*a22 - a12*a12; | |
| double c2 = a00 + a11 + a22; | | double c2 = a00 + a11 + a22; | |
| double c2Div3 = c2*inv3; | | double c2Div3 = c2*inv3; | |
| double aDiv3 = (c1 - c2*c2Div3)*inv3; | | double aDiv3 = (c1 - c2*c2Div3)*inv3; | |
| if (aDiv3 > 0.0) | | if (aDiv3 > 0.0) | |
| aDiv3 = 0.0; | | aDiv3 = 0.0; | |
| double mbDiv2 = 0.5*(c0 + c2Div3*(2.0*c2Div3*c2Div3 - c1)); | | double mbDiv2 = 0.5*(c0 + c2Div3*(2.0*c2Div3*c2Div3 - c1)); | |
| double q = mbDiv2*mbDiv2 + aDiv3*aDiv3*aDiv3; | | double q = mbDiv2*mbDiv2 + aDiv3*aDiv3*aDiv3; | |
| | | | |
| skipping to change at line 795 | | skipping to change at line 820 | |
| y = (y + l)/4.0; | | y = (y + l)/4.0; | |
| z = (z + l)/4.0; | | z = (z + l)/4.0; | |
| } | | } | |
| double d = X*Y - sq(Z); | | double d = X*Y - sq(Z); | |
| double p = X*Y*Z; | | double p = X*Y*Z; | |
| return (1.0 - d/10.0 + p/14.0 + sq(d)/24.0 - d*p*3.0/44.0) / VIGRA_CSTD
::sqrt(m); | | return (1.0 - d/10.0 + p/14.0 + sq(d)/24.0 - d*p*3.0/44.0) / VIGRA_CSTD
::sqrt(m); | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! The incomplete elliptic integral of the first kind. | | /** \brief The incomplete elliptic integral of the first kind. | |
| | | | |
|
| Computes | | This function computes | |
| | | | |
| \f[ | | \f[ | |
|
| \mbox{F}(x, k) = \int_0^x \frac{1}{\sqrt{1 - k^2 \sin(t)^2}} dt | | \mbox{F}(x, k) = \int_0^x \frac{1}{\sqrt{1 - k^2 \sin(t)^2}} d
t | |
| \f] | | \f] | |
| | | | |
| according to the algorithm given in Press et al. "Numerical Recipes
". | | according to the algorithm given in Press et al. "Numerical Recipes
". | |
| | | | |
| Note: In some libraries (e.g. Mathematica), the second parameter of
the elliptic integral | | Note: In some libraries (e.g. Mathematica), the second parameter of
the elliptic integral | |
| functions must be k^2 rather than k. Check the documentation when r
esults disagree! | | functions must be k^2 rather than k. Check the documentation when r
esults disagree! | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline double ellipticIntegralF(double x, double k) | | inline double ellipticIntegralF(double x, double k) | |
| { | | { | |
| double c2 = sq(VIGRA_CSTD::cos(x)); | | double c2 = sq(VIGRA_CSTD::cos(x)); | |
| double s = VIGRA_CSTD::sin(x); | | double s = VIGRA_CSTD::sin(x); | |
| return s*detail::ellipticRF(c2, 1.0 - sq(k*s), 1.0); | | return s*detail::ellipticRF(c2, 1.0 - sq(k*s), 1.0); | |
| } | | } | |
| | | | |
|
| /*! The incomplete elliptic integral of the second kind. | | /** \brief The incomplete elliptic integral of the second kind. | |
| | | | |
|
| Computes | | This function computes | |
| | | | |
| \f[ | | \f[ | |
| \mbox{E}(x, k) = \int_0^x \sqrt{1 - k^2 \sin(t)^2} dt | | \mbox{E}(x, k) = \int_0^x \sqrt{1 - k^2 \sin(t)^2} dt | |
| \f] | | \f] | |
| | | | |
| according to the algorithm given in Press et al. "Numerical Recipes
". The | | according to the algorithm given in Press et al. "Numerical Recipes
". The | |
| complete elliptic integral of the second kind is simply <tt>ellipti
cIntegralE(M_PI/2, k)</TT>. | | complete elliptic integral of the second kind is simply <tt>ellipti
cIntegralE(M_PI/2, k)</TT>. | |
| | | | |
| Note: In some libraries (e.g. Mathematica), the second parameter of
the elliptic integral | | Note: In some libraries (e.g. Mathematica), the second parameter of
the elliptic integral | |
| functions must be k^2 rather than k. Check the documentation when r
esults disagree! | | functions must be k^2 rather than k. Check the documentation when r
esults disagree! | |
| | | | |
| skipping to change at line 843 | | skipping to change at line 868 | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline double ellipticIntegralE(double x, double k) | | inline double ellipticIntegralE(double x, double k) | |
| { | | { | |
| double c2 = sq(VIGRA_CSTD::cos(x)); | | double c2 = sq(VIGRA_CSTD::cos(x)); | |
| double s = VIGRA_CSTD::sin(x); | | double s = VIGRA_CSTD::sin(x); | |
| k = sq(k*s); | | k = sq(k*s); | |
| return s*(detail::ellipticRF(c2, 1.0-k, 1.0) - k/3.0*detail::ellipticRD
(c2, 1.0-k, 1.0)); | | return s*(detail::ellipticRF(c2, 1.0-k, 1.0) - k/3.0*detail::ellipticRD
(c2, 1.0-k, 1.0)); | |
| } | | } | |
| | | | |
|
| #ifdef _MSC_VER | | #if defined(_MSC_VER) && _MSC_VER < 1800 | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| template <class T> | | template <class T> | |
| double erfImpl(T x) | | double erfImpl(T x) | |
| { | | { | |
| double t = 1.0/(1.0+0.5*VIGRA_CSTD::fabs(x)); | | double t = 1.0/(1.0+0.5*VIGRA_CSTD::fabs(x)); | |
| double ans = t*VIGRA_CSTD::exp(-x*x-1.26551223+t*(1.00002368+t*(0.37409
196+ | | double ans = t*VIGRA_CSTD::exp(-x*x-1.26551223+t*(1.00002368+t*(0.37409
196+ | |
| t*(0.09678418+t*(-0.18628806+t*(0.27886
807+ | | t*(0.09678418+t*(-0.18628806+t*(0.27886
807+ | |
| t*(-1.13520398+t*(1.48851587+t*(-0.8221
5223+ | | t*(-1.13520398+t*(1.48851587+t*(-0.8221
5223+ | |
| t*0.17087277))))))))); | | t*0.17087277))))))))); | |
| if (x >= 0.0) | | if (x >= 0.0) | |
| return 1.0 - ans; | | return 1.0 - ans; | |
| else | | else | |
| return ans - 1.0; | | return ans - 1.0; | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! The error function. | | /** \brief The error function. | |
| | | | |
| If <tt>erf()</tt> is not provided in the C standard math library (a
s it should according to the | | If <tt>erf()</tt> is not provided in the C standard math library (a
s it should according to the | |
| new C99 standard ?), VIGRA implements <tt>erf()</tt> as an approxim
ation of the error | | new C99 standard ?), VIGRA implements <tt>erf()</tt> as an approxim
ation of the error | |
| function | | function | |
| | | | |
| \f[ | | \f[ | |
| \mbox{erf}(x) = \int_0^x e^{-t^2} dt | | \mbox{erf}(x) = \int_0^x e^{-t^2} dt | |
| \f] | | \f] | |
| | | | |
| according to the formula given in Press et al. "Numerical Recipes". | | according to the formula given in Press et al. "Numerical Recipes". | |
| | | | |
| skipping to change at line 989 | | skipping to change at line 1014 | |
| if((pans * sum < eps2) && (hold < eps2)) | | if((pans * sum < eps2) && (hold < eps2)) | |
| break; // converged | | break; // converged | |
| } | | } | |
| if(m == maxit) | | if(m == maxit) | |
| vigra_fail("noncentralChi2P(): no convergence."); | | vigra_fail("noncentralChi2P(): no convergence."); | |
| return std::make_pair(0.5 * ao * density, std::min(1.0, std::max(0.0, a
o * probability))); | | return std::make_pair(0.5 * ao * density, std::min(1.0, std::max(0.0, a
o * probability))); | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! Chi square distribution. | | /** \brief Chi square distribution. | |
| | | | |
| Computes the density of a chi square distribution with \a degreesOf
Freedom | | Computes the density of a chi square distribution with \a degreesOf
Freedom | |
| and tolerance \a accuracy at the given argument \a arg | | and tolerance \a accuracy at the given argument \a arg | |
| by calling <tt>noncentralChi2(degreesOfFreedom, 0.0, arg, accuracy)
</tt>. | | by calling <tt>noncentralChi2(degreesOfFreedom, 0.0, arg, accuracy)
</tt>. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline double chi2(unsigned int degreesOfFreedom, double arg, double accura
cy = 1e-7) | | inline double chi2(unsigned int degreesOfFreedom, double arg, double accura
cy = 1e-7) | |
| { | | { | |
| return detail::noncentralChi2CDF(degreesOfFreedom, 0.0, arg, accuracy).
first; | | return detail::noncentralChi2CDF(degreesOfFreedom, 0.0, arg, accuracy).
first; | |
| } | | } | |
| | | | |
|
| /*! Cumulative chi square distribution. | | /** \brief Cumulative chi square distribution. | |
| | | | |
| Computes the cumulative density of a chi square distribution with \
a degreesOfFreedom | | Computes the cumulative density of a chi square distribution with \
a degreesOfFreedom | |
| and tolerance \a accuracy at the given argument \a arg, i.e. the pr
obability that | | and tolerance \a accuracy at the given argument \a arg, i.e. the pr
obability that | |
| a random number drawn from the distribution is below \a arg | | a random number drawn from the distribution is below \a arg | |
| by calling <tt>noncentralChi2CDF(degreesOfFreedom, 0.0, arg, accura
cy)</tt>. | | by calling <tt>noncentralChi2CDF(degreesOfFreedom, 0.0, arg, accura
cy)</tt>. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline double chi2CDF(unsigned int degreesOfFreedom, double arg, double acc
uracy = 1e-7) | | inline double chi2CDF(unsigned int degreesOfFreedom, double arg, double acc
uracy = 1e-7) | |
| { | | { | |
| return detail::noncentralChi2CDF(degreesOfFreedom, 0.0, arg, accuracy).
second; | | return detail::noncentralChi2CDF(degreesOfFreedom, 0.0, arg, accuracy).
second; | |
| } | | } | |
| | | | |
|
| /*! Non-central chi square distribution. | | /** \brief Non-central chi square distribution. | |
| | | | |
| Computes the density of a non-central chi square distribution with
\a degreesOfFreedom, | | Computes the density of a non-central chi square distribution with
\a degreesOfFreedom, | |
| noncentrality parameter \a noncentrality and tolerance \a accuracy
at the given argument | | noncentrality parameter \a noncentrality and tolerance \a accuracy
at the given argument | |
| \a arg. It uses Algorithm AS 231 from Appl. Statist. (1987) Vol.36,
No.3 (code ported from | | \a arg. It uses Algorithm AS 231 from Appl. Statist. (1987) Vol.36,
No.3 (code ported from | |
| http://lib.stat.cmu.edu/apstat/231). The algorithm has linear compl
exity in the number of | | http://lib.stat.cmu.edu/apstat/231). The algorithm has linear compl
exity in the number of | |
| degrees of freedom. | | degrees of freedom. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline double noncentralChi2(unsigned int degreesOfFreedom, | | inline double noncentralChi2(unsigned int degreesOfFreedom, | |
| double noncentrality, double arg, double accuracy = 1e-7) | | double noncentrality, double arg, double accuracy = 1e-7) | |
| { | | { | |
| return detail::noncentralChi2CDF(degreesOfFreedom, noncentrality, arg,
accuracy).first; | | return detail::noncentralChi2CDF(degreesOfFreedom, noncentrality, arg,
accuracy).first; | |
| } | | } | |
| | | | |
|
| /*! Cumulative non-central chi square distribution. | | /** \brief Cumulative non-central chi square distribution. | |
| | | | |
| Computes the cumulative density of a chi square distribution with \
a degreesOfFreedom, | | Computes the cumulative density of a chi square distribution with \
a degreesOfFreedom, | |
| noncentrality parameter \a noncentrality and tolerance \a accuracy
at the given argument | | noncentrality parameter \a noncentrality and tolerance \a accuracy
at the given argument | |
| \a arg, i.e. the probability that a random number drawn from the di
stribution is below \a arg | | \a arg, i.e. the probability that a random number drawn from the di
stribution is below \a arg | |
| It uses Algorithm AS 231 from Appl. Statist. (1987) Vol.36, No.3 (c
ode ported from | | It uses Algorithm AS 231 from Appl. Statist. (1987) Vol.36, No.3 (c
ode ported from | |
| http://lib.stat.cmu.edu/apstat/231). The algorithm has linear compl
exity in the number of | | http://lib.stat.cmu.edu/apstat/231). The algorithm has linear compl
exity in the number of | |
| degrees of freedom (see noncentralChi2CDFApprox() for a constant-ti
me algorithm). | | degrees of freedom (see noncentralChi2CDFApprox() for a constant-ti
me algorithm). | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline double noncentralChi2CDF(unsigned int degreesOfFreedom, | | inline double noncentralChi2CDF(unsigned int degreesOfFreedom, | |
| double noncentrality, double arg, double accuracy = 1e-7) | | double noncentrality, double arg, double accuracy = 1e-7) | |
| { | | { | |
| return detail::noncentralChi2CDF(degreesOfFreedom, noncentrality, arg,
accuracy).second; | | return detail::noncentralChi2CDF(degreesOfFreedom, noncentrality, arg,
accuracy).second; | |
| } | | } | |
| | | | |
|
| /*! Cumulative non-central chi square distribution (approximate). | | /** \brief Cumulative non-central chi square distribution (approximate)
. | |
| | | | |
| Computes approximate values of the cumulative density of a chi squa
re distribution with \a degreesOfFreedom, | | Computes approximate values of the cumulative density of a chi squa
re distribution with \a degreesOfFreedom, | |
| and noncentrality parameter \a noncentrality at the given argument | | and noncentrality parameter \a noncentrality at the given argument | |
| \a arg, i.e. the probability that a random number drawn from the di
stribution is below \a arg | | \a arg, i.e. the probability that a random number drawn from the di
stribution is below \a arg | |
| It uses the approximate transform into a normal distribution due to
Wilson and Hilferty | | It uses the approximate transform into a normal distribution due to
Wilson and Hilferty | |
| (see Abramovitz, Stegun: "Handbook of Mathematical Functions", form
ula 26.3.32). | | (see Abramovitz, Stegun: "Handbook of Mathematical Functions", form
ula 26.3.32). | |
| The algorithm's running time is independent of the inputs, i.e. is
should be used | | The algorithm's running time is independent of the inputs, i.e. is
should be used | |
| when noncentralChi2CDF() is too slow, and approximate values are su
fficient. The accuracy is only | | when noncentralChi2CDF() is too slow, and approximate values are su
fficient. The accuracy is only | |
| about 0.1 for few degrees of freedom, but reaches about 0.001 above
dof = 5. | | about 0.1 for few degrees of freedom, but reaches about 0.001 above
dof = 5. | |
| | | | |
| | | | |
| skipping to change at line 1087 | | skipping to change at line 1112 | |
| T facLM(T l, T m) | | T facLM(T l, T m) | |
| { | | { | |
| T tmp = NumericTraits<T>::one(); | | T tmp = NumericTraits<T>::one(); | |
| for(T f = l-m+1; f <= l+m; ++f) | | for(T f = l-m+1; f <= l+m; ++f) | |
| tmp *= f; | | tmp *= f; | |
| return tmp; | | return tmp; | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! Associated Legendre polynomial. | | /** \brief Associated Legendre polynomial. | |
| | | | |
| Computes the value of the associated Legendre polynomial of order <
tt>l, m</tt> | | Computes the value of the associated Legendre polynomial of order <
tt>l, m</tt> | |
| for argument <tt>x</tt>. <tt>x</tt> must be in the range <tt>[-1.0,
1.0]</tt>, | | for argument <tt>x</tt>. <tt>x</tt> must be in the range <tt>[-1.0,
1.0]</tt>, | |
| otherwise an exception is thrown. The standard Legendre polynomials
are the | | otherwise an exception is thrown. The standard Legendre polynomials
are the | |
| special case <tt>m == 0</tt>. | | special case <tt>m == 0</tt>. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class REAL> | | template <class REAL> | |
| | | | |
| skipping to change at line 1136 | | skipping to change at line 1161 | |
| REAL other = 0.0; | | REAL other = 0.0; | |
| for(unsigned int i = m+2; i <= l; ++i) | | for(unsigned int i = m+2; i <= l; ++i) | |
| { | | { | |
| other = ( (2.0*i-1.0) * x * result_1 - (i+m-1.0)*result) / (i-m); | | other = ( (2.0*i-1.0) * x * result_1 - (i+m-1.0)*result) / (i-m); | |
| result = result_1; | | result = result_1; | |
| result_1 = other; | | result_1 = other; | |
| } | | } | |
| return other; | | return other; | |
| } | | } | |
| | | | |
|
| /*! Legendre polynomial. | | /** \brief \brief Legendre polynomial. | |
| | | | |
| Computes the value of the Legendre polynomial of order <tt>l</tt> f
or argument <tt>x</tt>. | | Computes the value of the Legendre polynomial of order <tt>l</tt> f
or argument <tt>x</tt>. | |
| <tt>x</tt> must be in the range <tt>[-1.0, 1.0]</tt>, otherwise an
exception is thrown. | | <tt>x</tt> must be in the range <tt>[-1.0, 1.0]</tt>, otherwise an
exception is thrown. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class REAL> | | template <class REAL> | |
| REAL legendre(unsigned int l, REAL x) | | REAL legendre(unsigned int l, REAL x) | |
| { | | { | |
| return legendre(l, 0, x); | | return legendre(l, 0, x); | |
| } | | } | |
| | | | |
|
| /*! sin(pi*x). | | /** \brief sin(pi*x). | |
| | | | |
| Essentially calls <tt>std::sin(M_PI*x)</tt> but uses a more accurat
e implementation | | Essentially calls <tt>std::sin(M_PI*x)</tt> but uses a more accurat
e implementation | |
| to make sure that <tt>sin_pi(1.0) == 0.0</tt> (which does not hold
for | | to make sure that <tt>sin_pi(1.0) == 0.0</tt> (which does not hold
for | |
| <tt>std::sin(M_PI)</tt> due to round-off error), and <tt>sin_pi(0.5
) == 1.0</tt>. | | <tt>std::sin(M_PI)</tt> due to round-off error), and <tt>sin_pi(0.5
) == 1.0</tt>. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class REAL> | | template <class REAL> | |
| REAL sin_pi(REAL x) | | REAL sin_pi(REAL x) | |
| | | | |
| skipping to change at line 1189 | | skipping to change at line 1214 | |
| rem = 1.0 - rem; | | rem = 1.0 - rem; | |
| if(rem == 0.5) | | if(rem == 0.5) | |
| rem = NumericTraits<REAL>::one(); | | rem = NumericTraits<REAL>::one(); | |
| else | | else | |
| rem = std::sin(M_PI * rem); | | rem = std::sin(M_PI * rem); | |
| return invert | | return invert | |
| ? -rem | | ? -rem | |
| : rem; | | : rem; | |
| } | | } | |
| | | | |
|
| /*! cos(pi*x). | | /** \brief cos(pi*x). | |
| | | | |
| Essentially calls <tt>std::cos(M_PI*x)</tt> but uses a more accurat
e implementation | | Essentially calls <tt>std::cos(M_PI*x)</tt> but uses a more accurat
e implementation | |
| to make sure that <tt>cos_pi(1.0) == -1.0</tt> and <tt>cos_pi(0.5)
== 0.0</tt>. | | to make sure that <tt>cos_pi(1.0) == -1.0</tt> and <tt>cos_pi(0.5)
== 0.0</tt>. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class REAL> | | template <class REAL> | |
| REAL cos_pi(REAL x) | | REAL cos_pi(REAL x) | |
| { | | { | |
| return sin_pi(x+0.5); | | return sin_pi(x+0.5); | |
| } | | } | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| template <class REAL> | | template <class REAL> | |
|
| REAL gammaImpl(REAL x) | | struct GammaImpl | |
| | | { | |
| | | static REAL gamma(REAL x); | |
| | | static REAL loggamma(REAL x); | |
| | | | |
| | | static double g[]; | |
| | | static double a[]; | |
| | | static double t[]; | |
| | | static double u[]; | |
| | | static double v[]; | |
| | | static double s[]; | |
| | | static double r[]; | |
| | | static double w[]; | |
| | | }; | |
| | | | |
| | | template <class REAL> | |
| | | double GammaImpl<REAL>::g[] = { | |
| | | 1.0, | |
| | | 0.5772156649015329, | |
| | | -0.6558780715202538, | |
| | | -0.420026350340952e-1, | |
| | | 0.1665386113822915, | |
| | | -0.421977345555443e-1, | |
| | | -0.9621971527877e-2, | |
| | | 0.7218943246663e-2, | |
| | | -0.11651675918591e-2, | |
| | | -0.2152416741149e-3, | |
| | | 0.1280502823882e-3, | |
| | | -0.201348547807e-4, | |
| | | -0.12504934821e-5, | |
| | | 0.1133027232e-5, | |
| | | -0.2056338417e-6, | |
| | | 0.6116095e-8, | |
| | | 0.50020075e-8, | |
| | | -0.11812746e-8, | |
| | | 0.1043427e-9, | |
| | | 0.77823e-11, | |
| | | -0.36968e-11, | |
| | | 0.51e-12, | |
| | | -0.206e-13, | |
| | | -0.54e-14, | |
| | | 0.14e-14 | |
| | | }; | |
| | | | |
| | | template <class REAL> | |
| | | double GammaImpl<REAL>::a[] = { | |
| | | 7.72156649015328655494e-02, | |
| | | 3.22467033424113591611e-01, | |
| | | 6.73523010531292681824e-02, | |
| | | 2.05808084325167332806e-02, | |
| | | 7.38555086081402883957e-03, | |
| | | 2.89051383673415629091e-03, | |
| | | 1.19270763183362067845e-03, | |
| | | 5.10069792153511336608e-04, | |
| | | 2.20862790713908385557e-04, | |
| | | 1.08011567247583939954e-04, | |
| | | 2.52144565451257326939e-05, | |
| | | 4.48640949618915160150e-05 | |
| | | }; | |
| | | | |
| | | template <class REAL> | |
| | | double GammaImpl<REAL>::t[] = { | |
| | | 4.83836122723810047042e-01, | |
| | | -1.47587722994593911752e-01, | |
| | | 6.46249402391333854778e-02, | |
| | | -3.27885410759859649565e-02, | |
| | | 1.79706750811820387126e-02, | |
| | | -1.03142241298341437450e-02, | |
| | | 6.10053870246291332635e-03, | |
| | | -3.68452016781138256760e-03, | |
| | | 2.25964780900612472250e-03, | |
| | | -1.40346469989232843813e-03, | |
| | | 8.81081882437654011382e-04, | |
| | | -5.38595305356740546715e-04, | |
| | | 3.15632070903625950361e-04, | |
| | | -3.12754168375120860518e-04, | |
| | | 3.35529192635519073543e-04 | |
| | | }; | |
| | | | |
| | | template <class REAL> | |
| | | double GammaImpl<REAL>::u[] = { | |
| | | -7.72156649015328655494e-02, | |
| | | 6.32827064025093366517e-01, | |
| | | 1.45492250137234768737e+00, | |
| | | 9.77717527963372745603e-01, | |
| | | 2.28963728064692451092e-01, | |
| | | 1.33810918536787660377e-02 | |
| | | }; | |
| | | | |
| | | template <class REAL> | |
| | | double GammaImpl<REAL>::v[] = { | |
| | | 0.0, | |
| | | 2.45597793713041134822e+00, | |
| | | 2.12848976379893395361e+00, | |
| | | 7.69285150456672783825e-01, | |
| | | 1.04222645593369134254e-01, | |
| | | 3.21709242282423911810e-03 | |
| | | }; | |
| | | | |
| | | template <class REAL> | |
| | | double GammaImpl<REAL>::s[] = { | |
| | | -7.72156649015328655494e-02, | |
| | | 2.14982415960608852501e-01, | |
| | | 3.25778796408930981787e-01, | |
| | | 1.46350472652464452805e-01, | |
| | | 2.66422703033638609560e-02, | |
| | | 1.84028451407337715652e-03, | |
| | | 3.19475326584100867617e-05 | |
| | | }; | |
| | | | |
| | | template <class REAL> | |
| | | double GammaImpl<REAL>::r[] = { | |
| | | 0.0, | |
| | | 1.39200533467621045958e+00, | |
| | | 7.21935547567138069525e-01, | |
| | | 1.71933865632803078993e-01, | |
| | | 1.86459191715652901344e-02, | |
| | | 7.77942496381893596434e-04, | |
| | | 7.32668430744625636189e-06 | |
| | | }; | |
| | | | |
| | | template <class REAL> | |
| | | double GammaImpl<REAL>::w[] = { | |
| | | 4.18938533204672725052e-01, | |
| | | 8.33333333333329678849e-02, | |
| | | -2.77777777728775536470e-03, | |
| | | 7.93650558643019558500e-04, | |
| | | -5.95187557450339963135e-04, | |
| | | 8.36339918996282139126e-04, | |
| | | -1.63092934096575273989e-03 | |
| | | }; | |
| | | | |
| | | template <class REAL> | |
| | | REAL GammaImpl<REAL>::gamma(REAL x) | |
| { | | { | |
| int i, k, m, ix = (int)x; | | int i, k, m, ix = (int)x; | |
| double ga = 0.0, gr = 0.0, r = 0.0, z = 0.0; | | double ga = 0.0, gr = 0.0, r = 0.0, z = 0.0; | |
| | | | |
|
| static double g[] = { | | | |
| 1.0, | | | |
| 0.5772156649015329, | | | |
| -0.6558780715202538, | | | |
| -0.420026350340952e-1, | | | |
| 0.1665386113822915, | | | |
| -0.421977345555443e-1, | | | |
| -0.9621971527877e-2, | | | |
| 0.7218943246663e-2, | | | |
| -0.11651675918591e-2, | | | |
| -0.2152416741149e-3, | | | |
| 0.1280502823882e-3, | | | |
| -0.201348547807e-4, | | | |
| -0.12504934821e-5, | | | |
| 0.1133027232e-5, | | | |
| -0.2056338417e-6, | | | |
| 0.6116095e-8, | | | |
| 0.50020075e-8, | | | |
| -0.11812746e-8, | | | |
| 0.1043427e-9, | | | |
| 0.77823e-11, | | | |
| -0.36968e-11, | | | |
| 0.51e-12, | | | |
| -0.206e-13, | | | |
| -0.54e-14, | | | |
| 0.14e-14}; | | | |
| | | | |
| vigra_precondition(x <= 171.0, | | vigra_precondition(x <= 171.0, | |
| "gamma(): argument cannot exceed 171.0."); | | "gamma(): argument cannot exceed 171.0."); | |
| | | | |
| if (x == ix) | | if (x == ix) | |
| { | | { | |
| if (ix > 0) | | if (ix > 0) | |
| { | | { | |
| ga = 1.0; // use factorial | | ga = 1.0; // use factorial | |
| for (i=2; i<ix; ++i) | | for (i=2; i<ix; ++i) | |
| { | | { | |
| | | | |
| skipping to change at line 1306 | | skipping to change at line 1437 | |
| * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. | | * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. | |
| * | | * | |
| * Developed at SunPro, a Sun Microsystems, Inc. business. | | * Developed at SunPro, a Sun Microsystems, Inc. business. | |
| * Permission to use, copy, modify, and distribute this | | * Permission to use, copy, modify, and distribute this | |
| * software is freely granted, provided that this notice | | * software is freely granted, provided that this notice | |
| * is preserved. | | * is preserved. | |
| * ==================================================== | | * ==================================================== | |
| * | | * | |
| */ | | */ | |
| template <class REAL> | | template <class REAL> | |
|
| REAL loggammaImpl(REAL x) | | REAL GammaImpl<REAL>::loggamma(REAL x) | |
| { | | { | |
| vigra_precondition(x > 0.0, | | vigra_precondition(x > 0.0, | |
| "loggamma(): argument must be positive."); | | "loggamma(): argument must be positive."); | |
| | | | |
| vigra_precondition(x <= 1.0e307, | | vigra_precondition(x <= 1.0e307, | |
| "loggamma(): argument must not exceed 1e307."); | | "loggamma(): argument must not exceed 1e307."); | |
| | | | |
| double res; | | double res; | |
| | | | |
| if (x < 4.2351647362715017e-22) | | if (x < 4.2351647362715017e-22) | |
| { | | { | |
| res = -std::log(x); | | res = -std::log(x); | |
| } | | } | |
| else if ((x == 2.0) || (x == 1.0)) | | else if ((x == 2.0) || (x == 1.0)) | |
| { | | { | |
| res = 0.0; | | res = 0.0; | |
| } | | } | |
| else if (x < 2.0) | | else if (x < 2.0) | |
| { | | { | |
|
| static const double a[] = { 7.72156649015328655494e-02, | | const double tc = 1.46163214496836224576e+00; | |
| 3.22467033424113591611e-01, | | const double tf = -1.21486290535849611461e-01; | |
| 6.73523010531292681824e-02, | | const double tt = -3.63867699703950536541e-18; | |
| 2.05808084325167332806e-02, | | | |
| 7.38555086081402883957e-03, | | | |
| 2.89051383673415629091e-03, | | | |
| 1.19270763183362067845e-03, | | | |
| 5.10069792153511336608e-04, | | | |
| 2.20862790713908385557e-04, | | | |
| 1.08011567247583939954e-04, | | | |
| 2.52144565451257326939e-05, | | | |
| 4.48640949618915160150e-05 }; | | | |
| static const double t[] = { 4.83836122723810047042e-01, | | | |
| -1.47587722994593911752e-01, | | | |
| 6.46249402391333854778e-02, | | | |
| -3.27885410759859649565e-02, | | | |
| 1.79706750811820387126e-02, | | | |
| -1.03142241298341437450e-02, | | | |
| 6.10053870246291332635e-03, | | | |
| -3.68452016781138256760e-03, | | | |
| 2.25964780900612472250e-03, | | | |
| -1.40346469989232843813e-03, | | | |
| 8.81081882437654011382e-04, | | | |
| -5.38595305356740546715e-04, | | | |
| 3.15632070903625950361e-04, | | | |
| -3.12754168375120860518e-04, | | | |
| 3.35529192635519073543e-04 }; | | | |
| static const double u[] = { -7.72156649015328655494e-02, | | | |
| 6.32827064025093366517e-01, | | | |
| 1.45492250137234768737e+00, | | | |
| 9.77717527963372745603e-01, | | | |
| 2.28963728064692451092e-01, | | | |
| 1.33810918536787660377e-02 }; | | | |
| static const double v[] = { 0.0, | | | |
| 2.45597793713041134822e+00, | | | |
| 2.12848976379893395361e+00, | | | |
| 7.69285150456672783825e-01, | | | |
| 1.04222645593369134254e-01, | | | |
| 3.21709242282423911810e-03 }; | | | |
| static const double tc = 1.46163214496836224576e+00; | | | |
| static const double tf = -1.21486290535849611461e-01; | | | |
| static const double tt = -3.63867699703950536541e-18; | | | |
| if (x <= 0.9) | | if (x <= 0.9) | |
| { | | { | |
| res = -std::log(x); | | res = -std::log(x); | |
| if (x >= 0.7316) | | if (x >= 0.7316) | |
| { | | { | |
| double y = 1.0-x; | | double y = 1.0-x; | |
| double z = y*y; | | double z = y*y; | |
| double p1 = a[0]+z*(a[2]+z*(a[4]+z*(a[6]+z*(a[8]+z*a[10])))
); | | double p1 = a[0]+z*(a[2]+z*(a[4]+z*(a[6]+z*(a[8]+z*a[10])))
); | |
| double p2 = z*(a[1]+z*(a[3]+z*(a[5]+z*(a[7]+z*(a[9]+z*a[11]
))))); | | double p2 = z*(a[1]+z*(a[3]+z*(a[5]+z*(a[7]+z*(a[9]+z*a[11]
))))); | |
| double p = y*p1+p2; | | double p = y*p1+p2; | |
| | | | |
| skipping to change at line 1433 | | skipping to change at line 1525 | |
| { | | { | |
| double y = x-1.0; | | double y = x-1.0; | |
| double p1 = y*(u[0]+y*(u[1]+y*(u[2]+y*(u[3]+y*(u[4]+y*u[5])
)))); | | double p1 = y*(u[0]+y*(u[1]+y*(u[2]+y*(u[3]+y*(u[4]+y*u[5])
)))); | |
| double p2 = 1.0+y*(v[1]+y*(v[2]+y*(v[3]+y*(v[4]+y*v[5])))); | | double p2 = 1.0+y*(v[1]+y*(v[2]+y*(v[3]+y*(v[4]+y*v[5])))); | |
| res += (-0.5*y + p1/p2); | | res += (-0.5*y + p1/p2); | |
| } | | } | |
| } | | } | |
| } | | } | |
| else if(x < 8.0) | | else if(x < 8.0) | |
| { | | { | |
|
| static const double s[] = { -7.72156649015328655494e-02, | | | |
| 2.14982415960608852501e-01, | | | |
| 3.25778796408930981787e-01, | | | |
| 1.46350472652464452805e-01, | | | |
| 2.66422703033638609560e-02, | | | |
| 1.84028451407337715652e-03, | | | |
| 3.19475326584100867617e-05 }; | | | |
| static const double r[] = { 0.0, | | | |
| 1.39200533467621045958e+00, | | | |
| 7.21935547567138069525e-01, | | | |
| 1.71933865632803078993e-01, | | | |
| 1.86459191715652901344e-02, | | | |
| 7.77942496381893596434e-04, | | | |
| 7.32668430744625636189e-06 }; | | | |
| double i = std::floor(x); | | double i = std::floor(x); | |
| double y = x-i; | | double y = x-i; | |
| double p = y*(s[0]+y*(s[1]+y*(s[2]+y*(s[3]+y*(s[4]+y*(s[5]+y*s[6]))
)))); | | double p = y*(s[0]+y*(s[1]+y*(s[2]+y*(s[3]+y*(s[4]+y*(s[5]+y*s[6]))
)))); | |
| double q = 1.0+y*(r[1]+y*(r[2]+y*(r[3]+y*(r[4]+y*(r[5]+y*r[6]))))); | | double q = 1.0+y*(r[1]+y*(r[2]+y*(r[3]+y*(r[4]+y*(r[5]+y*r[6]))))); | |
| res = 0.5*y+p/q; | | res = 0.5*y+p/q; | |
| double z = 1.0; | | double z = 1.0; | |
| while (i > 2.0) | | while (i > 2.0) | |
| { | | { | |
| --i; | | --i; | |
| z *= (y+i); | | z *= (y+i); | |
| } | | } | |
| res += std::log(z); | | res += std::log(z); | |
| } | | } | |
| else if (x < 2.8823037615171174e+17) | | else if (x < 2.8823037615171174e+17) | |
| { | | { | |
|
| static const double w[] = { 4.18938533204672725052e-01, | | | |
| 8.33333333333329678849e-02, | | | |
| -2.77777777728775536470e-03, | | | |
| 7.93650558643019558500e-04, | | | |
| -5.95187557450339963135e-04, | | | |
| 8.36339918996282139126e-04, | | | |
| -1.63092934096575273989e-03 }; | | | |
| double t = std::log(x); | | double t = std::log(x); | |
| double z = 1.0/x; | | double z = 1.0/x; | |
| double y = z*z; | | double y = z*z; | |
| double yy = w[0]+z*(w[1]+y*(w[2]+y*(w[3]+y*(w[4]+y*(w[5]+y*w[6]))))
); | | double yy = w[0]+z*(w[1]+y*(w[2]+y*(w[3]+y*(w[4]+y*(w[5]+y*w[6]))))
); | |
| res = (x-0.5)*(t-1.0)+yy; | | res = (x-0.5)*(t-1.0)+yy; | |
| } | | } | |
| else | | else | |
| { | | { | |
| res = x*(std::log(x) - 1.0); | | res = x*(std::log(x) - 1.0); | |
| } | | } | |
| | | | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! The gamma function. | | /** \brief The gamma function. | |
| | | | |
| This function implements the algorithm from<br> | | This function implements the algorithm from<br> | |
| Zhang and Jin: "Computation of Special Functions", John Wiley and S
ons, 1996. | | Zhang and Jin: "Computation of Special Functions", John Wiley and S
ons, 1996. | |
| | | | |
| The argument must be <= 171.0 and cannot be zero or a negative inte
ger. An | | The argument must be <= 171.0 and cannot be zero or a negative inte
ger. An | |
| exception is thrown when these conditions are violated. | | exception is thrown when these conditions are violated. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline double gamma(double x) | | inline double gamma(double x) | |
| { | | { | |
|
| return detail::gammaImpl(x); | | return detail::GammaImpl<double>::gamma(x); | |
| } | | } | |
| | | | |
|
| /*! The natural logarithm of the gamma function. | | /** \brief The natural logarithm of the gamma function. | |
| | | | |
| This function is based on a free implementation by Sun Microsystems
, Inc., see | | This function is based on a free implementation by Sun Microsystems
, Inc., see | |
| <a href="http://www.sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/sr
c/newlib/libm/mathfp/er_lgamma.c?rev=1.6&content-type=text/plain&cvsroot=sr
c">sourceware.org</a> archive. It can be removed once all compilers support
the new C99 | | <a href="http://www.sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/sr
c/newlib/libm/mathfp/er_lgamma.c?rev=1.6&content-type=text/plain&cvsroot=sr
c">sourceware.org</a> archive. It can be removed once all compilers support
the new C99 | |
| math functions. | | math functions. | |
| | | | |
| The argument must be positive and < 1e30. An exception is thrown wh
en these conditions are violated. | | The argument must be positive and < 1e30. An exception is thrown wh
en these conditions are violated. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| inline double loggamma(double x) | | inline double loggamma(double x) | |
| { | | { | |
|
| return detail::loggammaImpl(x); | | return detail::GammaImpl<double>::loggamma(x); | |
| } | | } | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| // both f1 and f2 are unsigned here | | // both f1 and f2 are unsigned here | |
| template<class FPT> | | template<class FPT> | |
| inline | | inline | |
| FPT safeFloatDivision( FPT f1, FPT f2 ) | | FPT safeFloatDivision( FPT f1, FPT f2 ) | |
| { | | { | |
| return f2 < NumericTraits<FPT>::one() && f1 > f2 * NumericTraits<FPT>:
:max() | | return f2 < NumericTraits<FPT>::one() && f1 > f2 * NumericTraits<FPT>:
:max() | |
| ? NumericTraits<FPT>::max() | | ? NumericTraits<FPT>::max() | |
| : (f2 > NumericTraits<FPT>::one() && f1 < f2 * NumericTrait
s<FPT>::smallestPositive()) || | | : (f2 > NumericTraits<FPT>::one() && f1 < f2 * NumericTrait
s<FPT>::smallestPositive()) || | |
| f1 == NumericTraits<FPT>::zero() | | f1 == NumericTraits<FPT>::zero() | |
| ? NumericTraits<FPT>::zero() | | ? NumericTraits<FPT>::zero() | |
| : f1/f2; | | : f1/f2; | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! Tolerance based floating-point comparison. | | /** \brief Tolerance based floating-point equality. | |
| | | | |
| Check whether two floating point numbers are equal within the given
tolerance. | | Check whether two floating point numbers are equal within the given
tolerance. | |
| This is useful because floating point numbers that should be equal
in theory are | | This is useful because floating point numbers that should be equal
in theory are | |
| rarely exactly equal in practice. If the tolerance \a epsilon is no
t given, | | rarely exactly equal in practice. If the tolerance \a epsilon is no
t given, | |
| twice the machine epsilon is used. | | twice the machine epsilon is used. | |
| | | | |
| <b>\#include</b> \<vigra/mathutil.hxx\><br> | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| | | | |
| skipping to change at line 1567 | | skipping to change at line 1638 | |
| return (d1 <= epsilon && d2 <= epsilon); | | return (d1 <= epsilon && d2 <= epsilon); | |
| } | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| inline bool closeAtTolerance(T1 l, T2 r) | | inline bool closeAtTolerance(T1 l, T2 r) | |
| { | | { | |
| typedef typename PromoteTraits<T1, T2>::Promote T; | | typedef typename PromoteTraits<T1, T2>::Promote T; | |
| return closeAtTolerance(l, r, T(2.0) * NumericTraits<T>::epsilon()); | | return closeAtTolerance(l, r, T(2.0) * NumericTraits<T>::epsilon()); | |
| } | | } | |
| | | | |
|
| | | /** \brief Tolerance based floating-point less-or-equal. | |
| | | | |
| | | Check whether two floating point numbers are less or equal within t | |
| | | he given tolerance. | |
| | | That is, \a l can actually be greater than \a r within the given \a | |
| | | epsilon. | |
| | | This is useful because floating point numbers that should be equal | |
| | | in theory are | |
| | | rarely exactly equal in practice. If the tolerance \a epsilon is no | |
| | | t given, | |
| | | twice the machine epsilon is used. | |
| | | | |
| | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| | | Namespace: vigra | |
| | | */ | |
| | | template <class T1, class T2> | |
| | | inline bool | |
| | | lessEqualAtTolerance(T1 l, T2 r, typename PromoteTraits<T1, T2>::Promote ep | |
| | | silon) | |
| | | { | |
| | | return l < r || closeAtTolerance(l, r, epsilon); | |
| | | } | |
| | | | |
| | | template <class T1, class T2> | |
| | | inline bool lessEqualAtTolerance(T1 l, T2 r) | |
| | | { | |
| | | typedef typename PromoteTraits<T1, T2>::Promote T; | |
| | | return lessEqualAtTolerance(l, r, T(2.0) * NumericTraits<T>::epsilon()) | |
| | | ; | |
| | | } | |
| | | | |
| | | /** \brief Tolerance based floating-point greater-or-equal. | |
| | | | |
| | | Check whether two floating point numbers are greater or equal withi | |
| | | n the given tolerance. | |
| | | That is, \a l can actually be less than \a r within the given \a ep | |
| | | silon. | |
| | | This is useful because floating point numbers that should be equal | |
| | | in theory are | |
| | | rarely exactly equal in practice. If the tolerance \a epsilon is no | |
| | | t given, | |
| | | twice the machine epsilon is used. | |
| | | | |
| | | <b>\#include</b> \<vigra/mathutil.hxx\><br> | |
| | | Namespace: vigra | |
| | | */ | |
| | | template <class T1, class T2> | |
| | | inline bool | |
| | | greaterEqualAtTolerance(T1 l, T2 r, typename PromoteTraits<T1, T2>::Promote | |
| | | epsilon) | |
| | | { | |
| | | return r < l || closeAtTolerance(l, r, epsilon); | |
| | | } | |
| | | | |
| | | template <class T1, class T2> | |
| | | inline bool greaterEqualAtTolerance(T1 l, T2 r) | |
| | | { | |
| | | typedef typename PromoteTraits<T1, T2>::Promote T; | |
| | | return greaterEqualAtTolerance(l, r, T(2.0) * NumericTraits<T>::epsilon | |
| | | ()); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
|
| | | #define VIGRA_MATH_FUNC_HELPER(TYPE) \ | |
| | | inline TYPE clipLower(const TYPE t){ \ | |
| | | return t < static_cast<TYPE>(0.0) ? static_cast<TYPE>(0.0) : t; \ | |
| | | } \ | |
| | | inline TYPE clipLower(const TYPE t,const TYPE valLow){ \ | |
| | | return t < static_cast<TYPE>(valLow) ? static_cast<TYPE>(valLow) : | |
| | | t; \ | |
| | | } \ | |
| | | inline TYPE clipUpper(const TYPE t,const TYPE valHigh){ \ | |
| | | return t > static_cast<TYPE>(valHigh) ? static_cast<TYPE>(valHigh) | |
| | | : t; \ | |
| | | } \ | |
| | | inline TYPE clip(const TYPE t,const TYPE valLow, const TYPE valHigh){ \ | |
| | | if(t<valLow) \ | |
| | | return valLow; \ | |
| | | else if(t>valHigh) \ | |
| | | return valHigh; \ | |
| | | else \ | |
| | | return t; \ | |
| | | } \ | |
| | | inline TYPE sum(const TYPE t){ \ | |
| | | return t; \ | |
| | | }\ | |
| | | inline NumericTraits<TYPE>::RealPromote mean(const TYPE t){ \ | |
| | | return t; \ | |
| | | }\ | |
| | | inline TYPE isZero(const TYPE t){ \ | |
| | | return t==static_cast<TYPE>(0); \ | |
| | | } \ | |
| | | inline NumericTraits<TYPE>::RealPromote sizeDividedSquaredNorm(const TY | |
| | | PE t){ \ | |
| | | return squaredNorm(t); \ | |
| | | } \ | |
| | | inline NumericTraits<TYPE>::RealPromote sizeDividedNorm(const TYPE t){ | |
| | | \ | |
| | | return norm(t); \ | |
| | | } | |
| | | | |
| | | VIGRA_MATH_FUNC_HELPER(unsigned char) | |
| | | VIGRA_MATH_FUNC_HELPER(unsigned short) | |
| | | VIGRA_MATH_FUNC_HELPER(unsigned int) | |
| | | VIGRA_MATH_FUNC_HELPER(unsigned long) | |
| | | VIGRA_MATH_FUNC_HELPER(unsigned long long) | |
| | | VIGRA_MATH_FUNC_HELPER(signed char) | |
| | | VIGRA_MATH_FUNC_HELPER(signed short) | |
| | | VIGRA_MATH_FUNC_HELPER(signed int) | |
| | | VIGRA_MATH_FUNC_HELPER(signed long) | |
| | | VIGRA_MATH_FUNC_HELPER(signed long long) | |
| | | VIGRA_MATH_FUNC_HELPER(float) | |
| | | VIGRA_MATH_FUNC_HELPER(double) | |
| | | VIGRA_MATH_FUNC_HELPER(long double) | |
| | | | |
| | | #undef VIGRA_MATH_FUNC_HELPER | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif /* VIGRA_MATHUTIL_HXX */ | | #endif /* VIGRA_MATHUTIL_HXX */ | |
| | | | |
End of changes. 59 change blocks. |
| 146 lines changed or deleted | | 334 lines changed or added | |
|
| matrix.hxx | | matrix.hxx | |
| | | | |
| skipping to change at line 116 | | skipping to change at line 116 | |
| (no one wants to spend half the day installing a new library just to | | (no one wants to spend half the day installing a new library just to | |
| discover that the new algorithm idea didn't work anyway). | | discover that the new algorithm idea didn't work anyway). | |
| | | | |
| <b>See also:</b> | | <b>See also:</b> | |
| <ul> | | <ul> | |
| <li> \ref LinearAlgebraFunctions | | <li> \ref LinearAlgebraFunctions | |
| </ul> | | </ul> | |
| | | | |
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
|
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class ALLOC = std::allocator<T> > | | template <class T, class ALLOC = std::allocator<T> > | |
| class Matrix | | class Matrix | |
| : public MultiArray<2, T, ALLOC> | | : public MultiArray<2, T, ALLOC> | |
| { | | { | |
| typedef MultiArray<2, T, ALLOC> BaseType; | | typedef MultiArray<2, T, ALLOC> BaseType; | |
| | | | |
| public: | | public: | |
| typedef Matrix<T, ALLOC> matrix_type; | | typedef Matrix<T, ALLOC> matrix_type; | |
| typedef TemporaryMatrix<T, ALLOC> temp_type; | | typedef TemporaryMatrix<T, ALLOC> temp_type; | |
|
| typedef MultiArrayView<2, T, UnstridedArrayTag> view_type; | | typedef MultiArrayView<2, T> view_type; | |
| typedef typename BaseType::value_type value_type; | | typedef typename BaseType::value_type value_type; | |
| typedef typename BaseType::pointer pointer; | | typedef typename BaseType::pointer pointer; | |
| typedef typename BaseType::const_pointer const_pointer; | | typedef typename BaseType::const_pointer const_pointer; | |
| typedef typename BaseType::reference reference; | | typedef typename BaseType::reference reference; | |
| typedef typename BaseType::const_reference const_reference; | | typedef typename BaseType::const_reference const_reference; | |
| typedef typename BaseType::difference_type difference_type; | | typedef typename BaseType::difference_type difference_type; | |
| typedef typename BaseType::difference_type_1 difference_type_1; | | typedef typename BaseType::difference_type_1 difference_type_1; | |
| typedef ALLOC allocator_type; | | typedef ALLOC allocator_type; | |
| | | | |
| /** default constructor | | /** default constructor | |
| | | | |
| skipping to change at line 153 | | skipping to change at line 153 | |
| */ | | */ | |
| explicit Matrix(ALLOC const & alloc) | | explicit Matrix(ALLOC const & alloc) | |
| : BaseType(alloc) | | : BaseType(alloc) | |
| {} | | {} | |
| | | | |
| /** construct with given shape and init all | | /** construct with given shape and init all | |
| elements with zero. Note that the order of the axes is | | elements with zero. Note that the order of the axes is | |
| <tt>difference_type(rows, columns)</tt> which | | <tt>difference_type(rows, columns)</tt> which | |
| is the opposite of the usual VIGRA convention. | | is the opposite of the usual VIGRA convention. | |
| */ | | */ | |
|
| explicit Matrix(const difference_type &shape, | | explicit Matrix(const difference_type &aShape, | |
| ALLOC const & alloc = allocator_type()) | | ALLOC const & alloc = allocator_type()) | |
|
| : BaseType(shape, alloc) | | : BaseType(aShape, alloc) | |
| {} | | {} | |
| | | | |
| /** construct with given shape and init all | | /** construct with given shape and init all | |
| elements with zero. Note that the order of the axes is | | elements with zero. Note that the order of the axes is | |
| <tt>(rows, columns)</tt> which | | <tt>(rows, columns)</tt> which | |
| is the opposite of the usual VIGRA convention. | | is the opposite of the usual VIGRA convention. | |
| */ | | */ | |
| Matrix(difference_type_1 rows, difference_type_1 columns, | | Matrix(difference_type_1 rows, difference_type_1 columns, | |
| ALLOC const & alloc = allocator_type()) | | ALLOC const & alloc = allocator_type()) | |
| : BaseType(difference_type(rows, columns), alloc) | | : BaseType(difference_type(rows, columns), alloc) | |
| {} | | {} | |
| | | | |
| /** construct with given shape and init all | | /** construct with given shape and init all | |
| elements with the constant \a init. Note that the order of the
axes is | | elements with the constant \a init. Note that the order of the
axes is | |
| <tt>difference_type(rows, columns)</tt> which | | <tt>difference_type(rows, columns)</tt> which | |
| is the opposite of the usual VIGRA convention. | | is the opposite of the usual VIGRA convention. | |
| */ | | */ | |
|
| Matrix(const difference_type &shape, const_reference init, | | Matrix(const difference_type &aShape, const_reference init, | |
| allocator_type const & alloc = allocator_type()) | | allocator_type const & alloc = allocator_type()) | |
|
| : BaseType(shape, init, alloc) | | : BaseType(aShape, init, alloc) | |
| {} | | {} | |
| | | | |
| /** construct with given shape and init all | | /** construct with given shape and init all | |
| elements with the constant \a init. Note that the order of the
axes is | | elements with the constant \a init. Note that the order of the
axes is | |
| <tt>(rows, columns)</tt> which | | <tt>(rows, columns)</tt> which | |
| is the opposite of the usual VIGRA convention. | | is the opposite of the usual VIGRA convention. | |
| */ | | */ | |
| Matrix(difference_type_1 rows, difference_type_1 columns, const_referen
ce init, | | Matrix(difference_type_1 rows, difference_type_1 columns, const_referen
ce init, | |
| allocator_type const & alloc = allocator_type()) | | allocator_type const & alloc = allocator_type()) | |
| : BaseType(difference_type(rows, columns), init, alloc) | | : BaseType(difference_type(rows, columns), init, alloc) | |
| | | | |
| skipping to change at line 335 | | skipping to change at line 335 | |
| | | | |
| /** reshape to the given shape and initialize with \a init. | | /** reshape to the given shape and initialize with \a init. | |
| */ | | */ | |
| void reshape(difference_type_1 rows, difference_type_1 columns, const_r
eference init) | | void reshape(difference_type_1 rows, difference_type_1 columns, const_r
eference init) | |
| { | | { | |
| BaseType::reshape(difference_type(rows, columns), init); | | BaseType::reshape(difference_type(rows, columns), init); | |
| } | | } | |
| | | | |
| /** reshape to the given shape and initialize with zero. | | /** reshape to the given shape and initialize with zero. | |
| */ | | */ | |
|
| void reshape(difference_type const & shape) | | void reshape(difference_type const & newShape) | |
| { | | { | |
|
| BaseType::reshape(shape); | | BaseType::reshape(newShape); | |
| } | | } | |
| | | | |
| /** reshape to the given shape and initialize with \a init. | | /** reshape to the given shape and initialize with \a init. | |
| */ | | */ | |
|
| void reshape(difference_type const & shape, const_reference init) | | void reshape(difference_type const & newShape, const_reference init) | |
| { | | { | |
|
| BaseType::reshape(shape, init); | | BaseType::reshape(newShape, init); | |
| } | | } | |
| | | | |
| /** Create a matrix view that represents the row vector of row \a d
. | | /** Create a matrix view that represents the row vector of row \a d
. | |
| */ | | */ | |
| view_type rowVector(difference_type_1 d) const | | view_type rowVector(difference_type_1 d) const | |
| { | | { | |
| return vigra::linalg::rowVector(*this, d); | | return vigra::linalg::rowVector(*this, d); | |
| } | | } | |
| | | | |
| /** Create a matrix view that represents the column vector of colum
n \a d. | | /** Create a matrix view that represents the column vector of colum
n \a d. | |
| | | | |
| skipping to change at line 550 | | skipping to change at line 550 | |
| // Functions receiving a TemporaryMatrix can thus often avoid to allocate n
ew temporary | | // Functions receiving a TemporaryMatrix can thus often avoid to allocate n
ew temporary | |
| // memory. | | // memory. | |
| template <class T, class ALLOC> // default ALLOC already declared above | | template <class T, class ALLOC> // default ALLOC already declared above | |
| class TemporaryMatrix | | class TemporaryMatrix | |
| : public Matrix<T, ALLOC> | | : public Matrix<T, ALLOC> | |
| { | | { | |
| typedef Matrix<T, ALLOC> BaseType; | | typedef Matrix<T, ALLOC> BaseType; | |
| public: | | public: | |
| typedef Matrix<T, ALLOC> matrix_type; | | typedef Matrix<T, ALLOC> matrix_type; | |
| typedef TemporaryMatrix<T, ALLOC> temp_type; | | typedef TemporaryMatrix<T, ALLOC> temp_type; | |
|
| typedef MultiArrayView<2, T, UnstridedArrayTag> view_type; | | typedef MultiArrayView<2, T, StridedArrayTag> view_type; | |
| typedef typename BaseType::value_type value_type; | | typedef typename BaseType::value_type value_type; | |
| typedef typename BaseType::pointer pointer; | | typedef typename BaseType::pointer pointer; | |
| typedef typename BaseType::const_pointer const_pointer; | | typedef typename BaseType::const_pointer const_pointer; | |
| typedef typename BaseType::reference reference; | | typedef typename BaseType::reference reference; | |
| typedef typename BaseType::const_reference const_reference; | | typedef typename BaseType::const_reference const_reference; | |
| typedef typename BaseType::difference_type difference_type; | | typedef typename BaseType::difference_type difference_type; | |
| typedef typename BaseType::difference_type_1 difference_type_1; | | typedef typename BaseType::difference_type_1 difference_type_1; | |
| typedef ALLOC allocator_type; | | typedef ALLOC allocator_type; | |
| | | | |
| TemporaryMatrix(difference_type const & shape) | | TemporaryMatrix(difference_type const & shape) | |
| | | | |
| skipping to change at line 660 | | skipping to change at line 660 | |
| /** \defgroup LinearAlgebraFunctions Matrix Functions | | /** \defgroup LinearAlgebraFunctions Matrix Functions | |
| | | | |
| \brief Basic matrix algebra, element-wise mathematical functions, row a
nd columns statistics, data normalization etc. | | \brief Basic matrix algebra, element-wise mathematical functions, row a
nd columns statistics, data normalization etc. | |
| | | | |
| \ingroup LinearAlgebraModule | | \ingroup LinearAlgebraModule | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /** Number of rows of a matrix represented as a <tt>MultiArrayView<2, .
..></tt> | | /** Number of rows of a matrix represented as a <tt>MultiArrayView<2, .
..></tt> | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline MultiArrayIndex | | inline MultiArrayIndex | |
| rowCount(const MultiArrayView<2, T, C> &x) | | rowCount(const MultiArrayView<2, T, C> &x) | |
| { | | { | |
| return x.shape(0); | | return x.shape(0); | |
| } | | } | |
| | | | |
| /** Number of columns of a matrix represented as a <tt>MultiArrayView<2
, ...></tt> | | /** Number of columns of a matrix represented as a <tt>MultiArrayView<2
, ...></tt> | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline MultiArrayIndex | | inline MultiArrayIndex | |
| columnCount(const MultiArrayView<2, T, C> &x) | | columnCount(const MultiArrayView<2, T, C> &x) | |
| { | | { | |
| return x.shape(1); | | return x.shape(1); | |
| } | | } | |
| | | | |
| /** Create a row vector view for row \a d of the matrix \a m | | /** Create a row vector view for row \a d of the matrix \a m | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline MultiArrayView <2, T, C> | | inline MultiArrayView <2, T, C> | |
| rowVector(MultiArrayView <2, T, C> const & m, MultiArrayIndex d) | | rowVector(MultiArrayView <2, T, C> const & m, MultiArrayIndex d) | |
| { | | { | |
| typedef typename MultiArrayView <2, T, C>::difference_type Shape; | | typedef typename MultiArrayView <2, T, C>::difference_type Shape; | |
| return m.subarray(Shape(d, 0), Shape(d+1, columnCount(m))); | | return m.subarray(Shape(d, 0), Shape(d+1, columnCount(m))); | |
| } | | } | |
| | | | |
| /** Create a row vector view of the matrix \a m starting at element \a
first and ranging | | /** Create a row vector view of the matrix \a m starting at element \a
first and ranging | |
| to column \a end (non-inclusive). | | to column \a end (non-inclusive). | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline MultiArrayView <2, T, C> | | inline MultiArrayView <2, T, C> | |
| rowVector(MultiArrayView <2, T, C> const & m, MultiArrayShape<2>::type firs
t, MultiArrayIndex end) | | rowVector(MultiArrayView <2, T, C> const & m, MultiArrayShape<2>::type firs
t, MultiArrayIndex end) | |
| { | | { | |
| typedef typename MultiArrayView <2, T, C>::difference_type Shape; | | typedef typename MultiArrayView <2, T, C>::difference_type Shape; | |
| return m.subarray(first, Shape(first[0]+1, end)); | | return m.subarray(first, Shape(first[0]+1, end)); | |
| } | | } | |
| | | | |
| /** Create a column vector view for column \a d of the matrix \a m | | /** Create a column vector view for column \a d of the matrix \a m | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline MultiArrayView <2, T, C> | | inline MultiArrayView <2, T, C> | |
| columnVector(MultiArrayView<2, T, C> const & m, MultiArrayIndex d) | | columnVector(MultiArrayView<2, T, C> const & m, MultiArrayIndex d) | |
| { | | { | |
| typedef typename MultiArrayView <2, T, C>::difference_type Shape; | | typedef typename MultiArrayView <2, T, C>::difference_type Shape; | |
| return m.subarray(Shape(0, d), Shape(rowCount(m), d+1)); | | return m.subarray(Shape(0, d), Shape(rowCount(m), d+1)); | |
| } | | } | |
| | | | |
| /** Create a column vector view of the matrix \a m starting at element
\a first and | | /** Create a column vector view of the matrix \a m starting at element
\a first and | |
| ranging to row \a end (non-inclusive). | | ranging to row \a end (non-inclusive). | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| **/ | | **/ | |
| template <class T, class C> | | template <class T, class C> | |
| inline MultiArrayView <2, T, C> | | inline MultiArrayView <2, T, C> | |
| columnVector(MultiArrayView<2, T, C> const & m, MultiArrayShape<2>::type fi
rst, int end) | | columnVector(MultiArrayView<2, T, C> const & m, MultiArrayShape<2>::type fi
rst, int end) | |
| { | | { | |
| typedef typename MultiArrayView <2, T, C>::difference_type Shape; | | typedef typename MultiArrayView <2, T, C>::difference_type Shape; | |
| return m.subarray(first, Shape(end, first[1]+1)); | | return m.subarray(first, Shape(end, first[1]+1)); | |
| } | | } | |
| | | | |
| /** Create a sub vector view of the vector \a m starting at element \a
first and | | /** Create a sub vector view of the vector \a m starting at element \a
first and | |
| ranging to row \a end (non-inclusive). | | ranging to row \a end (non-inclusive). | |
| | | | |
| Note: This function may only be called when either <tt>rowCount(m)
== 1</tt> or | | Note: This function may only be called when either <tt>rowCount(m)
== 1</tt> or | |
| <tt>columnCount(m) == 1</tt>, i.e. when \a m really represents a ve
ctor. | | <tt>columnCount(m) == 1</tt>, i.e. when \a m really represents a ve
ctor. | |
| Otherwise, a PreconditionViolation exception is raised. | | Otherwise, a PreconditionViolation exception is raised. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| **/ | | **/ | |
| template <class T, class C> | | template <class T, class C> | |
| inline MultiArrayView <2, T, C> | | inline MultiArrayView <2, T, C> | |
| subVector(MultiArrayView<2, T, C> const & m, int first, int end) | | subVector(MultiArrayView<2, T, C> const & m, int first, int end) | |
| { | | { | |
| typedef typename MultiArrayView <2, T, C>::difference_type Shape; | | typedef typename MultiArrayView <2, T, C>::difference_type Shape; | |
| if(columnCount(m) == 1) | | if(columnCount(m) == 1) | |
| return m.subarray(Shape(first, 0), Shape(end, 1)); | | return m.subarray(Shape(first, 0), Shape(end, 1)); | |
| vigra_precondition(rowCount(m) == 1, | | vigra_precondition(rowCount(m) == 1, | |
| "linalg::subVector(): Input must be a vector (1xN or
Nx1)."); | | "linalg::subVector(): Input must be a vector (1xN or
Nx1)."); | |
| return m.subarray(Shape(0, first), Shape(1, end)); | | return m.subarray(Shape(0, first), Shape(1, end)); | |
| } | | } | |
| | | | |
| /** Check whether matrix \a m is symmetric. | | /** Check whether matrix \a m is symmetric. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| bool | | bool | |
| isSymmetric(MultiArrayView<2, T, C> const & m) | | isSymmetric(MultiArrayView<2, T, C> const & m) | |
| { | | { | |
| const MultiArrayIndex size = rowCount(m); | | const MultiArrayIndex size = rowCount(m); | |
| if(size != columnCount(m)) | | if(size != columnCount(m)) | |
| return false; | | return false; | |
| | | | |
| for(MultiArrayIndex i = 0; i < size; ++i) | | for(MultiArrayIndex i = 0; i < size; ++i) | |
| for(MultiArrayIndex j = i+1; j < size; ++j) | | for(MultiArrayIndex j = i+1; j < size; ++j) | |
| if(m(j, i) != m(i, j)) | | if(m(j, i) != m(i, j)) | |
| return false; | | return false; | |
| return true; | | return true; | |
| } | | } | |
| | | | |
| /** Compute the trace of a square matrix. | | /** Compute the trace of a square matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| typename NumericTraits<T>::Promote | | typename NumericTraits<T>::Promote | |
| trace(MultiArrayView<2, T, C> const & m) | | trace(MultiArrayView<2, T, C> const & m) | |
| { | | { | |
| typedef typename NumericTraits<T>::Promote SumType; | | typedef typename NumericTraits<T>::Promote SumType; | |
| | | | |
| const MultiArrayIndex size = rowCount(m); | | const MultiArrayIndex size = rowCount(m); | |
| vigra_precondition(size == columnCount(m), "linalg::trace(): Matrix mus
t be square."); | | vigra_precondition(size == columnCount(m), "linalg::trace(): Matrix mus
t be square."); | |
| | | | |
| skipping to change at line 812 | | skipping to change at line 812 | |
| for(MultiArrayIndex i = 0; i < size; ++i) | | for(MultiArrayIndex i = 0; i < size; ++i) | |
| sum += m(i, i); | | sum += m(i, i); | |
| return sum; | | return sum; | |
| } | | } | |
| | | | |
| #ifdef DOXYGEN // documentation only -- function is already defined in vigr
a/multi_array.hxx | | #ifdef DOXYGEN // documentation only -- function is already defined in vigr
a/multi_array.hxx | |
| | | | |
| /** calculate the squared Frobenius norm of a matrix. | | /** calculate the squared Frobenius norm of a matrix. | |
| Equal to the sum of squares of the matrix elements. | | Equal to the sum of squares of the matrix elements. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> | | <b>\#include</b> \<vigra/matrix.hxx\> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T, class ALLOC> | | template <class T, class ALLOC> | |
| typename Matrix<T, ALLLOC>::SquaredNormType | | typename Matrix<T, ALLLOC>::SquaredNormType | |
| squaredNorm(const Matrix<T, ALLLOC> &a); | | squaredNorm(const Matrix<T, ALLLOC> &a); | |
| | | | |
| /** calculate the Frobenius norm of a matrix. | | /** calculate the Frobenius norm of a matrix. | |
| Equal to the root of the sum of squares of the matrix elements. | | Equal to the root of the sum of squares of the matrix elements. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> | | <b>\#include</b> \<vigra/matrix.hxx\> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T, class ALLOC> | | template <class T, class ALLOC> | |
| typename Matrix<T, ALLLOC>::NormType | | typename Matrix<T, ALLLOC>::NormType | |
| norm(const Matrix<T, ALLLOC> &a); | | norm(const Matrix<T, ALLLOC> &a); | |
| | | | |
| #endif // DOXYGEN | | #endif // DOXYGEN | |
| | | | |
| /** initialize the given square matrix as an identity matrix. | | /** initialize the given square matrix as an identity matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| void identityMatrix(MultiArrayView<2, T, C> &r) | | void identityMatrix(MultiArrayView<2, T, C> &r) | |
| { | | { | |
| const MultiArrayIndex rows = rowCount(r); | | const MultiArrayIndex rows = rowCount(r); | |
| vigra_precondition(rows == columnCount(r), | | vigra_precondition(rows == columnCount(r), | |
| "identityMatrix(): Matrix must be square."); | | "identityMatrix(): Matrix must be square."); | |
| for(MultiArrayIndex i = 0; i < rows; ++i) { | | for(MultiArrayIndex i = 0; i < rows; ++i) { | |
| for(MultiArrayIndex j = 0; j < rows; ++j) | | for(MultiArrayIndex j = 0; j < rows; ++j) | |
| | | | |
| skipping to change at line 857 | | skipping to change at line 857 | |
| } | | } | |
| } | | } | |
| | | | |
| /** create an identity matrix of the given size. | | /** create an identity matrix of the given size. | |
| Usage: | | Usage: | |
| | | | |
| \code | | \code | |
| vigra::Matrix<double> m = vigra::identityMatrix<double>(size); | | vigra::Matrix<double> m = vigra::identityMatrix<double>(size); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T> | | template <class T> | |
| TemporaryMatrix<T> identityMatrix(MultiArrayIndex size) | | TemporaryMatrix<T> identityMatrix(MultiArrayIndex size) | |
| { | | { | |
| TemporaryMatrix<T> ret(size, size, NumericTraits<T>::zero()); | | TemporaryMatrix<T> ret(size, size, NumericTraits<T>::zero()); | |
| for(MultiArrayIndex i = 0; i < size; ++i) | | for(MultiArrayIndex i = 0; i < size; ++i) | |
| ret(i, i) = NumericTraits<T>::one(); | | ret(i, i) = NumericTraits<T>::one(); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| /** create matrix of ones of the given size. | | /** create matrix of ones of the given size. | |
| Usage: | | Usage: | |
| | | | |
| \code | | \code | |
| vigra::Matrix<double> m = vigra::ones<double>(rows, cols); | | vigra::Matrix<double> m = vigra::ones<double>(rows, cols); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T> | | template <class T> | |
| TemporaryMatrix<T> ones(MultiArrayIndex rows, MultiArrayIndex cols) | | TemporaryMatrix<T> ones(MultiArrayIndex rows, MultiArrayIndex cols) | |
| { | | { | |
| return TemporaryMatrix<T>(rows, cols, NumericTraits<T>::one()); | | return TemporaryMatrix<T>(rows, cols, NumericTraits<T>::one()); | |
| } | | } | |
| | | | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| void diagonalMatrixImpl(MultiArrayView<1, T, C1> const & v, MultiArrayView<
2, T, C2> &r) | | void diagonalMatrixImpl(MultiArrayView<1, T, C1> const & v, MultiArrayView<
2, T, C2> &r) | |
| | | | |
| skipping to change at line 901 | | skipping to change at line 901 | |
| vigra_precondition(rowCount(r) == size && columnCount(r) == size, | | vigra_precondition(rowCount(r) == size && columnCount(r) == size, | |
| "diagonalMatrix(): result must be a square matrix."); | | "diagonalMatrix(): result must be a square matrix."); | |
| for(MultiArrayIndex i = 0; i < size; ++i) | | for(MultiArrayIndex i = 0; i < size; ++i) | |
| r(i, i) = v(i); | | r(i, i) = v(i); | |
| } | | } | |
| | | | |
| /** make a diagonal matrix from a vector. | | /** make a diagonal matrix from a vector. | |
| The vector is given as matrix \a v, which must either have a single | | The vector is given as matrix \a v, which must either have a single | |
| row or column. The result is written into the square matrix \a r. | | row or column. The result is written into the square matrix \a r. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| void diagonalMatrix(MultiArrayView<2, T, C1> const & v, MultiArrayView<2, T
, C2> &r) | | void diagonalMatrix(MultiArrayView<2, T, C1> const & v, MultiArrayView<2, T
, C2> &r) | |
| { | | { | |
| vigra_precondition(rowCount(v) == 1 || columnCount(v) == 1, | | vigra_precondition(rowCount(v) == 1 || columnCount(v) == 1, | |
| "diagonalMatrix(): input must be a vector."); | | "diagonalMatrix(): input must be a vector."); | |
| r.init(NumericTraits<T>::zero()); | | r.init(NumericTraits<T>::zero()); | |
| if(rowCount(v) == 1) | | if(rowCount(v) == 1) | |
| diagonalMatrixImpl(v.bindInner(0), r); | | diagonalMatrixImpl(v.bindInner(0), r); | |
| | | | |
| skipping to change at line 929 | | skipping to change at line 929 | |
| row or column. The result is returned as a temporary matrix. | | row or column. The result is returned as a temporary matrix. | |
| Usage: | | Usage: | |
| | | | |
| \code | | \code | |
| vigra::Matrix<double> v(1, len); | | vigra::Matrix<double> v(1, len); | |
| v = ...; | | v = ...; | |
| | | | |
| vigra::Matrix<double> m = diagonalMatrix(v); | | vigra::Matrix<double> m = diagonalMatrix(v); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| TemporaryMatrix<T> diagonalMatrix(MultiArrayView<2, T, C> const & v) | | TemporaryMatrix<T> diagonalMatrix(MultiArrayView<2, T, C> const & v) | |
| { | | { | |
| vigra_precondition(rowCount(v) == 1 || columnCount(v) == 1, | | vigra_precondition(rowCount(v) == 1 || columnCount(v) == 1, | |
| "diagonalMatrix(): input must be a vector."); | | "diagonalMatrix(): input must be a vector."); | |
| MultiArrayIndex size = v.elementCount(); | | MultiArrayIndex size = v.elementCount(); | |
| TemporaryMatrix<T> ret(size, size, NumericTraits<T>::zero()); | | TemporaryMatrix<T> ret(size, size, NumericTraits<T>::zero()); | |
| if(rowCount(v) == 1) | | if(rowCount(v) == 1) | |
| diagonalMatrixImpl(v.bindInner(0), ret); | | diagonalMatrixImpl(v.bindInner(0), ret); | |
| else | | else | |
| diagonalMatrixImpl(v.bindOuter(0), ret); | | diagonalMatrixImpl(v.bindOuter(0), ret); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| /** transpose matrix \a v. | | /** transpose matrix \a v. | |
| The result is written into \a r which must have the correct (i.e. | | The result is written into \a r which must have the correct (i.e. | |
| transposed) shape. | | transposed) shape. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| void transpose(const MultiArrayView<2, T, C1> &v, MultiArrayView<2, T, C2>
&r) | | void transpose(const MultiArrayView<2, T, C1> &v, MultiArrayView<2, T, C2>
&r) | |
| { | | { | |
| const MultiArrayIndex rows = rowCount(r); | | const MultiArrayIndex rows = rowCount(r); | |
| const MultiArrayIndex cols = columnCount(r); | | const MultiArrayIndex cols = columnCount(r); | |
| vigra_precondition(rows == columnCount(v) && cols == rowCount(v), | | vigra_precondition(rows == columnCount(v) && cols == rowCount(v), | |
| "transpose(): arrays must have transposed shapes."); | | "transpose(): arrays must have transposed shapes."); | |
| for(MultiArrayIndex i = 0; i < cols; ++i) | | for(MultiArrayIndex i = 0; i < cols; ++i) | |
| | | | |
| skipping to change at line 980 | | skipping to change at line 980 | |
| is assigned to another matrix. | | is assigned to another matrix. | |
| Usage: | | Usage: | |
| | | | |
| \code | | \code | |
| vigra::Matrix<double> v(rows, cols); | | vigra::Matrix<double> v(rows, cols); | |
| v = ...; | | v = ...; | |
| | | | |
| vigra::Matrix<double> m = transpose(v); | | vigra::Matrix<double> m = transpose(v); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline MultiArrayView<2, T, StridedArrayTag> | | inline MultiArrayView<2, T, StridedArrayTag> | |
| transpose(MultiArrayView<2, T, C> const & v) | | transpose(MultiArrayView<2, T, C> const & v) | |
| { | | { | |
| return v.transpose(); | | return v.transpose(); | |
| } | | } | |
| | | | |
| /** Create new matrix by concatenating two matrices \a a and \a b verti
cally, i.e. on top of each other. | | /** Create new matrix by concatenating two matrices \a a and \a b verti
cally, i.e. on top of each other. | |
| The two matrices must have the same number of columns. | | The two matrices must have the same number of columns. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| joinVertically(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T
, C2> &b) | | joinVertically(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T
, C2> &b) | |
| { | | { | |
| typedef typename TemporaryMatrix<T>::difference_type Shape; | | typedef typename TemporaryMatrix<T>::difference_type Shape; | |
| | | | |
| MultiArrayIndex n = columnCount(a); | | MultiArrayIndex n = columnCount(a); | |
| vigra_precondition(n == columnCount(b), | | vigra_precondition(n == columnCount(b), | |
| | | | |
| skipping to change at line 1021 | | skipping to change at line 1021 | |
| TemporaryMatrix<T> t(ma + mb, n, T()); | | TemporaryMatrix<T> t(ma + mb, n, T()); | |
| t.subarray(Shape(0,0), Shape(ma, n)) = a; | | t.subarray(Shape(0,0), Shape(ma, n)) = a; | |
| t.subarray(Shape(ma,0), Shape(ma+mb, n)) = b; | | t.subarray(Shape(ma,0), Shape(ma+mb, n)) = b; | |
| return t; | | return t; | |
| } | | } | |
| | | | |
| /** Create new matrix by concatenating two matrices \a a and \a b horiz
ontally, i.e. side by side. | | /** Create new matrix by concatenating two matrices \a a and \a b horiz
ontally, i.e. side by side. | |
| The two matrices must have the same number of rows. | | The two matrices must have the same number of rows. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| joinHorizontally(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2,
T, C2> &b) | | joinHorizontally(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2,
T, C2> &b) | |
| { | | { | |
| typedef typename TemporaryMatrix<T>::difference_type Shape; | | typedef typename TemporaryMatrix<T>::difference_type Shape; | |
| | | | |
| MultiArrayIndex m = rowCount(a); | | MultiArrayIndex m = rowCount(a); | |
| vigra_precondition(m == rowCount(b), | | vigra_precondition(m == rowCount(b), | |
| | | | |
| skipping to change at line 1049 | | skipping to change at line 1049 | |
| t.subarray(Shape(0, na), Shape(m, na + nb)) = b; | | t.subarray(Shape(0, na), Shape(m, na + nb)) = b; | |
| return t; | | return t; | |
| } | | } | |
| | | | |
| /** Initialize a matrix with repeated copies of a given matrix. | | /** Initialize a matrix with repeated copies of a given matrix. | |
| | | | |
| Matrix \a r will consist of \a verticalCount downward repetitions o
f \a v, | | Matrix \a r will consist of \a verticalCount downward repetitions o
f \a v, | |
| and \a horizontalCount side-by-side repetitions. When \a v has size
<tt>m</tt> by <tt>n</tt>, | | and \a horizontalCount side-by-side repetitions. When \a v has size
<tt>m</tt> by <tt>n</tt>, | |
| \a r must have size <tt>(m*verticalCount)</tt> by <tt>(n*horizontal
Count)</tt>. | | \a r must have size <tt>(m*verticalCount)</tt> by <tt>(n*horizontal
Count)</tt>. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| void repeatMatrix(MultiArrayView<2, T, C1> const & v, MultiArrayView<2, T,
C2> &r, | | void repeatMatrix(MultiArrayView<2, T, C1> const & v, MultiArrayView<2, T,
C2> &r, | |
| unsigned int verticalCount, unsigned int horizontalCount) | | unsigned int verticalCount, unsigned int horizontalCount) | |
| { | | { | |
| typedef typename Matrix<T>::difference_type Shape; | | typedef typename Matrix<T>::difference_type Shape; | |
| | | | |
| MultiArrayIndex m = rowCount(v), n = columnCount(v); | | MultiArrayIndex m = rowCount(v), n = columnCount(v); | |
| vigra_precondition(m*verticalCount == rowCount(r) && n*horizontalCount
== columnCount(r), | | vigra_precondition(m*verticalCount == rowCount(r) && n*horizontalCount
== columnCount(r), | |
| "repeatMatrix(): Shape mismatch."); | | "repeatMatrix(): Shape mismatch."); | |
| | | | |
|
| for(MultiArrayIndex l=0; l<(MultiArrayIndex)horizontalCount; ++l) | | for(MultiArrayIndex l=0; l<static_cast<MultiArrayIndex>(horizontalCount
); ++l) | |
| { | | { | |
|
| for(MultiArrayIndex k=0; k<(MultiArrayIndex)verticalCount; ++k) | | for(MultiArrayIndex k=0; k<static_cast<MultiArrayIndex>(verticalCou
nt); ++k) | |
| { | | { | |
| r.subarray(Shape(k*m, l*n), Shape((k+1)*m, (l+1)*n)) = v; | | r.subarray(Shape(k*m, l*n), Shape((k+1)*m, (l+1)*n)) = v; | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| /** Create a new matrix by repeating a given matrix. | | /** Create a new matrix by repeating a given matrix. | |
| | | | |
| The resulting matrix \a r will consist of \a verticalCount downward
repetitions of \a v, | | The resulting matrix \a r will consist of \a verticalCount downward
repetitions of \a v, | |
| and \a horizontalCount side-by-side repetitions, i.e. it will be of
size | | and \a horizontalCount side-by-side repetitions, i.e. it will be of
size | |
| <tt>(m*verticalCount)</tt> by <tt>(n*horizontalCount)</tt> when \a
v has size <tt>m</tt> by <tt>n</tt>. | | <tt>(m*verticalCount)</tt> by <tt>(n*horizontalCount)</tt> when \a
v has size <tt>m</tt> by <tt>n</tt>. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| TemporaryMatrix<T> | | TemporaryMatrix<T> | |
| repeatMatrix(MultiArrayView<2, T, C> const & v, unsigned int verticalCount,
unsigned int horizontalCount) | | repeatMatrix(MultiArrayView<2, T, C> const & v, unsigned int verticalCount,
unsigned int horizontalCount) | |
| { | | { | |
| MultiArrayIndex m = rowCount(v), n = columnCount(v); | | MultiArrayIndex m = rowCount(v), n = columnCount(v); | |
| TemporaryMatrix<T> ret(verticalCount*m, horizontalCount*n); | | TemporaryMatrix<T> ret(verticalCount*m, horizontalCount*n); | |
| repeatMatrix(v, ret, verticalCount, horizontalCount); | | repeatMatrix(v, ret, verticalCount, horizontalCount); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| /** add matrices \a a and \a b. | | /** add matrices \a a and \a b. | |
| The result is written into \a r. All three matrices must have the s
ame shape. | | The result is written into \a r. All three matrices must have the s
ame shape. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| void add(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | | void add(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | |
| MultiArrayView<2, T, C3> &r) | | MultiArrayView<2, T, C3> &r) | |
| { | | { | |
| const MultiArrayIndex rrows = rowCount(r); | | const MultiArrayIndex rrows = rowCount(r); | |
| const MultiArrayIndex rcols = columnCount(r); | | const MultiArrayIndex rcols = columnCount(r); | |
| vigra_precondition(rrows == rowCount(a) && rcols == columnCount(a) && | | vigra_precondition(rrows == rowCount(a) && rcols == columnCount(a) && | |
| rrows == rowCount(b) && rcols == columnCount(b), | | rrows == rowCount(b) && rcols == columnCount(b), | |
| | | | |
| skipping to change at line 1121 | | skipping to change at line 1121 | |
| for(MultiArrayIndex j = 0; j < rrows; ++j) { | | for(MultiArrayIndex j = 0; j < rrows; ++j) { | |
| r(j, i) = a(j, i) + b(j, i); | | r(j, i) = a(j, i) + b(j, i); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| /** add matrices \a a and \a b. | | /** add matrices \a a and \a b. | |
| The two matrices must have the same shape. | | The two matrices must have the same shape. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator+(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b) | | operator+(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b) | |
| { | | { | |
| return TemporaryMatrix<T>(a) += b; | | return TemporaryMatrix<T>(a) += b; | |
| } | | } | |
| | | | |
| template <class T, class C> | | template <class T, class C> | |
| | | | |
| skipping to change at line 1156 | | skipping to change at line 1156 | |
| template <class T> | | template <class T> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator+(const TemporaryMatrix<T> &a, const TemporaryMatrix<T> &b) | | operator+(const TemporaryMatrix<T> &a, const TemporaryMatrix<T> &b) | |
| { | | { | |
| return const_cast<TemporaryMatrix<T> &>(a) += b; | | return const_cast<TemporaryMatrix<T> &>(a) += b; | |
| } | | } | |
| | | | |
| /** add scalar \a b to every element of the matrix \a a. | | /** add scalar \a b to every element of the matrix \a a. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator+(const MultiArrayView<2, T, C> &a, T b) | | operator+(const MultiArrayView<2, T, C> &a, T b) | |
| { | | { | |
| return TemporaryMatrix<T>(a) += b; | | return TemporaryMatrix<T>(a) += b; | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator+(const TemporaryMatrix<T> &a, T b) | | operator+(const TemporaryMatrix<T> &a, T b) | |
| { | | { | |
| return const_cast<TemporaryMatrix<T> &>(a) += b; | | return const_cast<TemporaryMatrix<T> &>(a) += b; | |
| } | | } | |
| | | | |
| /** add scalar \a a to every element of the matrix \a b. | | /** add scalar \a a to every element of the matrix \a b. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator+(T a, const MultiArrayView<2, T, C> &b) | | operator+(T a, const MultiArrayView<2, T, C> &b) | |
| { | | { | |
| return TemporaryMatrix<T>(b) += a; | | return TemporaryMatrix<T>(b) += a; | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator+(T a, const TemporaryMatrix<T> &b) | | operator+(T a, const TemporaryMatrix<T> &b) | |
| { | | { | |
| return const_cast<TemporaryMatrix<T> &>(b) += a; | | return const_cast<TemporaryMatrix<T> &>(b) += a; | |
| } | | } | |
| | | | |
| /** subtract matrix \a b from \a a. | | /** subtract matrix \a b from \a a. | |
| The result is written into \a r. All three matrices must have the s
ame shape. | | The result is written into \a r. All three matrices must have the s
ame shape. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| void sub(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | | void sub(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | |
| MultiArrayView<2, T, C3> &r) | | MultiArrayView<2, T, C3> &r) | |
| { | | { | |
| const MultiArrayIndex rrows = rowCount(r); | | const MultiArrayIndex rrows = rowCount(r); | |
| const MultiArrayIndex rcols = columnCount(r); | | const MultiArrayIndex rcols = columnCount(r); | |
| vigra_precondition(rrows == rowCount(a) && rcols == columnCount(a) && | | vigra_precondition(rrows == rowCount(a) && rcols == columnCount(a) && | |
| rrows == rowCount(b) && rcols == columnCount(b), | | rrows == rowCount(b) && rcols == columnCount(b), | |
| | | | |
| skipping to change at line 1223 | | skipping to change at line 1223 | |
| for(MultiArrayIndex j = 0; j < rrows; ++j) { | | for(MultiArrayIndex j = 0; j < rrows; ++j) { | |
| r(j, i) = a(j, i) - b(j, i); | | r(j, i) = a(j, i) - b(j, i); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| /** subtract matrix \a b from \a a. | | /** subtract matrix \a b from \a a. | |
| The two matrices must have the same shape. | | The two matrices must have the same shape. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator-(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b) | | operator-(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b) | |
| { | | { | |
| return TemporaryMatrix<T>(a) -= b; | | return TemporaryMatrix<T>(a) -= b; | |
| } | | } | |
| | | | |
| template <class T, class C> | | template <class T, class C> | |
| | | | |
| skipping to change at line 1266 | | skipping to change at line 1266 | |
| template <class T> | | template <class T> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator-(const TemporaryMatrix<T> &a, const TemporaryMatrix<T> &b) | | operator-(const TemporaryMatrix<T> &a, const TemporaryMatrix<T> &b) | |
| { | | { | |
| return const_cast<TemporaryMatrix<T> &>(a) -= b; | | return const_cast<TemporaryMatrix<T> &>(a) -= b; | |
| } | | } | |
| | | | |
| /** negate matrix \a a. | | /** negate matrix \a a. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator-(const MultiArrayView<2, T, C> &a) | | operator-(const MultiArrayView<2, T, C> &a) | |
| { | | { | |
| return TemporaryMatrix<T>(a) *= -NumericTraits<T>::one(); | | return TemporaryMatrix<T>(a) *= -NumericTraits<T>::one(); | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator-(const TemporaryMatrix<T> &a) | | operator-(const TemporaryMatrix<T> &a) | |
| { | | { | |
| return const_cast<TemporaryMatrix<T> &>(a) *= -NumericTraits<T>::one(); | | return const_cast<TemporaryMatrix<T> &>(a) *= -NumericTraits<T>::one(); | |
| } | | } | |
| | | | |
| /** subtract scalar \a b from every element of the matrix \a a. | | /** subtract scalar \a b from every element of the matrix \a a. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator-(const MultiArrayView<2, T, C> &a, T b) | | operator-(const MultiArrayView<2, T, C> &a, T b) | |
| { | | { | |
| return TemporaryMatrix<T>(a) -= b; | | return TemporaryMatrix<T>(a) -= b; | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator-(const TemporaryMatrix<T> &a, T b) | | operator-(const TemporaryMatrix<T> &a, T b) | |
| { | | { | |
| return const_cast<TemporaryMatrix<T> &>(a) -= b; | | return const_cast<TemporaryMatrix<T> &>(a) -= b; | |
| } | | } | |
| | | | |
| /** subtract every element of the matrix \a b from scalar \a a. | | /** subtract every element of the matrix \a b from scalar \a a. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator-(T a, const MultiArrayView<2, T, C> &b) | | operator-(T a, const MultiArrayView<2, T, C> &b) | |
| { | | { | |
| return TemporaryMatrix<T>(b.shape(), a) -= b; | | return TemporaryMatrix<T>(b.shape(), a) -= b; | |
| } | | } | |
| | | | |
| /** calculate the inner product of two matrices representing vectors. | | /** calculate the inner product of two matrices representing vectors. | |
| Typically, matrix \a x has a single row, and matrix \a y has | | Typically, matrix \a x has a single row, and matrix \a y has | |
| a single column, and the other dimensions match. In addition, this | | a single column, and the other dimensions match. In addition, this | |
| function handles the cases when either or both of the two inputs ar
e | | function handles the cases when either or both of the two inputs ar
e | |
| transposed (e.g. it can compute the dot product of two column vecto
rs). | | transposed (e.g. it can compute the dot product of two column vecto
rs). | |
| A <tt>PreconditionViolation</tt> exception is thrown when | | A <tt>PreconditionViolation</tt> exception is thrown when | |
| the shape conditions are violated. | | the shape conditions are violated. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| typename NormTraits<T>::SquaredNormType | | typename NormTraits<T>::SquaredNormType | |
| dot(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2> &y) | | dot(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2> &y) | |
| { | | { | |
| typename NormTraits<T>::SquaredNormType ret = | | typename NormTraits<T>::SquaredNormType ret = | |
| NumericTraits<typename NormTraits<T>::SquaredNormType>::zero(); | | NumericTraits<typename NormTraits<T>::SquaredNormType>::zero(); | |
| if(y.shape(1) == 1) | | if(y.shape(1) == 1) | |
| { | | { | |
| | | | |
| skipping to change at line 1369 | | skipping to change at line 1369 | |
| vigra_precondition(false, "dot(): wrong matrix shapes."); | | vigra_precondition(false, "dot(): wrong matrix shapes."); | |
| } | | } | |
| else | | else | |
| vigra_precondition(false, "dot(): wrong matrix shapes."); | | vigra_precondition(false, "dot(): wrong matrix shapes."); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| /** calculate the inner product of two vectors. The vector | | /** calculate the inner product of two vectors. The vector | |
| lengths must match. | | lengths must match. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| typename NormTraits<T>::SquaredNormType | | typename NormTraits<T>::SquaredNormType | |
| dot(const MultiArrayView<1, T, C1> &x, const MultiArrayView<1, T, C2> &y) | | dot(const MultiArrayView<1, T, C1> &x, const MultiArrayView<1, T, C2> &y) | |
| { | | { | |
| const MultiArrayIndex n = x.elementCount(); | | const MultiArrayIndex n = x.elementCount(); | |
| vigra_precondition(n == y.elementCount(), | | vigra_precondition(n == y.elementCount(), | |
| "dot(): shape mismatch."); | | "dot(): shape mismatch."); | |
| typename NormTraits<T>::SquaredNormType ret = | | typename NormTraits<T>::SquaredNormType ret = | |
| NumericTraits<typename NormTraits<T>::SquaredNormType>::zer
o(); | | NumericTraits<typename NormTraits<T>::SquaredNormType>::zer
o(); | |
| for(MultiArrayIndex i = 0; i < n; ++i) | | for(MultiArrayIndex i = 0; i < n; ++i) | |
| ret += x(i) * y(i); | | ret += x(i) * y(i); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| /** calculate the cross product of two vectors of length 3. | | /** calculate the cross product of two vectors of length 3. | |
| The result is written into \a r. | | The result is written into \a r. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| void cross(const MultiArrayView<1, T, C1> &x, const MultiArrayView<1, T, C2
> &y, | | void cross(const MultiArrayView<1, T, C1> &x, const MultiArrayView<1, T, C2
> &y, | |
| MultiArrayView<1, T, C3> &r) | | MultiArrayView<1, T, C3> &r) | |
| { | | { | |
| vigra_precondition(3 == x.elementCount() && 3 == y.elementCount() && 3
== r.elementCount(), | | vigra_precondition(3 == x.elementCount() && 3 == y.elementCount() && 3
== r.elementCount(), | |
| "cross(): vectors must have length 3."); | | "cross(): vectors must have length 3."); | |
| r(0) = x(1)*y(2) - x(2)*y(1); | | r(0) = x(1)*y(2) - x(2)*y(1); | |
| r(1) = x(2)*y(0) - x(0)*y(2); | | r(1) = x(2)*y(0) - x(0)*y(2); | |
| r(2) = x(0)*y(1) - x(1)*y(0); | | r(2) = x(0)*y(1) - x(1)*y(0); | |
| } | | } | |
| | | | |
| /** calculate the cross product of two matrices representing vectors. | | /** calculate the cross product of two matrices representing vectors. | |
| That is, \a x, \a y, and \a r must have a single column of length 3
. The result | | That is, \a x, \a y, and \a r must have a single column of length 3
. The result | |
| is written into \a r. | | is written into \a r. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| void cross(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2
> &y, | | void cross(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2
> &y, | |
| MultiArrayView<2, T, C3> &r) | | MultiArrayView<2, T, C3> &r) | |
| { | | { | |
| vigra_precondition(3 == rowCount(x) && 3 == rowCount(y) && 3 == rowCoun
t(r) , | | vigra_precondition(3 == rowCount(x) && 3 == rowCount(y) && 3 == rowCoun
t(r) , | |
| "cross(): vectors must have length 3."); | | "cross(): vectors must have length 3."); | |
| r(0,0) = x(1,0)*y(2,0) - x(2,0)*y(1,0); | | r(0,0) = x(1,0)*y(2,0) - x(2,0)*y(1,0); | |
| r(1,0) = x(2,0)*y(0,0) - x(0,0)*y(2,0); | | r(1,0) = x(2,0)*y(0,0) - x(0,0)*y(2,0); | |
| r(2,0) = x(0,0)*y(1,0) - x(1,0)*y(0,0); | | r(2,0) = x(0,0)*y(1,0) - x(1,0)*y(0,0); | |
| } | | } | |
| | | | |
| /** calculate the cross product of two matrices representing vectors. | | /** calculate the cross product of two matrices representing vectors. | |
| That is, \a x, and \a y must have a single column of length 3. The
result | | That is, \a x, and \a y must have a single column of length 3. The
result | |
| is returned as a temporary matrix. | | is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| TemporaryMatrix<T> | | TemporaryMatrix<T> | |
| cross(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2> &y) | | cross(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2> &y) | |
| { | | { | |
| TemporaryMatrix<T> ret(3, 1); | | TemporaryMatrix<T> ret(3, 1); | |
| cross(x, y, ret); | | cross(x, y, ret); | |
| return ret; | | return ret; | |
| } | | } | |
| /** calculate the outer product of two matrices representing vectors. | | /** calculate the outer product of two matrices representing vectors. | |
| That is, matrix \a x must have a single column, and matrix \a y mus
t | | That is, matrix \a x must have a single column, and matrix \a y mus
t | |
| have a single row, and the other dimensions must match. The result | | have a single row, and the other dimensions must match. The result | |
| is written into \a r. | | is written into \a r. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| void outer(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2
> &y, | | void outer(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2
> &y, | |
| MultiArrayView<2, T, C3> &r) | | MultiArrayView<2, T, C3> &r) | |
| { | | { | |
| const MultiArrayIndex rows = rowCount(r); | | const MultiArrayIndex rows = rowCount(r); | |
| const MultiArrayIndex cols = columnCount(r); | | const MultiArrayIndex cols = columnCount(r); | |
| vigra_precondition(rows == rowCount(x) && cols == columnCount(y) && | | vigra_precondition(rows == rowCount(x) && cols == columnCount(y) && | |
| 1 == columnCount(x) && 1 == rowCount(y), | | 1 == columnCount(x) && 1 == rowCount(y), | |
| | | | |
| skipping to change at line 1468 | | skipping to change at line 1468 | |
| for(MultiArrayIndex i = 0; i < cols; ++i) | | for(MultiArrayIndex i = 0; i < cols; ++i) | |
| for(MultiArrayIndex j = 0; j < rows; ++j) | | for(MultiArrayIndex j = 0; j < rows; ++j) | |
| r(j, i) = x(j, 0) * y(0, i); | | r(j, i) = x(j, 0) * y(0, i); | |
| } | | } | |
| | | | |
| /** calculate the outer product of two matrices representing vectors. | | /** calculate the outer product of two matrices representing vectors. | |
| That is, matrix \a x must have a single column, and matrix \a y mus
t | | That is, matrix \a x must have a single column, and matrix \a y mus
t | |
| have a single row, and the other dimensions must match. The result | | have a single row, and the other dimensions must match. The result | |
| is returned as a temporary matrix. | | is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| TemporaryMatrix<T> | | TemporaryMatrix<T> | |
| outer(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2> &y) | | outer(const MultiArrayView<2, T, C1> &x, const MultiArrayView<2, T, C2> &y) | |
| { | | { | |
| const MultiArrayIndex rows = rowCount(x); | | const MultiArrayIndex rows = rowCount(x); | |
| const MultiArrayIndex cols = columnCount(y); | | const MultiArrayIndex cols = columnCount(y); | |
| vigra_precondition(1 == columnCount(x) && 1 == rowCount(y), | | vigra_precondition(1 == columnCount(x) && 1 == rowCount(y), | |
| "outer(): shape mismatch."); | | "outer(): shape mismatch."); | |
| TemporaryMatrix<T> ret(rows, cols); | | TemporaryMatrix<T> ret(rows, cols); | |
| outer(x, y, ret); | | outer(x, y, ret); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| /** calculate the outer product of a matrix (representing a vector) wit
h itself. | | /** calculate the outer product of a matrix (representing a vector) wit
h itself. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| TemporaryMatrix<T> | | TemporaryMatrix<T> | |
| outer(const MultiArrayView<2, T, C> &x) | | outer(const MultiArrayView<2, T, C> &x) | |
| { | | { | |
| const MultiArrayIndex rows = rowCount(x); | | const MultiArrayIndex rows = rowCount(x); | |
| const MultiArrayIndex cols = columnCount(x); | | const MultiArrayIndex cols = columnCount(x); | |
| vigra_precondition(rows == 1 || cols == 1, | | vigra_precondition(rows == 1 || cols == 1, | |
| "outer(): matrix does not represent a vector."); | | "outer(): matrix does not represent a vector."); | |
| | | | |
| skipping to change at line 1518 | | skipping to change at line 1518 | |
| } | | } | |
| else | | else | |
| { | | { | |
| for(MultiArrayIndex i = 0; i < size; ++i) | | for(MultiArrayIndex i = 0; i < size; ++i) | |
| for(MultiArrayIndex j = 0; j < size; ++j) | | for(MultiArrayIndex j = 0; j < size; ++j) | |
| ret(j, i) = x(j, 0) * x(i, 0); | | ret(j, i) = x(j, 0) * x(i, 0); | |
| } | | } | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
|
| | | /** calculate the outer product of a TinyVector with itself. | |
| | | The result is returned as a temporary matrix. | |
| | | | |
| | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| | | Namespaces: vigra and vigra::linalg | |
| | | */ | |
| | | template <class T, int N> | |
| | | TemporaryMatrix<T> | |
| | | outer(const TinyVector<T, N> &x) | |
| | | { | |
| | | TemporaryMatrix<T> ret(N, N); | |
| | | | |
| | | for(MultiArrayIndex i = 0; i < N; ++i) | |
| | | for(MultiArrayIndex j = 0; j < N; ++j) | |
| | | ret(j, i) = x[j] * x[i]; | |
| | | return ret; | |
| | | } | |
| | | | |
| template <class T> | | template <class T> | |
| class PointWise | | class PointWise | |
| { | | { | |
| public: | | public: | |
| T const & t; | | T const & t; | |
| | | | |
| PointWise(T const & it) | | PointWise(T const & it) | |
| : t(it) | | : t(it) | |
| {} | | {} | |
| }; | | }; | |
| | | | |
| template <class T> | | template <class T> | |
| PointWise<T> pointWise(T const & t) | | PointWise<T> pointWise(T const & t) | |
| { | | { | |
| return PointWise<T>(t); | | return PointWise<T>(t); | |
| } | | } | |
| | | | |
| /** multiply matrix \a a with scalar \a b. | | /** multiply matrix \a a with scalar \a b. | |
| The result is written into \a r. \a a and \a r must have the same s
hape. | | The result is written into \a r. \a a and \a r must have the same s
hape. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| void smul(const MultiArrayView<2, T, C1> &a, T b, MultiArrayView<2, T, C2>
&r) | | void smul(const MultiArrayView<2, T, C1> &a, T b, MultiArrayView<2, T, C2>
&r) | |
| { | | { | |
| const MultiArrayIndex rows = rowCount(a); | | const MultiArrayIndex rows = rowCount(a); | |
| const MultiArrayIndex cols = columnCount(a); | | const MultiArrayIndex cols = columnCount(a); | |
| vigra_precondition(rows == rowCount(r) && cols == columnCount(r), | | vigra_precondition(rows == rowCount(r) && cols == columnCount(r), | |
| "smul(): Matrix sizes must agree."); | | "smul(): Matrix sizes must agree."); | |
| | | | |
| for(MultiArrayIndex i = 0; i < cols; ++i) | | for(MultiArrayIndex i = 0; i < cols; ++i) | |
| for(MultiArrayIndex j = 0; j < rows; ++j) | | for(MultiArrayIndex j = 0; j < rows; ++j) | |
| r(j, i) = a(j, i) * b; | | r(j, i) = a(j, i) * b; | |
| } | | } | |
| | | | |
| /** multiply scalar \a a with matrix \a b. | | /** multiply scalar \a a with matrix \a b. | |
| The result is written into \a r. \a b and \a r must have the same s
hape. | | The result is written into \a r. \a b and \a r must have the same s
hape. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C2, class C3> | | template <class T, class C2, class C3> | |
| void smul(T a, const MultiArrayView<2, T, C2> &b, MultiArrayView<2, T, C3>
&r) | | void smul(T a, const MultiArrayView<2, T, C2> &b, MultiArrayView<2, T, C3>
&r) | |
| { | | { | |
| smul(b, a, r); | | smul(b, a, r); | |
| } | | } | |
| | | | |
| /** perform matrix multiplication of matrices \a a and \a b. | | /** perform matrix multiplication of matrices \a a and \a b. | |
| The result is written into \a r. The three matrices must have match
ing shapes. | | The result is written into \a r. The three matrices must have match
ing shapes. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| void mmul(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | | void mmul(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | |
| MultiArrayView<2, T, C3> &r) | | MultiArrayView<2, T, C3> &r) | |
| { | | { | |
| const MultiArrayIndex rrows = rowCount(r); | | const MultiArrayIndex rrows = rowCount(r); | |
| const MultiArrayIndex rcols = columnCount(r); | | const MultiArrayIndex rcols = columnCount(r); | |
| const MultiArrayIndex acols = columnCount(a); | | const MultiArrayIndex acols = columnCount(a); | |
| vigra_precondition(rrows == rowCount(a) && rcols == columnCount(b) && a
cols == rowCount(b), | | vigra_precondition(rrows == rowCount(a) && rcols == columnCount(b) && a
cols == rowCount(b), | |
| | | | |
| skipping to change at line 1600 | | skipping to change at line 1619 | |
| for(MultiArrayIndex k = 1; k < acols; ++k) | | for(MultiArrayIndex k = 1; k < acols; ++k) | |
| for(MultiArrayIndex j = 0; j < rrows; ++j) | | for(MultiArrayIndex j = 0; j < rrows; ++j) | |
| r(j, i) += a(j, k) * b(k, i); | | r(j, i) += a(j, k) * b(k, i); | |
| } | | } | |
| } | | } | |
| | | | |
| /** perform matrix multiplication of matrices \a a and \a b. | | /** perform matrix multiplication of matrices \a a and \a b. | |
| \a a and \a b must have matching shapes. | | \a a and \a b must have matching shapes. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| mmul(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2> &b) | | mmul(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2> &b) | |
| { | | { | |
| TemporaryMatrix<T> ret(rowCount(a), columnCount(b)); | | TemporaryMatrix<T> ret(rowCount(a), columnCount(b)); | |
| mmul(a, b, ret); | | mmul(a, b, ret); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| /** multiply two matrices \a a and \a b pointwise. | | /** multiply two matrices \a a and \a b pointwise. | |
| The result is written into \a r. All three matrices must have the s
ame shape. | | The result is written into \a r. All three matrices must have the s
ame shape. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| void pmul(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | | void pmul(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | |
| MultiArrayView<2, T, C3> &r) | | MultiArrayView<2, T, C3> &r) | |
| { | | { | |
| const MultiArrayIndex rrows = rowCount(r); | | const MultiArrayIndex rrows = rowCount(r); | |
| const MultiArrayIndex rcols = columnCount(r); | | const MultiArrayIndex rcols = columnCount(r); | |
| vigra_precondition(rrows == rowCount(a) && rcols == columnCount(a) && | | vigra_precondition(rrows == rowCount(a) && rcols == columnCount(a) && | |
| rrows == rowCount(b) && rcols == columnCount(b), | | rrows == rowCount(b) && rcols == columnCount(b), | |
| | | | |
| skipping to change at line 1641 | | skipping to change at line 1660 | |
| for(MultiArrayIndex j = 0; j < rrows; ++j) { | | for(MultiArrayIndex j = 0; j < rrows; ++j) { | |
| r(j, i) = a(j, i) * b(j, i); | | r(j, i) = a(j, i) * b(j, i); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| /** multiply matrices \a a and \a b pointwise. | | /** multiply matrices \a a and \a b pointwise. | |
| \a a and \a b must have matching shapes. | | \a a and \a b must have matching shapes. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| pmul(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2> &b) | | pmul(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2> &b) | |
| { | | { | |
| TemporaryMatrix<T> ret(a.shape()); | | TemporaryMatrix<T> ret(a.shape()); | |
| pmul(a, b, ret); | | pmul(a, b, ret); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| skipping to change at line 1668 | | skipping to change at line 1687 | |
| Usage: | | Usage: | |
| | | | |
| \code | | \code | |
| Matrix<double> a(m,n), b(m,n); | | Matrix<double> a(m,n), b(m,n); | |
| | | | |
| Matrix<double> c = a * pointWise(b); | | Matrix<double> c = a * pointWise(b); | |
| // is equivalent to | | // is equivalent to | |
| // Matrix<double> c = pmul(a, b); | | // Matrix<double> c = pmul(a, b); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C, class U> | | template <class T, class C, class U> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator*(const MultiArrayView<2, T, C> &a, PointWise<U> b) | | operator*(const MultiArrayView<2, T, C> &a, PointWise<U> b) | |
| { | | { | |
| return pmul(a, b.t); | | return pmul(a, b.t); | |
| } | | } | |
| | | | |
| /** multiply matrix \a a with scalar \a b. | | /** multiply matrix \a a with scalar \a b. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator*(const MultiArrayView<2, T, C> &a, T b) | | operator*(const MultiArrayView<2, T, C> &a, T b) | |
| { | | { | |
| return TemporaryMatrix<T>(a) *= b; | | return TemporaryMatrix<T>(a) *= b; | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator*(const TemporaryMatrix<T> &a, T b) | | operator*(const TemporaryMatrix<T> &a, T b) | |
| { | | { | |
| return const_cast<TemporaryMatrix<T> &>(a) *= b; | | return const_cast<TemporaryMatrix<T> &>(a) *= b; | |
| } | | } | |
| | | | |
| /** multiply scalar \a a with matrix \a b. | | /** multiply scalar \a a with matrix \a b. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator*(T a, const MultiArrayView<2, T, C> &b) | | operator*(T a, const MultiArrayView<2, T, C> &b) | |
| { | | { | |
| return TemporaryMatrix<T>(b) *= a; | | return TemporaryMatrix<T>(b) *= a; | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator*(T a, const TemporaryMatrix<T> &b) | | operator*(T a, const TemporaryMatrix<T> &b) | |
| { | | { | |
| return const_cast<TemporaryMatrix<T> &>(b) *= a; | | return const_cast<TemporaryMatrix<T> &>(b) *= a; | |
| } | | } | |
| | | | |
| /** multiply matrix \a a with TinyVector \a b. | | /** multiply matrix \a a with TinyVector \a b. | |
| \a a must be of size <tt>N x N</tt>. Vector \a b and the result | | \a a must be of size <tt>N x N</tt>. Vector \a b and the result | |
| vector are interpreted as column vectors. | | vector are interpreted as column vectors. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class A, int N, class DATA, class DERIVED> | | template <class T, class A, int N, class DATA, class DERIVED> | |
| TinyVector<T, N> | | TinyVector<T, N> | |
| operator*(const Matrix<T, A> &a, const TinyVectorBase<T, N, DATA, DERIVED>
&b) | | operator*(const Matrix<T, A> &a, const TinyVectorBase<T, N, DATA, DERIVED>
&b) | |
| { | | { | |
| vigra_precondition(N == rowCount(a) && N == columnCount(a), | | vigra_precondition(N == rowCount(a) && N == columnCount(a), | |
| "operator*(Matrix, TinyVector): Shape mismatch."); | | "operator*(Matrix, TinyVector): Shape mismatch."); | |
| | | | |
| TinyVector<T, N> res = TinyVectorView<T, N>(&a(0,0)) * b[0]; | | TinyVector<T, N> res = TinyVectorView<T, N>(&a(0,0)) * b[0]; | |
| for(MultiArrayIndex i = 1; i < N; ++i) | | for(MultiArrayIndex i = 1; i < N; ++i) | |
| res += TinyVectorView<T, N>(&a(0,i)) * b[i]; | | res += TinyVectorView<T, N>(&a(0,i)) * b[i]; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| /** multiply TinyVector \a a with matrix \a b. | | /** multiply TinyVector \a a with matrix \a b. | |
| \a b must be of size <tt>N x N</tt>. Vector \a a and the result | | \a b must be of size <tt>N x N</tt>. Vector \a a and the result | |
| vector are interpreted as row vectors. | | vector are interpreted as row vectors. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, int N, class DATA, class DERIVED, class A> | | template <class T, int N, class DATA, class DERIVED, class A> | |
| TinyVector<T, N> | | TinyVector<T, N> | |
| operator*(const TinyVectorBase<T, N, DATA, DERIVED> &a, const Matrix<T, A>
&b) | | operator*(const TinyVectorBase<T, N, DATA, DERIVED> &a, const Matrix<T, A>
&b) | |
| { | | { | |
| vigra_precondition(N == rowCount(b) && N == columnCount(b), | | vigra_precondition(N == rowCount(b) && N == columnCount(b), | |
| "operator*(TinyVector, Matrix): Shape mismatch."); | | "operator*(TinyVector, Matrix): Shape mismatch."); | |
| | | | |
| TinyVector<T, N> res; | | TinyVector<T, N> res; | |
| for(MultiArrayIndex i = 0; i < N; ++i) | | for(MultiArrayIndex i = 0; i < N; ++i) | |
| res[i] = dot(a, TinyVectorView<T, N>(&b(0,i))); | | res[i] = dot(a, TinyVectorView<T, N>(&b(0,i))); | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| /** perform matrix multiplication of matrices \a a and \a b. | | /** perform matrix multiplication of matrices \a a and \a b. | |
| \a a and \a b must have matching shapes. | | \a a and \a b must have matching shapes. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator*(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b) | | operator*(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b) | |
| { | | { | |
| TemporaryMatrix<T> ret(rowCount(a), columnCount(b)); | | TemporaryMatrix<T> ret(rowCount(a), columnCount(b)); | |
| mmul(a, b, ret); | | mmul(a, b, ret); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| /** divide matrix \a a by scalar \a b. | | /** divide matrix \a a by scalar \a b. | |
| The result is written into \a r. \a a and \a r must have the same s
hape. | | The result is written into \a r. \a a and \a r must have the same s
hape. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| void sdiv(const MultiArrayView<2, T, C1> &a, T b, MultiArrayView<2, T, C2>
&r) | | void sdiv(const MultiArrayView<2, T, C1> &a, T b, MultiArrayView<2, T, C2>
&r) | |
| { | | { | |
| const MultiArrayIndex rows = rowCount(a); | | const MultiArrayIndex rows = rowCount(a); | |
| const MultiArrayIndex cols = columnCount(a); | | const MultiArrayIndex cols = columnCount(a); | |
| vigra_precondition(rows == rowCount(r) && cols == columnCount(r), | | vigra_precondition(rows == rowCount(r) && cols == columnCount(r), | |
| "sdiv(): Matrix sizes must agree."); | | "sdiv(): Matrix sizes must agree."); | |
| | | | |
| for(MultiArrayIndex i = 0; i < cols; ++i) | | for(MultiArrayIndex i = 0; i < cols; ++i) | |
| for(MultiArrayIndex j = 0; j < rows; ++j) | | for(MultiArrayIndex j = 0; j < rows; ++j) | |
| r(j, i) = a(j, i) / b; | | r(j, i) = a(j, i) / b; | |
| } | | } | |
| | | | |
| /** divide two matrices \a a and \a b pointwise. | | /** divide two matrices \a a and \a b pointwise. | |
| The result is written into \a r. All three matrices must have the s
ame shape. | | The result is written into \a r. All three matrices must have the s
ame shape. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| void pdiv(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | | void pdiv(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2>
&b, | |
| MultiArrayView<2, T, C3> &r) | | MultiArrayView<2, T, C3> &r) | |
| { | | { | |
| const MultiArrayIndex rrows = rowCount(r); | | const MultiArrayIndex rrows = rowCount(r); | |
| const MultiArrayIndex rcols = columnCount(r); | | const MultiArrayIndex rcols = columnCount(r); | |
| vigra_precondition(rrows == rowCount(a) && rcols == columnCount(a) && | | vigra_precondition(rrows == rowCount(a) && rcols == columnCount(a) && | |
| rrows == rowCount(b) && rcols == columnCount(b), | | rrows == rowCount(b) && rcols == columnCount(b), | |
| | | | |
| skipping to change at line 1828 | | skipping to change at line 1847 | |
| for(MultiArrayIndex j = 0; j < rrows; ++j) { | | for(MultiArrayIndex j = 0; j < rrows; ++j) { | |
| r(j, i) = a(j, i) / b(j, i); | | r(j, i) = a(j, i) / b(j, i); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| /** divide matrices \a a and \a b pointwise. | | /** divide matrices \a a and \a b pointwise. | |
| \a a and \a b must have matching shapes. | | \a a and \a b must have matching shapes. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| pdiv(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2> &b) | | pdiv(const MultiArrayView<2, T, C1> &a, const MultiArrayView<2, T, C2> &b) | |
| { | | { | |
| TemporaryMatrix<T> ret(a.shape()); | | TemporaryMatrix<T> ret(a.shape()); | |
| pdiv(a, b, ret); | | pdiv(a, b, ret); | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
| skipping to change at line 1855 | | skipping to change at line 1874 | |
| Usage: | | Usage: | |
| | | | |
| \code | | \code | |
| Matrix<double> a(m,n), b(m,n); | | Matrix<double> a(m,n), b(m,n); | |
| | | | |
| Matrix<double> c = a / pointWise(b); | | Matrix<double> c = a / pointWise(b); | |
| // is equivalent to | | // is equivalent to | |
| // Matrix<double> c = pdiv(a, b); | | // Matrix<double> c = pdiv(a, b); | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C, class U> | | template <class T, class C, class U> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator/(const MultiArrayView<2, T, C> &a, PointWise<U> b) | | operator/(const MultiArrayView<2, T, C> &a, PointWise<U> b) | |
| { | | { | |
| return pdiv(a, b.t); | | return pdiv(a, b.t); | |
| } | | } | |
| | | | |
| /** divide matrix \a a by scalar \a b. | | /** divide matrix \a a by scalar \a b. | |
| The result is returned as a temporary matrix. | | The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator/(const MultiArrayView<2, T, C> &a, T b) | | operator/(const MultiArrayView<2, T, C> &a, T b) | |
| { | | { | |
| return TemporaryMatrix<T>(a) /= b; | | return TemporaryMatrix<T>(a) /= b; | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator/(const TemporaryMatrix<T> &a, T b) | | operator/(const TemporaryMatrix<T> &a, T b) | |
| { | | { | |
| return const_cast<TemporaryMatrix<T> &>(a) /= b; | | return const_cast<TemporaryMatrix<T> &>(a) /= b; | |
| } | | } | |
| | | | |
| /** Create a matrix whose elements are the quotients between scalar \a
a and | | /** Create a matrix whose elements are the quotients between scalar \a
a and | |
| matrix \a b. The result is returned as a temporary matrix. | | matrix \a b. The result is returned as a temporary matrix. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: vigra::linalg | | Namespace: vigra::linalg | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| inline TemporaryMatrix<T> | | inline TemporaryMatrix<T> | |
| operator/(T a, const MultiArrayView<2, T, C> &b) | | operator/(T a, const MultiArrayView<2, T, C> &b) | |
| { | | { | |
| return TemporaryMatrix<T>(b.shape(), a) / pointWise(b); | | return TemporaryMatrix<T>(b.shape(), a) / pointWise(b); | |
| } | | } | |
| | | | |
| using vigra::argMin; | | using vigra::argMin; | |
| using vigra::argMinIf; | | using vigra::argMinIf; | |
| using vigra::argMax; | | using vigra::argMax; | |
| using vigra::argMaxIf; | | using vigra::argMaxIf; | |
| | | | |
|
| /*! Find the index of the minimum element in a matrix. | | /** \brief Find the index of the minimum element in a matrix. | |
| | | | |
| The function returns the index in column-major scan-order sense, | | The function returns the index in column-major scan-order sense, | |
| i.e. according to the order used by <tt>MultiArrayView::operator[]<
/tt>. | | i.e. according to the order used by <tt>MultiArrayView::operator[]<
/tt>. | |
| If the matrix is actually a vector, this is just the row or columns
index. | | If the matrix is actually a vector, this is just the row or columns
index. | |
| In case of a truly 2-dimensional matrix, the index can be converted
to an | | In case of a truly 2-dimensional matrix, the index can be converted
to an | |
| index pair by calling <tt>MultiArrayView::scanOrderIndexToCoordinat
e()</tt> | | index pair by calling <tt>MultiArrayView::scanOrderIndexToCoordinat
e()</tt> | |
| | | | |
| <b>Required Interface:</b> | | <b>Required Interface:</b> | |
| | | | |
| \code | | \code | |
| | | | |
| skipping to change at line 1939 | | skipping to change at line 1958 | |
| { | | { | |
| if(a[k] < vopt) | | if(a[k] < vopt) | |
| { | | { | |
| vopt = a[k]; | | vopt = a[k]; | |
| best = k; | | best = k; | |
| } | | } | |
| } | | } | |
| return best; | | return best; | |
| } | | } | |
| | | | |
|
| /*! Find the index of the maximum element in a matrix. | | /** \brief Find the index of the maximum element in a matrix. | |
| | | | |
| The function returns the index in column-major scan-order sense, | | The function returns the index in column-major scan-order sense, | |
| i.e. according to the order used by <tt>MultiArrayView::operator[]<
/tt>. | | i.e. according to the order used by <tt>MultiArrayView::operator[]<
/tt>. | |
| If the matrix is actually a vector, this is just the row or columns
index. | | If the matrix is actually a vector, this is just the row or columns
index. | |
| In case of a truly 2-dimensional matrix, the index can be converted
to an | | In case of a truly 2-dimensional matrix, the index can be converted
to an | |
| index pair by calling <tt>MultiArrayView::scanOrderIndexToCoordinat
e()</tt> | | index pair by calling <tt>MultiArrayView::scanOrderIndexToCoordinat
e()</tt> | |
| | | | |
| <b>Required Interface:</b> | | <b>Required Interface:</b> | |
| | | | |
| \code | | \code | |
| | | | |
| skipping to change at line 1972 | | skipping to change at line 1991 | |
| { | | { | |
| if(vopt < a[k]) | | if(vopt < a[k]) | |
| { | | { | |
| vopt = a[k]; | | vopt = a[k]; | |
| best = k; | | best = k; | |
| } | | } | |
| } | | } | |
| return best; | | return best; | |
| } | | } | |
| | | | |
|
| /*! Find the index of the minimum element in a matrix subject to a cond
ition. | | /** \brief Find the index of the minimum element in a matrix subject to
a condition. | |
| | | | |
| The function returns <tt>-1</tt> if no element conforms to \a condi
tion. | | The function returns <tt>-1</tt> if no element conforms to \a condi
tion. | |
| Otherwise, the index of the maximum element is returned in column-m
ajor scan-order sense, | | Otherwise, the index of the maximum element is returned in column-m
ajor scan-order sense, | |
| i.e. according to the order used by <tt>MultiArrayView::operator[]<
/tt>. | | i.e. according to the order used by <tt>MultiArrayView::operator[]<
/tt>. | |
| If the matrix is actually a vector, this is just the row or columns
index. | | If the matrix is actually a vector, this is just the row or columns
index. | |
| In case of a truly 2-dimensional matrix, the index can be converted
to an | | In case of a truly 2-dimensional matrix, the index can be converted
to an | |
| index pair by calling <tt>MultiArrayView::scanOrderIndexToCoordinat
e()</tt> | | index pair by calling <tt>MultiArrayView::scanOrderIndexToCoordinat
e()</tt> | |
| | | | |
| <b>Required Interface:</b> | | <b>Required Interface:</b> | |
| | | | |
| | | | |
| skipping to change at line 2007 | | skipping to change at line 2026 | |
| { | | { | |
| if(condition(a[k]) && a[k] < vopt) | | if(condition(a[k]) && a[k] < vopt) | |
| { | | { | |
| vopt = a[k]; | | vopt = a[k]; | |
| best = k; | | best = k; | |
| } | | } | |
| } | | } | |
| return best; | | return best; | |
| } | | } | |
| | | | |
|
| /*! Find the index of the maximum element in a matrix subject to a cond
ition. | | /** \brief Find the index of the maximum element in a matrix subject to
a condition. | |
| | | | |
| The function returns <tt>-1</tt> if no element conforms to \a condi
tion. | | The function returns <tt>-1</tt> if no element conforms to \a condi
tion. | |
| Otherwise, the index of the maximum element is returned in column-m
ajor scan-order sense, | | Otherwise, the index of the maximum element is returned in column-m
ajor scan-order sense, | |
| i.e. according to the order used by <tt>MultiArrayView::operator[]<
/tt>. | | i.e. according to the order used by <tt>MultiArrayView::operator[]<
/tt>. | |
| If the matrix is actually a vector, this is just the row or columns
index. | | If the matrix is actually a vector, this is just the row or columns
index. | |
| In case of a truly 2-dimensional matrix, the index can be converted
to an | | In case of a truly 2-dimensional matrix, the index can be converted
to an | |
| index pair by calling <tt>MultiArrayView::scanOrderIndexToCoordinat
e()</tt> | | index pair by calling <tt>MultiArrayView::scanOrderIndexToCoordinat
e()</tt> | |
| | | | |
| <b>Required Interface:</b> | | <b>Required Interface:</b> | |
| | | | |
| | | | |
| skipping to change at line 2100 | | skipping to change at line 2119 | |
| } | | } | |
| | | | |
| template <class C> | | template <class C> | |
| linalg::TemporaryMatrix<int> pow(MultiArrayView<2, int, C> const & v, int e
xponent) | | linalg::TemporaryMatrix<int> pow(MultiArrayView<2, int, C> const & v, int e
xponent) | |
| { | | { | |
| linalg::TemporaryMatrix<int> t(v.shape()); | | linalg::TemporaryMatrix<int> t(v.shape()); | |
| MultiArrayIndex m = rowCount(v), n = columnCount(v); | | MultiArrayIndex m = rowCount(v), n = columnCount(v); | |
| | | | |
| for(MultiArrayIndex i = 0; i < n; ++i) | | for(MultiArrayIndex i = 0; i < n; ++i) | |
| for(MultiArrayIndex j = 0; j < m; ++j) | | for(MultiArrayIndex j = 0; j < m; ++j) | |
|
| t(j, i) = (int)vigra::pow((double)v(j, i), exponent); | | t(j, i) = static_cast<int>(vigra::pow(static_cast<double>(v(j,
i)), exponent)); | |
| return t; | | return t; | |
| } | | } | |
| | | | |
| inline | | inline | |
| linalg::TemporaryMatrix<int> pow(linalg::TemporaryMatrix<int> const & v, in
t exponent) | | linalg::TemporaryMatrix<int> pow(linalg::TemporaryMatrix<int> const & v, in
t exponent) | |
| { | | { | |
| linalg::TemporaryMatrix<int> & t = const_cast<linalg::TemporaryMatrix<i
nt> &>(v); | | linalg::TemporaryMatrix<int> & t = const_cast<linalg::TemporaryMatrix<i
nt> &>(v); | |
| MultiArrayIndex m = rowCount(t), n = columnCount(t); | | MultiArrayIndex m = rowCount(t), n = columnCount(t); | |
| | | | |
| for(MultiArrayIndex i = 0; i < n; ++i) | | for(MultiArrayIndex i = 0; i < n; ++i) | |
| for(MultiArrayIndex j = 0; j < m; ++j) | | for(MultiArrayIndex j = 0; j < m; ++j) | |
|
| t(j, i) = (int)vigra::pow((double)t(j, i), exponent); | | t(j, i) = static_cast<int>(vigra::pow(static_cast<double>(t(j,
i)), exponent)); | |
| return t; | | return t; | |
| } | | } | |
| | | | |
| /** Matrix point-wise sqrt. */ | | /** Matrix point-wise sqrt. */ | |
| template <class T, class C> | | template <class T, class C> | |
| linalg::TemporaryMatrix<T> sqrt(MultiArrayView<2, T, C> const & v); | | linalg::TemporaryMatrix<T> sqrt(MultiArrayView<2, T, C> const & v); | |
| /** Matrix point-wise exp. */ | | /** Matrix point-wise exp. */ | |
| template <class T, class C> | | template <class T, class C> | |
| linalg::TemporaryMatrix<T> exp(MultiArrayView<2, T, C> const & v); | | linalg::TemporaryMatrix<T> exp(MultiArrayView<2, T, C> const & v); | |
| /** Matrix point-wise log. */ | | /** Matrix point-wise log. */ | |
| | | | |
| skipping to change at line 2289 | | skipping to change at line 2308 | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| namespace std { | | namespace std { | |
| | | | |
| /** \addtogroup LinearAlgebraFunctions | | /** \addtogroup LinearAlgebraFunctions | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /** print a matrix \a m to the stream \a s. | | /** print a matrix \a m to the stream \a s. | |
| | | | |
|
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
| Namespace: std | | Namespace: std | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| ostream & | | ostream & | |
| operator<<(ostream & s, const vigra::MultiArrayView<2, T, C> &m) | | operator<<(ostream & s, const vigra::MultiArrayView<2, T, C> &m) | |
| { | | { | |
| const vigra::MultiArrayIndex rows = vigra::linalg::rowCount(m); | | const vigra::MultiArrayIndex rows = vigra::linalg::rowCount(m); | |
| const vigra::MultiArrayIndex cols = vigra::linalg::columnCount(m); | | const vigra::MultiArrayIndex cols = vigra::linalg::columnCount(m); | |
| ios::fmtflags flags = s.setf(ios::right | ios::fixed, ios::adjustfield
| ios::floatfield); | | ios::fmtflags flags = s.setf(ios::right | ios::fixed, ios::adjustfield
| ios::floatfield); | |
| for(vigra::MultiArrayIndex j = 0; j < rows; ++j) | | for(vigra::MultiArrayIndex j = 0; j < rows; ++j) | |
| | | | |
| skipping to change at line 2365 | | skipping to change at line 2384 | |
| vigra_precondition(1 == rowCount(mean) && n == columnCount(mean) && | | vigra_precondition(1 == rowCount(mean) && n == columnCount(mean) && | |
| 1 == rowCount(sumOfSquaredDifferences) && n == colum
nCount(sumOfSquaredDifferences), | | 1 == rowCount(sumOfSquaredDifferences) && n == colum
nCount(sumOfSquaredDifferences), | |
| "columnStatistics(): Shape mismatch between input an
d output."); | | "columnStatistics(): Shape mismatch between input an
d output."); | |
| | | | |
| // two-pass algorithm for incremental variance computation | | // two-pass algorithm for incremental variance computation | |
| mean.init(NumericTraits<T2>::zero()); | | mean.init(NumericTraits<T2>::zero()); | |
| for(MultiArrayIndex k=0; k<m; ++k) | | for(MultiArrayIndex k=0; k<m; ++k) | |
| { | | { | |
| mean += rowVector(A, k); | | mean += rowVector(A, k); | |
| } | | } | |
|
| mean /= (double)m; | | mean /= static_cast<double>(m); | |
| | | | |
| sumOfSquaredDifferences.init(NumericTraits<T3>::zero()); | | sumOfSquaredDifferences.init(NumericTraits<T3>::zero()); | |
| for(MultiArrayIndex k=0; k<m; ++k) | | for(MultiArrayIndex k=0; k<m; ++k) | |
| { | | { | |
| sumOfSquaredDifferences += sq(rowVector(A, k) - mean); | | sumOfSquaredDifferences += sq(rowVector(A, k) - mean); | |
| } | | } | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| | | | |
| skipping to change at line 2422 | | skipping to change at line 2441 | |
| MultiArrayView<2, T2, C2> & mean, | | MultiArrayView<2, T2, C2> & mean, | |
| MultiArrayView<2, T3, C3> & stdDev, | | MultiArrayView<2, T3, C3> & stdDev, | |
| MultiArrayView<2, T4, C4> & norm); | | MultiArrayView<2, T4, C4> & norm); | |
| } } | | } } | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
|
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| | | | |
| \code | | \code | |
| Matrix A(rows, columns); | | Matrix A(rows, columns); | |
| .. // fill A | | .. // fill A | |
| Matrix columnMean(1, columns), columnStdDev(1, columns), columnNorm(1,
columns); | | Matrix columnMean(1, columns), columnStdDev(1, columns), columnNorm(1,
columns); | |
| | | | |
| columnStatistics(A, columnMean, columnStdDev, columnNorm); | | columnStatistics(A, columnMean, columnStdDev, columnNorm); | |
| | | | |
| \endcode | | \endcode | |
|
| */ | | */ | |
| doxygen_overloaded_function(template <...> void columnStatistics) | | doxygen_overloaded_function(template <...> void columnStatistics) | |
| | | | |
| template <class T1, class C1, class T2, class C2> | | template <class T1, class C1, class T2, class C2> | |
| void | | void | |
| columnStatistics(MultiArrayView<2, T1, C1> const & A, | | columnStatistics(MultiArrayView<2, T1, C1> const & A, | |
| MultiArrayView<2, T2, C2> & mean) | | MultiArrayView<2, T2, C2> & mean) | |
| { | | { | |
| MultiArrayIndex m = rowCount(A); | | MultiArrayIndex m = rowCount(A); | |
| MultiArrayIndex n = columnCount(A); | | MultiArrayIndex n = columnCount(A); | |
| vigra_precondition(1 == rowCount(mean) && n == columnCount(mean), | | vigra_precondition(1 == rowCount(mean) && n == columnCount(mean), | |
| | | | |
| skipping to change at line 2525 | | skipping to change at line 2544 | |
| MultiArrayView<2, T2, C2> & mean, | | MultiArrayView<2, T2, C2> & mean, | |
| MultiArrayView<2, T3, C3> & stdDev, | | MultiArrayView<2, T3, C3> & stdDev, | |
| MultiArrayView<2, T4, C4> & norm); | | MultiArrayView<2, T4, C4> & norm); | |
| } } | | } } | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
|
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| | | | |
| \code | | \code | |
| Matrix A(rows, columns); | | Matrix A(rows, columns); | |
| .. // fill A | | .. // fill A | |
| Matrix rowMean(rows, 1), rowStdDev(rows, 1), rowNorm(rows, 1); | | Matrix rowMean(rows, 1), rowStdDev(rows, 1), rowNorm(rows, 1); | |
| | | | |
| rowStatistics(a, rowMean, rowStdDev, rowNorm); | | rowStatistics(a, rowMean, rowStdDev, rowNorm); | |
| | | | |
| \endcode | | \endcode | |
| */ | | */ | |
| | | | |
| skipping to change at line 2594 | | skipping to change at line 2613 | |
| vigra_precondition(std::min(rowCount(features), columnCount(features))
== 1, | | vigra_precondition(std::min(rowCount(features), columnCount(features))
== 1, | |
| "updateCovarianceMatrix(): Features must be a row or column vecto
r."); | | "updateCovarianceMatrix(): Features must be a row or column vecto
r."); | |
| vigra_precondition(mean.shape() == features.shape(), | | vigra_precondition(mean.shape() == features.shape(), | |
| "updateCovarianceMatrix(): Shape mismatch between feature vector
and mean vector."); | | "updateCovarianceMatrix(): Shape mismatch between feature vector
and mean vector."); | |
| vigra_precondition(n == rowCount(covariance) && n == columnCount(covari
ance), | | vigra_precondition(n == rowCount(covariance) && n == columnCount(covari
ance), | |
| "updateCovarianceMatrix(): Shape mismatch between feature vector
and covariance matrix."); | | "updateCovarianceMatrix(): Shape mismatch between feature vector
and covariance matrix."); | |
| | | | |
| // West's algorithm for incremental covariance matrix computation | | // West's algorithm for incremental covariance matrix computation | |
| Matrix<T2> t = features - mean; | | Matrix<T2> t = features - mean; | |
| ++count; | | ++count; | |
|
| double f = 1.0 / count, | | T2 f = T2(1.0) / count, | |
| f1 = 1.0 - f; | | f1 = T2(1.0) - f; | |
| mean += f*t; | | mean += f*t; | |
| | | | |
| if(rowCount(features) == 1) // update column covariance from current ro
w | | if(rowCount(features) == 1) // update column covariance from current ro
w | |
| { | | { | |
| for(MultiArrayIndex k=0; k<n; ++k) | | for(MultiArrayIndex k=0; k<n; ++k) | |
| { | | { | |
| covariance(k, k) += f1*sq(t(0, k)); | | covariance(k, k) += f1*sq(t(0, k)); | |
| for(MultiArrayIndex l=k+1; l<n; ++l) | | for(MultiArrayIndex l=k+1; l<n; ++l) | |
| { | | { | |
| covariance(k, l) += f1*t(0, k)*t(0, l); | | covariance(k, l) += f1*t(0, k)*t(0, l); | |
| | | | |
| skipping to change at line 2626 | | skipping to change at line 2645 | |
| { | | { | |
| covariance(k, l) += f1*t(k, 0)*t(l, 0); | | covariance(k, l) += f1*t(k, 0)*t(l, 0); | |
| covariance(l, k) = covariance(k, l); | | covariance(l, k) = covariance(k, l); | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! Compute the covariance matrix between the columns of a matrix \a fe
atures. | | /** \brief Compute the covariance matrix between the columns of a matri
x \a features. | |
| | | | |
| The result matrix \a covariance must by a square matrix with as man
y rows and | | The result matrix \a covariance must by a square matrix with as man
y rows and | |
| columns as the number of columns in matrix \a features. | | columns as the number of columns in matrix \a features. | |
| | | | |
| <b>\#include</b> \<vigra/matrix.hxx\><br> | | <b>\#include</b> \<vigra/matrix.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T1, class C1, class T2, class C2> | | template <class T1, class C1, class T2, class C2> | |
| void covarianceMatrixOfColumns(MultiArrayView<2, T1, C1> const & features, | | void covarianceMatrixOfColumns(MultiArrayView<2, T1, C1> const & features, | |
| MultiArrayView<2, T2, C2> & covariance) | | MultiArrayView<2, T2, C2> & covariance) | |
| | | | |
| skipping to change at line 2649 | | skipping to change at line 2668 | |
| vigra_precondition(n == rowCount(covariance) && n == columnCount(covari
ance), | | vigra_precondition(n == rowCount(covariance) && n == columnCount(covari
ance), | |
| "covarianceMatrixOfColumns(): Shape mismatch between feature matr
ix and covariance matrix."); | | "covarianceMatrixOfColumns(): Shape mismatch between feature matr
ix and covariance matrix."); | |
| MultiArrayIndex count = 0; | | MultiArrayIndex count = 0; | |
| Matrix<T2> means(1, n); | | Matrix<T2> means(1, n); | |
| covariance.init(NumericTraits<T2>::zero()); | | covariance.init(NumericTraits<T2>::zero()); | |
| for(MultiArrayIndex k=0; k<m; ++k) | | for(MultiArrayIndex k=0; k<m; ++k) | |
| detail::updateCovarianceMatrix(rowVector(features, k), count, means
, covariance); | | detail::updateCovarianceMatrix(rowVector(features, k), count, means
, covariance); | |
| covariance /= T2(m - 1); | | covariance /= T2(m - 1); | |
| } | | } | |
| | | | |
|
| /*! Compute the covariance matrix between the columns of a matrix \a fe
atures. | | /** \brief Compute the covariance matrix between the columns of a matri
x \a features. | |
| | | | |
| The result is returned as a square temporary matrix with as many ro
ws and | | The result is returned as a square temporary matrix with as many ro
ws and | |
| columns as the number of columns in matrix \a features. | | columns as the number of columns in matrix \a features. | |
| | | | |
| <b>\#include</b> \<vigra/matrix.hxx\><br> | | <b>\#include</b> \<vigra/matrix.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| TemporaryMatrix<T> | | TemporaryMatrix<T> | |
| covarianceMatrixOfColumns(MultiArrayView<2, T, C> const & features) | | covarianceMatrixOfColumns(MultiArrayView<2, T, C> const & features) | |
| { | | { | |
| TemporaryMatrix<T> res(columnCount(features), columnCount(features)); | | TemporaryMatrix<T> res(columnCount(features), columnCount(features)); | |
| covarianceMatrixOfColumns(features, res); | | covarianceMatrixOfColumns(features, res); | |
| return res; | | return res; | |
| } | | } | |
| | | | |
|
| /*! Compute the covariance matrix between the rows of a matrix \a featu
res. | | /** \brief Compute the covariance matrix between the rows of a matrix \
a features. | |
| | | | |
| The result matrix \a covariance must by a square matrix with as man
y rows and | | The result matrix \a covariance must by a square matrix with as man
y rows and | |
| columns as the number of rows in matrix \a features. | | columns as the number of rows in matrix \a features. | |
| | | | |
| <b>\#include</b> \<vigra/matrix.hxx\><br> | | <b>\#include</b> \<vigra/matrix.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T1, class C1, class T2, class C2> | | template <class T1, class C1, class T2, class C2> | |
| void covarianceMatrixOfRows(MultiArrayView<2, T1, C1> const & features, | | void covarianceMatrixOfRows(MultiArrayView<2, T1, C1> const & features, | |
| MultiArrayView<2, T2, C2> & covariance) | | MultiArrayView<2, T2, C2> & covariance) | |
| { | | { | |
| MultiArrayIndex m = rowCount(features), n = columnCount(features); | | MultiArrayIndex m = rowCount(features), n = columnCount(features); | |
| vigra_precondition(m == rowCount(covariance) && m == columnCount(covari
ance), | | vigra_precondition(m == rowCount(covariance) && m == columnCount(covari
ance), | |
| "covarianceMatrixOfRows(): Shape mismatch between feature matrix
and covariance matrix."); | | "covarianceMatrixOfRows(): Shape mismatch between feature matrix
and covariance matrix."); | |
| MultiArrayIndex count = 0; | | MultiArrayIndex count = 0; | |
| Matrix<T2> means(m, 1); | | Matrix<T2> means(m, 1); | |
| covariance.init(NumericTraits<T2>::zero()); | | covariance.init(NumericTraits<T2>::zero()); | |
| for(MultiArrayIndex k=0; k<n; ++k) | | for(MultiArrayIndex k=0; k<n; ++k) | |
| detail::updateCovarianceMatrix(columnVector(features, k), count, me
ans, covariance); | | detail::updateCovarianceMatrix(columnVector(features, k), count, me
ans, covariance); | |
|
| covariance /= T2(m - 1); | | covariance /= T2(n - 1); | |
| } | | } | |
| | | | |
|
| /*! Compute the covariance matrix between the rows of a matrix \a featu
res. | | /** \brief Compute the covariance matrix between the rows of a matrix \
a features. | |
| | | | |
| The result is returned as a square temporary matrix with as many ro
ws and | | The result is returned as a square temporary matrix with as many ro
ws and | |
| columns as the number of rows in matrix \a features. | | columns as the number of rows in matrix \a features. | |
| | | | |
| <b>\#include</b> \<vigra/matrix.hxx\><br> | | <b>\#include</b> \<vigra/matrix.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class T, class C> | | template <class T, class C> | |
| TemporaryMatrix<T> | | TemporaryMatrix<T> | |
| covarianceMatrixOfRows(MultiArrayView<2, T, C> const & features) | | covarianceMatrixOfRows(MultiArrayView<2, T, C> const & features) | |
| | | | |
| skipping to change at line 2811 | | skipping to change at line 2830 | |
| } | | } | |
| else | | else | |
| { | | { | |
| scaling(0, k) = NumericTraits<T>::one(); | | scaling(0, k) = NumericTraits<T>::one(); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /*! Standardize the columns of a matrix according to given <tt>DataPrep
arationGoals</tt>. | | /** \brief Standardize the columns of a matrix according to given <tt>D
ataPreparationGoals</tt>. | |
| | | | |
| For every column of the matrix \a A, this function computes mean, | | For every column of the matrix \a A, this function computes mean, | |
| standard deviation, and norm. It then applies a linear transformation t
o the values of | | standard deviation, and norm. It then applies a linear transformation t
o the values of | |
| the column according to these statistics and the given <tt>DataPreparat
ionGoals</tt>. | | the column according to these statistics and the given <tt>DataPreparat
ionGoals</tt>. | |
| The result is returned in matrix \a res which must have the same size a
s \a A. | | The result is returned in matrix \a res which must have the same size a
s \a A. | |
| Optionally, the transformation applied can also be returned in the matr
ices \a offset | | Optionally, the transformation applied can also be returned in the matr
ices \a offset | |
| and \a scaling (see below for an example how these matrices can be used
to standardize | | and \a scaling (see below for an example how these matrices can be used
to standardize | |
| more data according to the same transformation). | | more data according to the same transformation). | |
| | | | |
| The following <tt>DataPreparationGoals</tt> are supported: | | The following <tt>DataPreparationGoals</tt> are supported: | |
| | | | |
| skipping to change at line 2868 | | skipping to change at line 2887 | |
| prepareColumns(MultiArrayView<2, T, C1> const & A, | | prepareColumns(MultiArrayView<2, T, C1> const & A, | |
| MultiArrayView<2, T, C2> & res, | | MultiArrayView<2, T, C2> & res, | |
| DataPreparationGoals goals = ZeroMean | UnitVariance
); | | DataPreparationGoals goals = ZeroMean | UnitVariance
); | |
| } } | | } } | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
|
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| | | | |
| \code | | \code | |
| Matrix A(rows, columns); | | Matrix A(rows, columns); | |
| .. // fill A | | .. // fill A | |
| Matrix standardizedA(rows, columns), offset(1, columns), scaling(1, col
umns); | | Matrix standardizedA(rows, columns), offset(1, columns), scaling(1, col
umns); | |
| | | | |
| prepareColumns(A, standardizedA, offset, scaling, ZeroMean | UnitNorm); | | prepareColumns(A, standardizedA, offset, scaling, ZeroMean | UnitNorm); | |
| | | | |
| // use offset and scaling to prepare additional data according to the s
ame transformation | | // use offset and scaling to prepare additional data according to the s
ame transformation | |
| Matrix newData(nrows, columns); | | Matrix newData(nrows, columns); | |
| | | | |
| skipping to change at line 2904 | | skipping to change at line 2923 | |
| | | | |
| template <class T, class C1, class C2> | | template <class T, class C1, class C2> | |
| inline void | | inline void | |
| prepareColumns(MultiArrayView<2, T, C1> const & A, MultiArrayView<2, T, C2>
& res, | | prepareColumns(MultiArrayView<2, T, C1> const & A, MultiArrayView<2, T, C2>
& res, | |
| DataPreparationGoals goals = ZeroMean | UnitVariance) | | DataPreparationGoals goals = ZeroMean | UnitVariance) | |
| { | | { | |
| Matrix<T> offset(1, columnCount(A)), scaling(1, columnCount(A)); | | Matrix<T> offset(1, columnCount(A)), scaling(1, columnCount(A)); | |
| detail::prepareDataImpl(A, res, offset, scaling, goals); | | detail::prepareDataImpl(A, res, offset, scaling, goals); | |
| } | | } | |
| | | | |
|
| /*! Standardize the rows of a matrix according to given <tt>DataPrepara
tionGoals</tt>. | | /** \brief Standardize the rows of a matrix according to given <tt>Data
PreparationGoals</tt>. | |
| | | | |
| This algorithm works in the same way as \ref prepareColumns() (see ther
e for detailed | | This algorithm works in the same way as \ref prepareColumns() (see ther
e for detailed | |
| documentation), but is applied to the rows of the matrix \a A instead.
Accordingly, the | | documentation), but is applied to the rows of the matrix \a A instead.
Accordingly, the | |
| matrices holding the parameters of the linear transformation must be co
lumn vectors | | matrices holding the parameters of the linear transformation must be co
lumn vectors | |
| with as many rows as \a A. | | with as many rows as \a A. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
| Standardize the matrix and return the parameters of the linear transfor
mation. | | Standardize the matrix and return the parameters of the linear transfor
mation. | |
| The matrices \a offset and \a scaling must be column vectors | | The matrices \a offset and \a scaling must be column vectors | |
| | | | |
| skipping to change at line 2944 | | skipping to change at line 2963 | |
| prepareRows(MultiArrayView<2, T, C1> const & A, | | prepareRows(MultiArrayView<2, T, C1> const & A, | |
| MultiArrayView<2, T, C2> & res, | | MultiArrayView<2, T, C2> & res, | |
| DataPreparationGoals goals = ZeroMean | UnitVariance); | | DataPreparationGoals goals = ZeroMean | UnitVariance); | |
| } } | | } } | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/matrix.hxx\> or<br> | | <b>\#include</b> \<vigra/matrix.hxx\> or<br> | |
| <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | | <b>\#include</b> \<vigra/linear_algebra.hxx\><br> | |
|
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| | | | |
| \code | | \code | |
| Matrix A(rows, columns); | | Matrix A(rows, columns); | |
| .. // fill A | | .. // fill A | |
| Matrix standardizedA(rows, columns), offset(rows, 1), scaling(rows, 1); | | Matrix standardizedA(rows, columns), offset(rows, 1), scaling(rows, 1); | |
| | | | |
| prepareRows(A, standardizedA, offset, scaling, ZeroMean | UnitNorm); | | prepareRows(A, standardizedA, offset, scaling, ZeroMean | UnitNorm); | |
| | | | |
| // use offset and scaling to prepare additional data according to the s
ame transformation | | // use offset and scaling to prepare additional data according to the s
ame transformation | |
| Matrix newData(rows, ncolumns); | | Matrix newData(rows, ncolumns); | |
| | | | |
End of changes. 92 change blocks. |
| 148 lines changed or deleted | | 167 lines changed or added | |
|
| multi_array.hxx | | multi_array.hxx | |
| | | | |
| skipping to change at line 44 | | skipping to change at line 44 | |
| /************************************************************************/ | | /************************************************************************/ | |
| | | | |
| #ifndef VIGRA_MULTI_ARRAY_HXX | | #ifndef VIGRA_MULTI_ARRAY_HXX | |
| #define VIGRA_MULTI_ARRAY_HXX | | #define VIGRA_MULTI_ARRAY_HXX | |
| | | | |
| #include <memory> | | #include <memory> | |
| #include <algorithm> | | #include <algorithm> | |
| #include "accessor.hxx" | | #include "accessor.hxx" | |
| #include "tinyvector.hxx" | | #include "tinyvector.hxx" | |
| #include "rgbvalue.hxx" | | #include "rgbvalue.hxx" | |
|
| #include "basicimageview.hxx" | | #include "basicimage.hxx" | |
| #include "imageiterator.hxx" | | #include "imageiterator.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "multi_iterator.hxx" | | #include "multi_iterator.hxx" | |
|
| | | #include "multi_pointoperators.hxx" | |
| #include "metaprogramming.hxx" | | #include "metaprogramming.hxx" | |
| #include "mathutil.hxx" | | #include "mathutil.hxx" | |
|
| | | #include "algorithm.hxx" | |
| | | | |
| // Bounds checking Macro used if VIGRA_CHECK_BOUNDS is defined. | | // Bounds checking Macro used if VIGRA_CHECK_BOUNDS is defined. | |
| #ifdef VIGRA_CHECK_BOUNDS | | #ifdef VIGRA_CHECK_BOUNDS | |
| #define VIGRA_ASSERT_INSIDE(diff) \ | | #define VIGRA_ASSERT_INSIDE(diff) \ | |
| vigra_precondition(this->isInside(diff), "Index out of bounds") | | vigra_precondition(this->isInside(diff), "Index out of bounds") | |
| #else | | #else | |
| #define VIGRA_ASSERT_INSIDE(diff) | | #define VIGRA_ASSERT_INSIDE(diff) | |
| #endif | | #endif | |
| | | | |
| namespace vigra | | namespace vigra | |
| { | | { | |
| | | | |
| namespace detail | | namespace detail | |
| { | | { | |
|
| /********************************************************/ | | | |
| /* */ | | | |
| /* defaultStride */ | | | |
| /* */ | | | |
| /********************************************************/ | | | |
| | | | |
| /* generates the stride for a gapless shape. | | | |
| | | | |
| Namespace: vigra::detail | | | |
| */ | | | |
| template <unsigned int N> | | | |
| inline TinyVector <MultiArrayIndex, N> | | | |
| defaultStride(const TinyVector <MultiArrayIndex, N> &shape) | | | |
| { | | | |
| TinyVector <MultiArrayIndex, N> ret; | | | |
| ret [0] = 1; | | | |
| for (int i = 1; i < (int)N; ++i) | | | |
| ret [i] = ret [i-1] * shape [i-1]; | | | |
| return ret; | | | |
| } | | | |
| | | | |
| /********************************************************/ | | | |
| /* */ | | | |
| /* ScanOrderToOffset */ | | | |
| /* */ | | | |
| /********************************************************/ | | | |
| | | | |
| /* transforms an index in scan order sense to a pointer offset in a possibl | | | |
| y | | | |
| strided, multi-dimensional array. | | | |
| | | | |
| Namespace: vigra::detail | | | |
| */ | | | |
| | | | |
| template <int K> | | | |
| struct ScanOrderToOffset | | | |
| { | | | |
| template <int N> | | | |
| static MultiArrayIndex | | | |
| exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> &shape, | | | |
| const TinyVector <MultiArrayIndex, N> & stride) | | | |
| { | | | |
| return stride[N-K] * (d % shape[N-K]) + | | | |
| ScanOrderToOffset<K-1>::exec(d / shape[N-K], shape, stride); | | | |
| } | | | |
| }; | | | |
| | | | |
| template <> | | | |
| struct ScanOrderToOffset<1> | | | |
| { | | | |
| template <int N> | | | |
| static MultiArrayIndex | | | |
| exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> & /*shape | | | |
| */, | | | |
| const TinyVector <MultiArrayIndex, N> & stride) | | | |
| { | | | |
| return stride[N-1] * d; | | | |
| } | | | |
| }; | | | |
| | | | |
| template <int K> | | | |
| struct ScanOrderToCoordinate | | | |
| { | | | |
| template <int N> | | | |
| static void | | | |
| exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> &shape, | | | |
| TinyVector <MultiArrayIndex, N> & result) | | | |
| { | | | |
| result[N-K] = (d % shape[N-K]); | | | |
| ScanOrderToCoordinate<K-1>::exec(d / shape[N-K], shape, result); | | | |
| } | | | |
| }; | | | |
| | | | |
| template <> | | | |
| struct ScanOrderToCoordinate<1> | | | |
| { | | | |
| template <int N> | | | |
| static void | | | |
| exec(MultiArrayIndex d, const TinyVector <MultiArrayIndex, N> & /*shape | | | |
| */, | | | |
| TinyVector <MultiArrayIndex, N> & result) | | | |
| { | | | |
| result[N-1] = d; | | | |
| } | | | |
| }; | | | |
| | | | |
| template <class C> | | | |
| struct CoordinatesToOffest | | | |
| { | | | |
| template <int N> | | | |
| static MultiArrayIndex | | | |
| exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x) | | | |
| { | | | |
| return stride[0] * x; | | | |
| } | | | |
| template <int N> | | | |
| static MultiArrayIndex | | | |
| exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x, | | | |
| MultiArrayIndex y) | | | |
| { | | | |
| return stride[0] * x + stride[1] * y; | | | |
| } | | | |
| }; | | | |
| | | | |
| template <> | | | |
| struct CoordinatesToOffest<UnstridedArrayTag> | | | |
| { | | | |
| template <int N> | | | |
| static MultiArrayIndex | | | |
| exec(const TinyVector <MultiArrayIndex, N> & /*stride*/, MultiArrayInde | | | |
| x x) | | | |
| { | | | |
| return x; | | | |
| } | | | |
| template <int N> | | | |
| static MultiArrayIndex | | | |
| exec(const TinyVector <MultiArrayIndex, N> & stride, MultiArrayIndex x, | | | |
| MultiArrayIndex y) | | | |
| { | | | |
| return x + stride[1] * y; | | | |
| } | | | |
| }; | | | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* MaybeStrided */ | | /* MaybeStrided */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /* metatag implementing a test for marking MultiArrays that were | | /* metatag implementing a test for marking MultiArrays that were | |
| indexed at the zero'th dimension as strided, and all others as | | indexed at the zero'th dimension as strided, and all others as | |
| unstrided. | | unstrided. | |
| | | | |
|
| <b>\#include</b> | | <b>\#include</b> \<vigra/multi_array.hxx\> <br/> | |
| \<vigra/multi_array.hxx\> | | Namespace: vigra::detail | |
| | | | |
| Namespace: vigra::detail | | | |
| */ | | */ | |
| template <class StrideTag, unsigned int N> | | template <class StrideTag, unsigned int N> | |
| struct MaybeStrided | | struct MaybeStrided | |
| { | | { | |
| typedef StrideTag type; | | typedef StrideTag type; | |
| }; | | }; | |
| | | | |
| template <class StrideTag> | | template <class StrideTag> | |
| struct MaybeStrided <StrideTag, 0> | | struct MaybeStrided <StrideTag, 0> | |
| { | | { | |
| | | | |
| skipping to change at line 217 | | skipping to change at line 101 | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* MultiIteratorChooser */ | | /* MultiIteratorChooser */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /* metatag implementing a test (by pattern matching) for marking | | /* metatag implementing a test (by pattern matching) for marking | |
| MultiArrays that were indexed at the zero'th dimension as strided. | | MultiArrays that were indexed at the zero'th dimension as strided. | |
| | | | |
|
| <b>\#include</b> | | <b>\#include</b> \<vigra/multi_array.hxx\> <br/> | |
| \<vigra/multi_array.hxx\> | | Namespace: vigra::detail | |
| | | | |
| Namespace: vigra::detail | | | |
| */ | | */ | |
| template <class O> | | template <class O> | |
|
| struct MultiIteratorChooser | | struct MultiIteratorChooser; | |
| { | | | |
| struct Nil {}; | | | |
| | | | |
| template <unsigned int N, class T, class REFERENCE, class POINTER> | | | |
| struct Traverser | | | |
| { | | | |
| typedef Nil type; | | | |
| }; | | | |
| }; | | | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* MultiIteratorChooser <StridedArrayTag> */ | | /* MultiIteratorChooser <StridedArrayTag> */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /* specialization of the MultiIteratorChooser for strided arrays. | | /* specialization of the MultiIteratorChooser for strided arrays. | |
| | | | |
|
| <b>\#include</b> | | <b>\#include</b> \<vigra/multi_array.hxx\> <br/> | |
| \<vigra/multi_array.hxx\> | | Namespace: vigra::detail | |
| | | | |
| Namespace: vigra::detail | | | |
| */ | | */ | |
| template <> | | template <> | |
| struct MultiIteratorChooser <StridedArrayTag> | | struct MultiIteratorChooser <StridedArrayTag> | |
| { | | { | |
| template <unsigned int N, class T, class REFERENCE, class POINTER> | | template <unsigned int N, class T, class REFERENCE, class POINTER> | |
| struct Traverser | | struct Traverser | |
| { | | { | |
| typedef StridedMultiIterator <N, T, REFERENCE, POINTER> type; | | typedef StridedMultiIterator <N, T, REFERENCE, POINTER> type; | |
| }; | | }; | |
|
| | | | |
| | | template <unsigned int N, class T, class REFERENCE, class POINTER> | |
| | | struct Iterator | |
| | | { | |
| | | typedef StridedScanOrderIterator <N, T, REFERENCE, POINTER> type; | |
| | | }; | |
| | | | |
| | | template <class Iter, class View> | |
| | | static Iter constructIterator(View * v) | |
| | | { | |
| | | return v->begin(); | |
| | | } | |
| }; | | }; | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* MultiIteratorChooser <UnstridedArrayTag> */ | | /* MultiIteratorChooser <UnstridedArrayTag> */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /* specialization of the MultiIteratorChooser for unstrided arrays. | | /* specialization of the MultiIteratorChooser for unstrided arrays. | |
| | | | |
|
| <b>\#include</b> | | <b>\#include</b> \<vigra/multi_array.hxx\> <br/> | |
| \<vigra/multi_array.hxx\> | | Namespace: vigra::detail | |
| | | | |
| Namespace: vigra::detail | | | |
| */ | | */ | |
| template <> | | template <> | |
| struct MultiIteratorChooser <UnstridedArrayTag> | | struct MultiIteratorChooser <UnstridedArrayTag> | |
| { | | { | |
| template <unsigned int N, class T, class REFERENCE, class POINTER> | | template <unsigned int N, class T, class REFERENCE, class POINTER> | |
| struct Traverser | | struct Traverser | |
| { | | { | |
| typedef MultiIterator <N, T, REFERENCE, POINTER> type; | | typedef MultiIterator <N, T, REFERENCE, POINTER> type; | |
| }; | | }; | |
|
| | | | |
| | | template <unsigned int N, class T, class REFERENCE, class POINTER> | |
| | | struct Iterator | |
| | | { | |
| | | typedef POINTER type; | |
| | | }; | |
| | | | |
| | | template <class Iter, class View> | |
| | | static Iter constructIterator(View * v) | |
| | | { | |
| | | return v->data(); | |
| | | } | |
| }; | | }; | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* helper functions */ | | /* helper functions */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class DestIterator, class Shape, class T> | | template <class DestIterator, class Shape, class T> | |
| inline void | | inline void | |
| | | | |
| skipping to change at line 314 | | skipping to change at line 207 | |
| initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>()); | | initMultiArrayData(d.begin(), shape, init, MetaInt<N-1>()); | |
| } | | } | |
| } | | } | |
| | | | |
| // FIXME: the explicit overload for MultiIterator<1, UInt8, ... > works aro
und a compiler crash in VisualStudio 2010 | | // FIXME: the explicit overload for MultiIterator<1, UInt8, ... > works aro
und a compiler crash in VisualStudio 2010 | |
| #define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \ | | #define VIGRA_COPY_MULTI_ARRAY_DATA(name, op) \ | |
| template <class SrcIterator, class Shape, class DestIterator> \ | | template <class SrcIterator, class Shape, class DestIterator> \ | |
| inline void \ | | inline void \ | |
| name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me
taInt<0>) \ | | name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me
taInt<0>) \ | |
| { \ | | { \ | |
|
| SrcIterator send = s + shape[0]; \ | | for(MultiArrayIndex i=0; i < shape[0]; ++i, ++s, ++d) \ | |
| for(; s < send; ++s, ++d) \ | | | |
| { \ | | { \ | |
| *d op detail::RequiresExplicitCast<typename DestIterator::value_typ
e>::cast(*s); \ | | *d op detail::RequiresExplicitCast<typename DestIterator::value_typ
e>::cast(*s); \ | |
| } \ | | } \ | |
| } \ | | } \ | |
| \ | | \ | |
| template <class Ref, class Ptr, class Shape, class DestIterator> \ | | template <class Ref, class Ptr, class Shape, class DestIterator> \ | |
| inline void \ | | inline void \ | |
| name##MultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape const & sh
ape, DestIterator d, MetaInt<0>) \ | | name##MultiArrayData(MultiIterator<1, UInt8, Ref, Ptr> si, Shape const & sh
ape, DestIterator d, MetaInt<0>) \ | |
| { \ | | { \ | |
|
| Ptr s = &(*si), send = s + shape[0]; \ | | Ptr s = &(*si); \ | |
| for(; s < send; ++s, ++d) \ | | for(MultiArrayIndex i=0; i < shape[0]; ++i, ++s, ++d) \ | |
| { \ | | { \ | |
| *d op detail::RequiresExplicitCast<typename DestIterator::value_typ
e>::cast(*s); \ | | *d op detail::RequiresExplicitCast<typename DestIterator::value_typ
e>::cast(*s); \ | |
| } \ | | } \ | |
| } \ | | } \ | |
| \ | | \ | |
| template <class SrcIterator, class Shape, class DestIterator, int N> \ | | template <class SrcIterator, class Shape, class DestIterator, int N> \ | |
| void \ | | void \ | |
| name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me
taInt<N>) \ | | name##MultiArrayData(SrcIterator s, Shape const & shape, DestIterator d, Me
taInt<N>) \ | |
| { \ | | { \ | |
|
| SrcIterator send = s + shape[N]; \ | | for(MultiArrayIndex i=0; i < shape[N]; ++i, ++s, ++d) \ | |
| for(; s < send; ++s, ++d) \ | | | |
| { \ | | { \ | |
| name##MultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>());
\ | | name##MultiArrayData(s.begin(), shape, d.begin(), MetaInt<N-1>());
\ | |
| } \ | | } \ | |
| } \ | | } \ | |
| \ | | \ | |
| template <class DestIterator, class Shape, class T> \ | | template <class DestIterator, class Shape, class T> \ | |
| inline void \ | | inline void \ | |
| name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & i
nit, MetaInt<0>) \ | | name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & i
nit, MetaInt<0>) \ | |
| { \ | | { \ | |
|
| DestIterator dend = d + shape[0]; \ | | for(MultiArrayIndex i=0; i < shape[0]; ++i, ++d) \ | |
| for(; d < dend; ++d) \ | | | |
| { \ | | { \ | |
| *d op detail::RequiresExplicitCast<typename DestIterator::value_typ
e>::cast(init); \ | | *d op detail::RequiresExplicitCast<typename DestIterator::value_typ
e>::cast(init); \ | |
| } \ | | } \ | |
| } \ | | } \ | |
| \ | | \ | |
| template <class DestIterator, class Shape, class T, int N> \ | | template <class DestIterator, class Shape, class T, int N> \ | |
| void \ | | void \ | |
| name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & i
nit, MetaInt<N>) \ | | name##ScalarMultiArrayData(DestIterator d, Shape const & shape, T const & i
nit, MetaInt<N>) \ | |
| { \ | | { \ | |
|
| DestIterator dend = d + shape[N]; \ | | for(MultiArrayIndex i=0; i < shape[N]; ++i, ++d) \ | |
| for(; d < dend; ++d) \ | | | |
| { \ | | { \ | |
| name##ScalarMultiArrayData(d.begin(), shape, init, MetaInt<N-1>());
\ | | name##ScalarMultiArrayData(d.begin(), shape, init, MetaInt<N-1>());
\ | |
| } \ | | } \ | |
| } | | } | |
| | | | |
| VIGRA_COPY_MULTI_ARRAY_DATA(copy, =) | | VIGRA_COPY_MULTI_ARRAY_DATA(copy, =) | |
| VIGRA_COPY_MULTI_ARRAY_DATA(copyAdd, +=) | | VIGRA_COPY_MULTI_ARRAY_DATA(copyAdd, +=) | |
| VIGRA_COPY_MULTI_ARRAY_DATA(copySub, -=) | | VIGRA_COPY_MULTI_ARRAY_DATA(copySub, -=) | |
| VIGRA_COPY_MULTI_ARRAY_DATA(copyMul, *=) | | VIGRA_COPY_MULTI_ARRAY_DATA(copyMul, *=) | |
| VIGRA_COPY_MULTI_ARRAY_DATA(copyDiv, /=) | | VIGRA_COPY_MULTI_ARRAY_DATA(copyDiv, /=) | |
| | | | |
| skipping to change at line 589 | | skipping to change at line 478 | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* MultiArrayView */ | | /* MultiArrayView */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| // forward declarations | | // forward declarations | |
| | | | |
|
| template <unsigned int N, class T, class C = UnstridedArrayTag> | | | |
| class MultiArrayView; | | | |
| template <unsigned int N, class T, class A = std::allocator<T> > | | | |
| class MultiArray; | | | |
| | | | |
| namespace multi_math { | | namespace multi_math { | |
| | | | |
| template <class T> | | template <class T> | |
| struct MultiMathOperand; | | struct MultiMathOperand; | |
| | | | |
|
| namespace detail { | | namespace math_detail { | |
| | | | |
| template <unsigned int N, class T, class C, class E> | | template <unsigned int N, class T, class C, class E> | |
| void assign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &); | | void assign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &); | |
| | | | |
| template <unsigned int N, class T, class C, class E> | | template <unsigned int N, class T, class C, class E> | |
| void plusAssign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &); | | void plusAssign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &); | |
| | | | |
| template <unsigned int N, class T, class C, class E> | | template <unsigned int N, class T, class C, class E> | |
| void minusAssign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &); | | void minusAssign(MultiArrayView<N, T, C>, MultiMathOperand<E> const &); | |
| | | | |
| | | | |
| skipping to change at line 631 | | skipping to change at line 515 | |
| | | | |
| template <unsigned int N, class T, class A, class E> | | template <unsigned int N, class T, class A, class E> | |
| void minusAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> const &
); | | void minusAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> const &
); | |
| | | | |
| template <unsigned int N, class T, class A, class E> | | template <unsigned int N, class T, class A, class E> | |
| void multiplyAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> cons
t &); | | void multiplyAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> cons
t &); | |
| | | | |
| template <unsigned int N, class T, class A, class E> | | template <unsigned int N, class T, class A, class E> | |
| void divideAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> const
&); | | void divideAssignOrResize(MultiArray<N, T, A> &, MultiMathOperand<E> const
&); | |
| | | | |
|
| } // namespace detail | | } // namespace math_detail | |
| | | | |
| } // namespace multi_math | | } // namespace multi_math | |
| | | | |
| template <class T> class FindSum; | | template <class T> class FindSum; | |
| | | | |
| struct UnsuitableTypeForExpandElements {}; | | struct UnsuitableTypeForExpandElements {}; | |
| | | | |
| template <class T> | | template <class T> | |
| struct ExpandElementResult | | struct ExpandElementResult | |
| { | | { | |
| | | | |
| skipping to change at line 718 | | skipping to change at line 602 | |
| template <unsigned int N, class T, class C> | | template <unsigned int N, class T, class C> | |
| struct NormTraits<MultiArrayView<N, T, C> > | | struct NormTraits<MultiArrayView<N, T, C> > | |
| { | | { | |
| typedef MultiArrayView<N, T, C> Ty
pe; | | typedef MultiArrayView<N, T, C> Ty
pe; | |
| typedef typename NormTraits<T>::SquaredNormType SquaredNormType; | | typedef typename NormTraits<T>::SquaredNormType SquaredNormType; | |
| typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult No
rmType; | | typedef typename SquareRootTraits<SquaredNormType>::SquareRootResult No
rmType; | |
| }; | | }; | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| struct NormTraits<MultiArray<N, T, A> > | | struct NormTraits<MultiArray<N, T, A> > | |
|
| : public NormTraits<MultiArrayView<N, T, UnstridedArrayTag> > | | : public NormTraits<typename MultiArray<N, T, A>::view_type> | |
| { | | { | |
|
| typedef NormTraits<MultiArrayView<N, T, UnstridedArrayTag> > BaseType; | | typedef NormTraits<typename MultiArray<N, T, A>::view_type> BaseType; | |
| typedef MultiArray<N, T, A> Type; | | typedef MultiArray<N, T, A> Type; | |
| typedef typename BaseType::SquaredNormType SquaredNor
mType; | | typedef typename BaseType::SquaredNormType SquaredNor
mType; | |
| typedef typename BaseType::NormType NormType; | | typedef typename BaseType::NormType NormType; | |
| }; | | }; | |
| | | | |
| /** \brief Base class for, and view to, \ref vigra::MultiArray. | | /** \brief Base class for, and view to, \ref vigra::MultiArray. | |
| | | | |
| This class implements the interface of both MultiArray and | | This class implements the interface of both MultiArray and | |
| MultiArrayView. By default, MultiArrayViews are tagged as | | MultiArrayView. By default, MultiArrayViews are tagged as | |
|
| unstrided. If necessary, strided arrays are constructed automatically | | strided (using <tt>StridedArrayTag</tt> as third template parameter). | |
| by calls to a variant of the bind...() function. | | This means that the array elements need not be consecutive in memory, | |
| | | making the view flexible to represent all kinds of subarrays and slices. | |
| | | In certain cases (which have become rare due to improvements of | |
| | | optimizer and processor technology), an array may be tagged with | |
| | | <tt>UnstridedArrayTag</tt> which indicates that the first array dimension | |
| | | is guaranteed to be unstrided, i.e. has consecutive elements in memory. | |
| | | | |
| In addition to the member functions described here, <tt>MultiArrayView</tt> | | In addition to the member functions described here, <tt>MultiArrayView</tt> | |
| and its subclasses support arithmetic and algebraic functions via the | | and its subclasses support arithmetic and algebraic functions via the | |
| module \ref MultiMathModule. | | module \ref MultiMathModule. | |
| | | | |
| If you want to apply an algorithm requiring an image to a | | If you want to apply an algorithm requiring an image to a | |
| <tt>MultiArrayView</tt> of appropriate (2-dimensional) shape, you can | | <tt>MultiArrayView</tt> of appropriate (2-dimensional) shape, you can | |
| create a \ref vigra::BasicImageView that acts as a wrapper with the | | create a \ref vigra::BasicImageView that acts as a wrapper with the | |
| necessary interface -- see \ref MultiArrayToImage. | | necessary interface -- see \ref MultiArrayToImage. | |
| | | | |
| | | | |
| skipping to change at line 753 | | skipping to change at line 642 | |
| \code | | \code | |
| N: the array dimension | | N: the array dimension | |
| | | | |
| T: the type of the array elements | | T: the type of the array elements | |
| | | | |
| C: a tag determining whether the array's inner dimension is strided | | C: a tag determining whether the array's inner dimension is strided | |
| or not. An array is unstrided if the array elements occupy consecuti
ve | | or not. An array is unstrided if the array elements occupy consecuti
ve | |
| memory location, strided if there is an offset in between (e.g. | | memory location, strided if there is an offset in between (e.g. | |
| when a view is created that skips every other array element). | | when a view is created that skips every other array element). | |
| The compiler can generate faster code for unstrided arrays. | | The compiler can generate faster code for unstrided arrays. | |
|
| Possible values: UnstridedArrayTag (default), StridedArrayTag | | Possible values: StridedArrayTag (default), UnstridedArrayTag | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> | | <b>\#include</b> \<vigra/multi_array.hxx\> <br/> | |
| \<vigra/multi_array.hxx\> | | | |
| | | | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
| class MultiArrayView | | class MultiArrayView | |
| { | | { | |
| public: | | public: | |
| | | | |
| /** the array's actual dimensionality. | | /** the array's actual dimensionality. | |
| This ensures that MultiArrayView can also be used for | | This ensures that MultiArrayView can also be used for | |
| scalars (that is, when <tt>N == 0</tt>). Calculated as:<br> | | scalars (that is, when <tt>N == 0</tt>). Calculated as:<br> | |
| | | | |
| skipping to change at line 799 | | skipping to change at line 686 | |
| typedef value_type *pointer; | | typedef value_type *pointer; | |
| | | | |
| /** const pointer type | | /** const pointer type | |
| */ | | */ | |
| typedef const value_type *const_pointer; | | typedef const value_type *const_pointer; | |
| | | | |
| /** difference type (used for multi-dimensional offsets and indices
) | | /** difference type (used for multi-dimensional offsets and indices
) | |
| */ | | */ | |
| typedef typename MultiArrayShape<actual_dimension>::type difference_typ
e; | | typedef typename MultiArrayShape<actual_dimension>::type difference_typ
e; | |
| | | | |
|
| | | /** key type (argument of index operator array[i] -- same as differ | |
| | | ence_type) | |
| | | */ | |
| | | typedef difference_type key_type; | |
| | | | |
| /** size type | | /** size type | |
| */ | | */ | |
| typedef difference_type size_type; | | typedef difference_type size_type; | |
| | | | |
| /** difference and index type for a single dimension | | /** difference and index type for a single dimension | |
| */ | | */ | |
| typedef MultiArrayIndex difference_type_1; | | typedef MultiArrayIndex difference_type_1; | |
| | | | |
| /** scan-order iterator (StridedScanOrderIterator) type | | /** scan-order iterator (StridedScanOrderIterator) type | |
| */ | | */ | |
| | | | |
| skipping to change at line 833 | | skipping to change at line 724 | |
| StrideTag>::template Traverser <actual_dimension, T, T const &, T c
onst *>::type const_traverser; | | StrideTag>::template Traverser <actual_dimension, T, T const &, T c
onst *>::type const_traverser; | |
| | | | |
| /** the view type associated with this array. | | /** the view type associated with this array. | |
| */ | | */ | |
| typedef MultiArrayView <N, T, StrideTag> view_type; | | typedef MultiArrayView <N, T, StrideTag> view_type; | |
| | | | |
| /** the matrix type associated with this array. | | /** the matrix type associated with this array. | |
| */ | | */ | |
| typedef MultiArray <N, T> matrix_type; | | typedef MultiArray <N, T> matrix_type; | |
| | | | |
|
| protected: | | bool checkInnerStride(UnstridedArrayTag) const | |
| | | { | |
| | | return m_stride[0] <= 1; | |
| | | } | |
| | | | |
| | | bool checkInnerStride(StridedArrayTag) const | |
| | | { | |
| | | return true; | |
| | | } | |
| | | | |
| | | protected: | |
| | | | |
| typedef typename difference_type::value_type diff_zero_t; | | typedef typename difference_type::value_type diff_zero_t; | |
| | | | |
| /** the shape of the image pointed to is stored here. | | /** the shape of the image pointed to is stored here. | |
| */ | | */ | |
| difference_type m_shape; | | difference_type m_shape; | |
| | | | |
| /** the strides (offset of a sample to the next) for every dimensio
n | | /** the strides (offset of a sample to the next) for every dimensio
n | |
| are stored here. | | are stored here. | |
| */ | | */ | |
| difference_type m_stride; | | difference_type m_stride; | |
| | | | |
| /** pointer to the image. | | /** pointer to the image. | |
| */ | | */ | |
| pointer m_ptr; | | pointer m_ptr; | |
| | | | |
|
| | | template <class CN> | |
| | | void assignImpl(const MultiArrayView <N, T, CN>& rhs); | |
| | | | |
| template <class U, class CN> | | template <class U, class CN> | |
| void copyImpl(const MultiArrayView <N, U, CN>& rhs); | | void copyImpl(const MultiArrayView <N, U, CN>& rhs); | |
| | | | |
| template <class U, class CN> | | template <class U, class CN> | |
| void swapDataImpl(MultiArrayView <N, U, CN> rhs); | | void swapDataImpl(MultiArrayView <N, U, CN> rhs); | |
| | | | |
| template <class CN> | | template <class CN> | |
| bool arraysOverlap(const MultiArrayView <N, T, CN>& rhs) const; | | bool arraysOverlap(const MultiArrayView <N, T, CN>& rhs) const; | |
| | | | |
| template <class U, class CN> | | template <class U, class CN> | |
| bool arraysOverlap(const MultiArrayView <N, U, CN>&) const | | bool arraysOverlap(const MultiArrayView <N, U, CN>&) const | |
| { | | { | |
| return false; | | return false; | |
| } | | } | |
| | | | |
|
| bool checkInnerStride(UnstridedArrayTag) | | | |
| { | | | |
| return m_stride[0] <= 1; | | | |
| } | | | |
| | | | |
| bool checkInnerStride(StridedArrayTag) | | | |
| { | | | |
| return true; | | | |
| } | | | |
| | | | |
| public: | | public: | |
| | | | |
| /** default constructor: create an invalid view, | | /** default constructor: create an invalid view, | |
| * i.e. hasData() returns false and size() is zero. | | * i.e. hasData() returns false and size() is zero. | |
| */ | | */ | |
| MultiArrayView () | | MultiArrayView () | |
| : m_shape (diff_zero_t(0)), m_stride (diff_zero_t(0)), m_ptr (0) | | : m_shape (diff_zero_t(0)), m_stride (diff_zero_t(0)), m_ptr (0) | |
| {} | | {} | |
| | | | |
|
| | | /** construct from another array view. | |
| | | Throws a precondition error if this array has UnstridedArrayTag | |
| | | , but the | |
| | | innermost dimension of \a other is strided. | |
| | | */ | |
| | | template <class Stride> | |
| | | MultiArrayView (const MultiArrayView<N, T, Stride> &other) | |
| | | : m_shape (other.shape()), | |
| | | m_stride (other.stride()), | |
| | | m_ptr (other.data()) | |
| | | { | |
| | | vigra_precondition(other.checkInnerStride(StrideTag()), | |
| | | "MultiArrayView<..., UnstridedArrayTag>(MultiArrayView const &) | |
| | | : cannot create unstrided view from strided array."); | |
| | | } | |
| | | | |
| /** construct from shape and pointer | | /** construct from shape and pointer | |
| */ | | */ | |
|
| MultiArrayView (const difference_type &shape, pointer ptr) | | MultiArrayView (const difference_type &shape, const_pointer ptr) | |
| : m_shape (shape), | | : m_shape (shape), | |
|
| m_stride (detail::defaultStride <MultiArrayView<N,T>::actual_dimensio | | m_stride (detail::defaultStride<actual_dimension>(shape)), | |
| n> (shape)), | | m_ptr (const_cast<pointer>(ptr)) | |
| m_ptr (ptr) | | | |
| {} | | {} | |
| | | | |
| /** Construct from shape, strides (offset of a sample to the | | /** Construct from shape, strides (offset of a sample to the | |
| next) for every dimension, and pointer. (Note that | | next) for every dimension, and pointer. (Note that | |
| strides are not given in bytes, but in offset steps of the | | strides are not given in bytes, but in offset steps of the | |
| respective pointer type.) | | respective pointer type.) | |
| */ | | */ | |
| MultiArrayView (const difference_type &shape, | | MultiArrayView (const difference_type &shape, | |
| const difference_type &stride, | | const difference_type &stride, | |
|
| pointer ptr) | | const_pointer ptr) | |
| : m_shape (shape), | | : m_shape (shape), | |
| m_stride (stride), | | m_stride (stride), | |
|
| m_ptr (ptr) | | m_ptr (const_cast<pointer>(ptr)) | |
| { | | { | |
| vigra_precondition(checkInnerStride(StrideTag()), | | vigra_precondition(checkInnerStride(StrideTag()), | |
| "MultiArrayView<..., UnstridedArrayTag>::MultiArrayView(): Firs
t dimension of given array is not unstrided."); | | "MultiArrayView<..., UnstridedArrayTag>::MultiArrayView(): Firs
t dimension of given array is not unstrided."); | |
| } | | } | |
| | | | |
|
| | | /** Construct from an old-style BasicImage. | |
| | | */ | |
| | | template <class ALLOC> | |
| | | MultiArrayView (BasicImage<T, ALLOC> const & image) | |
| | | : m_shape (Shape2(image.width(), image.height())), | |
| | | m_stride (detail::defaultStride<actual_dimension>(m_shape)), | |
| | | m_ptr (const_cast<pointer>(image.data())) | |
| | | {} | |
| | | | |
| /** Conversion to a strided view. | | /** Conversion to a strided view. | |
| */ | | */ | |
| operator MultiArrayView<N, T, StridedArrayTag>() const | | operator MultiArrayView<N, T, StridedArrayTag>() const | |
| { | | { | |
| return MultiArrayView<N, T, StridedArrayTag>(m_shape, m_stride, m_p
tr); | | return MultiArrayView<N, T, StridedArrayTag>(m_shape, m_stride, m_p
tr); | |
| } | | } | |
| | | | |
|
| | | /** Reset this <tt>MultiArrayView</tt> to an invalid state (as after | |
| | | default construction). | |
| | | Can e.g. be used prior to assignment to make a view object p | |
| | | oint to new data. | |
| | | */ | |
| | | void reset() { | |
| | | m_shape = diff_zero_t(0); | |
| | | m_stride = diff_zero_t(0); | |
| | | m_ptr = 0; | |
| | | } | |
| | | | |
| /** Assignment. There are 3 cases: | | /** Assignment. There are 3 cases: | |
| | | | |
| <ul> | | <ul> | |
| <li> When this <tt>MultiArrayView</tt> does not point to valid
data | | <li> When this <tt>MultiArrayView</tt> does not point to valid
data | |
|
| (e.g. after default construction), it becomes a copy of \a | | (e.g. after default construction), it becomes a new view o | |
| rhs. | | f \a rhs. | |
| <li> When the shapes of the two arrays match, the array content | | <li> Otherwise, when the shapes of the two arrays match, the co | |
| s are copied. | | ntents | |
| | | (i.e. the elements) of \a rhs are copied. | |
| <li> Otherwise, a <tt>PreconditionViolation</tt> exception is t
hrown. | | <li> Otherwise, a <tt>PreconditionViolation</tt> exception is t
hrown. | |
| </ul> | | </ul> | |
| */ | | */ | |
|
| MultiArrayView & operator=(MultiArrayView const & rhs); | | MultiArrayView & operator=(MultiArrayView const & rhs) | |
| | | { | |
| | | if(this != &rhs) | |
| | | assignImpl(rhs); | |
| | | return *this; | |
| | | } | |
| | | | |
|
| /** Assignment of a differently typed MultiArrayView. Fails with | | template<class Stride2> | |
| <tt>PreconditionViolation</tt> exception when the shapes do not | | MultiArrayView & operator=(MultiArrayView<N, T, Stride2> const & rhs) | |
| match. | | { | |
| | | assignImpl(rhs); | |
| | | return *this; | |
| | | } | |
| | | | |
| | | /** Assignment of a differently typed MultiArrayView. It copies the | |
| | | elements | |
| | | of\a rhs or fails with <tt>PreconditionViolation</tt> exception | |
| | | when | |
| | | the shapes do not match. | |
| */ | | */ | |
| template<class U, class C1> | | template<class U, class C1> | |
| MultiArrayView & operator=(MultiArrayView<N, U, C1> const & rhs) | | MultiArrayView & operator=(MultiArrayView<N, U, C1> const & rhs) | |
| { | | { | |
| vigra_precondition(this->shape() == rhs.shape(), | | vigra_precondition(this->shape() == rhs.shape(), | |
|
| "MultiArrayView::operator=() size mismatch."); | | "MultiArrayView::operator=(): shape mismatch."); | |
| this->copyImpl(rhs); | | this->copyImpl(rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Assignment of a scalar. Equivalent to MultiArrayView::init(v). | | /** Assignment of a scalar. Equivalent to MultiArrayView::init(v). | |
| */ | | */ | |
| MultiArrayView & operator=(value_type const & v) | | MultiArrayView & operator=(value_type const & v) | |
| { | | { | |
| return init(v); | | return init(v); | |
| } | | } | |
| | | | |
| skipping to change at line 1007 | | skipping to change at line 947 | |
| detail::copyDivScalarMultiArrayData(traverser_begin(), shape(), rhs
, MetaInt<actual_dimension-1>()); | | detail::copyDivScalarMultiArrayData(traverser_begin(), shape(), rhs
, MetaInt<actual_dimension-1>()); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Assignment of an array expression. Fails with | | /** Assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArrayView & operator=(multi_math::MultiMathOperand<Expression> con
st & rhs) | | MultiArrayView & operator=(multi_math::MultiMathOperand<Expression> con
st & rhs) | |
| { | | { | |
|
| multi_math::detail::assign(*this, rhs); | | multi_math::math_detail::assign(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Add-assignment of an array expression. Fails with | | /** Add-assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArrayView & operator+=(multi_math::MultiMathOperand<Expression> co
nst & rhs) | | MultiArrayView & operator+=(multi_math::MultiMathOperand<Expression> co
nst & rhs) | |
| { | | { | |
|
| multi_math::detail::plusAssign(*this, rhs); | | multi_math::math_detail::plusAssign(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Subtract-assignment of an array expression. Fails with | | /** Subtract-assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArrayView & operator-=(multi_math::MultiMathOperand<Expression> co
nst & rhs) | | MultiArrayView & operator-=(multi_math::MultiMathOperand<Expression> co
nst & rhs) | |
| { | | { | |
|
| multi_math::detail::minusAssign(*this, rhs); | | multi_math::math_detail::minusAssign(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Multiply-assignment of an array expression. Fails with | | /** Multiply-assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArrayView & operator*=(multi_math::MultiMathOperand<Expression> co
nst & rhs) | | MultiArrayView & operator*=(multi_math::MultiMathOperand<Expression> co
nst & rhs) | |
| { | | { | |
|
| multi_math::detail::multiplyAssign(*this, rhs); | | multi_math::math_detail::multiplyAssign(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Divide-assignment of an array expression. Fails with | | /** Divide-assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArrayView & operator/=(multi_math::MultiMathOperand<Expression> co
nst & rhs) | | MultiArrayView & operator/=(multi_math::MultiMathOperand<Expression> co
nst & rhs) | |
| { | | { | |
|
| multi_math::detail::divideAssign(*this, rhs); | | multi_math::math_detail::divideAssign(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** array access. | | /** array access. | |
| */ | | */ | |
| reference operator[] (const difference_type &d) | | reference operator[] (const difference_type &d) | |
| { | | { | |
| VIGRA_ASSERT_INSIDE(d); | | VIGRA_ASSERT_INSIDE(d); | |
| return m_ptr [dot (d, m_stride)]; | | return m_ptr [dot (d, m_stride)]; | |
| } | | } | |
| | | | |
| skipping to change at line 1262 | | skipping to change at line 1202 | |
| } | | } | |
| | | | |
| /** check whether the array is unstrided (i.e. has consecutive memo
ry) up | | /** check whether the array is unstrided (i.e. has consecutive memo
ry) up | |
| to the given dimension. | | to the given dimension. | |
| | | | |
| \a dimension can range from 0 ... N-1. If a certain dimension i
s unstrided, | | \a dimension can range from 0 ... N-1. If a certain dimension i
s unstrided, | |
| all lower dimensions are also unstrided. | | all lower dimensions are also unstrided. | |
| */ | | */ | |
| bool isUnstrided(unsigned int dimension = N-1) const | | bool isUnstrided(unsigned int dimension = N-1) const | |
| { | | { | |
|
| difference_type p = shape() - difference_type(1); | | difference_type s = vigra::detail::defaultStride<actual_dimension>( | |
| for(unsigned int k = dimension+1; k < N; ++k) | | shape()); | |
| p[k] = 0; | | for(unsigned int k = 0; k <= dimension; ++k) | |
| return (&operator[](p) - m_ptr) == coordinateToScanOrderIndex(p); | | if(stride(k) != s[k]) | |
| | | return false; | |
| | | return true; | |
| } | | } | |
| | | | |
| /** bind the M outmost dimensions to certain indices. | | /** bind the M outmost dimensions to certain indices. | |
| this reduces the dimensionality of the image to | | this reduces the dimensionality of the image to | |
| max { 1, N-M }. | | max { 1, N-M }. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| \code | | \code | |
| // create a 3D array of size 40x30x20 | | // create a 3D array of size 40x30x20 | |
| typedef MultiArray<3, double>::difference_type Shape; | | typedef MultiArray<3, double>::difference_type Shape; | |
| | | | |
| skipping to change at line 1448 | | skipping to change at line 1389 | |
| | | | |
| // temporarily add a singleton dimension to the destination arr
ay | | // temporarily add a singleton dimension to the destination arr
ay | |
| transformMultiArray(srcMultiArrayRange(original), | | transformMultiArray(srcMultiArrayRange(original), | |
| destMultiArrayRange(rowAverages.insertSingl
etonDimension(0)), | | destMultiArrayRange(rowAverages.insertSingl
etonDimension(0)), | |
| FindAverage<double>()); | | FindAverage<double>()); | |
| \endcode | | \endcode | |
| */ | | */ | |
| MultiArrayView <N+1, T, StrideTag> | | MultiArrayView <N+1, T, StrideTag> | |
| insertSingletonDimension (difference_type_1 i) const; | | insertSingletonDimension (difference_type_1 i) const; | |
| | | | |
|
| | | /** create a multiband view for this array. | |
| | | | |
| | | The type <tt>MultiArrayView<N, Multiband<T> ></tt> tells VIGRA | |
| | | algorithms which recognize the <tt>Multiband</tt> modifier to | |
| | | interpret the outermost (last) dimension as a channel dimension | |
| | | . | |
| | | In effect, these algorithms will treat the data as a set of | |
| | | (N-1)-dimensional arrays instead of a single N-dimensional arra | |
| | | y. | |
| | | */ | |
| | | MultiArrayView<N, Multiband<value_type>, StrideTag> multiband() const | |
| | | { | |
| | | return MultiArrayView<N, Multiband<value_type>, StrideTag>(*this); | |
| | | } | |
| | | | |
| /** Create a view to the diagonal elements of the array. | | /** Create a view to the diagonal elements of the array. | |
| | | | |
| This produces a 1D array view whose size equals the size | | This produces a 1D array view whose size equals the size | |
| of the shortest dimension of the original array. | | of the shortest dimension of the original array. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| \code | | \code | |
| // create a 3D array of size 40x30x20 | | // create a 3D array of size 40x30x20 | |
| typedef MultiArray<3, double>::difference_type Shape; | | typedef MultiArray<3, double>::difference_type Shape; | |
| MultiArray<3, double> array3(Shape(40, 30, 20)); | | MultiArray<3, double> array3(Shape(40, 30, 20)); | |
| | | | |
| skipping to change at line 1472 | | skipping to change at line 1426 | |
| \endcode | | \endcode | |
| */ | | */ | |
| MultiArrayView<1, T, StridedArrayTag> diagonal() const | | MultiArrayView<1, T, StridedArrayTag> diagonal() const | |
| { | | { | |
| return MultiArrayView<1, T, StridedArrayTag>(Shape1(vigra::min(m_sh
ape)), | | return MultiArrayView<1, T, StridedArrayTag>(Shape1(vigra::min(m_sh
ape)), | |
| Shape1(vigra::sum(m_st
ride)), m_ptr); | | Shape1(vigra::sum(m_st
ride)), m_ptr); | |
| } | | } | |
| | | | |
| /** create a rectangular subarray that spans between the | | /** create a rectangular subarray that spans between the | |
| points p and q, where p is in the subarray, q not. | | points p and q, where p is in the subarray, q not. | |
|
| | | If an element of p or q is negative, it is subtracted | |
| | | from the correspongng shape. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| \code | | \code | |
| // create a 3D array of size 40x30x20 | | // create a 3D array of size 40x30x20 | |
| typedef MultiArray<3, double>::difference_type Shape; | | typedef MultiArray<3, double>::difference_type Shape; | |
| MultiArray<3, double> array3(Shape(40, 30, 20)); | | MultiArray<3, double> array3(Shape(40, 30, 20)); | |
| | | | |
| // get a subarray set is smaller by one element at all sides | | // get a subarray set is smaller by one element at all sides | |
|
| MultiArrayView <3, double> subarray = array3.subarray(Shape(1,1 | | MultiArrayView <3, double> subarray = array3.subarray(Shape(1, | |
| ,1), Shape(39, 29, 19)); | | 1,1), Shape(39, 29, 19)); | |
| | | | |
| | | // specifying the end point with a vector of '-1' is equivalent | |
| | | MultiArrayView <3, double> subarray2 = array3.subarray(Shape(1, | |
| | | 1,1), Shape(-1, -1, -1)); | |
| \endcode | | \endcode | |
| */ | | */ | |
|
| MultiArrayView subarray (const difference_type &p, | | MultiArrayView subarray (difference_type p, difference_type q) const | |
| const difference_type &q) const | | | |
| { | | { | |
|
| | | detail::RelativeToAbsoluteCoordinate<actual_dimension-1>::exec(shap | |
| | | e(), p); | |
| | | detail::RelativeToAbsoluteCoordinate<actual_dimension-1>::exec(shap | |
| | | e(), q); | |
| const difference_type_1 offset = dot (m_stride, p); | | const difference_type_1 offset = dot (m_stride, p); | |
| return MultiArrayView (q - p, m_stride, m_ptr + offset); | | return MultiArrayView (q - p, m_stride, m_ptr + offset); | |
| } | | } | |
| | | | |
| /** apply an additional striding to the image, thereby reducing | | /** apply an additional striding to the image, thereby reducing | |
| the shape of the array. | | the shape of the array. | |
| for example, multiplying the stride of dimension one by three | | for example, multiplying the stride of dimension one by three | |
| turns an appropriately laid out (interleaved) rgb image into | | turns an appropriately laid out (interleaved) rgb image into | |
| a single band image. | | a single band image. | |
| */ | | */ | |
| MultiArrayView <N, T, StridedArrayTag> | | MultiArrayView <N, T, StridedArrayTag> | |
| stridearray (const difference_type &s) const | | stridearray (const difference_type &s) const | |
| { | | { | |
| difference_type shape = m_shape; | | difference_type shape = m_shape; | |
| for (unsigned int i = 0; i < actual_dimension; ++i) | | for (unsigned int i = 0; i < actual_dimension; ++i) | |
|
| shape [i] /= s [i]; | | shape[i] = (shape[i] + s[i] - 1) / s[i]; | |
| return MultiArrayView <N, T, StridedArrayTag>(shape, m_stride * s,
m_ptr); | | return MultiArrayView <N, T, StridedArrayTag>(shape, m_stride * s,
m_ptr); | |
| } | | } | |
| | | | |
| /** Transpose an array. If N==2, this implements the usual matrix t
ransposition. | | /** Transpose an array. If N==2, this implements the usual matrix t
ransposition. | |
| For N > 2, it reverses the order of the indices. | | For N > 2, it reverses the order of the indices. | |
| | | | |
| <b>Usage:</b><br> | | <b>Usage:</b><br> | |
| \code | | \code | |
| typedef MultiArray<2, double>::difference_type Shape; | | typedef MultiArray<2, double>::difference_type Shape; | |
| MultiArray<2, double> array(10, 20); | | MultiArray<2, double> array(10, 20); | |
| | | | |
|
| MultiArray<2, double, StridedArrayTag> transposed = array.trans
pose(); | | MultiArrayView<2, double, StridedArrayTag> transposed = array.t
ranspose(); | |
| | | | |
| for(int i=0; i<array.shape(0), ++i) | | for(int i=0; i<array.shape(0), ++i) | |
| for(int j=0; j<array.shape(1); ++j) | | for(int j=0; j<array.shape(1); ++j) | |
| assert(array(i, j) == transposed(j, i)); | | assert(array(i, j) == transposed(j, i)); | |
| \endcode | | \endcode | |
| */ | | */ | |
| MultiArrayView <N, T, StridedArrayTag> | | MultiArrayView <N, T, StridedArrayTag> | |
| transpose () const | | transpose () const | |
| { | | { | |
| difference_type shape(m_shape.begin(), difference_type::ReverseCopy
), | | difference_type shape(m_shape.begin(), difference_type::ReverseCopy
), | |
| stride(m_stride.begin(), difference_type::ReverseCo
py); | | stride(m_stride.begin(), difference_type::ReverseCo
py); | |
| return MultiArrayView <N, T, StridedArrayTag>(shape, stride, m_ptr)
; | | return MultiArrayView <N, T, StridedArrayTag>(shape, stride, m_ptr)
; | |
| } | | } | |
| | | | |
|
| /** permute the dimensions of the array. | | /** Permute the dimensions of the array. | |
| The function exchanges the meaning of the dimensions without co | | The function exchanges the orer of the array's axes without cop | |
| pying the data. | | ying the data. | |
| In case of a 2-dimensional array, this is simply array transpos | | Argument\a permutation specifies the desired order such that | |
| ition. In higher dimensions, | | <tt>permutation[k] = j</tt> means that axis <tt>j</tt> in the o | |
| there are more possibilities. | | riginal array | |
| | | becomes axis <tt>k</tt> in the transposed array. | |
| | | | |
| <b>Usage:</b><br> | | <b>Usage:</b><br> | |
| \code | | \code | |
| typedef MultiArray<2, double>::difference_type Shape; | | typedef MultiArray<2, double>::difference_type Shape; | |
| MultiArray<2, double> array(10, 20); | | MultiArray<2, double> array(10, 20); | |
| | | | |
|
| MultiArray<2, double, StridedArrayTag> transposed = array.permu
teDimensions(Shape(1,0)); | | MultiArrayView<2, double, StridedArrayTag> transposed = array.t
ranspose(Shape(1,0)); | |
| | | | |
| for(int i=0; i<array.shape(0), ++i) | | for(int i=0; i<array.shape(0), ++i) | |
| for(int j=0; j<array.shape(1); ++j) | | for(int j=0; j<array.shape(1); ++j) | |
| assert(array(i, j) == transposed(j, i)); | | assert(array(i, j) == transposed(j, i)); | |
| \endcode | | \endcode | |
| */ | | */ | |
| MultiArrayView <N, T, StridedArrayTag> | | MultiArrayView <N, T, StridedArrayTag> | |
|
| | | transpose(const difference_type &permutation) const | |
| | | { | |
| | | return permuteDimensions(permutation); | |
| | | } | |
| | | | |
| | | MultiArrayView <N, T, StridedArrayTag> | |
| permuteDimensions (const difference_type &s) const; | | permuteDimensions (const difference_type &s) const; | |
| | | | |
| /** Permute the dimensions of the array so that the strides are in
ascending order. | | /** Permute the dimensions of the array so that the strides are in
ascending order. | |
| Determines the appropriate permutation and then calls permuteDi
mensions(). | | Determines the appropriate permutation and then calls permuteDi
mensions(). | |
| */ | | */ | |
| MultiArrayView <N, T, StridedArrayTag> | | MultiArrayView <N, T, StridedArrayTag> | |
| permuteStridesAscending() const; | | permuteStridesAscending() const; | |
| | | | |
| /** Permute the dimensions of the array so that the strides are in
descending order. | | /** Permute the dimensions of the array so that the strides are in
descending order. | |
| Determines the appropriate permutation and then calls permuteDi
mensions(). | | Determines the appropriate permutation and then calls permuteDi
mensions(). | |
| | | | |
| skipping to change at line 1615 | | skipping to change at line 1582 | |
| } | | } | |
| | | | |
| /** return the array's shape at a certain dimension | | /** return the array's shape at a certain dimension | |
| (same as <tt>size(n)</tt>). | | (same as <tt>size(n)</tt>). | |
| */ | | */ | |
| difference_type_1 shape (difference_type_1 n) const | | difference_type_1 shape (difference_type_1 n) const | |
| { | | { | |
| return m_shape [n]; | | return m_shape [n]; | |
| } | | } | |
| | | | |
|
| | | /** return the array's width (same as <tt>shape(0)</tt>). | |
| | | */ | |
| | | difference_type_1 width() const | |
| | | { | |
| | | return m_shape [0]; | |
| | | } | |
| | | | |
| | | /** return the array's height (same as <tt>shape(1)</tt>). | |
| | | */ | |
| | | difference_type_1 height() const | |
| | | { | |
| | | return m_shape [1]; | |
| | | } | |
| | | | |
| /** return the array's stride for every dimension. | | /** return the array's stride for every dimension. | |
| */ | | */ | |
| const difference_type & stride () const | | const difference_type & stride () const | |
| { | | { | |
| return m_stride; | | return m_stride; | |
| } | | } | |
| | | | |
| /** return the array's stride at a certain dimension. | | /** return the array's stride at a certain dimension. | |
| */ | | */ | |
| difference_type_1 stride (int n) const | | difference_type_1 stride (int n) const | |
| | | | |
| skipping to change at line 1657 | | skipping to change at line 1638 | |
| | | | |
| /** check whether the given point is in the array range. | | /** check whether the given point is in the array range. | |
| */ | | */ | |
| bool isInside (difference_type const & p) const | | bool isInside (difference_type const & p) const | |
| { | | { | |
| for(int d=0; d<actual_dimension; ++d) | | for(int d=0; d<actual_dimension; ++d) | |
| if(p[d] < 0 || p[d] >= shape(d)) | | if(p[d] < 0 || p[d] >= shape(d)) | |
| return false; | | return false; | |
| return true; | | return true; | |
| } | | } | |
|
| | | /** check whether the given point is not in the array range. | |
| | | */ | |
| | | bool isOutside (difference_type const & p) const | |
| | | { | |
| | | for(int d=0; d<actual_dimension; ++d) | |
| | | if(p[d] < 0 || p[d] >= shape(d)) | |
| | | return true; | |
| | | return false; | |
| | | } | |
| | | | |
| /** Check if the array contains only non-zero elements (or if all e
lements | | /** Check if the array contains only non-zero elements (or if all e
lements | |
| are 'true' if the value type is 'bool'). | | are 'true' if the value type is 'bool'). | |
| */ | | */ | |
| bool all() const | | bool all() const | |
| { | | { | |
| bool res = true; | | bool res = true; | |
| detail::reduceOverMultiArray(traverser_begin(), shape(), | | detail::reduceOverMultiArray(traverser_begin(), shape(), | |
| res, | | res, | |
| detail::AllTrueReduceFunctor(), | | detail::AllTrueReduceFunctor(), | |
| | | | |
| skipping to change at line 1685 | | skipping to change at line 1675 | |
| { | | { | |
| bool res = false; | | bool res = false; | |
| detail::reduceOverMultiArray(traverser_begin(), shape(), | | detail::reduceOverMultiArray(traverser_begin(), shape(), | |
| res, | | res, | |
| detail::AnyTrueReduceFunctor(), | | detail::AnyTrueReduceFunctor(), | |
| MetaInt<actual_dimension-1>()); | | MetaInt<actual_dimension-1>()); | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| /** Find the minimum and maximum element in this array. | | /** Find the minimum and maximum element in this array. | |
|
| See \ref FeatureAccumulators for a general feature | | See \ref FeatureAccumulators for a general feature | |
| extraction framework. | | extraction framework. | |
| */ | | */ | |
| void minmax(T * minimum, T * maximum) const | | void minmax(T * minimum, T * maximum) const | |
| { | | { | |
| std::pair<T, T> res(NumericTraits<T>::max(), NumericTraits<T>::min(
)); | | std::pair<T, T> res(NumericTraits<T>::max(), NumericTraits<T>::min(
)); | |
| detail::reduceOverMultiArray(traverser_begin(), shape(), | | detail::reduceOverMultiArray(traverser_begin(), shape(), | |
| res, | | res, | |
| detail::MinmaxReduceFunctor(), | | detail::MinmaxReduceFunctor(), | |
| MetaInt<actual_dimension-1>()); | | MetaInt<actual_dimension-1>()); | |
| *minimum = res.first; | | *minimum = res.first; | |
| *maximum = res.second; | | *maximum = res.second; | |
| } | | } | |
| | | | |
| /** Compute the mean and variance of the values in this array. | | /** Compute the mean and variance of the values in this array. | |
|
| See \ref FeatureAccumulators for a general feature | | See \ref FeatureAccumulators for a general feature | |
| extraction framework. | | extraction framework. | |
| */ | | */ | |
| template <class U> | | template <class U> | |
| void meanVariance(U * mean, U * variance) const | | void meanVariance(U * mean, U * variance) const | |
| { | | { | |
| typedef typename NumericTraits<U>::RealPromote R; | | typedef typename NumericTraits<U>::RealPromote R; | |
|
| R zero; | | R zero = R(); | |
| triple<double, R, R> res(0.0, zero, zero); | | triple<double, R, R> res(0.0, zero, zero); | |
| detail::reduceOverMultiArray(traverser_begin(), shape(), | | detail::reduceOverMultiArray(traverser_begin(), shape(), | |
| res, | | res, | |
| detail::MeanVarianceReduceFunctor(), | | detail::MeanVarianceReduceFunctor(), | |
| MetaInt<actual_dimension-1>()); | | MetaInt<actual_dimension-1>()); | |
| *mean = res.second; | | *mean = res.second; | |
| *variance = res.third / res.first; | | *variance = res.third / res.first; | |
| } | | } | |
| | | | |
| /** Compute the sum of the array elements. | | /** Compute the sum of the array elements. | |
| | | | |
| skipping to change at line 1749 | | skipping to change at line 1739 | |
| \arg sums must have the same shape as this array, except for th
e | | \arg sums must have the same shape as this array, except for th
e | |
| axes along which the sum is to be accumulated. These axes must
be | | axes along which the sum is to be accumulated. These axes must
be | |
| singletons. Note that you must include <tt>multi_pointoperators
.hxx</tt> | | singletons. Note that you must include <tt>multi_pointoperators
.hxx</tt> | |
| for this function to work. | | for this function to work. | |
| | | | |
| <b>Usage:</b> | | <b>Usage:</b> | |
| \code | | \code | |
| #include <vigra/multi_array.hxx> | | #include <vigra/multi_array.hxx> | |
| #include <vigra/multi_pointoperators.hxx> | | #include <vigra/multi_pointoperators.hxx> | |
| | | | |
|
| MultiArray<2, double> A(rows, cols); | | MultiArray<2, double> A(Shape2(rows, cols)); | |
| ... // fill A | | ... // fill A | |
| | | | |
| // make the first axis a singleton to sum over the first index | | // make the first axis a singleton to sum over the first index | |
|
| MultiArray<2, double> rowSums(1, cols); | | MultiArray<2, double> rowSums(Shape2(1, cols)); | |
| A.sum(rowSums); | | A.sum(rowSums); | |
| | | | |
| // this is equivalent to | | // this is equivalent to | |
| transformMultiArray(srcMultiArrayRange(A), | | transformMultiArray(srcMultiArrayRange(A), | |
| destMultiArrayRange(rowSums), | | destMultiArrayRange(rowSums), | |
| FindSum<double>()); | | FindSum<double>()); | |
| \endcode | | \endcode | |
| */ | | */ | |
| template <class U, class S> | | template <class U, class S> | |
| void sum(MultiArrayView<N, U, S> sums) const | | void sum(MultiArrayView<N, U, S> sums) const | |
| | | | |
| skipping to change at line 1847 | | skipping to change at line 1837 | |
| bool hasData () const | | bool hasData () const | |
| { | | { | |
| return m_ptr != 0; | | return m_ptr != 0; | |
| } | | } | |
| | | | |
| /** returns a scan-order iterator pointing | | /** returns a scan-order iterator pointing | |
| to the first array element. | | to the first array element. | |
| */ | | */ | |
| iterator begin() | | iterator begin() | |
| { | | { | |
|
| return iterator(m_ptr, m_shape, m_stride); | | return iterator(*this); | |
| } | | } | |
| | | | |
| /** returns a const scan-order iterator pointing | | /** returns a const scan-order iterator pointing | |
| to the first array element. | | to the first array element. | |
| */ | | */ | |
| const_iterator begin() const | | const_iterator begin() const | |
| { | | { | |
|
| return const_iterator(m_ptr, m_shape, m_stride); | | return const_iterator(*this); | |
| } | | } | |
| | | | |
| /** returns a scan-order iterator pointing | | /** returns a scan-order iterator pointing | |
| beyond the last array element. | | beyond the last array element. | |
| */ | | */ | |
| iterator end() | | iterator end() | |
| { | | { | |
| return begin().getEndIterator(); | | return begin().getEndIterator(); | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 1914 | | skipping to change at line 1904 | |
| beyond the last element in dimension N, and to the | | beyond the last element in dimension N, and to the | |
| first element in every other dimension. | | first element in every other dimension. | |
| */ | | */ | |
| const_traverser traverser_end () const | | const_traverser traverser_end () const | |
| { | | { | |
| const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ()); | | const_traverser ret (m_ptr, m_stride.begin (), m_shape.begin ()); | |
| ret += m_shape [actual_dimension-1]; | | ret += m_shape [actual_dimension-1]; | |
| return ret; | | return ret; | |
| } | | } | |
| | | | |
|
| view_type view () | | view_type view () const | |
| { | | { | |
| return *this; | | return *this; | |
| } | | } | |
| }; | | }; | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
|
| MultiArrayView<N, T, StrideTag> & | | class MultiArrayView<N, Multiband<T>, StrideTag> | |
| MultiArrayView <N, T, StrideTag>::operator=(MultiArrayView const & rhs) | | : public MultiArrayView<N, T, StrideTag> | |
| | | { | |
| | | public: | |
| | | MultiArrayView(MultiArrayView<N, T, StrideTag> const & v) | |
| | | : MultiArrayView<N, T, StrideTag>(v) | |
| | | {} | |
| | | }; | |
| | | | |
| | | template <unsigned int N, class T, class Stride1> | |
| | | template <class Stride2> | |
| | | void | |
| | | MultiArrayView <N, T, Stride1>::assignImpl(MultiArrayView<N, T, Stride2> co | |
| | | nst & rhs) | |
| { | | { | |
|
| if(this == &rhs) | | | |
| return *this; | | | |
| vigra_precondition(this->shape() == rhs.shape() || m_ptr == 0, | | | |
| "MultiArrayView::operator=(MultiArrayView const &) size mismatch.") | | | |
| ; | | | |
| if(m_ptr == 0) | | if(m_ptr == 0) | |
| { | | { | |
|
| m_shape = rhs.m_shape; | | vigra_precondition(rhs.checkInnerStride(Stride1()), | |
| m_stride = rhs.m_stride; | | "MultiArrayView<..., UnstridedArrayTag>::operator=(MultiArrayVi | |
| m_ptr = rhs.m_ptr; | | ew const &): cannot create unstrided view from strided array."); | |
| | | | |
| | | m_shape = rhs.shape(); | |
| | | m_stride = rhs.stride(); | |
| | | m_ptr = rhs.data(); | |
| } | | } | |
| else | | else | |
|
| | | { | |
| | | vigra_precondition(this->shape() == rhs.shape(), | |
| | | "MultiArrayView::operator=(MultiArrayView const &): shape misma | |
| | | tch."); | |
| this->copyImpl(rhs); | | this->copyImpl(rhs); | |
|
| return *this; | | } | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
| template <class CN> | | template <class CN> | |
| bool | | bool | |
| MultiArrayView <N, T, StrideTag>::arraysOverlap(const MultiArrayView <N, T,
CN>& rhs) const | | MultiArrayView <N, T, StrideTag>::arraysOverlap(const MultiArrayView <N, T,
CN>& rhs) const | |
| { | | { | |
| vigra_precondition (shape () == rhs.shape (), | | vigra_precondition (shape () == rhs.shape (), | |
| "MultiArrayView::arraysOverlap(): shape mismatch."); | | "MultiArrayView::arraysOverlap(): shape mismatch."); | |
| const_pointer first_element = this->m_ptr, | | const_pointer first_element = this->m_ptr, | |
| | | | |
| skipping to change at line 2040 | | skipping to change at line 2043 | |
| MultiArrayView <N, T, StrideTag>::permuteDimensions (const difference_type
&s) const | | MultiArrayView <N, T, StrideTag>::permuteDimensions (const difference_type
&s) const | |
| { | | { | |
| difference_type shape, stride, check((typename difference_type::value_t
ype)0); | | difference_type shape, stride, check((typename difference_type::value_t
ype)0); | |
| for (unsigned int i = 0; i < actual_dimension; ++i) | | for (unsigned int i = 0; i < actual_dimension; ++i) | |
| { | | { | |
| shape[i] = m_shape[s[i]]; | | shape[i] = m_shape[s[i]]; | |
| stride[i] = m_stride[s[i]]; | | stride[i] = m_stride[s[i]]; | |
| ++check[s[i]]; | | ++check[s[i]]; | |
| } | | } | |
| vigra_precondition(check == difference_type(1), | | vigra_precondition(check == difference_type(1), | |
|
| "MultiArrayView::permuteDimensions(): every dimension must occur exa
ctly once."); | | "MultiArrayView::transpose(): every dimension must occur exactly onc
e."); | |
| return MultiArrayView <N, T, StridedArrayTag>(shape, stride, m_ptr); | | return MultiArrayView <N, T, StridedArrayTag>(shape, stride, m_ptr); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
| typename MultiArrayView <N, T, StrideTag>::difference_type | | typename MultiArrayView <N, T, StrideTag>::difference_type | |
| MultiArrayView <N, T, StrideTag>::strideOrdering(difference_type stride) | | MultiArrayView <N, T, StrideTag>::strideOrdering(difference_type stride) | |
| { | | { | |
| difference_type permutation; | | difference_type permutation; | |
| for(int k=0; k<(int)N; ++k) | | for(int k=0; k<(int)N; ++k) | |
| permutation[k] = k; | | permutation[k] = k; | |
| | | | |
| skipping to change at line 2087 | | skipping to change at line 2090 | |
| permutation[ordering[k]] = k; | | permutation[ordering[k]] = k; | |
| return permuteDimensions(permutation); | | return permuteDimensions(permutation); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
| MultiArrayView <N, T, StridedArrayTag> | | MultiArrayView <N, T, StridedArrayTag> | |
| MultiArrayView <N, T, StrideTag>::permuteStridesDescending() const | | MultiArrayView <N, T, StrideTag>::permuteStridesDescending() const | |
| { | | { | |
| difference_type ordering(strideOrdering(m_stride)), permutation; | | difference_type ordering(strideOrdering(m_stride)), permutation; | |
| for(MultiArrayIndex k=0; k<N; ++k) | | for(MultiArrayIndex k=0; k<N; ++k) | |
|
| permutation[ordering[N-1-k]] = k; | | permutation[N-1-ordering[k]] = k; | |
| return permuteDimensions(permutation); | | return permuteDimensions(permutation); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
| template <int M, class Index> | | template <int M, class Index> | |
| MultiArrayView <N-M, T, StrideTag> | | MultiArrayView <N-M, T, StrideTag> | |
| MultiArrayView <N, T, StrideTag>::bindOuter (const TinyVector <Index, M> &d
) const | | MultiArrayView <N, T, StrideTag>::bindOuter (const TinyVector <Index, M> &d
) const | |
| { | | { | |
| TinyVector <MultiArrayIndex, M> stride; | | TinyVector <MultiArrayIndex, M> stride; | |
| stride.init (m_stride.begin () + N-M, m_stride.end ()); | | stride.init (m_stride.begin () + N-M, m_stride.end ()); | |
| pointer ptr = m_ptr + dot (d, stride); | | pointer ptr = m_ptr + dot (d, stride); | |
| static const int NNew = (N-M == 0) ? 1 : N-M; | | static const int NNew = (N-M == 0) ? 1 : N-M; | |
| TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride; | | TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride; | |
| if (N-M == 0) | | if (N-M == 0) | |
| { | | { | |
| inner_shape [0] = 1; | | inner_shape [0] = 1; | |
|
| inner_stride [0] = 0; | | inner_stride [0] = 1; | |
| } | | } | |
| else | | else | |
| { | | { | |
| inner_shape.init (m_shape.begin (), m_shape.end () - M); | | inner_shape.init (m_shape.begin (), m_shape.end () - M); | |
| inner_stride.init (m_stride.begin (), m_stride.end () - M); | | inner_stride.init (m_stride.begin (), m_stride.end () - M); | |
| } | | } | |
| return MultiArrayView <N-M, T, StrideTag> (inner_shape, inner_stride, p
tr); | | return MultiArrayView <N-M, T, StrideTag> (inner_shape, inner_stride, p
tr); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
| | | | |
| skipping to change at line 2127 | | skipping to change at line 2130 | |
| MultiArrayView <N, T, StrideTag>::bindInner (const TinyVector <Index, M> &d
) const | | MultiArrayView <N, T, StrideTag>::bindInner (const TinyVector <Index, M> &d
) const | |
| { | | { | |
| TinyVector <MultiArrayIndex, M> stride; | | TinyVector <MultiArrayIndex, M> stride; | |
| stride.init (m_stride.begin (), m_stride.end () - N + M); | | stride.init (m_stride.begin (), m_stride.end () - N + M); | |
| pointer ptr = m_ptr + dot (d, stride); | | pointer ptr = m_ptr + dot (d, stride); | |
| static const int NNew = (N-M == 0) ? 1 : N-M; | | static const int NNew = (N-M == 0) ? 1 : N-M; | |
| TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride; | | TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride; | |
| if (N-M == 0) | | if (N-M == 0) | |
| { | | { | |
| outer_shape [0] = 1; | | outer_shape [0] = 1; | |
|
| outer_stride [0] = 0; | | outer_stride [0] = 1; | |
| } | | } | |
| else | | else | |
| { | | { | |
| outer_shape.init (m_shape.begin () + M, m_shape.end ()); | | outer_shape.init (m_shape.begin () + M, m_shape.end ()); | |
| outer_stride.init (m_stride.begin () + M, m_stride.end ()); | | outer_stride.init (m_stride.begin () + M, m_stride.end ()); | |
| } | | } | |
| return MultiArrayView <N-M, T, StridedArrayTag> | | return MultiArrayView <N-M, T, StridedArrayTag> | |
| (outer_shape, outer_stride, ptr); | | (outer_shape, outer_stride, ptr); | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 2149 | | skipping to change at line 2152 | |
| template <unsigned int M> | | template <unsigned int M> | |
| MultiArrayView <N-1, T, typename detail::MaybeStrided<StrideTag, M>::type > | | MultiArrayView <N-1, T, typename detail::MaybeStrided<StrideTag, M>::type > | |
| MultiArrayView <N, T, StrideTag>::bind (difference_type_1 d) const | | MultiArrayView <N, T, StrideTag>::bind (difference_type_1 d) const | |
| { | | { | |
| static const int NNew = (N-1 == 0) ? 1 : N-1; | | static const int NNew = (N-1 == 0) ? 1 : N-1; | |
| TinyVector <MultiArrayIndex, NNew> shape, stride; | | TinyVector <MultiArrayIndex, NNew> shape, stride; | |
| // the remaining dimensions are 0..n-1,n+1..N-1 | | // the remaining dimensions are 0..n-1,n+1..N-1 | |
| if (N-1 == 0) | | if (N-1 == 0) | |
| { | | { | |
| shape[0] = 1; | | shape[0] = 1; | |
|
| stride[0] = 0; | | stride[0] = 1; | |
| } | | } | |
| else | | else | |
| { | | { | |
| std::copy (m_shape.begin (), m_shape.begin () + M, shape.begin ()); | | std::copy (m_shape.begin (), m_shape.begin () + M, shape.begin ()); | |
| std::copy (m_shape.begin () + M+1, m_shape.end (), | | std::copy (m_shape.begin () + M+1, m_shape.end (), | |
| shape.begin () + M); | | shape.begin () + M); | |
| std::copy (m_stride.begin (), m_stride.begin () + M, stride.begin (
)); | | std::copy (m_stride.begin (), m_stride.begin () + M, stride.begin (
)); | |
| std::copy (m_stride.begin () + M+1, m_stride.end (), | | std::copy (m_stride.begin () + M+1, m_stride.end (), | |
| stride.begin () + M); | | stride.begin () + M); | |
| } | | } | |
| | | | |
| skipping to change at line 2173 | | skipping to change at line 2176 | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
| MultiArrayView <N - 1, T, StrideTag> | | MultiArrayView <N - 1, T, StrideTag> | |
| MultiArrayView <N, T, StrideTag>::bindOuter (difference_type_1 d) const | | MultiArrayView <N, T, StrideTag>::bindOuter (difference_type_1 d) const | |
| { | | { | |
| static const int NNew = (N-1 == 0) ? 1 : N-1; | | static const int NNew = (N-1 == 0) ? 1 : N-1; | |
| TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride; | | TinyVector <MultiArrayIndex, NNew> inner_shape, inner_stride; | |
| if (N-1 == 0) | | if (N-1 == 0) | |
| { | | { | |
| inner_shape [0] = 1; | | inner_shape [0] = 1; | |
|
| inner_stride [0] = 0; | | inner_stride [0] = 1; | |
| } | | } | |
| else | | else | |
| { | | { | |
| inner_shape.init (m_shape.begin (), m_shape.end () - 1); | | inner_shape.init (m_shape.begin (), m_shape.end () - 1); | |
| inner_stride.init (m_stride.begin (), m_stride.end () - 1); | | inner_stride.init (m_stride.begin (), m_stride.end () - 1); | |
| } | | } | |
| return MultiArrayView <N-1, T, StrideTag> (inner_shape, inner_stride, | | return MultiArrayView <N-1, T, StrideTag> (inner_shape, inner_stride, | |
| m_ptr + d * m_stride [N-1]); | | m_ptr + d * m_stride [N-1]); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | template <unsigned int N, class T, class StrideTag> | |
| MultiArrayView <N - 1, T, StridedArrayTag> | | MultiArrayView <N - 1, T, StridedArrayTag> | |
| MultiArrayView <N, T, StrideTag>::bindInner (difference_type_1 d) const | | MultiArrayView <N, T, StrideTag>::bindInner (difference_type_1 d) const | |
| { | | { | |
| static const int NNew = (N-1 == 0) ? 1 : N-1; | | static const int NNew = (N-1 == 0) ? 1 : N-1; | |
| TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride; | | TinyVector <MultiArrayIndex, NNew> outer_shape, outer_stride; | |
| if (N-1 == 0) | | if (N-1 == 0) | |
| { | | { | |
| outer_shape [0] = 1; | | outer_shape [0] = 1; | |
|
| outer_stride [0] = 0; | | outer_stride [0] = 1; | |
| } | | } | |
| else | | else | |
| { | | { | |
| outer_shape.init (m_shape.begin () + 1, m_shape.end ()); | | outer_shape.init (m_shape.begin () + 1, m_shape.end ()); | |
| outer_stride.init (m_stride.begin () + 1, m_stride.end ()); | | outer_stride.init (m_stride.begin () + 1, m_stride.end ()); | |
| } | | } | |
| return MultiArrayView <N-1, T, StridedArrayTag> | | return MultiArrayView <N-1, T, StridedArrayTag> | |
| (outer_shape, outer_stride, m_ptr + d * m_stride [0]); | | (outer_shape, outer_stride, m_ptr + d * m_stride [0]); | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 2217 | | skipping to change at line 2220 | |
| { | | { | |
| vigra_precondition ( | | vigra_precondition ( | |
| n < static_cast <int> (N), | | n < static_cast <int> (N), | |
| "MultiArrayView <N, T, StrideTag>::bindAt(): dimension out of range
."); | | "MultiArrayView <N, T, StrideTag>::bindAt(): dimension out of range
."); | |
| static const int NNew = (N-1 == 0) ? 1 : N-1; | | static const int NNew = (N-1 == 0) ? 1 : N-1; | |
| TinyVector <MultiArrayIndex, NNew> shape, stride; | | TinyVector <MultiArrayIndex, NNew> shape, stride; | |
| // the remaining dimensions are 0..n-1,n+1..N-1 | | // the remaining dimensions are 0..n-1,n+1..N-1 | |
| if (N-1 == 0) | | if (N-1 == 0) | |
| { | | { | |
| shape [0] = 1; | | shape [0] = 1; | |
|
| stride [0] = 0; | | stride [0] = 1; | |
| } | | } | |
| else | | else | |
| { | | { | |
| std::copy (m_shape.begin (), m_shape.begin () + n, shape.begin ()); | | std::copy (m_shape.begin (), m_shape.begin () + n, shape.begin ()); | |
| std::copy (m_shape.begin () + n+1, m_shape.end (), | | std::copy (m_shape.begin () + n+1, m_shape.end (), | |
| shape.begin () + n); | | shape.begin () + n); | |
| std::copy (m_stride.begin (), m_stride.begin () + n, stride.begin (
)); | | std::copy (m_stride.begin (), m_stride.begin () + n, stride.begin (
)); | |
| std::copy (m_stride.begin () + n+1, m_stride.end (), | | std::copy (m_stride.begin () + n+1, m_stride.end (), | |
| stride.begin () + n); | | stride.begin () + n); | |
| } | | } | |
| | | | |
| skipping to change at line 2377 | | skipping to change at line 2380 | |
| The template parameters are as follows | | The template parameters are as follows | |
| \code | | \code | |
| N: the array dimension | | N: the array dimension | |
| | | | |
| T: the type of the array elements | | T: the type of the array elements | |
| | | | |
| A: the allocator used for internal storage management | | A: the allocator used for internal storage management | |
| (default: std::allocator<T>) | | (default: std::allocator<T>) | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> | | <b>\#include</b> \<vigra/multi_array.hxx\> <br/> | |
| \<vigra/multi_array.hxx\> | | | |
| | | | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <unsigned int N, class T, class A /* default already declared abov
e */> | | template <unsigned int N, class T, class A /* default already declared abov
e */> | |
|
| class MultiArray : public MultiArrayView <N, T> | | class MultiArray | |
| | | : public MultiArrayView <N, typename vigra::detail::ResolveMultiband<T>::ty | |
| | | pe, | |
| | | typename vigra::detail::ResolveMultiband<T>::St | |
| | | ride> | |
| { | | { | |
|
| | | public: | |
| | | typedef typename vigra::detail::ResolveMultiband<T>::Stride actual_stri | |
| | | de; | |
| | | | |
|
| public: | | /** the view type associated with this array. | |
| using MultiArrayView <N, T>::actual_dimension; | | */ | |
| | | typedef MultiArrayView <N, typename vigra::detail::ResolveMultiband<T>: | |
| | | :type, | |
| | | typename vigra::detail::ResolveMultiband<T>: | |
| | | :Stride> view_type; | |
| | | | |
| | | using view_type::actual_dimension; | |
| | | | |
| /** the allocator type used to allocate the memory | | /** the allocator type used to allocate the memory | |
| */ | | */ | |
| typedef A allocator_type; | | typedef A allocator_type; | |
| | | | |
|
| /** the view type associated with this array. | | | |
| */ | | | |
| typedef MultiArrayView <N, T> view_type; | | | |
| | | | |
| /** the matrix type associated with this array. | | /** the matrix type associated with this array. | |
| */ | | */ | |
| typedef MultiArray <N, T, A> matrix_type; | | typedef MultiArray <N, T, A> matrix_type; | |
| | | | |
| /** the array's value type | | /** the array's value type | |
| */ | | */ | |
| typedef typename view_type::value_type value_type; | | typedef typename view_type::value_type value_type; | |
| | | | |
| /** pointer type | | /** pointer type | |
| */ | | */ | |
| | | | |
| skipping to change at line 2435 | | skipping to change at line 2440 | |
| /** difference type (used for multi-dimensional offsets and indices
) | | /** difference type (used for multi-dimensional offsets and indices
) | |
| */ | | */ | |
| typedef typename view_type::difference_type difference_type; | | typedef typename view_type::difference_type difference_type; | |
| | | | |
| /** difference and index type for a single dimension | | /** difference and index type for a single dimension | |
| */ | | */ | |
| typedef typename view_type::difference_type_1 difference_type_1; | | typedef typename view_type::difference_type_1 difference_type_1; | |
| | | | |
| /** traverser type | | /** traverser type | |
| */ | | */ | |
|
| typedef typename vigra::detail::MultiIteratorChooser < | | typedef typename view_type::traverser traverser; | |
| UnstridedArrayTag>::template Traverser <N, T, T &, T *>::type | | | |
| traverser; | | | |
| | | | |
| /** traverser type to const data | | /** traverser type to const data | |
| */ | | */ | |
|
| typedef typename vigra::detail::MultiIteratorChooser < | | typedef typename view_type::const_traverser const_traverser; | |
| UnstridedArrayTag>::template Traverser <N, T, T const &, T const *> | | | |
| ::type | | // /** sequential (random access) iterator type | |
| const_traverser; | | // */ | |
| | | // typedef typename vigra::detail::MultiIteratorChooser<actual_stride>: | |
| | | :template Iterator<N, value_type, reference, pointer>::type | |
| | | // iterator; | |
| | | | |
| | | // /** sequential (random access) const iterator type | |
| | | // */ | |
| | | // typedef typename vigra::detail::MultiIteratorChooser<actual_stride>: | |
| | | :template Iterator<N, value_type, const_reference, const_pointer>::type | |
| | | // const_iterator; | |
| | | | |
| /** sequential (random access) iterator type | | /** sequential (random access) iterator type | |
| */ | | */ | |
|
| typedef T * iterator; | | typedef typename view_type::iterator iterator; | |
| | | | |
| /** sequential (random access) const iterator type | | /** sequential (random access) const iterator type | |
| */ | | */ | |
|
| typedef T * const_iterator; | | typedef typename view_type::const_iterator const_iterator; | |
| | | | |
| protected: | | protected: | |
| | | | |
| typedef typename difference_type::value_type diff_zero_t; | | typedef typename difference_type::value_type diff_zero_t; | |
| | | | |
| /** the allocator used to allocate the memory | | /** the allocator used to allocate the memory | |
| */ | | */ | |
| allocator_type m_alloc; | | allocator_type m_alloc; | |
| | | | |
| /** allocate memory for s pixels, write its address into the given | | /** allocate memory for s pixels, write its address into the given | |
| | | | |
| skipping to change at line 2488 | | skipping to change at line 2499 | |
| /** deallocate the memory (of length s) starting at the given addre
ss. | | /** deallocate the memory (of length s) starting at the given addre
ss. | |
| */ | | */ | |
| void deallocate (pointer &ptr, difference_type_1 s); | | void deallocate (pointer &ptr, difference_type_1 s); | |
| | | | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| void copyOrReshape (const MultiArrayView<N, U, StrideTag> &rhs); | | void copyOrReshape (const MultiArrayView<N, U, StrideTag> &rhs); | |
| public: | | public: | |
| /** default constructor | | /** default constructor | |
| */ | | */ | |
| MultiArray () | | MultiArray () | |
|
| : MultiArrayView <N, T> (difference_type (diff_zero_t(0)), | | : view_type (difference_type (diff_zero_t(0)), | |
| difference_type (diff_zero_t(0)), 0) | | difference_type (diff_zero_t(0)), 0) | |
| {} | | {} | |
| | | | |
| /** construct with given allocator | | /** construct with given allocator | |
| */ | | */ | |
| MultiArray (allocator_type const & alloc) | | MultiArray (allocator_type const & alloc) | |
|
| : MultiArrayView <N, T> (difference_type (diff_zero_t(0)), | | : view_type(difference_type (diff_zero_t(0)), | |
| difference_type (diff_zero_t(0)), 0), | | difference_type (diff_zero_t(0)), 0), | |
| m_alloc(alloc) | | m_alloc(alloc) | |
| {} | | {} | |
| | | | |
| /** construct with given length | | /** construct with given length | |
| | | | |
| Use only for 1-dimensional arrays (<tt>N==1</tt>). | | Use only for 1-dimensional arrays (<tt>N==1</tt>). | |
| */ | | */ | |
| explicit MultiArray (difference_type_1 length, | | explicit MultiArray (difference_type_1 length, | |
| allocator_type const & alloc = allocator_type()); | | allocator_type const & alloc = allocator_type()); | |
| | | | |
|
| | | /** construct with given width and height | |
| | | | |
| | | Use only for 2-dimensional arrays (<tt>N==2</tt>). | |
| | | */ | |
| | | MultiArray (difference_type_1 width, difference_type_1 height, | |
| | | allocator_type const & alloc = allocator_type()); | |
| | | | |
| /** construct with given shape | | /** construct with given shape | |
| */ | | */ | |
| explicit MultiArray (const difference_type &shape, | | explicit MultiArray (const difference_type &shape, | |
| allocator_type const & alloc = allocator_type()); | | allocator_type const & alloc = allocator_type()); | |
| | | | |
| /** construct from shape with an initial value | | /** construct from shape with an initial value | |
| */ | | */ | |
| MultiArray (const difference_type &shape, const_reference init, | | MultiArray (const difference_type &shape, const_reference init, | |
| allocator_type const & alloc = allocator_type()); | | allocator_type const & alloc = allocator_type()); | |
| | | | |
|
| | | /** construct from shape and initialize with a linear sequence in s | |
| | | can order | |
| | | (i.e. first pixel gets value 0, second on gets value 1 and so o | |
| | | n). | |
| | | */ | |
| | | MultiArray (const difference_type &shape, MultiArrayInitializationTag i | |
| | | nit, | |
| | | allocator_type const & alloc = allocator_type()); | |
| | | | |
| /** construct from shape and copy values from the given array | | /** construct from shape and copy values from the given array | |
| */ | | */ | |
| MultiArray (const difference_type &shape, const_pointer init, | | MultiArray (const difference_type &shape, const_pointer init, | |
| allocator_type const & alloc = allocator_type()); | | allocator_type const & alloc = allocator_type()); | |
| | | | |
| /** copy constructor | | /** copy constructor | |
| */ | | */ | |
| MultiArray (const MultiArray &rhs) | | MultiArray (const MultiArray &rhs) | |
|
| : MultiArrayView <N, T> (rhs.m_shape, rhs.m_stride, 0), | | : view_type(rhs.m_shape, rhs.m_stride, 0), | |
| m_alloc (rhs.m_alloc) | | m_alloc (rhs.m_alloc) | |
| { | | { | |
| allocate (this->m_ptr, this->elementCount (), rhs.data ()); | | allocate (this->m_ptr, this->elementCount (), rhs.data ()); | |
| } | | } | |
| | | | |
| /** constructor from an array expression | | /** constructor from an array expression | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArray (multi_math::MultiMathOperand<Expression> const & rhs, | | MultiArray (multi_math::MultiMathOperand<Expression> const & rhs, | |
| allocator_type const & alloc = allocator_type()) | | allocator_type const & alloc = allocator_type()) | |
|
| : MultiArrayView <N, T> (difference_type (diff_zero_t(0)), | | : view_type(difference_type (diff_zero_t(0)), | |
| difference_type (diff_zero_t(0)), 0), | | difference_type (diff_zero_t(0)), 0), | |
| m_alloc (alloc) | | m_alloc (alloc) | |
| { | | { | |
|
| multi_math::detail::assignOrResize(*this, rhs); | | multi_math::math_detail::assignOrResize(*this, rhs); | |
| } | | } | |
| | | | |
| /** construct by copying from a MultiArrayView | | /** construct by copying from a MultiArrayView | |
| */ | | */ | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| MultiArray (const MultiArrayView<N, U, StrideTag> &rhs, | | MultiArray (const MultiArrayView<N, U, StrideTag> &rhs, | |
| allocator_type const & alloc = allocator_type()); | | allocator_type const & alloc = allocator_type()); | |
| | | | |
| /** assignment.<br> | | /** assignment.<br> | |
| If the size of \a rhs is the same as the left-hand side arrays'
s old size, only | | If the size of \a rhs is the same as the left-hand side arrays'
s old size, only | |
| | | | |
| skipping to change at line 2681 | | skipping to change at line 2705 | |
| { | | { | |
| view_type::operator/=(rhs); | | view_type::operator/=(rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| /** Assignment of an array expression. Fails with | | /** Assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArray & operator=(multi_math::MultiMathOperand<Expression> const &
rhs) | | MultiArray & operator=(multi_math::MultiMathOperand<Expression> const &
rhs) | |
| { | | { | |
|
| multi_math::detail::assignOrResize(*this, rhs); | | multi_math::math_detail::assignOrResize(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Add-assignment of an array expression. Fails with | | /** Add-assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArray & operator+=(multi_math::MultiMathOperand<Expression> const
& rhs) | | MultiArray & operator+=(multi_math::MultiMathOperand<Expression> const
& rhs) | |
| { | | { | |
|
| multi_math::detail::plusAssignOrResize(*this, rhs); | | multi_math::math_detail::plusAssignOrResize(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Subtract-assignment of an array expression. Fails with | | /** Subtract-assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArray & operator-=(multi_math::MultiMathOperand<Expression> const
& rhs) | | MultiArray & operator-=(multi_math::MultiMathOperand<Expression> const
& rhs) | |
| { | | { | |
|
| multi_math::detail::minusAssignOrResize(*this, rhs); | | multi_math::math_detail::minusAssignOrResize(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Multiply-assignment of an array expression. Fails with | | /** Multiply-assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArray & operator*=(multi_math::MultiMathOperand<Expression> const
& rhs) | | MultiArray & operator*=(multi_math::MultiMathOperand<Expression> const
& rhs) | |
| { | | { | |
|
| multi_math::detail::multiplyAssignOrResize(*this, rhs); | | multi_math::math_detail::multiplyAssignOrResize(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Divide-assignment of an array expression. Fails with | | /** Divide-assignment of an array expression. Fails with | |
| <tt>PreconditionViolation</tt> exception when the shapes do not
match. | | <tt>PreconditionViolation</tt> exception when the shapes do not
match. | |
| */ | | */ | |
| template<class Expression> | | template<class Expression> | |
| MultiArray & operator/=(multi_math::MultiMathOperand<Expression> const
& rhs) | | MultiArray & operator/=(multi_math::MultiMathOperand<Expression> const
& rhs) | |
| { | | { | |
|
| multi_math::detail::divideAssignOrResize(*this, rhs); | | multi_math::math_detail::divideAssignOrResize(*this, rhs); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** destructor | | /** destructor | |
| */ | | */ | |
| ~MultiArray () | | ~MultiArray () | |
| { | | { | |
| deallocate (this->m_ptr, this->elementCount ()); | | deallocate (this->m_ptr, this->elementCount ()); | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 2747 | | skipping to change at line 2771 | |
| view_type::init(init); | | view_type::init(init); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Allocate new memory with the given shape and initialize with ze
ros.<br> | | /** Allocate new memory with the given shape and initialize with ze
ros.<br> | |
| <em>Note:</em> this operation invalidates all dependent objects | | <em>Note:</em> this operation invalidates all dependent objects | |
| (array views and iterators) | | (array views and iterators) | |
| */ | | */ | |
| void reshape (const difference_type &shape) | | void reshape (const difference_type &shape) | |
| { | | { | |
|
| reshape (shape, T()); | | reshape (shape, value_type()); | |
| } | | } | |
| | | | |
| /** Allocate new memory with the given shape and initialize it | | /** Allocate new memory with the given shape and initialize it | |
| with the given value.<br> | | with the given value.<br> | |
| <em>Note:</em> this operation invalidates all dependent objects | | <em>Note:</em> this operation invalidates all dependent objects | |
| (array views and iterators) | | (array views and iterators) | |
| */ | | */ | |
| void reshape (const difference_type &shape, const_reference init); | | void reshape (const difference_type &shape, const_reference init); | |
| | | | |
| /** Swap the contents with another MultiArray. This is fast, | | /** Swap the contents with another MultiArray. This is fast, | |
| because no data are copied, but only pointers and shapes swappe
d. | | because no data are copied, but only pointers and shapes swappe
d. | |
| <em>Note:</em> this operation invalidates all dependent objects | | <em>Note:</em> this operation invalidates all dependent objects | |
| (array views and iterators) | | (array views and iterators) | |
| */ | | */ | |
| void swap (MultiArray & other); | | void swap (MultiArray & other); | |
| | | | |
|
| /** sequential iterator pointing to the first array element. | | // /** sequential iterator pointing to the first array element. | |
| */ | | // */ | |
| iterator begin () | | // iterator begin () | |
| { | | // { | |
| return this->data(); | | // return vigra::detail::MultiIteratorChooser<actual_stride>::templ | |
| } | | ate constructIterator<iterator>((view_type *)this); | |
| | | // } | |
| /** sequential iterator pointing beyond the last array element. | | | |
| */ | | // /** sequential iterator pointing beyond the last array element. | |
| iterator end () | | // */ | |
| { | | // iterator end () | |
| return this->data() + this->elementCount(); | | // { | |
| } | | // return begin() + this->elementCount(); | |
| | | // } | |
| /** sequential const iterator pointing to the first array element. | | | |
| */ | | // /** sequential const iterator pointing to the first array elemen | |
| const_iterator begin () const | | t. | |
| { | | // */ | |
| return this->data(); | | // const_iterator begin () const | |
| } | | // { | |
| | | // return vigra::detail::MultiIteratorChooser<actual_stride>::templ | |
| /** sequential const iterator pointing beyond the last array elemen | | ate constructIterator<iterator>((view_type const *)this); | |
| t. | | // } | |
| */ | | | |
| const_iterator end () const | | // /** sequential const iterator pointing beyond the last array ele | |
| { | | ment. | |
| return this->data() + this->elementCount(); | | // */ | |
| } | | // const_iterator end () const | |
| | | // { | |
| | | // return begin() + this->elementCount(); | |
| | | // } | |
| | | | |
| /** get the allocator. | | /** get the allocator. | |
| */ | | */ | |
| allocator_type const & allocator () const | | allocator_type const & allocator () const | |
| { | | { | |
| return m_alloc; | | return m_alloc; | |
| } | | } | |
|
| | | | |
| | | static difference_type defaultStride(difference_type const & shape) | |
| | | { | |
| | | return vigra::detail::ResolveMultiband<T>::defaultStride(shape); | |
| | | } | |
| }; | | }; | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| MultiArray <N, T, A>::MultiArray (difference_type_1 length, | | MultiArray <N, T, A>::MultiArray (difference_type_1 length, | |
| allocator_type const & alloc) | | allocator_type const & alloc) | |
|
| : MultiArrayView <N, T> (difference_type(length), | | : view_type(difference_type(length), | |
| detail::defaultStride <1> (difference_type(length) | | defaultStride(difference_type(length)), | |
| ), | | 0), | |
| 0), | | m_alloc(alloc) | |
| | | { | |
| | | allocate (this->m_ptr, this->elementCount (), value_type()); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T, class A> | |
| | | MultiArray <N, T, A>::MultiArray (difference_type_1 width, difference_type_ | |
| | | 1 height, | |
| | | allocator_type const & alloc) | |
| | | : view_type(difference_type(width, height), | |
| | | defaultStride(difference_type(width, height)), | |
| | | 0), | |
| m_alloc(alloc) | | m_alloc(alloc) | |
| { | | { | |
|
| allocate (this->m_ptr, this->elementCount (), T()); | | allocate (this->m_ptr, this->elementCount (), value_type()); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| MultiArray <N, T, A>::MultiArray (const difference_type &shape, | | MultiArray <N, T, A>::MultiArray (const difference_type &shape, | |
| allocator_type const & alloc) | | allocator_type const & alloc) | |
|
| : MultiArrayView <N, T> (shape, | | : view_type(shape, | |
| detail::defaultStride <MultiArrayView<N,T>::actual | | defaultStride(shape), | |
| _dimension> (shape), | | 0), | |
| 0), | | | |
| m_alloc(alloc) | | m_alloc(alloc) | |
| { | | { | |
| if (N == 0) | | if (N == 0) | |
| { | | { | |
| this->m_shape [0] = 1; | | this->m_shape [0] = 1; | |
|
| this->m_stride [0] = 0; | | this->m_stride [0] = 1; | |
| } | | } | |
|
| allocate (this->m_ptr, this->elementCount (), T()); | | allocate (this->m_ptr, this->elementCount (), value_type()); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| MultiArray <N, T, A>::MultiArray (const difference_type &shape, const_refer
ence init, | | MultiArray <N, T, A>::MultiArray (const difference_type &shape, const_refer
ence init, | |
| allocator_type const & alloc) | | allocator_type const & alloc) | |
|
| : MultiArrayView <N, T> (shape, | | : view_type(shape, | |
| detail::defaultStride <MultiArrayView<N,T>::actual | | defaultStride(shape), | |
| _dimension> (shape), | | 0), | |
| 0), | | | |
| m_alloc(alloc) | | m_alloc(alloc) | |
| { | | { | |
| if (N == 0) | | if (N == 0) | |
| { | | { | |
| this->m_shape [0] = 1; | | this->m_shape [0] = 1; | |
|
| this->m_stride [0] = 0; | | this->m_stride [0] = 1; | |
| } | | } | |
| allocate (this->m_ptr, this->elementCount (), init); | | allocate (this->m_ptr, this->elementCount (), init); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
|
| | | MultiArray <N, T, A>::MultiArray (const difference_type &shape, MultiArrayI | |
| | | nitializationTag init, | |
| | | allocator_type const & alloc) | |
| | | : view_type(shape, | |
| | | defaultStride(shape), | |
| | | 0), | |
| | | m_alloc(alloc) | |
| | | { | |
| | | if (N == 0) | |
| | | { | |
| | | this->m_shape [0] = 1; | |
| | | this->m_stride [0] = 1; | |
| | | } | |
| | | allocate (this->m_ptr, this->elementCount (), value_type()); | |
| | | switch(init) | |
| | | { | |
| | | case LinearSequence: | |
| | | linearSequence(this->begin(), this->end()); | |
| | | break; | |
| | | default: | |
| | | vigra_precondition(false, | |
| | | "MultiArray(): invalid MultiArrayInitializationTag."); | |
| | | } | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T, class A> | |
| MultiArray <N, T, A>::MultiArray (const difference_type &shape, const_point
er init, | | MultiArray <N, T, A>::MultiArray (const difference_type &shape, const_point
er init, | |
| allocator_type const & alloc) | | allocator_type const & alloc) | |
|
| : MultiArrayView <N, T> (shape, | | : view_type(shape, | |
| detail::defaultStride <MultiArrayView<N,T>::actual | | defaultStride(shape), | |
| _dimension> (shape), | | 0), | |
| 0), | | | |
| m_alloc(alloc) | | m_alloc(alloc) | |
| { | | { | |
| if (N == 0) | | if (N == 0) | |
| { | | { | |
| this->m_shape [0] = 1; | | this->m_shape [0] = 1; | |
|
| this->m_stride [0] = 0; | | this->m_stride [0] = 1; | |
| } | | } | |
| allocate (this->m_ptr, this->elementCount (), init); | | allocate (this->m_ptr, this->elementCount (), init); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| MultiArray <N, T, A>::MultiArray(const MultiArrayView<N, U, StrideTag> &rh
s, | | MultiArray <N, T, A>::MultiArray(const MultiArrayView<N, U, StrideTag> &rh
s, | |
| allocator_type const & alloc) | | allocator_type const & alloc) | |
|
| : MultiArrayView <N, T> (rhs.shape(), | | : view_type(rhs.shape(), | |
| detail::defaultStride <MultiArrayView<N,T>::actual | | defaultStride(rhs.shape()), | |
| _dimension>(rhs.shape()), | | 0), | |
| 0), | | | |
| m_alloc (alloc) | | m_alloc (alloc) | |
| { | | { | |
| allocate (this->m_ptr, rhs); | | allocate (this->m_ptr, rhs); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| void | | void | |
| MultiArray <N, T, A>::copyOrReshape(const MultiArrayView<N, U, StrideTag> &
rhs) | | MultiArray <N, T, A>::copyOrReshape(const MultiArrayView<N, U, StrideTag> &
rhs) | |
| { | | { | |
| | | | |
| skipping to change at line 2889 | | skipping to change at line 2954 | |
| { | | { | |
| MultiArray t(rhs); | | MultiArray t(rhs); | |
| this->swap(t); | | this->swap(t); | |
| } | | } | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| void MultiArray <N, T, A>::reshape (const difference_type & new_shape, | | void MultiArray <N, T, A>::reshape (const difference_type & new_shape, | |
| const_reference initial) | | const_reference initial) | |
| { | | { | |
|
| if (N== 0) | | if (N == 0) | |
| { | | { | |
| return; | | return; | |
| } | | } | |
| else if(new_shape == this->shape()) | | else if(new_shape == this->shape()) | |
| { | | { | |
| this->init(initial); | | this->init(initial); | |
| } | | } | |
| else | | else | |
| { | | { | |
|
| difference_type new_stride = detail::defaultStride <MultiArrayView< | | difference_type new_stride = defaultStride(new_shape); | |
| N,T>::actual_dimension> (new_shape); | | difference_type_1 new_size = prod(new_shape); | |
| difference_type_1 new_size = new_shape [MultiArrayView<N,T>::actual | | pointer new_ptr = pointer(); | |
| _dimension-1] * new_stride [MultiArrayView<N,T>::actual_dimension-1]; | | | |
| T *new_ptr; | | | |
| allocate (new_ptr, new_size, initial); | | allocate (new_ptr, new_size, initial); | |
| deallocate (this->m_ptr, this->elementCount ()); | | deallocate (this->m_ptr, this->elementCount ()); | |
| this->m_ptr = new_ptr; | | this->m_ptr = new_ptr; | |
| this->m_shape = new_shape; | | this->m_shape = new_shape; | |
| this->m_stride = new_stride; | | this->m_stride = new_stride; | |
| } | | } | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| inline void | | inline void | |
| | | | |
| skipping to change at line 2926 | | skipping to change at line 2991 | |
| std::swap(this->m_shape, other.m_shape); | | std::swap(this->m_shape, other.m_shape); | |
| std::swap(this->m_stride, other.m_stride); | | std::swap(this->m_stride, other.m_stride); | |
| std::swap(this->m_ptr, other.m_ptr); | | std::swap(this->m_ptr, other.m_ptr); | |
| std::swap(this->m_alloc, other.m_alloc); | | std::swap(this->m_alloc, other.m_alloc); | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| void MultiArray <N, T, A>::allocate (pointer & ptr, difference_type_1 s, | | void MultiArray <N, T, A>::allocate (pointer & ptr, difference_type_1 s, | |
| const_reference init) | | const_reference init) | |
| { | | { | |
|
| | | if(s == 0) | |
| | | { | |
| | | ptr = 0; | |
| | | return; | |
| | | } | |
| ptr = m_alloc.allocate ((typename A::size_type)s); | | ptr = m_alloc.allocate ((typename A::size_type)s); | |
|
| difference_type_1 i; | | difference_type_1 i = 0; | |
| try { | | try { | |
|
| for (i = 0; i < s; ++i) | | for (; i < s; ++i) | |
| m_alloc.construct (ptr + i, init); | | m_alloc.construct (ptr + i, init); | |
| } | | } | |
| catch (...) { | | catch (...) { | |
| for (difference_type_1 j = 0; j < i; ++j) | | for (difference_type_1 j = 0; j < i; ++j) | |
| m_alloc.destroy (ptr + j); | | m_alloc.destroy (ptr + j); | |
| m_alloc.deallocate (ptr, (typename A::size_type)s); | | m_alloc.deallocate (ptr, (typename A::size_type)s); | |
| throw; | | throw; | |
| } | | } | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| template <class U> | | template <class U> | |
| void MultiArray <N, T, A>::allocate (pointer & ptr, difference_type_1 s, | | void MultiArray <N, T, A>::allocate (pointer & ptr, difference_type_1 s, | |
| U const * init) | | U const * init) | |
| { | | { | |
|
| | | if(s == 0) | |
| | | { | |
| | | ptr = 0; | |
| | | return; | |
| | | } | |
| ptr = m_alloc.allocate ((typename A::size_type)s); | | ptr = m_alloc.allocate ((typename A::size_type)s); | |
|
| difference_type_1 i; | | difference_type_1 i = 0; | |
| try { | | try { | |
|
| for (i = 0; i < s; ++i, ++init) | | for (; i < s; ++i, ++init) | |
| m_alloc.construct (ptr + i, *init); | | m_alloc.construct (ptr + i, *init); | |
| } | | } | |
| catch (...) { | | catch (...) { | |
| for (difference_type_1 j = 0; j < i; ++j) | | for (difference_type_1 j = 0; j < i; ++j) | |
| m_alloc.destroy (ptr + j); | | m_alloc.destroy (ptr + j); | |
| m_alloc.deallocate (ptr, (typename A::size_type)s); | | m_alloc.deallocate (ptr, (typename A::size_type)s); | |
| throw; | | throw; | |
| } | | } | |
| } | | } | |
| | | | |
| template <unsigned int N, class T, class A> | | template <unsigned int N, class T, class A> | |
| template <class U, class StrideTag> | | template <class U, class StrideTag> | |
| void MultiArray <N, T, A>::allocate (pointer & ptr, MultiArrayView<N, U, St
rideTag> const & init) | | void MultiArray <N, T, A>::allocate (pointer & ptr, MultiArrayView<N, U, St
rideTag> const & init) | |
| { | | { | |
| difference_type_1 s = init.elementCount(); | | difference_type_1 s = init.elementCount(); | |
|
| | | if(s == 0) | |
| | | { | |
| | | ptr = 0; | |
| | | return; | |
| | | } | |
| ptr = m_alloc.allocate ((typename A::size_type)s); | | ptr = m_alloc.allocate ((typename A::size_type)s); | |
| pointer p = ptr; | | pointer p = ptr; | |
| try { | | try { | |
| detail::uninitializedCopyMultiArrayData(init.traverser_begin(), ini
t.shape(), | | detail::uninitializedCopyMultiArrayData(init.traverser_begin(), ini
t.shape(), | |
| p, m_alloc, MetaInt<actual_
dimension-1>()); | | p, m_alloc, MetaInt<actual_
dimension-1>()); | |
| } | | } | |
| catch (...) { | | catch (...) { | |
| for (pointer pp = ptr; pp < p; ++pp) | | for (pointer pp = ptr; pp < p; ++pp) | |
| m_alloc.destroy (pp); | | m_alloc.destroy (pp); | |
| m_alloc.deallocate (ptr, (typename A::size_type)s); | | m_alloc.deallocate (ptr, (typename A::size_type)s); | |
| | | | |
| skipping to change at line 3291 | | skipping to change at line 3371 | |
| return pair<ConstImageIterator<PixelType>, Accessor> | | return pair<ConstImageIterator<PixelType>, Accessor> | |
| (ul, Accessor()); | | (ul, Accessor()); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* makeBasicImageView */ | | /* makeBasicImageView */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
|
| /** \addtogroup MultiArrayToImage Wrap a \ref vigra::MultiArrayView in | | /** \addtogroup MultiArrayToImage Create BasicImageView from MultiArrayView | |
| a \ref vigra::BasicImageView | | s | |
| | | | |
| | | Some convenience functions for wrapping a \ref vigra::MultiArrayView's | |
| | | data in a \ref vigra::BasicImageView. | |
| */ | | */ | |
| //@{ | | //@{ | |
| /** Create a \ref vigra::BasicImageView from an unstrided 2-dimensional | | /** Create a \ref vigra::BasicImageView from an unstrided 2-dimensional | |
| \ref vigra::MultiArrayView. | | \ref vigra::MultiArrayView. | |
| | | | |
| The \ref vigra::BasicImageView will have the same <tt>value_type </tt> | | The \ref vigra::BasicImageView will have the same <tt>value_type </tt> | |
| as the original \ref vigra::MultiArrayView. | | as the original \ref vigra::MultiArrayView. | |
| */ | | */ | |
|
| template <class T> | | template <class T, class Stride> | |
| BasicImageView <T> | | BasicImageView <T> | |
|
| makeBasicImageView (MultiArrayView <2, T, UnstridedArrayTag> const &array) | | makeBasicImageView (MultiArrayView <2, T, Stride> const &array) | |
| { | | { | |
|
| | | vigra_precondition(array.isUnstrided(), | |
| | | "makeBasicImageView(array): array must be unstrided (i.e. array.isUn | |
| | | strided() == true)."); | |
| return BasicImageView <T> (array.data (), array.shape (0), | | return BasicImageView <T> (array.data (), array.shape (0), | |
|
| array.shape (1)); | | array.shape (1), array.stride(1)); | |
| } | | } | |
| | | | |
| /** Create a \ref vigra::BasicImageView from a 3-dimensional | | /** Create a \ref vigra::BasicImageView from a 3-dimensional | |
| \ref vigra::MultiArray. | | \ref vigra::MultiArray. | |
| | | | |
| This wrapper flattens the two innermost dimensions of the array | | This wrapper flattens the two innermost dimensions of the array | |
| into single rows of the resulting image. | | into single rows of the resulting image. | |
| The \ref vigra::BasicImageView will have the same <tt>value_type </tt> | | The \ref vigra::BasicImageView will have the same <tt>value_type </tt> | |
| as the original \ref vigra::MultiArray. | | as the original \ref vigra::MultiArray. | |
| */ | | */ | |
| template <class T> | | template <class T> | |
| BasicImageView <T> | | BasicImageView <T> | |
| makeBasicImageView (MultiArray <3, T> const &array) | | makeBasicImageView (MultiArray <3, T> const &array) | |
| { | | { | |
|
| | | vigra_precondition(array.stride(1) == array.shape(0), | |
| | | "makeBasicImageView(): cannot join strided dimensions"); | |
| return BasicImageView <T> (array.data (), | | return BasicImageView <T> (array.data (), | |
|
| array.shape (0)*array.shape (1), array.shape
(2)); | | array.shape (0)*array.shape (1), array.shape
(2), array.stride(2)); | |
| } | | } | |
| | | | |
| /** Create a \ref vigra::BasicImageView from a 3-dimensional | | /** Create a \ref vigra::BasicImageView from a 3-dimensional | |
| \ref vigra::MultiArray. | | \ref vigra::MultiArray. | |
| | | | |
| This wrapper only works if <tt>T</tt> is a scalar type and the | | This wrapper only works if <tt>T</tt> is a scalar type and the | |
| array's innermost dimension has size 3. It then re-interprets | | array's innermost dimension has size 3. It then re-interprets | |
| the data array as a 2-dimensional array with value_type | | the data array as a 2-dimensional array with value_type | |
| <tt>RGBValue<T></tt>. | | <tt>RGBValue<T></tt>. | |
| */ | | */ | |
|
| template <class T> | | template <class T, class Stride> | |
| BasicImageView <RGBValue<T> > | | BasicImageView <RGBValue<T> > | |
|
| makeRGBImageView (MultiArray<3, T> const &array) | | makeRGBImageView (MultiArrayView<3, T, Stride> const &array) | |
| { | | { | |
|
| vigra_precondition ( | | vigra_precondition(array.shape (0) == 3, | |
| array.shape (0) == 3, "makeRGBImageView(): array.shape(0) must be 3 | | "makeRGBImageView(): array.shape(0) must be 3."); | |
| ."); | | vigra_precondition(array.isUnstrided(), | |
| | | "makeRGBImageView(array): array must be unstrided (i.e. array.isUnst | |
| | | rided() == true)."); | |
| return BasicImageView <RGBValue<T> > ( | | return BasicImageView <RGBValue<T> > ( | |
| reinterpret_cast <RGBValue <T> *> (array.data ()), | | reinterpret_cast <RGBValue <T> *> (array.data ()), | |
| array.shape (1), array.shape (2)); | | array.shape (1), array.shape (2)); | |
| } | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #undef VIGRA_ASSERT_INSIDE | | #undef VIGRA_ASSERT_INSIDE | |
| | | | |
End of changes. 132 change blocks. |
| 358 lines changed or deleted | | 462 lines changed or added | |
|
| multi_convolution.hxx | | multi_convolution.hxx | |
| | | | |
| skipping to change at line 49 | | skipping to change at line 49 | |
| #define VIGRA_MULTI_CONVOLUTION_H | | #define VIGRA_MULTI_CONVOLUTION_H | |
| | | | |
| #include "separableconvolution.hxx" | | #include "separableconvolution.hxx" | |
| #include "array_vector.hxx" | | #include "array_vector.hxx" | |
| #include "multi_array.hxx" | | #include "multi_array.hxx" | |
| #include "accessor.hxx" | | #include "accessor.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "navigator.hxx" | | #include "navigator.hxx" | |
| #include "metaprogramming.hxx" | | #include "metaprogramming.hxx" | |
| #include "multi_pointoperators.hxx" | | #include "multi_pointoperators.hxx" | |
|
| | | #include "multi_math.hxx" | |
| #include "functorexpression.hxx" | | #include "functorexpression.hxx" | |
| #include "tinyvector.hxx" | | #include "tinyvector.hxx" | |
| #include "algorithm.hxx" | | #include "algorithm.hxx" | |
| | | | |
|
| | | #include <iostream> | |
| | | | |
| namespace vigra | | namespace vigra | |
| { | | { | |
| | | | |
| namespace detail | | namespace detail | |
| { | | { | |
| | | | |
| struct DoubleYielder | | struct DoubleYielder | |
| { | | { | |
| const double value; | | const double value; | |
| DoubleYielder(double v, unsigned, const char *const) : value(v) {} | | DoubleYielder(double v, unsigned, const char *const) : value(v) {} | |
| | | | |
| skipping to change at line 125 | | skipping to change at line 128 | |
| : sigma_eff_it(sigma_eff), sigma_d_it(sigma_d), step_size_it(step_s
ize) {} | | : sigma_eff_it(sigma_eff), sigma_d_it(sigma_d), step_size_it(step_s
ize) {} | |
| void operator++() | | void operator++() | |
| { | | { | |
| ++sigma_eff_it; | | ++sigma_eff_it; | |
| ++sigma_d_it; | | ++sigma_d_it; | |
| ++step_size_it; | | ++step_size_it; | |
| } | | } | |
| double sigma_eff() const { return *sigma_eff_it; } | | double sigma_eff() const { return *sigma_eff_it; } | |
| double sigma_d() const { return *sigma_d_it; } | | double sigma_d() const { return *sigma_d_it; } | |
| double step_size() const { return *step_size_it; } | | double step_size() const { return *step_size_it; } | |
|
| static double sqr(double x) { return x * x; } | | | |
| static void sigma_precondition(double sigma, const char *const function
_name) | | static void sigma_precondition(double sigma, const char *const function
_name) | |
| { | | { | |
| if (sigma < 0.0) | | if (sigma < 0.0) | |
| { | | { | |
| std::string msg = "(): Scale must be positive."; | | std::string msg = "(): Scale must be positive."; | |
| vigra_precondition(false, function_name + msg); | | vigra_precondition(false, function_name + msg); | |
| } | | } | |
| } | | } | |
| double sigma_scaled(const char *const function_name = "unknown function
") const | | double sigma_scaled(const char *const function_name = "unknown function
") const | |
| { | | { | |
| sigma_precondition(sigma_eff(), function_name); | | sigma_precondition(sigma_eff(), function_name); | |
| sigma_precondition(sigma_d(), function_name); | | sigma_precondition(sigma_d(), function_name); | |
|
| double sigma_squared = sqr(sigma_eff()) - sqr(sigma_d()); | | double sigma_squared = sq(sigma_eff()) - sq(sigma_d()); | |
| if (sigma_squared > 0.0) | | if (sigma_squared > 0.0) | |
| { | | { | |
| return std::sqrt(sigma_squared) / step_size(); | | return std::sqrt(sigma_squared) / step_size(); | |
| } | | } | |
| else | | else | |
| { | | { | |
| std::string msg = "(): Scale would be imaginary or zero."; | | std::string msg = "(): Scale would be imaginary or zero."; | |
| vigra_precondition(false, function_name + msg); | | vigra_precondition(false, function_name + msg); | |
| return 0; | | return 0; | |
| } | | } | |
| | | | |
| skipping to change at line 201 | | skipping to change at line 203 | |
| } | | } | |
| multiArrayScaleParam(double v0, double v1, double v2, double v3, doubl
e v4, const char *const function_name = "multiArrayScaleParam") | | multiArrayScaleParam(double v0, double v1, double v2, double v3, doubl
e v4, const char *const function_name = "multiArrayScaleParam") | |
| { | | { | |
| precondition(5, function_name); | | precondition(5, function_name); | |
| vec = p_vector(v0, v1, v2, v3, v4); | | vec = p_vector(v0, v1, v2, v3, v4); | |
| } | | } | |
| }; | | }; | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| #define VIGRA_CONVOLUTION_OPTIONS(function_name, default_value, member_name
) \ | | #define VIGRA_CONVOLUTION_OPTIONS(function_name, default_value, member_name
, getter_setter_name) \ | |
| template <class Param> \ | | template <class Param> \ | |
| ConvolutionOptions & function_name(const Param & val) \ | | ConvolutionOptions & function_name(const Param & val) \ | |
| { \ | | { \ | |
| member_name = ParamVec(val, "ConvolutionOptions::" #function_name);
\ | | member_name = ParamVec(val, "ConvolutionOptions::" #function_name);
\ | |
| return *this; \ | | return *this; \ | |
| } \ | | } \ | |
| ConvolutionOptions & function_name() \ | | ConvolutionOptions & function_name() \ | |
| { \ | | { \ | |
| member_name = ParamVec(default_value, "ConvolutionOptions::" #funct
ion_name); \ | | member_name = ParamVec(default_value, "ConvolutionOptions::" #funct
ion_name); \ | |
| return *this; \ | | return *this; \ | |
| | | | |
| skipping to change at line 232 | | skipping to change at line 234 | |
| } \ | | } \ | |
| ConvolutionOptions & function_name(double v0, double v1, double v2, dou
ble v3) \ | | ConvolutionOptions & function_name(double v0, double v1, double v2, dou
ble v3) \ | |
| { \ | | { \ | |
| member_name = ParamVec(v0, v1, v2, v3, "ConvolutionOptions::" #func
tion_name); \ | | member_name = ParamVec(v0, v1, v2, v3, "ConvolutionOptions::" #func
tion_name); \ | |
| return *this; \ | | return *this; \ | |
| } \ | | } \ | |
| ConvolutionOptions & function_name(double v0, double v1, double v2, dou
ble v3, double v4) \ | | ConvolutionOptions & function_name(double v0, double v1, double v2, dou
ble v3, double v4) \ | |
| { \ | | { \ | |
| member_name = ParamVec(v0, v1, v2, v3, v4, "ConvolutionOptions::" #
function_name); \ | | member_name = ParamVec(v0, v1, v2, v3, v4, "ConvolutionOptions::" #
function_name); \ | |
| return *this; \ | | return *this; \ | |
|
| | | } \ | |
| | | typename ParamVec::p_vector get##getter_setter_name()const{ \ | |
| | | return member_name.vec; \ | |
| | | } \ | |
| | | void set##getter_setter_name(typename ParamVec::p_vector vec){ \ | |
| | | member_name.vec = vec; \ | |
| } | | } | |
| | | | |
| /** \brief Options class template for convolutions. | | /** \brief Options class template for convolutions. | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| This class enables the calculation of scale space convolutions | | This class enables the calculation of scale space convolutions | |
| such as \ref gaussianGradientMultiArray() on data with anisotropic | | such as \ref gaussianGradientMultiArray() on data with anisotropic | |
| discretization. For these, the result of the ordinary calculation | | discretization. For these, the result of the ordinary calculation | |
| has to be multiplied by factors of \f$1/w^{n}\f$ for each dimension, | | has to be multiplied by factors of \f$1/w^{n}\f$ for each dimension, | |
| where \f$w\f$ is the step size of the grid in said dimension and | | where \f$w\f$ is the step size of the grid in said dimension and | |
| \f$n\f$ is the differential order of the convolution, e.g., 1 for | | \f$n\f$ is the differential order of the convolution, e.g., 1 for | |
| gaussianGradientMultiArray(), and 0 for gaussianSmoothMultiArray(), | | gaussianGradientMultiArray(), and 0 for gaussianSmoothMultiArray(), | |
| respectively. Also for each dimension in turn, the convolution's scale | | respectively. Also for each dimension in turn, the convolution's scale | |
| parameter \f$\sigma\f$ has to be replaced by | | parameter \f$\sigma\f$ has to be replaced by | |
| | | | |
| skipping to change at line 311 | | skipping to change at line 320 | |
| ArrayVector<double>::iterator i = step_size.begin(); | | ArrayVector<double>::iterator i = step_size.begin(); | |
| ++i; | | ++i; | |
| ConvolutionOptions<2> opt = ConvolutionOptions<2>().stepSize(i); | | ConvolutionOptions<2> opt = ConvolutionOptions<2>().stepSize(i); | |
| \endcode | | \endcode | |
| | | | |
| <b>general usage in a convolution function call:</b> | | <b>general usage in a convolution function call:</b> | |
| | | | |
| \code | | \code | |
| MultiArray<3, double> test_image; | | MultiArray<3, double> test_image; | |
| MultiArray<3, double> out_image; | | MultiArray<3, double> out_image; | |
|
| gaussianSmoothMultiArray(srcMultiArrayRange(test_image), | | | |
| destMultiArray(out_image), | | double scale = 5.0; | |
| 5.0, | | gaussianSmoothMultiArray(test_image, out_image, scale, | |
| ConvolutionOptions<3>() | | ConvolutionOptions<3>() | |
| .stepSize (1, 1, 3.2) | | .stepSize (1, 1, 3.2) | |
| .resolutionStdDev(1, 1, 4) | | .resolutionStdDev(1, 1, 4) | |
| ); | | ); | |
| \endcode | | \endcode | |
| | | | |
| */ | | */ | |
| template <unsigned dim> | | template <unsigned dim> | |
| class ConvolutionOptions | | class ConvolutionOptions | |
| { | | { | |
| | | | |
| skipping to change at line 367 | | skipping to change at line 376 | |
| | | | |
| ConvolutionOptions outerOptions() const | | ConvolutionOptions outerOptions() const | |
| { | | { | |
| ConvolutionOptions outer = *this; | | ConvolutionOptions outer = *this; | |
| // backward-compatible values: | | // backward-compatible values: | |
| return outer.stdDev(outer_scale()).resolutionStdDev(0.0); | | return outer.stdDev(outer_scale()).resolutionStdDev(0.0); | |
| } | | } | |
| | | | |
| // Step size per axis. | | // Step size per axis. | |
| // Default: dim values of 1.0 | | // Default: dim values of 1.0 | |
|
| VIGRA_CONVOLUTION_OPTIONS(stepSize, 1.0, step_size) | | VIGRA_CONVOLUTION_OPTIONS(stepSize, 1.0, step_size, StepSize) | |
| #ifdef DOXYGEN | | #ifdef DOXYGEN | |
| /** Step size(s) per axis, i.e., the distance between two | | /** Step size(s) per axis, i.e., the distance between two | |
| adjacent pixels. Required for <tt>MultiArray</tt> | | adjacent pixels. Required for <tt>MultiArray</tt> | |
| containing anisotropic data. | | containing anisotropic data. | |
| | | | |
| Note that a convolution containing a derivative operator | | Note that a convolution containing a derivative operator | |
| of order <tt>n</tt> results in a multiplication by | | of order <tt>n</tt> results in a multiplication by | |
| \f${\rm stepSize}^{-n}\f$ for each axis. | | \f${\rm stepSize}^{-n}\f$ for each axis. | |
| Also, the above standard deviations | | Also, the above standard deviations | |
| are scaled according to the step size of each axis. | | are scaled according to the step size of each axis. | |
| Default value for the options object if this member function is
not | | Default value for the options object if this member function is
not | |
| used: A value of 1.0 for each dimension. | | used: A value of 1.0 for each dimension. | |
| */ | | */ | |
| ConvolutionOptions<dim> & stepSize(...); | | ConvolutionOptions<dim> & stepSize(...); | |
| #endif | | #endif | |
| | | | |
| // Resolution standard deviation per axis. | | // Resolution standard deviation per axis. | |
| // Default: dim values of 0.0 | | // Default: dim values of 0.0 | |
|
| VIGRA_CONVOLUTION_OPTIONS(resolutionStdDev, 0.0, sigma_d) | | VIGRA_CONVOLUTION_OPTIONS(resolutionStdDev, 0.0, sigma_d, ResolutionStd
Dev) | |
| #ifdef DOXYGEN | | #ifdef DOXYGEN | |
| /** Resolution standard deviation(s) per axis, i.e., a supposed | | /** Resolution standard deviation(s) per axis, i.e., a supposed | |
| pre-existing gaussian filtering by this value. | | pre-existing gaussian filtering by this value. | |
| | | | |
| The standard deviation actually used by the convolution operato
rs | | The standard deviation actually used by the convolution operato
rs | |
| is \f$\sqrt{{\rm sigma}^{2} - {\rm resolutionStdDev}^{2}}\f$ fo
r each | | is \f$\sqrt{{\rm sigma}^{2} - {\rm resolutionStdDev}^{2}}\f$ fo
r each | |
| axis. | | axis. | |
| Default value for the options object if this member function is
not | | Default value for the options object if this member function is
not | |
| used: A value of 0.0 for each dimension. | | used: A value of 0.0 for each dimension. | |
| */ | | */ | |
| ConvolutionOptions<dim> & resolutionStdDev(...); | | ConvolutionOptions<dim> & resolutionStdDev(...); | |
| #endif | | #endif | |
| | | | |
| // Standard deviation of scale space operators. | | // Standard deviation of scale space operators. | |
| // Default: dim values of 0.0 | | // Default: dim values of 0.0 | |
|
| VIGRA_CONVOLUTION_OPTIONS(stdDev, 0.0, sigma_eff) | | VIGRA_CONVOLUTION_OPTIONS(stdDev, 0.0, sigma_eff, StdDev) | |
| VIGRA_CONVOLUTION_OPTIONS(innerScale, 0.0, sigma_eff) | | VIGRA_CONVOLUTION_OPTIONS(innerScale, 0.0, sigma_eff, InnerScale) | |
| | | | |
| #ifdef DOXYGEN | | #ifdef DOXYGEN | |
| /** Standard deviation(s) of scale space operators, or inner scale(
s) for \ref structureTensorMultiArray(). | | /** Standard deviation(s) of scale space operators, or inner scale(
s) for \ref structureTensorMultiArray(). | |
| | | | |
| Usually not | | Usually not | |
| needed, since a single value for all axes may be specified as a
parameter | | needed, since a single value for all axes may be specified as a
parameter | |
| <tt>sigma</tt> to the call of | | <tt>sigma</tt> to the call of | |
| an convolution operator such as \ref gaussianGradientMultiArray
(), and | | an convolution operator such as \ref gaussianGradientMultiArray
(), and | |
| anisotropic data requiring the use of the stepSize() member fun
ction. | | anisotropic data requiring the use of the stepSize() member fun
ction. | |
| Default value for the options object if this member function is
not | | Default value for the options object if this member function is
not | |
| | | | |
| skipping to change at line 433 | | skipping to change at line 442 | |
| an convolution operator such as \ref gaussianGradientMultiArray
(), and | | an convolution operator such as \ref gaussianGradientMultiArray
(), and | |
| anisotropic data requiring the use of the stepSize() member fun
ction. | | anisotropic data requiring the use of the stepSize() member fun
ction. | |
| Default value for the options object if this member function is
not | | Default value for the options object if this member function is
not | |
| used: A value of 0.0 for each dimension. | | used: A value of 0.0 for each dimension. | |
| */ | | */ | |
| ConvolutionOptions<dim> & innerScale(...); | | ConvolutionOptions<dim> & innerScale(...); | |
| #endif | | #endif | |
| | | | |
| // Outer scale, for structure tensor. | | // Outer scale, for structure tensor. | |
| // Default: dim values of 0.0 | | // Default: dim values of 0.0 | |
|
| VIGRA_CONVOLUTION_OPTIONS(outerScale, 0.0, outer_scale) | | VIGRA_CONVOLUTION_OPTIONS(outerScale, 0.0, outer_scale, OuterScale) | |
| #ifdef DOXYGEN | | #ifdef DOXYGEN | |
| /** Standard deviation(s) of the second convolution of the | | /** Standard deviation(s) of the second convolution of the | |
| structure tensor. | | structure tensor. | |
| | | | |
| Usually not needed, since a single value for | | Usually not needed, since a single value for | |
| all axes may be specified as a parameter <tt>outerScale</tt> to | | all axes may be specified as a parameter <tt>outerScale</tt> to | |
| the call of \ref structureTensorMultiArray(), and | | the call of \ref structureTensorMultiArray(), and | |
| anisotropic data requiring the use of the stepSize() member | | anisotropic data requiring the use of the stepSize() member | |
| function. | | function. | |
| Default value for the options object if this member function is
not | | Default value for the options object if this member function is
not | |
| | | | |
| skipping to change at line 471 | | skipping to change at line 480 | |
| Default: <tt>0.0</tt> (i.e. determine the window size automatic
ally) | | Default: <tt>0.0</tt> (i.e. determine the window size automatic
ally) | |
| */ | | */ | |
| ConvolutionOptions<dim> & filterWindowSize(double ratio) | | ConvolutionOptions<dim> & filterWindowSize(double ratio) | |
| { | | { | |
| vigra_precondition(ratio >= 0.0, | | vigra_precondition(ratio >= 0.0, | |
| "ConvolutionOptions::filterWindowSize(): ratio must not be nega
tive."); | | "ConvolutionOptions::filterWindowSize(): ratio must not be nega
tive."); | |
| window_ratio = ratio; | | window_ratio = ratio; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| | | double getFilterWindowSize() const { | |
| | | return window_ratio; | |
| | | } | |
| | | | |
| /** Restrict the filter to a subregion of the input array. | | /** Restrict the filter to a subregion of the input array. | |
| | | | |
| This is useful for speeding up computations by ignoring irrelev
ant | | This is useful for speeding up computations by ignoring irrelev
ant | |
| areas in the array. <b>Note:</b> It is assumed that the output
array | | areas in the array. <b>Note:</b> It is assumed that the output
array | |
|
| of the convolution has the size given in this function. | | of the convolution has the size given in this function. Negati | |
| | | ve ROI | |
| | | boundaries are interpreted relative to the end of the respectiv | |
| | | e dimension | |
| | | (i.e. <tt>if(to[k] < 0) to[k] += source.shape(k);</tt>). | |
| | | | |
| Default: <tt>from = Shape(), to = Shape()</tt> (i.e. use entire
array) | | Default: <tt>from = Shape(), to = Shape()</tt> (i.e. use entire
array) | |
| */ | | */ | |
| ConvolutionOptions<dim> & subarray(Shape const & from, Shape const & to
) | | ConvolutionOptions<dim> & subarray(Shape const & from, Shape const & to
) | |
| { | | { | |
| from_point = from; | | from_point = from; | |
| to_point = to; | | to_point = to; | |
| return *this; | | return *this; | |
| } | | } | |
|
| | | | |
| | | std::pair<Shape, Shape> getSubarray()const{ | |
| | | std::pair<Shape, Shape> res; | |
| | | res.first = from_point; | |
| | | res.second = to_point; | |
| | | return res; | |
| | | } | |
| }; | | }; | |
| | | | |
| namespace detail | | namespace detail | |
| { | | { | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* internalSeparableConvolveMultiArray */ | | /* internalSeparableConvolveMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| skipping to change at line 577 | | skipping to change at line 599 | |
| | | | |
| typedef typename NumericTraits<typename DestAccessor::value_type>::Real
Promote TmpType; | | typedef typename NumericTraits<typename DestAccessor::value_type>::Real
Promote TmpType; | |
| typedef MultiArray<N, TmpType> TmpArray; | | typedef MultiArray<N, TmpType> TmpArray; | |
| typedef typename TmpArray::traverser TmpIterator; | | typedef typename TmpArray::traverser TmpIterator; | |
| typedef typename AccessorTraits<TmpType>::default_accessor TmpAcessor; | | typedef typename AccessorTraits<TmpType>::default_accessor TmpAcessor; | |
| | | | |
| SrcShape sstart, sstop, axisorder, tmpshape; | | SrcShape sstart, sstop, axisorder, tmpshape; | |
| TinyVector<double, N> overhead; | | TinyVector<double, N> overhead; | |
| for(int k=0; k<N; ++k) | | for(int k=0; k<N; ++k) | |
| { | | { | |
|
| | | axisorder[k] = k; | |
| sstart[k] = start[k] - kit[k].right(); | | sstart[k] = start[k] - kit[k].right(); | |
| if(sstart[k] < 0) | | if(sstart[k] < 0) | |
| sstart[k] = 0; | | sstart[k] = 0; | |
| sstop[k] = stop[k] - kit[k].left(); | | sstop[k] = stop[k] - kit[k].left(); | |
| if(sstop[k] > shape[k]) | | if(sstop[k] > shape[k]) | |
| sstop[k] = shape[k]; | | sstop[k] = shape[k]; | |
| overhead[k] = double(sstop[k] - sstart[k]) / (stop[k] - start[k]); | | overhead[k] = double(sstop[k] - sstart[k]) / (stop[k] - start[k]); | |
| } | | } | |
| | | | |
| indexSort(overhead.begin(), overhead.end(), axisorder.begin(), std::gre
ater<double>()); | | indexSort(overhead.begin(), overhead.end(), axisorder.begin(), std::gre
ater<double>()); | |
|
| | | | |
| SrcShape dstart, dstop(sstop - sstart); | | SrcShape dstart, dstop(sstop - sstart); | |
| dstop[axisorder[0]] = stop[axisorder[0]] - start[axisorder[0]]; | | dstop[axisorder[0]] = stop[axisorder[0]] - start[axisorder[0]]; | |
| | | | |
| // temporary array to hold the current line to enable in-place operatio
n | | // temporary array to hold the current line to enable in-place operatio
n | |
| MultiArray<N, TmpType> tmp(dstop); | | MultiArray<N, TmpType> tmp(dstop); | |
| | | | |
| typedef MultiArrayNavigator<SrcIterator, N> SNavigator; | | typedef MultiArrayNavigator<SrcIterator, N> SNavigator; | |
| typedef MultiArrayNavigator<TmpIterator, N> TNavigator; | | typedef MultiArrayNavigator<TmpIterator, N> TNavigator; | |
|
| typedef MultiArrayNavigator<DestIterator, N> DNavigator; | | | |
| | | | |
| TmpAcessor acc; | | TmpAcessor acc; | |
| | | | |
| { | | { | |
| // only operate on first dimension here | | // only operate on first dimension here | |
| SNavigator snav( si, sstart, sstop, axisorder[0]); | | SNavigator snav( si, sstart, sstop, axisorder[0]); | |
| TNavigator tnav( tmp.traverser_begin(), dstart, dstop, axisorder[0]
); | | TNavigator tnav( tmp.traverser_begin(), dstart, dstop, axisorder[0]
); | |
| | | | |
| ArrayVector<TmpType> tmpline(sstop[axisorder[0]] - sstart[axisorder
[0]]); | | ArrayVector<TmpType> tmpline(sstop[axisorder[0]] - sstart[axisorder
[0]]); | |
| | | | |
| | | | |
| skipping to change at line 685 | | skipping to change at line 706 | |
| This function computes a separated convolution on all dimensions | | This function computes a separated convolution on all dimensions | |
| of the given multi-dimensional array. Both source and destination | | of the given multi-dimensional array. Both source and destination | |
| arrays are represented by iterators, shape objects and accessors. | | arrays are represented by iterators, shape objects and accessors. | |
| The destination array is required to already have the correct size. | | The destination array is required to already have the correct size. | |
| | | | |
| There are two variants of this functions: one takes a single kernel | | There are two variants of this functions: one takes a single kernel | |
| of type \ref vigra::Kernel1D which is then applied to all dimensions, | | of type \ref vigra::Kernel1D which is then applied to all dimensions, | |
| whereas the other requires an iterator referencing a sequence of | | whereas the other requires an iterator referencing a sequence of | |
| \ref vigra::Kernel1D objects, one for every dimension of the data. | | \ref vigra::Kernel1D objects, one for every dimension of the data. | |
| Then the first kernel in this sequence is applied to the innermost | | Then the first kernel in this sequence is applied to the innermost | |
|
| dimension (e.g. the x-dimension of an image), while the last is applied | | dimension (e.g. the x-axis of an image), while the last is applied to t | |
| to the | | he | |
| outermost dimension (e.g. the z-dimension in a 3D image). | | outermost dimension (e.g. the z-axis in a 3D image). | |
| | | | |
|
| This function may work in-place, which means that <tt>siter == diter</t
t> is allowed. | | This function may work in-place, which means that <tt>source.data() ==
dest.data()</tt> is allowed. | |
| A full-sized internal array is only allocated if working on the destina
tion | | A full-sized internal array is only allocated if working on the destina
tion | |
| array directly would cause round-off errors (i.e. if | | array directly would cause round-off errors (i.e. if | |
|
| <tt>typeid(typename NumericTraits<typename DestAccessor::value_type>::R | | <tt>typeid(typename NumericTraits<T2>::RealPromote) != typeid(T2)</tt>) | |
| ealPromote) | | . | |
| != typeid(typename DestAccessor::value_type)</tt>. | | | |
| | | | |
| If <tt>start</tt> and <tt>stop</tt> have non-default values, they must
represent | | If <tt>start</tt> and <tt>stop</tt> have non-default values, they must
represent | |
| a valid subarray of the input array. The convolution is then restricted
to that | | a valid subarray of the input array. The convolution is then restricted
to that | |
| subarray, and it is assumed that the output array only refers to the | | subarray, and it is assumed that the output array only refers to the | |
|
| subarray (i.e. <tt>diter</tt> points to the element corresponding to | | subarray (i.e. <tt>dest.shape() == stop - start</tt>). Negative ROI bou | |
| <tt>start</tt>). | | ndaries are | |
| | | interpreted relative to the end of the respective dimension | |
| | | (i.e. <tt>if(stop[k] < 0) stop[k] += source.shape(k);</tt>). | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // apply each kernel from the sequence 'kernels' in turn | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class KernelIterator> | |
| | | void | |
| | | separableConvolveMultiArray(MultiArrayView<N, T1, S1> const & sourc | |
| | | e, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | KernelIterator kernels, | |
| | | typename MultiArrayShape<N>::type start | |
| | | = typename MultiArrayShape<N>::type(), | |
| | | typename MultiArrayShape<N>::type stop | |
| | | = typename MultiArrayShape<N>::type()); | |
| | | | |
| | | // apply the same kernel to all dimensions | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T> | |
| | | void | |
| | | separableConvolveMultiArray(MultiArrayView<N, T1, S1> const & sourc | |
| | | e, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | Kernel1D<T> const & kernel, | |
| | | typename MultiArrayShape<N>::type const | |
| | | & start = typename MultiArrayShape<N>::type(), | |
| | | typename MultiArrayShape<N>::type const | |
| | | & stop = typename MultiArrayShape<N>::type()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{separableConvolveMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // apply the same kernel to all dimensions | | // apply the same kernel to all dimensions | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class T> | | class DestIterator, class DestAccessor, class T> | |
| void | | void | |
| separableConvolveMultiArray(SrcIterator siter, SrcShape const & sha
pe, SrcAccessor src, | | separableConvolveMultiArray(SrcIterator siter, SrcShape const & sha
pe, SrcAccessor src, | |
| DestIterator diter, DestAccessor dest, | | DestIterator diter, DestAccessor dest, | |
| Kernel1D<T> const & kernel, | | Kernel1D<T> const & kernel, | |
| SrcShape const & start = SrcShape(), | | SrcShape const & start = SrcShape(), | |
| | | | |
| skipping to change at line 726 | | skipping to change at line 775 | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class KernelItera
tor> | | class DestIterator, class DestAccessor, class KernelItera
tor> | |
| void | | void | |
| separableConvolveMultiArray(SrcIterator siter, SrcShape const & sha
pe, SrcAccessor src, | | separableConvolveMultiArray(SrcIterator siter, SrcShape const & sha
pe, SrcAccessor src, | |
| DestIterator diter, DestAccessor dest, | | DestIterator diter, DestAccessor dest, | |
| KernelIterator kernels, | | KernelIterator kernels, | |
| SrcShape const & start = SrcShape(), | | SrcShape const & start = SrcShape(), | |
| SrcShape const & stop = SrcShape()); | | SrcShape const & stop = SrcShape()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // apply the same kernel to all dimensions | | // apply the same kernel to all dimensions | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class T> | | class DestIterator, class DestAccessor, class T> | |
| void | | void | |
| separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | | separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | |
| pair<DestIterator, DestAccessor> const
& dest, | | pair<DestIterator, DestAccessor> const
& dest, | |
| Kernel1D<T> const & kernel, | | Kernel1D<T> const & kernel, | |
| | | | |
| skipping to change at line 751 | | skipping to change at line 799 | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class KernelItera
tor> | | class DestIterator, class DestAccessor, class KernelItera
tor> | |
| void | | void | |
| separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | | separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | |
| pair<DestIterator, DestAccessor> const
& dest, | | pair<DestIterator, DestAccessor> const
& dest, | |
| KernelIterator kernels, | | KernelIterator kernels, | |
| SrcShape const & start = SrcShape(), | | SrcShape const & start = SrcShape(), | |
| SrcShape const & stop = SrcShape()); | | SrcShape const & stop = SrcShape()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | Shape3 shape(width, height, depth); | |
| | | MultiArray<3, unsigned char> source(shape); | |
| | | MultiArray<3, float> dest(shape); | |
| | | ... | |
| | | Kernel1D<float> gauss; | |
| | | gauss.initGaussian(sigma); | |
| | | | |
| | | // smooth all dimensions with the same kernel | |
| | | separableConvolveMultiArray(source, dest, gauss); | |
| | | | |
| | | // create 3 Gauss kernels, one for each dimension, but smooth the z-axi | |
| | | s less | |
| | | ArrayVector<Kernel1D<float> > kernels(3, gauss); | |
| | | kernels[2].initGaussian(sigma / 2.0); | |
| | | | |
| | | // perform Gaussian smoothing on all dimensions | |
| | | separableConvolveMultiArray(source, dest, kernels.begin()); | |
| | | | |
| | | // create output array for a ROI | |
| | | MultiArray<3, float> destROI(shape - Shape3(10,10,10)); | |
| | | | |
| | | // only smooth the given ROI (ignore 5 pixels on all sides of the array | |
| | | ) | |
| | | separableConvolveMultiArray(source, destROI, gauss, Shape3(5,5,5), Shap | |
| | | e3(-5,-5,-5)); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{separableConvolveMultiArray} | |
| | | \code | |
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | MultiArray<3, unsigned char>::size_type shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
| MultiArray<3, float> dest(shape); | | MultiArray<3, float> dest(shape); | |
| ... | | ... | |
| Kernel1D<float> gauss; | | Kernel1D<float> gauss; | |
| gauss.initGaussian(sigma); | | gauss.initGaussian(sigma); | |
| // create 3 Gauss kernels, one for each dimension | | // create 3 Gauss kernels, one for each dimension | |
| ArrayVector<Kernel1D<float> > kernels(3, gauss); | | ArrayVector<Kernel1D<float> > kernels(3, gauss); | |
| | | | |
| // perform Gaussian smoothing on all dimensions | | // perform Gaussian smoothing on all dimensions | |
|
| separableConvolveMultiArray(srcMultiArrayRange(source), destMultiArray(
dest), | | separableConvolveMultiArray(source, dest, | |
| kernels.begin()); | | kernels.begin()); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | \code | |
| | | see \ref separableConvolveImage(), in addition: | |
| | | | |
|
| see \ref separableConvolveMultiArray(), in addition: | | NumericTraits<T1>::RealPromote s = src[0]; | |
| | | | |
|
| \code | | s = s + s; | |
| int dimension = 0; | | s = kernel(0) * s; | |
| VectorElementAccessor<DestAccessor> elementAccessor(0, dest); | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| \see vigra::Kernel1D, convolveLine() | | \see vigra::Kernel1D, convolveLine() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void separableConvolveMultiArray
) | | doxygen_overloaded_function(template <...> void separableConvolveMultiArray
) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class KernelIterator> | | class DestIterator, class DestAccessor, class KernelIterator> | |
| void | | void | |
| separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAcce
ssor src, | | separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAcce
ssor src, | |
| DestIterator d, DestAccessor dest, | | DestIterator d, DestAccessor dest, | |
| KernelIterator kernels, | | KernelIterator kernels, | |
|
| SrcShape const & start = SrcShape(), | | SrcShape start = SrcShape(), | |
| SrcShape const & stop = SrcShape()) | | SrcShape stop = SrcShape()) | |
| { | | { | |
| typedef typename NumericTraits<typename DestAccessor::value_type>::Real
Promote TmpType; | | typedef typename NumericTraits<typename DestAccessor::value_type>::Real
Promote TmpType; | |
| | | | |
| if(stop != SrcShape()) | | if(stop != SrcShape()) | |
| { | | { | |
|
| | | | |
| enum { N = 1 + SrcIterator::level }; | | enum { N = 1 + SrcIterator::level }; | |
|
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, start); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, stop); | |
| | | | |
| for(int k=0; k<N; ++k) | | for(int k=0; k<N; ++k) | |
| vigra_precondition(0 <= start[k] && start[k] < stop[k] && stop[
k] <= shape[k], | | vigra_precondition(0 <= start[k] && start[k] < stop[k] && stop[
k] <= shape[k], | |
| "separableConvolveMultiArray(): invalid subarray shape."); | | "separableConvolveMultiArray(): invalid subarray shape."); | |
| | | | |
| detail::internalSeparableConvolveSubarray(s, shape, src, d, dest, k
ernels, start, stop); | | detail::internalSeparableConvolveSubarray(s, shape, src, d, dest, k
ernels, start, stop); | |
| } | | } | |
| else if(!IsSameType<TmpType, typename DestAccessor::value_type>::boolRe
sult) | | else if(!IsSameType<TmpType, typename DestAccessor::value_type>::boolRe
sult) | |
| { | | { | |
| // need a temporary array to avoid rounding errors | | // need a temporary array to avoid rounding errors | |
| MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); | | MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); | |
| | | | |
| skipping to change at line 820 | | skipping to change at line 901 | |
| copyMultiArray(srcMultiArrayRange(tmpArray), destIter(d, dest)); | | copyMultiArray(srcMultiArrayRange(tmpArray), destIter(d, dest)); | |
| } | | } | |
| else | | else | |
| { | | { | |
| // work directly on the destination array | | // work directly on the destination array | |
| detail::internalSeparableConvolveMultiArrayTmp( s, shape, src, d, d
est, kernels ); | | detail::internalSeparableConvolveMultiArrayTmp( s, shape, src, d, d
est, kernels ); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
|
| class DestIterator, class DestAccessor, class KernelIterator> | | | |
| inline | | | |
| void separableConvolveMultiArray( | | | |
| triple<SrcIterator, SrcShape, SrcAccessor> const & source, | | | |
| pair<DestIterator, DestAccessor> const & dest, | | | |
| KernelIterator kit, | | | |
| SrcShape const & start = SrcShape(), | | | |
| SrcShape const & stop = SrcShape()) | | | |
| { | | | |
| separableConvolveMultiArray( source.first, source.second, source.third, | | | |
| dest.first, dest.second, kit, start, stop | | | |
| ); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor, class T> | | class DestIterator, class DestAccessor, class T> | |
| inline void | | inline void | |
| separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAcce
ssor src, | | separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAcce
ssor src, | |
| DestIterator d, DestAccessor dest, | | DestIterator d, DestAccessor dest, | |
| Kernel1D<T> const & kernel, | | Kernel1D<T> const & kernel, | |
| SrcShape const & start = SrcShape(), | | SrcShape const & start = SrcShape(), | |
| SrcShape const & stop = SrcShape()) | | SrcShape const & stop = SrcShape()) | |
| { | | { | |
| ArrayVector<Kernel1D<T> > kernels(shape.size(), kernel); | | ArrayVector<Kernel1D<T> > kernels(shape.size(), kernel); | |
| | | | |
| separableConvolveMultiArray( s, shape, src, d, dest, kernels.begin(), s
tart, stop); | | separableConvolveMultiArray( s, shape, src, d, dest, kernels.begin(), s
tart, stop); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
|
| | | class DestIterator, class DestAccessor, class KernelIterator> | |
| | | inline void | |
| | | separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons | |
| | | t & source, | |
| | | pair<DestIterator, DestAccessor> const & dest, | |
| | | KernelIterator kit, | |
| | | SrcShape const & start = SrcShape(), | |
| | | SrcShape const & stop = SrcShape()) | |
| | | { | |
| | | separableConvolveMultiArray( source.first, source.second, source.third, | |
| | | dest.first, dest.second, kit, start, stop | |
| | | ); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class T> | | class DestIterator, class DestAccessor, class T> | |
| inline void | | inline void | |
| separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & source, | | separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & source, | |
| pair<DestIterator, DestAccessor> const & dest, | | pair<DestIterator, DestAccessor> const & dest, | |
| Kernel1D<T> const & kernel, | | Kernel1D<T> const & kernel, | |
| SrcShape const & start = SrcShape(), | | SrcShape const & start = SrcShape(), | |
| SrcShape const & stop = SrcShape()) | | SrcShape const & stop = SrcShape()) | |
| { | | { | |
| ArrayVector<Kernel1D<T> > kernels(source.second.size(), kernel); | | ArrayVector<Kernel1D<T> > kernels(source.second.size(), kernel); | |
| | | | |
| separableConvolveMultiArray( source.first, source.second, source.third, | | separableConvolveMultiArray( source.first, source.second, source.third, | |
| dest.first, dest.second, kernels.begin(),
start, stop); | | dest.first, dest.second, kernels.begin(),
start, stop); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class KernelIterator> | |
| | | inline void | |
| | | separableConvolveMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | KernelIterator kit, | |
| | | typename MultiArrayShape<N>::type start = typen | |
| | | ame MultiArrayShape<N>::type(), | |
| | | typename MultiArrayShape<N>::type stop = typena | |
| | | me MultiArrayShape<N>::type()) | |
| | | { | |
| | | if(stop != typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), sta | |
| | | rt); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), sto | |
| | | p); | |
| | | vigra_precondition(dest.shape() == (stop - start), | |
| | | "separableConvolveMultiArray(): shape mismatch between ROI and | |
| | | output."); | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "separableConvolveMultiArray(): shape mismatch between input an | |
| | | d output."); | |
| | | } | |
| | | separableConvolveMultiArray( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), kit, start, stop ); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T> | |
| | | inline void | |
| | | separableConvolveMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | Kernel1D<T> const & kernel, | |
| | | typename MultiArrayShape<N>::type const & start | |
| | | = typename MultiArrayShape<N>::type(), | |
| | | typename MultiArrayShape<N>::type const & stop | |
| | | = typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | ArrayVector<Kernel1D<T> > kernels(N, kernel); | |
| | | separableConvolveMultiArray(source, dest, kernels.begin(), start, stop) | |
| | | ; | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* convolveMultiArrayOneDimension */ | | /* convolveMultiArrayOneDimension */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Convolution along a single dimension of a multi-dimensional arra
ys. | | /** \brief Convolution along a single dimension of a multi-dimensional arra
ys. | |
| | | | |
| This function computes a convolution along one dimension (specified by | | This function computes a convolution along one dimension (specified by | |
| the parameter <tt>dim</tt> of the given multi-dimensional array with th
e given | | the parameter <tt>dim</tt> of the given multi-dimensional array with th
e given | |
|
| <tt>kernel</tt>. Both source and destination arrays are represented by | | <tt>kernel</tt>. The destination array must already have the correct si | |
| iterators, shape objects and accessors. The destination array is requir | | ze. | |
| ed to | | | |
| already have the correct size. | | | |
| | | | |
| If <tt>start</tt> and <tt>stop</tt> have non-default values, they must
represent | | If <tt>start</tt> and <tt>stop</tt> have non-default values, they must
represent | |
| a valid subarray of the input array. The convolution is then restricted
to that | | a valid subarray of the input array. The convolution is then restricted
to that | |
| subarray, and it is assumed that the output array only refers to the | | subarray, and it is assumed that the output array only refers to the | |
|
| subarray (i.e. <tt>diter</tt> points to the element corresponding to | | subarray (i.e. <tt>dest.shape() == stop - start</tt>). Negative ROI bou | |
| <tt>start</tt>). | | ndaries are | |
| | | interpreted relative to the end of the respective dimension | |
| | | (i.e. <tt>if(stop[k] < 0) stop[k] += source.shape(k);</tt>). | |
| | | | |
|
| This function may work in-place, which means that <tt>siter == diter</t
t> is allowed. | | This function may work in-place, which means that <tt>source.data() ==
dest.data()</tt> is allowed. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T> | |
| | | void | |
| | | convolveMultiArrayOneDimension(MultiArrayView<N, T1, S1> const & so | |
| | | urce, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | unsigned int dim, | |
| | | Kernel1D<T> const & kernel, | |
| | | typename MultiArrayShape<N>::type st | |
| | | art = typename MultiArrayShape<N>::type(), | |
| | | typename MultiArrayShape<N>::type st | |
| | | op = typename MultiArrayShape<N>::type()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{convolveMultiArrayOneDimension} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class T> | | class DestIterator, class DestAccessor, class T> | |
| void | | void | |
| convolveMultiArrayOneDimension(SrcIterator siter, SrcShape const &
shape, SrcAccessor src, | | convolveMultiArrayOneDimension(SrcIterator siter, SrcShape const &
shape, SrcAccessor src, | |
| DestIterator diter, DestAccessor des
t, | | DestIterator diter, DestAccessor des
t, | |
| unsigned int dim, vigra::Kernel1D<T>
const & kernel, | | unsigned int dim, vigra::Kernel1D<T>
const & kernel, | |
| SrcShape const & start = SrcShape(), | | SrcShape const & start = SrcShape(), | |
| SrcShape const & stop = SrcShape()); | | SrcShape const & stop = SrcShape()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class T> | | class DestIterator, class DestAccessor, class T> | |
| void | | void | |
| convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAcc
essor> const & source, | | convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAcc
essor> const & source, | |
| pair<DestIterator, DestAccessor> con
st & dest, | | pair<DestIterator, DestAccessor> con
st & dest, | |
| unsigned int dim, vigra::Kernel1D<T>
const & kernel, | | unsigned int dim, vigra::Kernel1D<T>
const & kernel, | |
| SrcShape const & start = SrcShape(), | | SrcShape const & start = SrcShape(), | |
| SrcShape const & stop = SrcShape()); | | SrcShape const & stop = SrcShape()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | Shape3 shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
| MultiArray<3, float> dest(shape); | | MultiArray<3, float> dest(shape); | |
| ... | | ... | |
| Kernel1D<float> gauss; | | Kernel1D<float> gauss; | |
| gauss.initGaussian(sigma); | | gauss.initGaussian(sigma); | |
| | | | |
|
| // perform Gaussian smoothing along dimensions 1 (height) | | // perform Gaussian smoothing along dimension 1 (height) | |
| convolveMultiArrayOneDimension(srcMultiArrayRange(source), destMultiArr | | convolveMultiArrayOneDimension(source, dest, 1, gauss); | |
| ay(dest), 1, gauss); | | | |
| \endcode | | \endcode | |
| | | | |
| \see separableConvolveMultiArray() | | \see separableConvolveMultiArray() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void convolveMultiArrayOneDimens
ion) | | doxygen_overloaded_function(template <...> void convolveMultiArrayOneDimens
ion) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class T> | | class DestIterator, class DestAccessor, class T> | |
| void | | void | |
| convolveMultiArrayOneDimension(SrcIterator s, SrcShape const & shape, SrcAc
cessor src, | | convolveMultiArrayOneDimension(SrcIterator s, SrcShape const & shape, SrcAc
cessor src, | |
| | | | |
| skipping to change at line 971 | | skipping to change at line 1108 | |
| sstart[dim] = 0; | | sstart[dim] = 0; | |
| sstop[dim] = shape[dim]; | | sstop[dim] = shape[dim]; | |
| dstop = stop - start; | | dstop = stop - start; | |
| } | | } | |
| | | | |
| SNavigator snav( s, sstart, sstop, dim ); | | SNavigator snav( s, sstart, sstop, dim ); | |
| DNavigator dnav( d, dstart, dstop, dim ); | | DNavigator dnav( d, dstart, dstop, dim ); | |
| | | | |
| for( ; snav.hasMore(); snav++, dnav++ ) | | for( ; snav.hasMore(); snav++, dnav++ ) | |
| { | | { | |
|
| // first copy source to temp for maximum cache efficiency | | // first copy source to temp for maximum cache efficiency | |
| copyLine( snav.begin(), snav.end(), src, | | copyLine(snav.begin(), snav.end(), src, | |
| tmp.begin(), typename AccessorTraits<TmpType>::default_accessor( | | tmp.begin(), typename AccessorTraits<TmpType>::default_acc | |
| ) ); | | essor() ); | |
| | | | |
| convolveLine(srcIterRange( tmp.begin(), tmp.end(), TmpAccessor()), | | convolveLine(srcIterRange( tmp.begin(), tmp.end(), TmpAccessor()), | |
| destIter( dnav.begin(), dest ), | | destIter( dnav.begin(), dest ), | |
| kernel1d( kernel), start[dim], stop[dim]); | | kernel1d( kernel), start[dim], stop[dim]); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class T> | | class DestIterator, class DestAccessor, class T> | |
| inline void | | inline void | |
| convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAccessor> c
onst & source, | | convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAccessor> c
onst & source, | |
| pair<DestIterator, DestAccessor> const & des
t, | | pair<DestIterator, DestAccessor> const & des
t, | |
|
| unsigned int dim, vigra::Kernel1D<T> const & | | unsigned int dim, | |
| kernel, | | Kernel1D<T> const & kernel, | |
| SrcShape const & start = SrcShape(), | | SrcShape const & start = SrcShape(), | |
| SrcShape const & stop = SrcShape()) | | SrcShape const & stop = SrcShape()) | |
| { | | { | |
| convolveMultiArrayOneDimension(source.first, source.second, source.thir
d, | | convolveMultiArrayOneDimension(source.first, source.second, source.thir
d, | |
| dest.first, dest.second, dim, kernel, st
art, stop); | | dest.first, dest.second, dim, kernel, st
art, stop); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T> | |
| | | inline void | |
| | | convolveMultiArrayOneDimension(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | unsigned int dim, | |
| | | Kernel1D<T> const & kernel, | |
| | | typename MultiArrayShape<N>::type start = ty | |
| | | pename MultiArrayShape<N>::type(), | |
| | | typename MultiArrayShape<N>::type stop = typ | |
| | | ename MultiArrayShape<N>::type()) | |
| | | { | |
| | | if(stop != typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), sta | |
| | | rt); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), sto | |
| | | p); | |
| | | vigra_precondition(dest.shape() == (stop - start), | |
| | | "convolveMultiArrayOneDimension(): shape mismatch between ROI a | |
| | | nd output."); | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "convolveMultiArrayOneDimension(): shape mismatch between input | |
| | | and output."); | |
| | | } | |
| | | convolveMultiArrayOneDimension(srcMultiArrayRange(source), | |
| | | destMultiArray(dest), dim, kernel, start | |
| | | , stop); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* gaussianSmoothMultiArray */ | | /* gaussianSmoothMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Isotropic Gaussian smoothing of a multi-dimensional arrays. | | /** \brief Isotropic Gaussian smoothing of a multi-dimensional arrays. | |
| | | | |
| This function computes an isotropic convolution of the given N-dimensio
nal | | This function computes an isotropic convolution of the given N-dimensio
nal | |
| array with a Gaussian filter at the given standard deviation <tt>sigma<
/tt>. | | array with a Gaussian filter at the given standard deviation <tt>sigma<
/tt>. | |
| Both source and destination arrays are represented by | | Both source and destination arrays are represented by | |
| iterators, shape objects and accessors. The destination array is requir
ed to | | iterators, shape objects and accessors. The destination array is requir
ed to | |
| already have the correct size. This function may work in-place, which m
eans | | already have the correct size. This function may work in-place, which m
eans | |
|
| that <tt>siter == diter</tt> is allowed. It is implemented by a call to | | that <tt>source.data() == dest.data()</tt> is allowed. It is implemente
d by a call to | |
| \ref separableConvolveMultiArray() with the appropriate kernel. | | \ref separableConvolveMultiArray() with the appropriate kernel. | |
| | | | |
| Anisotropic data should be passed with appropriate | | Anisotropic data should be passed with appropriate | |
| \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | | \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | |
|
| unless the parameter <tt>sigma</tt> is left out. | | unless the parameter <tt>sigma</tt> is omitted. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // pass filter scale explicitly | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianSmoothMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOpt | |
| | | ions<N>()); | |
| | | | |
| | | // pass filer scale(s) in the option object | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianSmoothMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> opt); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{gaussianSmoothMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianSmoothMultiArray(SrcIterator siter, SrcShape const & shape,
SrcAccessor src, | | gaussianSmoothMultiArray(SrcIterator siter, SrcShape const & shape,
SrcAccessor src, | |
| DestIterator diter, DestAccessor dest, | | DestIterator diter, DestAccessor dest, | |
|
| double sigma, const ConvolutionOptions<N> | | double sigma, | |
| & opt); | | const ConvolutionOptions<N> & opt = Convol | |
| | | utionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor>
const & source, | | gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor>
const & source, | |
| pair<DestIterator, DestAccessor> const & d
est, | | pair<DestIterator, DestAccessor> const & d
est, | |
|
| double sigma, const ConvolutionOptions<N> | | double sigma, | |
| & opt); | | const ConvolutionOptions<N> & opt = Convol | |
| | | utionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | Shape3 shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
|
| MultiArray<3, float> dest(shape); | | MultiArray<3, float> dest(shape); | |
| ... | | ... | |
| // perform isotropic Gaussian smoothing at scale 'sigma' | | // perform isotropic Gaussian smoothing at scale 'sigma' | |
|
| gaussianSmoothMultiArray(srcMultiArrayRange(source), destMultiArray(des
t), sigma); | | gaussianSmoothMultiArray(source, dest, sigma); | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage with anisotropic data:</b> | | <b> Usage with anisotropic data:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | | |
| | | | |
| \code | | \code | |
|
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | Shape3 shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
|
| MultiArray<3, float> dest(shape); | | MultiArray<3, float> dest(shape); | |
| TinyVector<float, 3> step_size; | | TinyVector<float, 3> step_size; | |
| TinyVector<float, 3> resolution_sigmas; | | TinyVector<float, 3> resolution_sigmas; | |
| ... | | ... | |
| // perform anisotropic Gaussian smoothing at scale 'sigma' | | // perform anisotropic Gaussian smoothing at scale 'sigma' | |
|
| gaussianSmoothMultiArray(srcMultiArrayRange(source), destMultiArray(des
t), sigma, | | gaussianSmoothMultiArray(source, dest, sigma, | |
| ConvolutionOptions<3>().stepSize(step_size).re
solutionStdDev(resolution_sigmas)); | | ConvolutionOptions<3>().stepSize(step_size).re
solutionStdDev(resolution_sigmas)); | |
| \endcode | | \endcode | |
| | | | |
| \see separableConvolveMultiArray() | | \see separableConvolveMultiArray() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void gaussianSmoothMultiArray) | | doxygen_overloaded_function(template <...> void gaussianSmoothMultiArray) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianSmoothMultiArray( SrcIterator s, SrcShape const & shape, SrcAccesso
r src, | | gaussianSmoothMultiArray( SrcIterator s, SrcShape const & shape, SrcAccesso
r src, | |
| DestIterator d, DestAccessor dest, | | DestIterator d, DestAccessor dest, | |
| const ConvolutionOptions<SrcShape::static_size> & opt, | | const ConvolutionOptions<SrcShape::static_size> & opt, | |
| const char *const function_name = "gaussianSmoothMultiAr
ray" ) | | const char *const function_name = "gaussianSmoothMultiAr
ray" ) | |
| { | | { | |
|
| typedef typename DestAccessor::value_type DestType; | | | |
| | | | |
| static const int N = SrcShape::static_size; | | static const int N = SrcShape::static_size; | |
| | | | |
| typename ConvolutionOptions<N>::ScaleIterator params = opt.scaleParams(
); | | typename ConvolutionOptions<N>::ScaleIterator params = opt.scaleParams(
); | |
| ArrayVector<Kernel1D<double> > kernels(N); | | ArrayVector<Kernel1D<double> > kernels(N); | |
| | | | |
| for (int dim = 0; dim < N; ++dim, ++params) | | for (int dim = 0; dim < N; ++dim, ++params) | |
| kernels[dim].initGaussian(params.sigma_scaled(function_name), 1.0,
opt.window_ratio); | | kernels[dim].initGaussian(params.sigma_scaled(function_name), 1.0,
opt.window_ratio); | |
| | | | |
| separableConvolveMultiArray(s, shape, src, d, dest, kernels.begin(), op
t.from_point, opt.to_point); | | separableConvolveMultiArray(s, shape, src, d, dest, kernels.begin(), op
t.from_point, opt.to_point); | |
| } | | } | |
| | | | |
| skipping to change at line 1109 | | skipping to change at line 1296 | |
| const ConvolutionOptions<SrcShape::static_size> & opt =
ConvolutionOptions<SrcShape::static_size>()) | | const ConvolutionOptions<SrcShape::static_size> & opt =
ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
| ConvolutionOptions<SrcShape::static_size> par = opt; | | ConvolutionOptions<SrcShape::static_size> par = opt; | |
| gaussianSmoothMultiArray(s, shape, src, d, dest, par.stdDev(sigma)); | | gaussianSmoothMultiArray(s, shape, src, d, dest, par.stdDev(sigma)); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const &
source, | | gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const &
source, | |
|
| pair<DestIterator, DestAccessor> const & dest, | | pair<DestIterator, DestAccessor> const & dest, | |
| const ConvolutionOptions<SrcShape::static_size> & opt) | | const ConvolutionOptions<SrcShape::static_size> & | |
| | | opt) | |
| { | | { | |
| gaussianSmoothMultiArray( source.first, source.second, source.third, | | gaussianSmoothMultiArray( source.first, source.second, source.third, | |
| dest.first, dest.second, opt ); | | dest.first, dest.second, opt ); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const &
source, | | gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const &
source, | |
|
| pair<DestIterator, DestAccessor> const & dest, double sig | | pair<DestIterator, DestAccessor> const & dest, dou | |
| ma, | | ble sigma, | |
| const ConvolutionOptions<SrcShape::static_size> & opt = C | | const ConvolutionOptions<SrcShape::static_size> & | |
| onvolutionOptions<SrcShape::static_size>()) | | opt = ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
| gaussianSmoothMultiArray( source.first, source.second, source.third, | | gaussianSmoothMultiArray( source.first, source.second, source.third, | |
| dest.first, dest.second, sigma, opt ); | | dest.first, dest.second, sigma, opt ); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianSmoothMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> opt) | |
| | | { | |
| | | if(opt.to_point != typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .from_point); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .to_point); | |
| | | vigra_precondition(dest.shape() == (opt.to_point - opt.from_point), | |
| | | "gaussianSmoothMultiArray(): shape mismatch between ROI and out | |
| | | put."); | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "gaussianSmoothMultiArray(): shape mismatch between input and o | |
| | | utput."); | |
| | | } | |
| | | | |
| | | gaussianSmoothMultiArray( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), opt ); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianSmoothMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOptions<N>( | |
| | | )) | |
| | | { | |
| | | gaussianSmoothMultiArray( source, dest, opt.stdDev(sigma) ); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* gaussianGradientMultiArray */ | | /* gaussianGradientMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Calculate Gaussian gradient of a multi-dimensional arrays. | | /** \brief Calculate Gaussian gradient of a multi-dimensional arrays. | |
| | | | |
| This function computes the Gaussian gradient of the given N-dimensional | | This function computes the Gaussian gradient of the given N-dimensional | |
| array with a sequence of first-derivative-of-Gaussian filters at the gi
ven | | array with a sequence of first-derivative-of-Gaussian filters at the gi
ven | |
| standard deviation <tt>sigma</tt> (differentiation is applied to each d
imension | | standard deviation <tt>sigma</tt> (differentiation is applied to each d
imension | |
|
| in turn, starting with the innermost dimension). Both source and destin | | in turn, starting with the innermost dimension). The destination array | |
| ation arrays | | is | |
| are represented by iterators, shape objects and accessors. The destinat | | | |
| ion array is | | | |
| required to have a vector valued pixel type with as many elements as th
e number of | | required to have a vector valued pixel type with as many elements as th
e number of | |
| dimensions. This function is implemented by calls to | | dimensions. This function is implemented by calls to | |
| \ref separableConvolveMultiArray() with the appropriate kernels. | | \ref separableConvolveMultiArray() with the appropriate kernels. | |
| | | | |
| Anisotropic data should be passed with appropriate | | Anisotropic data should be passed with appropriate | |
| \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | | \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | |
|
| unless the parameter <tt>sigma</tt> is left out. | | unless the parameter <tt>sigma</tt> is omitted. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // pass filter scale explicitly | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianGradientMultiArray(MultiArrayView<N, T1, S1> const & source | |
| | | , | |
| | | MultiArrayView<N, TinyVector<T2, N>, S2> | |
| | | dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionO | |
| | | ptions<N>()); | |
| | | | |
| | | // pass filter scale(s) in option object | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianGradientMultiArray(MultiArrayView<N, T1, S1> const & source | |
| | | , | |
| | | MultiArrayView<N, TinyVector<T2, N>, S2> | |
| | | dest, | |
| | | ConvolutionOptions<N> opt); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{gaussianGradientMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianGradientMultiArray(SrcIterator siter, SrcShape const & shap
e, SrcAccessor src, | | gaussianGradientMultiArray(SrcIterator siter, SrcShape const & shap
e, SrcAccessor src, | |
| DestIterator diter, DestAccessor dest, | | DestIterator diter, DestAccessor dest, | |
|
| double sigma, const ConvolutionOptions<N | | double sigma, | |
| > & opt); | | const ConvolutionOptions<N> & opt = Conv | |
| | | olutionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccesso
r> const & source, | | gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccesso
r> const & source, | |
| pair<DestIterator, DestAccessor> const &
dest, | | pair<DestIterator, DestAccessor> const &
dest, | |
|
| double sigma, const ConvolutionOptions<N | | double sigma, | |
| > & opt); | | const ConvolutionOptions<N> & opt = Conv | |
| | | olutionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | Shape3 shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
| MultiArray<3, TinyVector<float, 3> > dest(shape); | | MultiArray<3, TinyVector<float, 3> > dest(shape); | |
| ... | | ... | |
| // compute Gaussian gradient at scale sigma | | // compute Gaussian gradient at scale sigma | |
|
| gaussianGradientMultiArray(srcMultiArrayRange(source), destMultiArray(d
est), sigma); | | gaussianGradientMultiArray(source, dest, sigma); | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage with anisotropic data:</b> | | <b> Usage with anisotropic data:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | | |
| | | | |
| \code | | \code | |
|
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | Shape3 shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
| MultiArray<3, TinyVector<float, 3> > dest(shape); | | MultiArray<3, TinyVector<float, 3> > dest(shape); | |
| TinyVector<float, 3> step_size; | | TinyVector<float, 3> step_size; | |
| TinyVector<float, 3> resolution_sigmas; | | TinyVector<float, 3> resolution_sigmas; | |
| ... | | ... | |
| // compute Gaussian gradient at scale sigma | | // compute Gaussian gradient at scale sigma | |
|
| gaussianGradientMultiArray(srcMultiArrayRange(source), destMultiArray(d
est), sigma, | | gaussianGradientMultiArray(source, dest, sigma, | |
| ConvolutionOptions<3>().stepSize(step_size).
resolutionStdDev(resolution_sigmas)); | | ConvolutionOptions<3>().stepSize(step_size).
resolutionStdDev(resolution_sigmas)); | |
| \endcode | | \endcode | |
| | | | |
|
| <b> Required Interface:</b> | | | |
| | | | |
| see \ref separableConvolveMultiArray(), in addition: | | | |
| | | | |
| \code | | | |
| int dimension = 0; | | | |
| VectorElementAccessor<DestAccessor> elementAccessor(0, dest); | | | |
| \endcode | | | |
| | | | |
| \see separableConvolveMultiArray() | | \see separableConvolveMultiArray() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void gaussianGradientMultiArray) | | doxygen_overloaded_function(template <...> void gaussianGradientMultiArray) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAcces
sor src, | | gaussianGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAcces
sor src, | |
| DestIterator di, DestAccessor dest, | | DestIterator di, DestAccessor dest, | |
| ConvolutionOptions<SrcShape::static_size> const
& opt, | | ConvolutionOptions<SrcShape::static_size> const
& opt, | |
| | | | |
| skipping to change at line 1266 | | skipping to change at line 1502 | |
| separableConvolveMultiArray(si, shape, src, di, ElementAccessor(dim
, dest), kernels.begin(), | | separableConvolveMultiArray(si, shape, src, di, ElementAccessor(dim
, dest), kernels.begin(), | |
| opt.from_point, opt.to_point); | | opt.from_point, opt.to_point); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| gaussianGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAcces
sor src, | | gaussianGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAcces
sor src, | |
| DestIterator di, DestAccessor dest, double sigma
, | | DestIterator di, DestAccessor dest, double sigma
, | |
|
| const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | | ConvolutionOptions<SrcShape::static_size> opt =
ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
|
| ConvolutionOptions<SrcShape::static_size> par = opt; | | gaussianGradientMultiArray(si, shape, src, di, dest, opt.stdDev(sigma)) | |
| gaussianGradientMultiArray(si, shape, src, di, dest, par.stdDev(sigma)) | | ; | |
| ; | | | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const
& source, | | gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const
& source, | |
| pair<DestIterator, DestAccessor> const & dest, | | pair<DestIterator, DestAccessor> const & dest, | |
| ConvolutionOptions<SrcShape::static_size> const
& opt ) | | ConvolutionOptions<SrcShape::static_size> const
& opt ) | |
| { | | { | |
| gaussianGradientMultiArray( source.first, source.second, source.third, | | gaussianGradientMultiArray( source.first, source.second, source.third, | |
| | | | |
| skipping to change at line 1295 | | skipping to change at line 1530 | |
| inline void | | inline void | |
| gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const
& source, | | gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const
& source, | |
| pair<DestIterator, DestAccessor> const & dest, | | pair<DestIterator, DestAccessor> const & dest, | |
| double sigma, | | double sigma, | |
| const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | | const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
| gaussianGradientMultiArray( source.first, source.second, source.third, | | gaussianGradientMultiArray( source.first, source.second, source.third, | |
| dest.first, dest.second, sigma, opt ); | | dest.first, dest.second, sigma, opt ); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianGradientMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, TinyVector<T2, N>, S2> dest, | |
| | | ConvolutionOptions<N> opt ) | |
| | | { | |
| | | if(opt.to_point != typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .from_point); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .to_point); | |
| | | vigra_precondition(dest.shape() == (opt.to_point - opt.from_point), | |
| | | "gaussianGradientMultiArray(): shape mismatch between ROI and o | |
| | | utput."); | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "gaussianGradientMultiArray(): shape mismatch between input and | |
| | | output."); | |
| | | } | |
| | | | |
| | | gaussianGradientMultiArray( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), opt ); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianGradientMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, TinyVector<T2, N>, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOptions<N | |
| | | >()) | |
| | | { | |
| | | gaussianGradientMultiArray( source, dest, opt.stdDev(sigma) ); | |
| | | } | |
| | | | |
| | | /********************************************************/ | |
| | | /* */ | |
| | | /* gaussianGradientMagnitude */ | |
| | | /* */ | |
| | | /********************************************************/ | |
| | | | |
| | | namespace detail { | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianGradientMagnitudeImpl(MultiArrayView<N+1, T1, S1> const & src, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> opt = ConvolutionOption | |
| | | s<N>()) | |
| | | { | |
| | | typename MultiArrayShape<N>::type shape(src.shape().template subarray<0 | |
| | | ,N>()); | |
| | | if(opt.to_point != typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, opt.from_poi | |
| | | nt); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, opt.to_point | |
| | | ); | |
| | | vigra_precondition(dest.shape() == (opt.to_point - opt.from_point), | |
| | | "gaussianGradientMagnitude(): shape mismatch between ROI and ou | |
| | | tput."); | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(shape == dest.shape(), | |
| | | "gaussianGradientMagnitude(): shape mismatch between input and | |
| | | output."); | |
| | | } | |
| | | | |
| | | dest.init(0.0); | |
| | | | |
| | | typedef typename NumericTraits<T1>::RealPromote TmpType; | |
| | | MultiArray<N, TinyVector<TmpType, N> > grad(dest.shape()); | |
| | | | |
| | | using namespace multi_math; | |
| | | | |
| | | for(int k=0; k<src.shape(N); ++k) | |
| | | { | |
| | | gaussianGradientMultiArray(src.bindOuter(k), grad, opt); | |
| | | | |
| | | dest += squaredNorm(grad); | |
| | | } | |
| | | dest = sqrt(dest); | |
| | | } | |
| | | | |
| | | } // namespace detail | |
| | | | |
| | | // documentation is in convolution.hxx | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianGradientMagnitude(MultiArrayView<N+1, Multiband<T1>, S1> const & sr | |
| | | c, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> const & opt) | |
| | | { | |
| | | detail::gaussianGradientMagnitudeImpl<N, T1>(src, dest, opt); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianGradientMagnitude(MultiArrayView<N, T1, S1> const & src, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> const & opt) | |
| | | { | |
| | | detail::gaussianGradientMagnitudeImpl<N, T1>(src.insertSingletonDimensi | |
| | | on(N), dest, opt); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, int M, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianGradientMagnitude(MultiArrayView<N, TinyVector<T1, M>, S1> const & | |
| | | src, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> const & opt) | |
| | | { | |
| | | detail::gaussianGradientMagnitudeImpl<N, T1>(src.expandElements(N), des | |
| | | t, opt); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, unsigned int R, unsigned int G, unsigne | |
| | | d int B, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianGradientMagnitude(MultiArrayView<N, RGBValue<T1, R, G, B>, S1> cons | |
| | | t & src, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> const & opt) | |
| | | { | |
| | | detail::gaussianGradientMagnitudeImpl<N, T1>(src.expandElements(N), des | |
| | | t, opt); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianGradientMagnitude(MultiArrayView<N, T1, S1> const & src, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOptions<N> | |
| | | ()) | |
| | | { | |
| | | gaussianGradientMagnitude(src, dest, opt.stdDev(sigma)); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianGradientMagnitude(MultiArrayView<N+1, Multiband<T1>, S1> const & sr | |
| | | c, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOptions<N> | |
| | | ()) | |
| | | { | |
| | | gaussianGradientMagnitude<N>(src, dest, opt.stdDev(sigma)); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* symmetricGradientMultiArray */ | | /* symmetricGradientMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Calculate gradient of a multi-dimensional arrays using symmetric
difference filters. | | /** \brief Calculate gradient of a multi-dimensional arrays using symmetric
difference filters. | |
| | | | |
| This function computes the gradient of the given N-dimensional | | This function computes the gradient of the given N-dimensional | |
| array with a sequence of symmetric difference filters a (differentiatio
n is applied | | array with a sequence of symmetric difference filters a (differentiatio
n is applied | |
|
| to each dimension in turn, starting with the innermost dimension). Both | | to each dimension in turn, starting with the innermost dimension). | |
| source and | | | |
| destination arrays are represented by iterators, shape objects and acce | | | |
| ssors. | | | |
| The destination array is required to have a vector valued pixel type wi
th as many | | The destination array is required to have a vector valued pixel type wi
th as many | |
| elements as the number of dimensions. This function is implemented by c
alls to | | elements as the number of dimensions. This function is implemented by c
alls to | |
| \ref convolveMultiArrayOneDimension() with the symmetric difference ker
nel. | | \ref convolveMultiArrayOneDimension() with the symmetric difference ker
nel. | |
| | | | |
| Anisotropic data should be passed with appropriate | | Anisotropic data should be passed with appropriate | |
| \ref ConvolutionOptions, the parameter <tt>opt</tt> is optional | | \ref ConvolutionOptions, the parameter <tt>opt</tt> is optional | |
| otherwise. | | otherwise. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | symmetricGradientMultiArray(MultiArrayView<N, T1, S1> const & sourc | |
| | | e, | |
| | | MultiArrayView<N, TinyVector<T2, N>, S2 | |
| | | > dest, | |
| | | ConvolutionOptions<N> opt = Convolution | |
| | | Options<N>()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{symmetricGradientMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| symmetricGradientMultiArray(SrcIterator siter, SrcShape const & sha
pe, SrcAccessor src, | | symmetricGradientMultiArray(SrcIterator siter, SrcShape const & sha
pe, SrcAccessor src, | |
| DestIterator diter, DestAccessor dest, | | DestIterator diter, DestAccessor dest, | |
|
| const ConvolutionOptions<N> & opt); | | const ConvolutionOptions<N> & opt = Con
volutionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | | symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | |
| pair<DestIterator, DestAccessor> const
& dest, | | pair<DestIterator, DestAccessor> const
& dest, | |
|
| const ConvolutionOptions<N> & opt); | | const ConvolutionOptions<N> & opt = Con
volutionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | MultiArray<3, unsigned char>::size_type shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
| MultiArray<3, TinyVector<float, 3> > dest(shape); | | MultiArray<3, TinyVector<float, 3> > dest(shape); | |
| ... | | ... | |
| // compute gradient | | // compute gradient | |
| symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray(
dest)); | | symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray(
dest)); | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage with anisotropic data:</b> | | <b> Usage with anisotropic data:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | | |
| | | | |
| \code | | \code | |
|
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | Shape3 shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
| MultiArray<3, TinyVector<float, 3> > dest(shape); | | MultiArray<3, TinyVector<float, 3> > dest(shape); | |
| TinyVector<float, 3> step_size; | | TinyVector<float, 3> step_size; | |
| ... | | ... | |
| // compute gradient | | // compute gradient | |
|
| symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray(
dest), | | symmetricGradientMultiArray(source, dest, | |
| ConvolutionOptions<3>().stepSize(step_size)
); | | ConvolutionOptions<3>().stepSize(step_size)
); | |
| \endcode | | \endcode | |
| | | | |
|
| <b> Required Interface:</b> | | | |
| | | | |
| see \ref convolveMultiArrayOneDimension(), in addition: | | | |
| | | | |
| \code | | | |
| int dimension = 0; | | | |
| VectorElementAccessor<DestAccessor> elementAccessor(0, dest); | | | |
| \endcode | | | |
| | | | |
| \see convolveMultiArrayOneDimension() | | \see convolveMultiArrayOneDimension() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void symmetricGradientMultiArray
) | | doxygen_overloaded_function(template <...> void symmetricGradientMultiArray
) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| symmetricGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAcce
ssor src, | | symmetricGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAcce
ssor src, | |
| DestIterator di, DestAccessor dest, | | DestIterator di, DestAccessor dest, | |
| const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | | const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | |
| | | | |
| skipping to change at line 1404 | | skipping to change at line 1786 | |
| typedef typename ConvolutionOptions<N>::StepIterator StepType; | | typedef typename ConvolutionOptions<N>::StepIterator StepType; | |
| | | | |
| for(int k=0; k<N; ++k) | | for(int k=0; k<N; ++k) | |
| if(shape[k] <=0) | | if(shape[k] <=0) | |
| return; | | return; | |
| | | | |
| vigra_precondition(N == (int)dest.size(di), | | vigra_precondition(N == (int)dest.size(di), | |
| "symmetricGradientMultiArray(): Wrong number of channels in output
array."); | | "symmetricGradientMultiArray(): Wrong number of channels in output
array."); | |
| | | | |
| Kernel1D<KernelType> filter; | | Kernel1D<KernelType> filter; | |
|
| filter.initSymmetricGradient(); | | filter.initSymmetricDifference(); | |
| | | | |
| StepType step_size_it = opt.stepParams(); | | StepType step_size_it = opt.stepParams(); | |
| | | | |
| typedef VectorElementAccessor<DestAccessor> ElementAccessor; | | typedef VectorElementAccessor<DestAccessor> ElementAccessor; | |
| | | | |
| // compute gradient components | | // compute gradient components | |
| for (int d = 0; d < N; ++d, ++step_size_it) | | for (int d = 0; d < N; ++d, ++step_size_it) | |
| { | | { | |
| Kernel1D<KernelType> symmetric(filter); | | Kernel1D<KernelType> symmetric(filter); | |
| detail::scaleKernel(symmetric, 1 / *step_size_it); | | detail::scaleKernel(symmetric, 1 / *step_size_it); | |
| | | | |
| skipping to change at line 1432 | | skipping to change at line 1814 | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & source, | | symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & source, | |
| pair<DestIterator, DestAccessor> const & dest, | | pair<DestIterator, DestAccessor> const & dest, | |
| const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | | const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
| symmetricGradientMultiArray(source.first, source.second, source.third, | | symmetricGradientMultiArray(source.first, source.second, source.third, | |
| dest.first, dest.second, opt); | | dest.first, dest.second, opt); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | symmetricGradientMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, TinyVector<T2, N>, S2> dest, | |
| | | ConvolutionOptions<N> opt = ConvolutionOptions< | |
| | | N>()) | |
| | | { | |
| | | if(opt.to_point != typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .from_point); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .to_point); | |
| | | vigra_precondition(dest.shape() == (opt.to_point - opt.from_point), | |
| | | "symmetricGradientMultiArray(): shape mismatch between ROI and | |
| | | output."); | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "symmetricGradientMultiArray(): shape mismatch between input an | |
| | | d output."); | |
| | | } | |
| | | | |
| | | symmetricGradientMultiArray(srcMultiArrayRange(source), | |
| | | destMultiArray(dest), opt); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* laplacianOfGaussianMultiArray */ | | /* laplacianOfGaussianMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Calculate Laplacian of a N-dimensional arrays using Gaussian der
ivative filters. | | /** \brief Calculate Laplacian of a N-dimensional arrays using Gaussian der
ivative filters. | |
| | | | |
|
| This function computes the Laplacian the given N-dimensional | | This function computes the Laplacian of the given N-dimensional | |
| array with a sequence of second-derivative-of-Gaussian filters at the g
iven | | array with a sequence of second-derivative-of-Gaussian filters at the g
iven | |
|
| standard deviation <tt>sigma</tt>. Both source and destination arrays | | standard deviation <tt>sigma</tt>. Both source and destination | |
| are represented by iterators, shape objects and accessors. Both source | | | |
| and destination | | | |
| arrays must have scalar value_type. This function is implemented by cal
ls to | | arrays must have scalar value_type. This function is implemented by cal
ls to | |
| \ref separableConvolveMultiArray() with the appropriate kernels, follow
ed by summation. | | \ref separableConvolveMultiArray() with the appropriate kernels, follow
ed by summation. | |
| | | | |
| Anisotropic data should be passed with appropriate | | Anisotropic data should be passed with appropriate | |
| \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | | \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | |
| unless the parameter <tt>sigma</tt> is left out. | | unless the parameter <tt>sigma</tt> is left out. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // pass scale explicitly | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | laplacianOfGaussianMultiArray(MultiArrayView<N, T1, S1> const & sou | |
| | | rce, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = Convoluti | |
| | | onOptions<N>()); | |
| | | | |
| | | // pass scale(s) in option object | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | laplacianOfGaussianMultiArray(MultiArrayView<N, T1, S1> const & sou | |
| | | rce, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> opt ); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{laplacianOfGaussianMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| laplacianOfGaussianMultiArray(SrcIterator siter, SrcShape const & s
hape, SrcAccessor src, | | laplacianOfGaussianMultiArray(SrcIterator siter, SrcShape const & s
hape, SrcAccessor src, | |
| DestIterator diter, DestAccessor dest
, | | DestIterator diter, DestAccessor dest
, | |
|
| double sigma, const ConvolutionOption | | double sigma, | |
| s<N> & opt); | | const ConvolutionOptions<N> & opt = C | |
| | | onvolutionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| laplacianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAcce
ssor> const & source, | | laplacianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAcce
ssor> const & source, | |
| pair<DestIterator, DestAccessor> cons
t & dest, | | pair<DestIterator, DestAccessor> cons
t & dest, | |
|
| double sigma, const ConvolutionOption | | double sigma, | |
| s<N> & opt); | | const ConvolutionOptions<N> & opt = C | |
| | | onvolutionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | Shape3 shape(width, height, depth); | |
| MultiArray<3, float> source(shape); | | MultiArray<3, float> source(shape); | |
| MultiArray<3, float> laplacian(shape); | | MultiArray<3, float> laplacian(shape); | |
| ... | | ... | |
| // compute Laplacian at scale sigma | | // compute Laplacian at scale sigma | |
|
| laplacianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArra
y(laplacian), sigma); | | laplacianOfGaussianMultiArray(source, laplacian, sigma); | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage with anisotropic data:</b> | | <b> Usage with anisotropic data:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | | |
| | | | |
| \code | | \code | |
| MultiArray<3, float> source(shape); | | MultiArray<3, float> source(shape); | |
| MultiArray<3, float> laplacian(shape); | | MultiArray<3, float> laplacian(shape); | |
| TinyVector<float, 3> step_size; | | TinyVector<float, 3> step_size; | |
| TinyVector<float, 3> resolution_sigmas; | | TinyVector<float, 3> resolution_sigmas; | |
| ... | | ... | |
| // compute Laplacian at scale sigma | | // compute Laplacian at scale sigma | |
|
| laplacianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArra
y(laplacian), sigma, | | laplacianOfGaussianMultiArray(source, laplacian, sigma, | |
| ConvolutionOptions<3>().stepSize(step_siz
e).resolutionStdDev(resolution_sigmas)); | | ConvolutionOptions<3>().stepSize(step_siz
e).resolutionStdDev(resolution_sigmas)); | |
| \endcode | | \endcode | |
| | | | |
|
| <b> Required Interface:</b> | | | |
| | | | |
| see \ref separableConvolveMultiArray(), in addition: | | | |
| | | | |
| \code | | | |
| int dimension = 0; | | | |
| VectorElementAccessor<DestAccessor> elementAccessor(0, dest); | | | |
| \endcode | | | |
| | | | |
| \see separableConvolveMultiArray() | | \see separableConvolveMultiArray() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void laplacianOfGaussianMultiArr
ay) | | doxygen_overloaded_function(template <...> void laplacianOfGaussianMultiArr
ay) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| laplacianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAc
cessor src, | | laplacianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAc
cessor src, | |
| DestIterator di, DestAccessor dest, | | DestIterator di, DestAccessor dest, | |
| ConvolutionOptions<SrcShape::static_size> con
st & opt ) | | ConvolutionOptions<SrcShape::static_size> con
st & opt ) | |
| | | | |
| skipping to change at line 1577 | | skipping to change at line 1998 | |
| di, dest, Arg1() + Arg2() ); | | di, dest, Arg1() + Arg2() ); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| laplacianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAc
cessor src, | | laplacianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAc
cessor src, | |
| DestIterator di, DestAccessor dest, double si
gma, | | DestIterator di, DestAccessor dest, double si
gma, | |
|
| const ConvolutionOptions<SrcShape::static_siz
e> & opt = ConvolutionOptions<SrcShape::static_size>()) | | ConvolutionOptions<SrcShape::static_size> opt
= ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
|
| ConvolutionOptions<SrcShape::static_size> par = opt; | | laplacianOfGaussianMultiArray(si, shape, src, di, dest, opt.stdDev(sigm | |
| laplacianOfGaussianMultiArray(si, shape, src, di, dest, par.stdDev(sigm | | a)); | |
| a)); | | | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| laplacianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> co
nst & source, | | laplacianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> co
nst & source, | |
| pair<DestIterator, DestAccessor> const & dest
, | | pair<DestIterator, DestAccessor> const & dest
, | |
| ConvolutionOptions<SrcShape::static_size> con
st & opt ) | | ConvolutionOptions<SrcShape::static_size> con
st & opt ) | |
| { | | { | |
| laplacianOfGaussianMultiArray( source.first, source.second, source.thir
d, | | laplacianOfGaussianMultiArray( source.first, source.second, source.thir
d, | |
| | | | |
| skipping to change at line 1606 | | skipping to change at line 2026 | |
| inline void | | inline void | |
| laplacianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> co
nst & source, | | laplacianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> co
nst & source, | |
| pair<DestIterator, DestAccessor> const & dest
, | | pair<DestIterator, DestAccessor> const & dest
, | |
| double sigma, | | double sigma, | |
| const ConvolutionOptions<SrcShape::static_siz
e> & opt = ConvolutionOptions<SrcShape::static_size>()) | | const ConvolutionOptions<SrcShape::static_siz
e> & opt = ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
| laplacianOfGaussianMultiArray( source.first, source.second, source.thir
d, | | laplacianOfGaussianMultiArray( source.first, source.second, source.thir
d, | |
| dest.first, dest.second, sigma, opt ); | | dest.first, dest.second, sigma, opt ); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | laplacianOfGaussianMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | ConvolutionOptions<N> opt ) | |
| | | { | |
| | | if(opt.to_point != typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .from_point); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .to_point); | |
| | | vigra_precondition(dest.shape() == (opt.to_point - opt.from_point), | |
| | | "laplacianOfGaussianMultiArray(): shape mismatch between ROI an | |
| | | d output."); | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "laplacianOfGaussianMultiArray(): shape mismatch between input | |
| | | and output."); | |
| | | } | |
| | | | |
| | | laplacianOfGaussianMultiArray( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), opt ); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | laplacianOfGaussianMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOption | |
| | | s<N>()) | |
| | | { | |
| | | laplacianOfGaussianMultiArray( source, dest, opt.stdDev(sigma) ); | |
| | | } | |
| | | | |
| | | /********************************************************/ | |
| | | /* */ | |
| | | /* gaussianDivergenceMultiArray */ | |
| | | /* */ | |
| | | /********************************************************/ | |
| | | | |
| | | /** \brief Calculate the divergence of a vector field using Gaussian deriva | |
| | | tive filters. | |
| | | | |
| | | This function computes the divergence of the given N-dimensional vector | |
| | | field | |
| | | with a sequence of first-derivative-of-Gaussian filters at the given | |
| | | standard deviation <tt>sigma</tt>. The input vector field can either be | |
| | | given as a sequence | |
| | | of scalar array views (one for each vector field component), represente | |
| | | d by an | |
| | | iterator range, or by a single vector array with the appropriate shape. | |
| | | This function is implemented by calls to | |
| | | \ref separableConvolveMultiArray() with the suitable kernels, followed | |
| | | by summation. | |
| | | | |
| | | Anisotropic data should be passed with appropriate | |
| | | \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option | |
| | | al | |
| | | unless the parameter <tt>sigma</tt> is omitted. | |
| | | | |
| | | <b> Declarations:</b> | |
| | | | |
| | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // specify input vector field as a sequence of scalar arrays | |
| | | template <class Iterator, | |
| | | unsigned int N, class T, class S> | |
| | | void | |
| | | gaussianDivergenceMultiArray(Iterator vectorField, Iterator vectorF | |
| | | ieldEnd, | |
| | | MultiArrayView<N, T, S> divergence, | |
| | | ConvolutionOptions<N> const & opt); | |
| | | | |
| | | template <class Iterator, | |
| | | unsigned int N, class T, class S> | |
| | | void | |
| | | gaussianDivergenceMultiArray(Iterator vectorField, Iterator vectorF | |
| | | ieldEnd, | |
| | | MultiArrayView<N, T, S> divergence, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = Convolutio | |
| | | nOptions<N>()); | |
| | | | |
| | | // pass input vector field as an array of vectors | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianDivergenceMultiArray(MultiArrayView<N, TinyVector<T1, N>, S | |
| | | 1> const & vectorField, | |
| | | MultiArrayView<N, T2, S2> divergence, | |
| | | ConvolutionOptions<N> const & opt); | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | gaussianDivergenceMultiArray(MultiArrayView<N, TinyVector<T1, N>, S | |
| | | 1> const & vectorField, | |
| | | MultiArrayView<N, T2, S2> divergence, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = Convolutio | |
| | | nOptions<N>()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | <b> Usage:</b> | |
| | | | |
| | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | Shape3 shape(width, height, depth); | |
| | | MultiArray<3, TinyVector<float, 3> > source(shape); | |
| | | MultiArray<3, float> laplacian(shape); | |
| | | ... | |
| | | // compute divergence at scale sigma | |
| | | gaussianDivergenceMultiArray(source, laplacian, sigma); | |
| | | \endcode | |
| | | | |
| | | <b> Usage with anisotropic data:</b> | |
| | | | |
| | | \code | |
| | | MultiArray<3, TinyVector<float, 3> > source(shape); | |
| | | MultiArray<3, float> laplacian(shape); | |
| | | TinyVector<float, 3> step_size; | |
| | | TinyVector<float, 3> resolution_sigmas; | |
| | | ... | |
| | | // compute divergence at scale sigma | |
| | | gaussianDivergenceMultiArray(source, laplacian, sigma, | |
| | | ConvolutionOptions<3>().stepSize(step_size | |
| | | ).resolutionStdDev(resolution_sigmas)); | |
| | | \endcode | |
| | | */ | |
| | | doxygen_overloaded_function(template <...> void gaussianDivergenceMultiArra | |
| | | y) | |
| | | | |
| | | template <class Iterator, | |
| | | unsigned int N, class T, class S> | |
| | | void | |
| | | gaussianDivergenceMultiArray(Iterator vectorField, Iterator vectorFieldEnd, | |
| | | MultiArrayView<N, T, S> divergence, | |
| | | ConvolutionOptions<N> opt) | |
| | | { | |
| | | typedef typename std::iterator_traits<Iterator>::value_type ArrayType; | |
| | | typedef typename ArrayType::value_type SrcType; | |
| | | typedef typename NumericTraits<SrcType>::RealPromote TmpType; | |
| | | typedef Kernel1D<double> Kernel; | |
| | | | |
| | | vigra_precondition(std::distance(vectorField, vectorFieldEnd) == N, | |
| | | "gaussianDivergenceMultiArray(): wrong number of input arrays."); | |
| | | // more checks are performed in separableConvolveMultiArray() | |
| | | | |
| | | typename ConvolutionOptions<N>::ScaleIterator params = opt.scaleParams( | |
| | | ); | |
| | | ArrayVector<double> sigmas(N); | |
| | | ArrayVector<Kernel> kernels(N); | |
| | | for(unsigned int k = 0; k < N; ++k, ++params) | |
| | | { | |
| | | sigmas[k] = params.sigma_scaled("gaussianDivergenceMultiArray"); | |
| | | kernels[k].initGaussian(sigmas[k], 1.0, opt.window_ratio); | |
| | | } | |
| | | | |
| | | MultiArray<N, TmpType> tmpDeriv(divergence.shape()); | |
| | | | |
| | | for(unsigned int k=0; k < N; ++k, ++vectorField) | |
| | | { | |
| | | kernels[k].initGaussianDerivative(sigmas[k], 1, 1.0, opt.window_rat | |
| | | io); | |
| | | if(k == 0) | |
| | | { | |
| | | separableConvolveMultiArray(*vectorField, divergence, kernels.b | |
| | | egin(), opt.from_point, opt.to_point); | |
| | | } | |
| | | else | |
| | | { | |
| | | separableConvolveMultiArray(*vectorField, tmpDeriv, kernels.beg | |
| | | in(), opt.from_point, opt.to_point); | |
| | | divergence += tmpDeriv; | |
| | | } | |
| | | kernels[k].initGaussian(sigmas[k], 1.0, opt.window_ratio); | |
| | | } | |
| | | } | |
| | | | |
| | | template <class Iterator, | |
| | | unsigned int N, class T, class S> | |
| | | inline void | |
| | | gaussianDivergenceMultiArray(Iterator vectorField, Iterator vectorFieldEnd, | |
| | | MultiArrayView<N, T, S> divergence, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOptions | |
| | | <N>()) | |
| | | { | |
| | | gaussianDivergenceMultiArray(vectorField, vectorFieldEnd, divergence, o | |
| | | pt.stdDev(sigma)); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianDivergenceMultiArray(MultiArrayView<N, TinyVector<T1, N>, S1> const | |
| | | & vectorField, | |
| | | MultiArrayView<N, T2, S2> divergence, | |
| | | ConvolutionOptions<N> const & opt) | |
| | | { | |
| | | ArrayVector<MultiArrayView<N, T1> > field; | |
| | | for(unsigned int k=0; k<N; ++k) | |
| | | field.push_back(vectorField.bindElementChannel(k)); | |
| | | | |
| | | gaussianDivergenceMultiArray(field.begin(), field.end(), divergence, op | |
| | | t); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | gaussianDivergenceMultiArray(MultiArrayView<N, TinyVector<T1, N>, S1> const | |
| | | & vectorField, | |
| | | MultiArrayView<N, T2, S2> divergence, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOptions | |
| | | <N>()) | |
| | | { | |
| | | gaussianDivergenceMultiArray(vectorField, divergence, opt.stdDev(sigma) | |
| | | ); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* hessianOfGaussianMultiArray */ | | /* hessianOfGaussianMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Calculate Hessian matrix of a N-dimensional arrays using Gaussia
n derivative filters. | | /** \brief Calculate Hessian matrix of a N-dimensional arrays using Gaussia
n derivative filters. | |
| | | | |
| This function computes the Hessian matrix the given scalar N-dimensiona
l | | This function computes the Hessian matrix the given scalar N-dimensiona
l | |
| array with a sequence of second-derivative-of-Gaussian filters at the g
iven | | array with a sequence of second-derivative-of-Gaussian filters at the g
iven | |
|
| standard deviation <tt>sigma</tt>. Both source and destination arrays | | standard deviation <tt>sigma</tt>. The destination array must | |
| are represented by iterators, shape objects and accessors. The destinat | | | |
| ion array must | | | |
| have a vector valued element type with N*(N+1)/2 elements (it represent
s the | | have a vector valued element type with N*(N+1)/2 elements (it represent
s the | |
|
| upper triangular part of the symmetric Hessian matrix). This function i | | upper triangular part of the symmetric Hessian matrix, flattened row-wi | |
| s implemented by calls to | | se). | |
| | | This function is implemented by calls to | |
| \ref separableConvolveMultiArray() with the appropriate kernels. | | \ref separableConvolveMultiArray() with the appropriate kernels. | |
| | | | |
| Anisotropic data should be passed with appropriate | | Anisotropic data should be passed with appropriate | |
| \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | | \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | |
|
| unless the parameter <tt>sigma</tt> is left out. | | unless the parameter <tt>sigma</tt> is omitted. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // pass scale explicitly | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | hessianOfGaussianMultiArray(MultiArrayView<N, T1, S1> const & sourc | |
| | | e, | |
| | | MultiArrayView<N, TinyVector<T2, int(N* | |
| | | (N+1)/2)>, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = Convolution | |
| | | Options<N>()); | |
| | | | |
| | | // pass scale(s) in option object | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | hessianOfGaussianMultiArray(MultiArrayView<N, T1, S1> const & sourc | |
| | | e, | |
| | | MultiArrayView<N, TinyVector<T2, int(N* | |
| | | (N+1)/2)>, S2> dest, | |
| | | ConvolutionOptions<N> opt); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{hessianOfGaussianMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| hessianOfGaussianMultiArray(SrcIterator siter, SrcShape const & sha
pe, SrcAccessor src, | | hessianOfGaussianMultiArray(SrcIterator siter, SrcShape const & sha
pe, SrcAccessor src, | |
| DestIterator diter, DestAccessor dest, | | DestIterator diter, DestAccessor dest, | |
|
| double sigma, const ConvolutionOptions< | | double sigma, | |
| N> & opt); | | const ConvolutionOptions<N> & opt = Con | |
| | | volutionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| hessianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | | hessianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | |
| pair<DestIterator, DestAccessor> const
& dest, | | pair<DestIterator, DestAccessor> const
& dest, | |
|
| double sigma, const ConvolutionOptions< | | double sigma, | |
| N> & opt); | | const ConvolutionOptions<N> & opt = Con | |
| | | volutionOptions<N>()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | Shape3 shape(width, height, depth); | |
| MultiArray<3, float> source(shape); | | MultiArray<3, float> source(shape); | |
| MultiArray<3, TinyVector<float, 6> > dest(shape); | | MultiArray<3, TinyVector<float, 6> > dest(shape); | |
| ... | | ... | |
| // compute Hessian at scale sigma | | // compute Hessian at scale sigma | |
|
| hessianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArray(
dest), sigma); | | hessianOfGaussianMultiArray(source, dest, sigma); | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage with anisotropic data:</b> | | <b> Usage with anisotropic data:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | | |
| | | | |
| \code | | \code | |
| MultiArray<3, float> source(shape); | | MultiArray<3, float> source(shape); | |
| MultiArray<3, TinyVector<float, 6> > dest(shape); | | MultiArray<3, TinyVector<float, 6> > dest(shape); | |
| TinyVector<float, 3> step_size; | | TinyVector<float, 3> step_size; | |
| TinyVector<float, 3> resolution_sigmas; | | TinyVector<float, 3> resolution_sigmas; | |
| ... | | ... | |
| // compute Hessian at scale sigma | | // compute Hessian at scale sigma | |
|
| hessianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArray(
dest), sigma, | | hessianOfGaussianMultiArray(source, dest, sigma, | |
| ConvolutionOptions<3>().stepSize(step_size)
.resolutionStdDev(resolution_sigmas)); | | ConvolutionOptions<3>().stepSize(step_size)
.resolutionStdDev(resolution_sigmas)); | |
| \endcode | | \endcode | |
| | | | |
|
| <b> Required Interface:</b> | | | |
| | | | |
| see \ref separableConvolveMultiArray(), in addition: | | | |
| | | | |
| \code | | | |
| int dimension = 0; | | | |
| VectorElementAccessor<DestAccessor> elementAccessor(0, dest); | | | |
| \endcode | | | |
| | | | |
| \see separableConvolveMultiArray(), vectorToTensorMultiArray() | | \see separableConvolveMultiArray(), vectorToTensorMultiArray() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void hessianOfGaussianMultiArray
) | | doxygen_overloaded_function(template <...> void hessianOfGaussianMultiArray
) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| hessianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAcce
ssor src, | | hessianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAcce
ssor src, | |
| DestIterator di, DestAccessor dest, | | DestIterator di, DestAccessor dest, | |
| ConvolutionOptions<SrcShape::static_size> const
& opt ) | | ConvolutionOptions<SrcShape::static_size> const
& opt ) | |
| | | | |
| skipping to change at line 1756 | | skipping to change at line 2394 | |
| kernels.begin(), opt.from_point, op
t.to_point); | | kernels.begin(), opt.from_point, op
t.to_point); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| hessianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAcce
ssor src, | | hessianOfGaussianMultiArray(SrcIterator si, SrcShape const & shape, SrcAcce
ssor src, | |
| DestIterator di, DestAccessor dest, double sigm
a, | | DestIterator di, DestAccessor dest, double sigm
a, | |
|
| const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | | ConvolutionOptions<SrcShape::static_size> opt =
ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
|
| ConvolutionOptions<SrcShape::static_size> par = opt; | | hessianOfGaussianMultiArray(si, shape, src, di, dest, opt.stdDev(sigma) | |
| hessianOfGaussianMultiArray(si, shape, src, di, dest, par.stdDev(sigma) | | ); | |
| ); | | | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| hessianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & source, | | hessianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & source, | |
| pair<DestIterator, DestAccessor> const & dest, | | pair<DestIterator, DestAccessor> const & dest, | |
| ConvolutionOptions<SrcShape::static_size> const
& opt ) | | ConvolutionOptions<SrcShape::static_size> const
& opt ) | |
| { | | { | |
| hessianOfGaussianMultiArray( source.first, source.second, source.third, | | hessianOfGaussianMultiArray( source.first, source.second, source.third, | |
| | | | |
| skipping to change at line 1785 | | skipping to change at line 2422 | |
| inline void | | inline void | |
| hessianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & source, | | hessianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & source, | |
| pair<DestIterator, DestAccessor> const & dest, | | pair<DestIterator, DestAccessor> const & dest, | |
| double sigma, | | double sigma, | |
| const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | | const ConvolutionOptions<SrcShape::static_size>
& opt = ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
| hessianOfGaussianMultiArray( source.first, source.second, source.third, | | hessianOfGaussianMultiArray( source.first, source.second, source.third, | |
| dest.first, dest.second, sigma, opt ); | | dest.first, dest.second, sigma, opt ); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | hessianOfGaussianMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, TinyVector<T2, int(N*(N+1)/2) | |
| | | >, S2> dest, | |
| | | ConvolutionOptions<N> opt ) | |
| | | { | |
| | | if(opt.to_point != typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .from_point); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .to_point); | |
| | | vigra_precondition(dest.shape() == (opt.to_point - opt.from_point), | |
| | | "hessianOfGaussianMultiArray(): shape mismatch between ROI and | |
| | | output."); | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "hessianOfGaussianMultiArray(): shape mismatch between input an | |
| | | d output."); | |
| | | } | |
| | | | |
| | | hessianOfGaussianMultiArray( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), opt ); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | hessianOfGaussianMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, TinyVector<T2, int(N*(N+1)/2) | |
| | | >, S2> dest, | |
| | | double sigma, | |
| | | ConvolutionOptions<N> opt = ConvolutionOptions< | |
| | | N>()) | |
| | | { | |
| | | hessianOfGaussianMultiArray( source, dest, opt.stdDev(sigma) ); | |
| | | } | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| template<int N, class VectorType> | | template<int N, class VectorType> | |
| struct StructurTensorFunctor | | struct StructurTensorFunctor | |
| { | | { | |
| typedef VectorType result_type; | | typedef VectorType result_type; | |
| typedef typename VectorType::value_type ValueType; | | typedef typename VectorType::value_type ValueType; | |
| | | | |
| template <class T> | | template <class T> | |
| VectorType operator()(T const & in) const | | VectorType operator()(T const & in) const | |
| | | | |
| skipping to change at line 1821 | | skipping to change at line 2493 | |
| /* */ | | /* */ | |
| /* structureTensorMultiArray */ | | /* structureTensorMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Calculate th structure tensor of a multi-dimensional arrays. | | /** \brief Calculate th structure tensor of a multi-dimensional arrays. | |
| | | | |
| This function computes the gradient (outer product) tensor for each ele
ment | | This function computes the gradient (outer product) tensor for each ele
ment | |
| of the given N-dimensional array with first-derivative-of-Gaussian filt
ers at | | of the given N-dimensional array with first-derivative-of-Gaussian filt
ers at | |
| the given <tt>innerScale</tt>, followed by Gaussian smoothing at <tt>ou
terScale</tt>. | | the given <tt>innerScale</tt>, followed by Gaussian smoothing at <tt>ou
terScale</tt>. | |
|
| Both source and destination arrays are represented by iterators, shape | | The destination array must have a vector valued pixel type with | |
| objects and | | | |
| accessors. The destination array must have a vector valued pixel type w | | | |
| ith | | | |
| N*(N+1)/2 elements (it represents the upper triangular part of the symm
etric | | N*(N+1)/2 elements (it represents the upper triangular part of the symm
etric | |
|
| structure tensor matrix). If the source array is also vector valued, th
e | | structure tensor matrix, flattened row-wise). If the source array is al
so vector valued, the | |
| resulting structure tensor is the sum of the individual tensors for eac
h channel. | | resulting structure tensor is the sum of the individual tensors for eac
h channel. | |
| This function is implemented by calls to | | This function is implemented by calls to | |
| \ref separableConvolveMultiArray() with the appropriate kernels. | | \ref separableConvolveMultiArray() with the appropriate kernels. | |
| | | | |
| Anisotropic data should be passed with appropriate | | Anisotropic data should be passed with appropriate | |
| \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | | \ref ConvolutionOptions, the parameter <tt>opt</tt> is otherwise option
al | |
| unless the parameters <tt>innerScale</tt> and <tt>outerScale</tt> are | | unless the parameters <tt>innerScale</tt> and <tt>outerScale</tt> are | |
|
| both left out. | | both omitted. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // pass scales explicitly | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | structureTensorMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, TinyVector<T2, int(N*(N | |
| | | +1)/2)>, S2> dest, | |
| | | double innerScale, double outerScale, | |
| | | ConvolutionOptions<N> opt = ConvolutionOp | |
| | | tions<N>()); | |
| | | | |
| | | // pass scales in option object | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | structureTensorMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, TinyVector<T2, int(N*(N | |
| | | +1)/2)>, S2> dest, | |
| | | ConvolutionOptions<N> opt ); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{structureTensorMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| structureTensorMultiArray(SrcIterator siter, SrcShape const & shape
, SrcAccessor src, | | structureTensorMultiArray(SrcIterator siter, SrcShape const & shape
, SrcAccessor src, | |
| DestIterator diter, DestAccessor dest, | | DestIterator diter, DestAccessor dest, | |
| double innerScale, double outerScale, | | double innerScale, double outerScale, | |
|
| const ConvolutionOptions<N> & opt); | | ConvolutionOptions<N> opt); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| structureTensorMultiArray(triple<SrcIterator, SrcShape, SrcAccessor
> const & source, | | structureTensorMultiArray(triple<SrcIterator, SrcShape, SrcAccessor
> const & source, | |
| pair<DestIterator, DestAccessor> const &
dest, | | pair<DestIterator, DestAccessor> const &
dest, | |
| double innerScale, double outerScale, | | double innerScale, double outerScale, | |
| const ConvolutionOptions<N> & opt); | | const ConvolutionOptions<N> & opt); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | <b>\#include</b> \<vigra/multi_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | Shape3 shape(width, height, depth); | |
| MultiArray<3, RGBValue<float> > source(shape); | | MultiArray<3, RGBValue<float> > source(shape); | |
| MultiArray<3, TinyVector<float, 6> > dest(shape); | | MultiArray<3, TinyVector<float, 6> > dest(shape); | |
| ... | | ... | |
| // compute structure tensor at scales innerScale and outerScale | | // compute structure tensor at scales innerScale and outerScale | |
|
| structureTensorMultiArray(srcMultiArrayRange(source), destMultiArray(de
st), innerScale, outerScale); | | structureTensorMultiArray(source, dest, innerScale, outerScale); | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage with anisotropic data:</b> | | <b> Usage with anisotropic data:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_convolution.hxx\> | | | |
| | | | |
| \code | | \code | |
| MultiArray<3, RGBValue<float> > source(shape); | | MultiArray<3, RGBValue<float> > source(shape); | |
| MultiArray<3, TinyVector<float, 6> > dest(shape); | | MultiArray<3, TinyVector<float, 6> > dest(shape); | |
| TinyVector<float, 3> step_size; | | TinyVector<float, 3> step_size; | |
| TinyVector<float, 3> resolution_sigmas; | | TinyVector<float, 3> resolution_sigmas; | |
| ... | | ... | |
| // compute structure tensor at scales innerScale and outerScale | | // compute structure tensor at scales innerScale and outerScale | |
|
| structureTensorMultiArray(srcMultiArrayRange(source), destMultiArray(de
st), innerScale, outerScale, | | structureTensorMultiArray(source, dest, innerScale, outerScale, | |
| ConvolutionOptions<3>().stepSize(step_size).r
esolutionStdDev(resolution_sigmas)); | | ConvolutionOptions<3>().stepSize(step_size).r
esolutionStdDev(resolution_sigmas)); | |
| \endcode | | \endcode | |
| | | | |
|
| <b> Required Interface:</b> | | | |
| | | | |
| see \ref separableConvolveMultiArray(), in addition: | | | |
| | | | |
| \code | | | |
| int dimension = 0; | | | |
| VectorElementAccessor<DestAccessor> elementAccessor(0, dest); | | | |
| \endcode | | | |
| | | | |
| \see separableConvolveMultiArray(), vectorToTensorMultiArray() | | \see separableConvolveMultiArray(), vectorToTensorMultiArray() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void structureTensorMultiArray) | | doxygen_overloaded_function(template <...> void structureTensorMultiArray) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| structureTensorMultiArray(SrcIterator si, SrcShape const & shape, SrcAccess
or src, | | structureTensorMultiArray(SrcIterator si, SrcShape const & shape, SrcAccess
or src, | |
| DestIterator di, DestAccessor dest, | | DestIterator di, DestAccessor dest, | |
|
| ConvolutionOptions<SrcShape::static_size> const &
opt) | | ConvolutionOptions<SrcShape::static_size> opt) | |
| { | | { | |
| static const int N = SrcShape::static_size; | | static const int N = SrcShape::static_size; | |
| static const int M = N*(N+1)/2; | | static const int M = N*(N+1)/2; | |
| | | | |
| typedef typename DestAccessor::value_type DestType; | | typedef typename DestAccessor::value_type DestType; | |
| typedef typename DestType::value_type DestValueType; | | typedef typename DestType::value_type DestValueType; | |
| typedef typename NumericTraits<DestValueType>::RealPromote KernelType; | | typedef typename NumericTraits<DestValueType>::RealPromote KernelType; | |
| typedef TinyVector<KernelType, N> GradientVector; | | typedef TinyVector<KernelType, N> GradientVector; | |
| typedef typename AccessorTraits<GradientVector>::default_accessor Gradi
entAccessor; | | typedef typename AccessorTraits<GradientVector>::default_accessor Gradi
entAccessor; | |
| typedef typename AccessorTraits<DestType>::default_accessor GradientTen
sorAccessor; | | typedef typename AccessorTraits<DestType>::default_accessor GradientTen
sorAccessor; | |
| | | | |
| skipping to change at line 1933 | | skipping to change at line 2618 | |
| vigra_precondition(M == (int)dest.size(di), | | vigra_precondition(M == (int)dest.size(di), | |
| "structureTensorMultiArray(): Wrong number of channels in output ar
ray."); | | "structureTensorMultiArray(): Wrong number of channels in output ar
ray."); | |
| | | | |
| ConvolutionOptions<N> innerOptions = opt; | | ConvolutionOptions<N> innerOptions = opt; | |
| ConvolutionOptions<N> outerOptions = opt.outerOptions(); | | ConvolutionOptions<N> outerOptions = opt.outerOptions(); | |
| typename ConvolutionOptions<N>::ScaleIterator params = outerOptions.sca
leParams(); | | typename ConvolutionOptions<N>::ScaleIterator params = outerOptions.sca
leParams(); | |
| | | | |
| SrcShape gradientShape(shape); | | SrcShape gradientShape(shape); | |
| if(opt.to_point != SrcShape()) | | if(opt.to_point != SrcShape()) | |
| { | | { | |
|
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, opt.from_poi | |
| | | nt); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(shape, opt.to_point | |
| | | ); | |
| | | | |
| for(int k=0; k<N; ++k, ++params) | | for(int k=0; k<N; ++k, ++params) | |
| { | | { | |
| Kernel1D<double> gauss; | | Kernel1D<double> gauss; | |
| gauss.initGaussian(params.sigma_scaled("structureTensorMultiArr
ay"), 1.0, opt.window_ratio); | | gauss.initGaussian(params.sigma_scaled("structureTensorMultiArr
ay"), 1.0, opt.window_ratio); | |
| int dilation = gauss.right(); | | int dilation = gauss.right(); | |
| innerOptions.from_point[k] = std::max<MultiArrayIndex>(0, opt.f
rom_point[k] - dilation); | | innerOptions.from_point[k] = std::max<MultiArrayIndex>(0, opt.f
rom_point[k] - dilation); | |
| innerOptions.to_point[k] = std::min<MultiArrayIndex>(shape[k],
opt.to_point[k] + dilation); | | innerOptions.to_point[k] = std::min<MultiArrayIndex>(shape[k],
opt.to_point[k] + dilation); | |
| } | | } | |
| outerOptions.from_point -= innerOptions.from_point; | | outerOptions.from_point -= innerOptions.from_point; | |
| outerOptions.to_point -= innerOptions.from_point; | | outerOptions.to_point -= innerOptions.from_point; | |
| | | | |
| skipping to change at line 1968 | | skipping to change at line 2656 | |
| di, dest, outerOptions, | | di, dest, outerOptions, | |
| "structureTensorMultiArray"); | | "structureTensorMultiArray"); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| structureTensorMultiArray(SrcIterator si, SrcShape const & shape, SrcAccess
or src, | | structureTensorMultiArray(SrcIterator si, SrcShape const & shape, SrcAccess
or src, | |
| DestIterator di, DestAccessor dest, | | DestIterator di, DestAccessor dest, | |
| double innerScale, double outerScale, | | double innerScale, double outerScale, | |
|
| const ConvolutionOptions<SrcShape::static_size> &
opt = ConvolutionOptions<SrcShape::static_size>()) | | ConvolutionOptions<SrcShape::static_size> opt = C
onvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
|
| ConvolutionOptions<SrcShape::static_size> par = opt; | | | |
| structureTensorMultiArray(si, shape, src, di, dest, | | structureTensorMultiArray(si, shape, src, di, dest, | |
|
| par.stdDev(innerScale).outerScale(outerScale)
); | | opt.stdDev(innerScale).outerScale(outerScale)
); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| structureTensorMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const
& source, | | structureTensorMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const
& source, | |
| pair<DestIterator, DestAccessor> const & dest, | | pair<DestIterator, DestAccessor> const & dest, | |
| ConvolutionOptions<SrcShape::static_size> const &
opt ) | | ConvolutionOptions<SrcShape::static_size> const &
opt ) | |
| { | | { | |
| structureTensorMultiArray( source.first, source.second, source.third, | | structureTensorMultiArray( source.first, source.second, source.third, | |
| | | | |
| skipping to change at line 1999 | | skipping to change at line 2686 | |
| structureTensorMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const
& source, | | structureTensorMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const
& source, | |
| pair<DestIterator, DestAccessor> const & dest, | | pair<DestIterator, DestAccessor> const & dest, | |
| double innerScale, double outerScale, | | double innerScale, double outerScale, | |
| const ConvolutionOptions<SrcShape::static_size> &
opt = ConvolutionOptions<SrcShape::static_size>()) | | const ConvolutionOptions<SrcShape::static_size> &
opt = ConvolutionOptions<SrcShape::static_size>()) | |
| { | | { | |
| structureTensorMultiArray( source.first, source.second, source.third, | | structureTensorMultiArray( source.first, source.second, source.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| innerScale, outerScale, opt); | | innerScale, outerScale, opt); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | structureTensorMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, TinyVector<T2, int(N*(N+1)/2)>, | |
| | | S2> dest, | |
| | | ConvolutionOptions<N> opt ) | |
| | | { | |
| | | if(opt.to_point != typename MultiArrayShape<N>::type()) | |
| | | { | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .from_point); | |
| | | detail::RelativeToAbsoluteCoordinate<N-1>::exec(source.shape(), opt | |
| | | .to_point); | |
| | | vigra_precondition(dest.shape() == (opt.to_point - opt.from_point), | |
| | | "structureTensorMultiArray(): shape mismatch between ROI and ou | |
| | | tput."); | |
| | | } | |
| | | else | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "structureTensorMultiArray(): shape mismatch between input and | |
| | | output."); | |
| | | } | |
| | | | |
| | | structureTensorMultiArray( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), opt ); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | structureTensorMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, TinyVector<T2, int(N*(N+1)/2)>, | |
| | | S2> dest, | |
| | | double innerScale, double outerScale, | |
| | | ConvolutionOptions<N> opt = ConvolutionOptions<N> | |
| | | ()) | |
| | | { | |
| | | structureTensorMultiArray(source, dest, opt.innerScale(innerScale).oute | |
| | | rScale(outerScale)); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } //-- namespace vigra | | } //-- namespace vigra | |
| | | | |
| #endif //-- VIGRA_MULTI_CONVOLUTION_H | | #endif //-- VIGRA_MULTI_CONVOLUTION_H | |
| | | | |
End of changes. 152 change blocks. |
| 238 lines changed or deleted | | 1083 lines changed or added | |
|
| multi_distance.hxx | | multi_distance.hxx | |
| /************************************************************************/ | | /************************************************************************/ | |
| /* */ | | /* */ | |
|
| /* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn */ | | /* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn, */ | |
| /* and Ullrich Koethe */ | | /* Philipp Schubert and Ullrich Koethe */ | |
| /* */ | | /* */ | |
| /* This file is part of the VIGRA computer vision library. */ | | /* This file is part of the VIGRA computer vision library. */ | |
| /* The VIGRA Website is */ | | /* The VIGRA Website is */ | |
| /* http://hci.iwr.uni-heidelberg.de/vigra/ */ | | /* http://hci.iwr.uni-heidelberg.de/vigra/ */ | |
| /* Please direct questions, bug reports, and contributions to */ | | /* Please direct questions, bug reports, and contributions to */ | |
| /* ullrich.koethe@iwr.uni-heidelberg.de or */ | | /* ullrich.koethe@iwr.uni-heidelberg.de or */ | |
| /* vigra@informatik.uni-hamburg.de */ | | /* vigra@informatik.uni-hamburg.de */ | |
| /* */ | | /* */ | |
| /* Permission is hereby granted, free of charge, to any person */ | | /* Permission is hereby granted, free of charge, to any person */ | |
| /* obtaining a copy of this software and associated documentation */ | | /* obtaining a copy of this software and associated documentation */ | |
| | | | |
| skipping to change at line 51 | | skipping to change at line 51 | |
| #include <functional> | | #include <functional> | |
| #include "array_vector.hxx" | | #include "array_vector.hxx" | |
| #include "multi_array.hxx" | | #include "multi_array.hxx" | |
| #include "accessor.hxx" | | #include "accessor.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "navigator.hxx" | | #include "navigator.hxx" | |
| #include "metaprogramming.hxx" | | #include "metaprogramming.hxx" | |
| #include "multi_pointoperators.hxx" | | #include "multi_pointoperators.hxx" | |
| #include "functorexpression.hxx" | | #include "functorexpression.hxx" | |
| | | | |
|
| | | #include "multi_gridgraph.hxx" //for boundaryGraph & boundaryMultiDista | |
| | | nce | |
| | | #include "union_find.hxx" //for boundaryGraph & boundaryMultiDistanc | |
| | | e | |
| | | | |
| namespace vigra | | namespace vigra | |
| { | | { | |
| | | | |
| namespace detail | | namespace detail | |
| { | | { | |
| | | | |
| template <class Value> | | template <class Value> | |
| struct DistParabolaStackEntry | | struct DistParabolaStackEntry | |
| { | | { | |
| double left, center, right; | | double left, center, right; | |
|
| Value prevVal; | | Value apex_height; | |
| | | | |
| DistParabolaStackEntry(Value const & p, double l, double c, double r) | | DistParabolaStackEntry(Value const & p, double l, double c, double r) | |
|
| : left(l), center(c), right(r), prevVal(p) | | : left(l), center(c), right(r), apex_height(p) | |
| {} | | {} | |
| }; | | }; | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* distParabola */ | | /* distParabola */ | |
| /* */ | | /* */ | |
| /* Version with sigma (parabola spread) for morphology */ | | /* Version with sigma (parabola spread) for morphology */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor > | | class DestIterator, class DestAccessor > | |
| void distParabola(SrcIterator is, SrcIterator iend, SrcAccessor sa, | | void distParabola(SrcIterator is, SrcIterator iend, SrcAccessor sa, | |
| DestIterator id, DestAccessor da, double sigma ) | | DestIterator id, DestAccessor da, double sigma ) | |
| { | | { | |
| // We assume that the data in the input is distance squared and treat i
t as such | | // We assume that the data in the input is distance squared and treat i
t as such | |
| double w = iend - is; | | double w = iend - is; | |
|
| | | if(w <= 0) | |
| | | return; | |
| | | | |
| double sigma2 = sigma * sigma; | | double sigma2 = sigma * sigma; | |
| double sigma22 = 2.0 * sigma2; | | double sigma22 = 2.0 * sigma2; | |
| | | | |
| typedef typename SrcAccessor::value_type SrcType; | | typedef typename SrcAccessor::value_type SrcType; | |
| typedef DistParabolaStackEntry<SrcType> Influence; | | typedef DistParabolaStackEntry<SrcType> Influence; | |
| std::vector<Influence> _stack; | | std::vector<Influence> _stack; | |
| _stack.push_back(Influence(sa(is), 0.0, 0.0, w)); | | _stack.push_back(Influence(sa(is), 0.0, 0.0, w)); | |
| | | | |
| ++is; | | ++is; | |
| double current = 1.0; | | double current = 1.0; | |
|
| while(current < w ) | | for(;current < w; ++is, ++current) | |
| { | | { | |
|
| Influence & s = _stack.back(); | | double intersection; | |
| double diff = current - s.center; | | | |
| double intersection = current + (sa(is) - s.prevVal - sigma2*sq(dif | | | |
| f)) / (sigma22 * diff); | | | |
| | | | |
|
| if( intersection < s.left) // previous point has no influence | | while(true) | |
| { | | { | |
|
| _stack.pop_back(); | | Influence & s = _stack.back(); | |
| if(_stack.empty()) | | double diff = current - s.center; | |
| | | intersection = current + (sa(is) - s.apex_height - sigma2*sq(di | |
| | | ff)) / (sigma22 * diff); | |
| | | | |
| | | if( intersection < s.left) // previous point has no influence | |
| { | | { | |
|
| _stack.push_back(Influence(sa(is), 0.0, current, w)); | | _stack.pop_back(); | |
| | | if(!_stack.empty()) | |
| | | continue; // try new top of stack without advancing cu | |
| | | rrent | |
| | | else | |
| | | intersection = 0.0; | |
| } | | } | |
|
| else | | else if(intersection < s.right) | |
| { | | { | |
|
| continue; // try new top of stack without advancing current | | s.right = intersection; | |
| } | | } | |
|
| | | break; | |
| } | | } | |
|
| else if(intersection < s.right) | | _stack.push_back(Influence(sa(is), intersection, current, w)); | |
| { | | | |
| s.right = intersection; | | | |
| _stack.push_back(Influence(sa(is), intersection, current, w)); | | | |
| } | | | |
| ++is; | | | |
| ++current; | | | |
| } | | } | |
| | | | |
| // Now we have the stack indicating which rows are influenced by (and t
herefore | | // Now we have the stack indicating which rows are influenced by (and t
herefore | |
| // closest to) which row. We can go through the stack and calculate the | | // closest to) which row. We can go through the stack and calculate the | |
| // distance squared for each element of the column. | | // distance squared for each element of the column. | |
| typename std::vector<Influence>::iterator it = _stack.begin(); | | typename std::vector<Influence>::iterator it = _stack.begin(); | |
| for(current = 0.0; current < w; ++current, ++id) | | for(current = 0.0; current < w; ++current, ++id) | |
| { | | { | |
| while( current >= it->right) | | while( current >= it->right) | |
| ++it; | | ++it; | |
|
| da.set(sigma2 * sq(current - it->center) + it->prevVal, id); | | da.set(sigma2 * sq(current - it->center) + it->apex_height, id); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void distParabola(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | inline void distParabola(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, double sigm
a) | | pair<DestIterator, DestAccessor> dest, double sigm
a) | |
| { | | { | |
| distParabola(src.first, src.second, src.third, | | distParabola(src.first, src.second, src.third, | |
| dest.first, dest.second, sigma); | | dest.first, dest.second, sigma); | |
| | | | |
| skipping to change at line 232 | | skipping to change at line 238 | |
| DestIterator di, DestAccess
or dest) | | DestIterator di, DestAccess
or dest) | |
| { | | { | |
| ArrayVector<double> sigmas(shape.size(), 1.0); | | ArrayVector<double> sigmas(shape.size(), 1.0); | |
| internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, f
alse ); | | internalSeparableMultiArrayDistTmp( si, shape, src, di, dest, sigmas, f
alse ); | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| /** \addtogroup MultiArrayDistanceTransform Euclidean distance transform fo
r multi-dimensional arrays. | | /** \addtogroup MultiArrayDistanceTransform Euclidean distance transform fo
r multi-dimensional arrays. | |
| | | | |
|
| These functions perform the Euclidean distance transform an arbitrary d | | These functions perform variants of the Euclidean distance transform on | |
| imensional | | arbitrary dimensional arrays. | |
| array that is specified by iterators (compatible to \ref MultiIteratorP | | | |
| age) | | | |
| and shape objects. It can therefore be applied to a wide range of data | | | |
| structures | | | |
| (\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.). | | | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* separableMultiDistSquared */ | | /* separableMultiDistSquared */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Euclidean distance squared on multi-dimensional arrays. | | /** \brief Euclidean distance squared on multi-dimensional arrays. | |
| | | | |
| The algorithm is taken from Donald Bailey: "An Efficient Euclidean Dist
ance Transform", | | The algorithm is taken from Donald Bailey: "An Efficient Euclidean Dist
ance Transform", | |
| Proc. IWCIA'04, Springer LNCS 3322, 2004. | | Proc. IWCIA'04, Springer LNCS 3322, 2004. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // explicitly specify pixel pitch for each coordinate | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Array> | |
| | | void | |
| | | separableMultiDistSquared(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | bool background, | |
| | | Array const & pixelPitch); | |
| | | | |
| | | // use default pixel pitch = 1.0 for each coordinate | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | separableMultiDistSquared(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | bool background); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{separableMultiDistSquared} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // explicitly specify pixel pitch for each coordinate | | // explicitly specify pixel pitch for each coordinate | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class Array> | | class DestIterator, class DestAccessor, class Array> | |
| void | | void | |
| separableMultiDistSquared( SrcIterator s, SrcShape const & shape, S
rcAccessor src, | | separableMultiDistSquared( SrcIterator s, SrcShape const & shape, S
rcAccessor src, | |
| DestIterator d, DestAccessor dest, | | DestIterator d, DestAccessor dest, | |
| bool background, | | bool background, | |
| Array const & pixelPitch); | | Array const & pixelPitch); | |
| | | | |
| skipping to change at line 274 | | skipping to change at line 302 | |
| // use default pixel pitch = 1.0 for each coordinate | | // use default pixel pitch = 1.0 for each coordinate | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| separableMultiDistSquared(SrcIterator siter, SrcShape const & shape
, SrcAccessor src, | | separableMultiDistSquared(SrcIterator siter, SrcShape const & shape
, SrcAccessor src, | |
| DestIterator diter, DestAccessor dest, | | DestIterator diter, DestAccessor dest, | |
| bool background); | | bool background); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // explicitly specify pixel pitch for each coordinate | | // explicitly specify pixel pitch for each coordinate | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class Array> | | class DestIterator, class DestAccessor, class Array> | |
| void | | void | |
| separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAccesso
r> const & source, | | separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAccesso
r> const & source, | |
| pair<DestIterator, DestAccessor> const &
dest, | | pair<DestIterator, DestAccessor> const &
dest, | |
| bool background, | | bool background, | |
| | | | |
| skipping to change at line 297 | | skipping to change at line 324 | |
| // use default pixel pitch = 1.0 for each coordinate | | // use default pixel pitch = 1.0 for each coordinate | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| separableMultiDistSquared(triple<SrcIterator, SrcShape, SrcAccessor
> const & source, | | separableMultiDistSquared(triple<SrcIterator, SrcShape, SrcAccessor
> const & source, | |
| pair<DestIterator, DestAccessor> const &
dest, | | pair<DestIterator, DestAccessor> const &
dest, | |
| bool background); | | bool background); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| This function performs a squared Euclidean squared distance transform o
n the given | | This function performs a squared Euclidean squared distance transform o
n the given | |
| multi-dimensional array. Both source and destination | | multi-dimensional array. Both source and destination | |
| arrays are represented by iterators, shape objects and accessors. | | arrays are represented by iterators, shape objects and accessors. | |
| The destination array is required to already have the correct size. | | The destination array is required to already have the correct size. | |
| | | | |
| This function expects a mask as its source, where background pixels are | | This function expects a mask as its source, where background pixels are | |
| marked as zero, and non-background pixels as non-zero. If the parameter | | marked as zero, and non-background pixels as non-zero. If the parameter | |
| <i>background</i> is true, then the squared distance of all background | | <i>background</i> is true, then the squared distance of all background | |
| pixels to the nearest object is calculated. Otherwise, the distance of
all | | pixels to the nearest object is calculated. Otherwise, the distance of
all | |
| | | | |
| skipping to change at line 321 | | skipping to change at line 349 | |
| microscopy, for example). | | microscopy, for example). | |
| | | | |
| This function may work in-place, which means that <tt>siter == diter</t
t> is allowed. | | This function may work in-place, which means that <tt>siter == diter</t
t> is allowed. | |
| A full-sized internal array is only allocated if working on the destina
tion | | A full-sized internal array is only allocated if working on the destina
tion | |
| array directly would cause overflow errors (i.e. if | | array directly would cause overflow errors (i.e. if | |
| <tt> NumericTraits<typename DestAccessor::value_type>::max() < N * M*M<
/tt>, where M is the | | <tt> NumericTraits<typename DestAccessor::value_type>::max() < N * M*M<
/tt>, where M is the | |
| size of the largest dimension of the array. | | size of the largest dimension of the array. | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_distance.hxx\> | | <b>\#include</b> \<vigra/multi_distance.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | Shape3 shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
| MultiArray<3, unsigned int> dest(shape); | | MultiArray<3, unsigned int> dest(shape); | |
| ... | | ... | |
| | | | |
| // Calculate Euclidean distance squared for all background pixels | | // Calculate Euclidean distance squared for all background pixels | |
|
| separableMultiDistSquared(srcMultiArrayRange(source), destMultiArray(de
st), true); | | separableMultiDistSquared(source, dest, true); | |
| \endcode | | \endcode | |
| | | | |
| \see vigra::distanceTransform(), vigra::separableMultiDistance() | | \see vigra::distanceTransform(), vigra::separableMultiDistance() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void separableMultiDistSquared) | | doxygen_overloaded_function(template <...> void separableMultiDistSquared) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class Array> | | class DestIterator, class DestAccessor, class Array> | |
| void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcA
ccessor src, | | void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcA
ccessor src, | |
| DestIterator d, DestAccessor dest, bool bac
kground, | | DestIterator d, DestAccessor dest, bool bac
kground, | |
| | | | |
| skipping to change at line 400 | | skipping to change at line 429 | |
| ifThenElse( Arg1() == Param(zero), Param(m
axDist), Param(rzero) )); | | ifThenElse( Arg1() == Param(zero), Param(m
axDist), Param(rzero) )); | |
| else | | else | |
| transformMultiArray( s, shape, src, d, dest, | | transformMultiArray( s, shape, src, d, dest, | |
| ifThenElse( Arg1() != Param(zero), Param(m
axDist), Param(rzero) )); | | ifThenElse( Arg1() != Param(zero), Param(m
axDist), Param(rzero) )); | |
| | | | |
| detail::internalSeparableMultiArrayDistTmp( d, shape, dest, d, dest
, pixelPitch); | | detail::internalSeparableMultiArrayDistTmp( d, shape, dest, d, dest
, pixelPitch); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
|
| class DestIterator, class DestAccessor, class Array> | | | |
| inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAcc | | | |
| essor> const & source, | | | |
| pair<DestIterator, DestAccessor> con | | | |
| st & dest, bool background, | | | |
| Array const & pixelPitch) | | | |
| { | | | |
| separableMultiDistSquared( source.first, source.second, source.third, | | | |
| dest.first, dest.second, background, pixelPi | | | |
| tch ); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline | | inline | |
| void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcA
ccessor src, | | void separableMultiDistSquared( SrcIterator s, SrcShape const & shape, SrcA
ccessor src, | |
| DestIterator d, DestAccessor dest, bool bac
kground) | | DestIterator d, DestAccessor dest, bool bac
kground) | |
| { | | { | |
| ArrayVector<double> pixelPitch(shape.size(), 1.0); | | ArrayVector<double> pixelPitch(shape.size(), 1.0); | |
| separableMultiDistSquared( s, shape, src, d, dest, background, pixelPit
ch ); | | separableMultiDistSquared( s, shape, src, d, dest, background, pixelPit
ch ); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
|
| | | class DestIterator, class DestAccessor, class Array> | |
| | | inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAcc | |
| | | essor> const & source, | |
| | | pair<DestIterator, DestAccessor> con | |
| | | st & dest, bool background, | |
| | | Array const & pixelPitch) | |
| | | { | |
| | | separableMultiDistSquared( source.first, source.second, source.third, | |
| | | dest.first, dest.second, background, pixelPi | |
| | | tch ); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAcc
essor> const & source, | | inline void separableMultiDistSquared( triple<SrcIterator, SrcShape, SrcAcc
essor> const & source, | |
| pair<DestIterator, DestAccessor> con
st & dest, bool background) | | pair<DestIterator, DestAccessor> con
st & dest, bool background) | |
| { | | { | |
| separableMultiDistSquared( source.first, source.second, source.third, | | separableMultiDistSquared( source.first, source.second, source.third, | |
| dest.first, dest.second, background ); | | dest.first, dest.second, background ); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Array> | |
| | | inline void | |
| | | separableMultiDistSquared(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, bool background, | |
| | | Array const & pixelPitch) | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "separableMultiDistSquared(): shape mismatch between input and outp | |
| | | ut."); | |
| | | separableMultiDistSquared( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), background, pixelPitch | |
| | | ); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | separableMultiDistSquared(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, bool background) | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "separableMultiDistSquared(): shape mismatch between input and outp | |
| | | ut."); | |
| | | separableMultiDistSquared( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), background ); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* separableMultiDistance */ | | /* separableMultiDistance */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Euclidean distance on multi-dimensional arrays. | | /** \brief Euclidean distance on multi-dimensional arrays. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // explicitly specify pixel pitch for each coordinate | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, class Array> | |
| | | void | |
| | | separableMultiDistance(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | bool background, | |
| | | Array const & pixelPitch); | |
| | | | |
| | | // use default pixel pitch = 1.0 for each coordinate | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | separableMultiDistance(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | bool background); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{separableMultiDistance} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // explicitly specify pixel pitch for each coordinate | | // explicitly specify pixel pitch for each coordinate | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class Array> | | class DestIterator, class DestAccessor, class Array> | |
| void | | void | |
| separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcA
ccessor src, | | separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcA
ccessor src, | |
| DestIterator d, DestAccessor dest, | | DestIterator d, DestAccessor dest, | |
| bool background, | | bool background, | |
| Array const & pixelPitch); | | Array const & pixelPitch); | |
| | | | |
| skipping to change at line 460 | | skipping to change at line 538 | |
| // use default pixel pitch = 1.0 for each coordinate | | // use default pixel pitch = 1.0 for each coordinate | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| separableMultiDistance(SrcIterator siter, SrcShape const & shape, S
rcAccessor src, | | separableMultiDistance(SrcIterator siter, SrcShape const & shape, S
rcAccessor src, | |
| DestIterator diter, DestAccessor dest, | | DestIterator diter, DestAccessor dest, | |
| bool background); | | bool background); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // explicitly specify pixel pitch for each coordinate | | // explicitly specify pixel pitch for each coordinate | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class Array> | | class DestIterator, class DestAccessor, class Array> | |
| void | | void | |
| separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccessor>
const & source, | | separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccessor>
const & source, | |
| pair<DestIterator, DestAccessor> const & de
st, | | pair<DestIterator, DestAccessor> const & de
st, | |
| bool background, | | bool background, | |
| | | | |
| skipping to change at line 483 | | skipping to change at line 560 | |
| // use default pixel pitch = 1.0 for each coordinate | | // use default pixel pitch = 1.0 for each coordinate | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| separableMultiDistance(triple<SrcIterator, SrcShape, SrcAccessor> c
onst & source, | | separableMultiDistance(triple<SrcIterator, SrcShape, SrcAccessor> c
onst & source, | |
| pair<DestIterator, DestAccessor> const & des
t, | | pair<DestIterator, DestAccessor> const & des
t, | |
| bool background); | | bool background); | |
| | | | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| This function performs a Euclidean distance transform on the given | | This function performs a Euclidean distance transform on the given | |
| multi-dimensional array. It simply calls \ref separableMultiDistSquared
() | | multi-dimensional array. It simply calls \ref separableMultiDistSquared
() | |
| and takes the pixel-wise square root of the result. See \ref separableM
ultiDistSquared() | | and takes the pixel-wise square root of the result. See \ref separableM
ultiDistSquared() | |
| for more documentation. | | for more documentation. | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_distance.hxx\> | | <b>\#include</b> \<vigra/multi_distance.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| MultiArray<3, unsigned char>::size_type shape(width, height, depth); | | Shape3 shape(width, height, depth); | |
| MultiArray<3, unsigned char> source(shape); | | MultiArray<3, unsigned char> source(shape); | |
| MultiArray<3, float> dest(shape); | | MultiArray<3, float> dest(shape); | |
| ... | | ... | |
| | | | |
|
| // Calculate Euclidean distance squared for all background pixels | | // Calculate Euclidean distance for all background pixels | |
| separableMultiDistance(srcMultiArrayRange(source), destMultiArray(dest) | | separableMultiDistance(source, dest, true); | |
| , true); | | | |
| \endcode | | \endcode | |
| | | | |
| \see vigra::distanceTransform(), vigra::separableMultiDistSquared() | | \see vigra::distanceTransform(), vigra::separableMultiDistSquared() | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void separableMultiDistance) | | doxygen_overloaded_function(template <...> void separableMultiDistance) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, class Array> | | class DestIterator, class DestAccessor, class Array> | |
| void separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAcce
ssor src, | | void separableMultiDistance( SrcIterator s, SrcShape const & shape, SrcAcce
ssor src, | |
| DestIterator d, DestAccessor dest, bool backgr
ound, | | DestIterator d, DestAccessor dest, bool backgr
ound, | |
| | | | |
| skipping to change at line 553 | | skipping to change at line 632 | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | | inline void separableMultiDistance( triple<SrcIterator, SrcShape, SrcAccess
or> const & source, | |
| pair<DestIterator, DestAccessor> const
& dest, bool background) | | pair<DestIterator, DestAccessor> const
& dest, bool background) | |
| { | | { | |
| separableMultiDistance( source.first, source.second, source.third, | | separableMultiDistance( source.first, source.second, source.third, | |
| dest.first, dest.second, background ); | | dest.first, dest.second, background ); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, class Array> | |
| | | inline void | |
| | | separableMultiDistance(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | bool background, | |
| | | Array const & pixelPitch) | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "separableMultiDistance(): shape mismatch between input and output. | |
| | | "); | |
| | | separableMultiDistance( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), background, pixelPitch ); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | separableMultiDistance(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | bool background) | |
| | | { | |
| | | vigra_precondition(source.shape() == dest.shape(), | |
| | | "separableMultiDistance(): shape mismatch between input and output. | |
| | | "); | |
| | | separableMultiDistance( srcMultiArrayRange(source), | |
| | | destMultiArray(dest), background ); | |
| | | } | |
| | | | |
| | | //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% BoundaryDistanceTransform %%%%% | |
| | | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
| | | | |
| | | //rewrite labeled data and work with separableMultiDist | |
| | | namespace lemon_graph { | |
| | | | |
| | | template <class Graph, class T1Map, class T2Map> | |
| | | void | |
| | | markRegionBoundaries(Graph const & g, | |
| | | T1Map const & labels, | |
| | | T2Map & out) | |
| | | { | |
| | | typedef typename Graph::NodeIt graph_scanner; | |
| | | typedef typename Graph::OutBackArcIt neighbor_iterator; | |
| | | | |
| | | //find faces | |
| | | for (graph_scanner node(g); node != INVALID; ++node) | |
| | | { | |
| | | typename T1Map::value_type center = labels[*node]; | |
| | | | |
| | | for (neighbor_iterator arc(g, node); arc != INVALID; ++arc) | |
| | | { | |
| | | // set adjacent nodes with different labels to 1 | |
| | | if(center != labels[g.target(*arc)]) | |
| | | { | |
| | | out[*node] = 1; | |
| | | out[g.target(*arc)] = 1; | |
| | | } | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| | | } //-- namspace lemon_graph | |
| | | | |
| | | doxygen_overloaded_function(template <...> unsigned int markRegionBoundarie | |
| | | s) | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | markRegionBoundaries(MultiArrayView<N, T1, S1> const & labels, | |
| | | MultiArrayView<N, T2, S2> out, | |
| | | NeighborhoodType neighborhood=DirectNeighborhood) | |
| | | { | |
| | | vigra_precondition(labels.shape() == out.shape(), | |
| | | "markRegionBoundaries(): shape mismatch between input and output.") | |
| | | ; | |
| | | | |
| | | GridGraph<N, undirected_tag> graph(labels.shape(), neighborhood); | |
| | | | |
| | | lemon_graph::markRegionBoundaries(graph, labels, out); | |
| | | } | |
| | | | |
| | | //MultiDistance which works directly on labeled data | |
| | | | |
| | | namespace detail | |
| | | { | |
| | | | |
| | | /********************************************************/ | |
| | | /* */ | |
| | | /* boundaryDistParabola */ | |
| | | /* */ | |
| | | /********************************************************/ | |
| | | | |
| | | template <class DestIterator, class LabelIterator> | |
| | | void | |
| | | boundaryDistParabola(DestIterator is, DestIterator iend, | |
| | | LabelIterator ilabels, | |
| | | double dmax, | |
| | | bool array_border_is_active=false) | |
| | | { | |
| | | // We assume that the data in the input is distance squared and treat i | |
| | | t as such | |
| | | double w = iend - is; | |
| | | if(w <= 0) | |
| | | return; | |
| | | | |
| | | DestIterator id = is; | |
| | | typedef typename LabelIterator::value_type LabelType; | |
| | | typedef typename DestIterator::value_type DestType; | |
| | | typedef detail::DistParabolaStackEntry<DestType> Influence; | |
| | | typedef std::vector<Influence> Stack; | |
| | | | |
| | | double apex_height = array_border_is_active | |
| | | ? 0.0 | |
| | | : dmax; | |
| | | Stack _stack(1, Influence(apex_height, 0.0, -1.0, w)); | |
| | | LabelType current_label = *ilabels; | |
| | | for(double begin = 0.0, current = 0.0; current <= w; ++ilabels, ++is, + | |
| | | +current) | |
| | | { | |
| | | apex_height = (current < w) | |
| | | ? (current_label == *ilabels) | |
| | | ? *is | |
| | | : 0.0 | |
| | | : array_border_is_active | |
| | | ? 0.0 | |
| | | : dmax; | |
| | | while(true) | |
| | | { | |
| | | Influence & s = _stack.back(); | |
| | | double diff = current - s.center; | |
| | | double intersection = current + (apex_height - s.apex_height - | |
| | | sq(diff)) / (2.0 * diff); | |
| | | | |
| | | if(intersection < s.left) // previous parabola has no influence | |
| | | { | |
| | | _stack.pop_back(); | |
| | | if(_stack.empty()) | |
| | | intersection = begin; // new parabola is valid for enti | |
| | | re present segment | |
| | | else | |
| | | continue; // try new top of stack without advancing to | |
| | | next pixel | |
| | | } | |
| | | else if(intersection < s.right) | |
| | | { | |
| | | s.right = intersection; | |
| | | } | |
| | | if(intersection < w) | |
| | | _stack.push_back(Influence(apex_height, intersection, curre | |
| | | nt, w)); | |
| | | if(current < w && current_label == *ilabels) | |
| | | break; // finished present pixel, advance to next one | |
| | | | |
| | | // label changed => finalize the current segment | |
| | | typename Stack::iterator it = _stack.begin(); | |
| | | for(double c = begin; c < current; ++c, ++id) | |
| | | { | |
| | | while(c >= it->right) | |
| | | ++it; | |
| | | *id = sq(c - it->center) + it->apex_height; | |
| | | } | |
| | | if(current == w) | |
| | | break; // stop when this was the last segment | |
| | | | |
| | | // initialize the new segment | |
| | | begin = current; | |
| | | current_label = *ilabels; | |
| | | apex_height = *is; | |
| | | Stack(1, Influence(0.0, begin-1.0, begin-1.0, w)).swap(_stack); | |
| | | // don't advance to next pixel here, because the present pixel | |
| | | must also | |
| | | // be analysed in the context of the new segment | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| | | /********************************************************/ | |
| | | /* */ | |
| | | /* internalBoundaryMultiArrayDist */ | |
| | | /* */ | |
| | | /********************************************************/ | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | internalBoundaryMultiArrayDist( | |
| | | MultiArrayView<N, T1, S1> const & labels, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | double dmax, bool array_border_is_active=false) | |
| | | { | |
| | | typedef typename MultiArrayView<N, T1, S1>::const_traverser LabelIterat | |
| | | or; | |
| | | typedef typename MultiArrayView<N, T2, S2>::traverser DestIterator; | |
| | | typedef MultiArrayNavigator<LabelIterator, N> LabelNavigator; | |
| | | typedef MultiArrayNavigator<DestIterator, N> DNavigator; | |
| | | | |
| | | dest = dmax; | |
| | | for( int d = 0; d < N; ++d ) | |
| | | { | |
| | | LabelNavigator lnav( labels.traverser_begin(), labels.shape(), d ); | |
| | | DNavigator dnav( dest.traverser_begin(), dest.shape(), d ); | |
| | | | |
| | | for( ; dnav.hasMore(); dnav++, lnav++ ) | |
| | | { | |
| | | boundaryDistParabola(dnav.begin(), dnav.end(), | |
| | | lnav.begin(), | |
| | | dmax, array_border_is_active); | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| | | } // namespace detail | |
| | | | |
| | | /** \brief Specify which boundary is used for boundaryMultiDistance(). | |
| | | | |
| | | */ | |
| | | enum BoundaryDistanceTag { | |
| | | OuterBoundary, ///< Pixels just outside of each region | |
| | | InterpixelBoundary, ///< Half-integer points between pixels of differen | |
| | | t labels | |
| | | InnerBoundary ///< Pixels just inside of each region | |
| | | }; | |
| | | | |
| | | /********************************************************/ | |
| | | /* */ | |
| | | /* boundaryMultiDistance */ | |
| | | /* */ | |
| | | /********************************************************/ | |
| | | | |
| | | /** \brief Euclidean distance to the implicit boundaries of a multi-dimensi | |
| | | onal label array. | |
| | | | |
| | | <b> Declarations:</b> | |
| | | | |
| | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | boundaryMultiDistance(MultiArrayView<N, T1, S1> const & labels, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | bool array_border_is_active=false, | |
| | | BoundaryDistanceTag boundary=InterpixelBounda | |
| | | ry); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | This function computes the distance transform of a labeled image <i>sim | |
| | | ultaneously</i> | |
| | | for all regions. Depending on the requested type of \a boundary, three | |
| | | modes | |
| | | are supported: | |
| | | <ul> | |
| | | <li><tt>OuterBoundary</tt>: In each region, compute the distance to the | |
| | | nearest pixel not | |
| | | belonging to that regions. This is the same as if a normal d | |
| | | istance transform | |
| | | where applied to a binary image containing just this region. | |
| | | </li> | |
| | | <li><tt>InterpixelBoundary</tt> (default): Like <tt>OuterBoundary</tt>, | |
| | | but shift the distance | |
| | | to the interpixel boundary by subtractiong 1/2. This make th | |
| | | e distences consistent | |
| | | accross boundaries.</li> | |
| | | <li><tt>InnerBoundary</tt>: In each region, compute the distance to the | |
| | | nearest pixel in the | |
| | | region which is adjacent to the boundary. </li> | |
| | | </ul> | |
| | | If <tt>array_border_is_active=true</tt>, the | |
| | | outer border of the array (i.e. the interpixel boundary between the arr | |
| | | ay | |
| | | and the infinite region) is also used. Otherwise (the default), regions | |
| | | touching the array border are treated as if they extended to infinity. | |
| | | | |
| | | <b> Usage:</b> | |
| | | | |
| | | <b>\#include</b> \<vigra/multi_distance.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | Shape3 shape(width, height, depth); | |
| | | MultiArray<3, unsigned char> source(shape); | |
| | | MultiArray<3, UInt32> labels(shape); | |
| | | MultiArray<3, float> dest(shape); | |
| | | ... | |
| | | | |
| | | // find regions (interpixel boundaries are implied) | |
| | | labelMultiArray(source, labels); | |
| | | | |
| | | // Calculate Euclidean distance to interpixel boundary for all pixels | |
| | | boundaryMultiDistance(labels, dest); | |
| | | \endcode | |
| | | | |
| | | \see vigra::distanceTransform(), vigra::separableMultiDistance() | |
| | | */ | |
| | | doxygen_overloaded_function(template <...> void boundaryMultiDistance) | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | boundaryMultiDistance(MultiArrayView<N, T1, S1> const & labels, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | bool array_border_is_active=false, | |
| | | BoundaryDistanceTag boundary=InterpixelBoundary) | |
| | | { | |
| | | vigra_precondition(labels.shape() == dest.shape(), | |
| | | "boundaryMultiDistance(): shape mismatch between input and output." | |
| | | ); | |
| | | | |
| | | using namespace vigra::functor; | |
| | | | |
| | | if(boundary == InnerBoundary) | |
| | | { | |
| | | MultiArray<N, unsigned char> boundaries(labels.shape()); | |
| | | | |
| | | markRegionBoundaries(labels, boundaries, IndirectNeighborhood); | |
| | | if(array_border_is_active) | |
| | | initMultiArrayBorder(boundaries, 1, 1); | |
| | | separableMultiDistance(boundaries, dest, true); | |
| | | } | |
| | | else | |
| | | { | |
| | | T2 offset = 0.0; | |
| | | | |
| | | if(boundary == InterpixelBoundary) | |
| | | { | |
| | | vigra_precondition(!NumericTraits<T2>::isIntegral::value, | |
| | | "boundaryMultiDistance(..., InterpixelBoundary): output pix | |
| | | el type must be float or double."); | |
| | | offset = T2(0.5); | |
| | | } | |
| | | double dmax = squaredNorm(labels.shape()) + N; | |
| | | if(dmax > double(NumericTraits<T2>::max())) | |
| | | { | |
| | | // need a temporary array to avoid overflows | |
| | | typedef typename NumericTraits<T2>::RealPromote Real; | |
| | | MultiArray<N, Real> tmpArray(labels.shape()); | |
| | | detail::internalBoundaryMultiArrayDist(labels, tmpArray, | |
| | | dmax, array_border_is | |
| | | _active); | |
| | | transformMultiArray(tmpArray, dest, sqrt(Arg1()) - Param(offset | |
| | | ) ); | |
| | | } | |
| | | else | |
| | | { | |
| | | // can work directly on the destination array | |
| | | detail::internalBoundaryMultiArrayDist(labels, dest, dmax, arra | |
| | | y_border_is_active); | |
| | | transformMultiArray(dest, dest, sqrt(Arg1()) - Param(offset) ); | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } //-- namespace vigra | | } //-- namespace vigra | |
| | | | |
| #endif //-- VIGRA_MULTI_DISTANCE_HXX | | #endif //-- VIGRA_MULTI_DISTANCE_HXX | |
| | | | |
End of changes. 32 change blocks. |
| 55 lines changed or deleted | | 491 lines changed or added | |
|
| multi_fft.hxx | | multi_fft.hxx | |
| | | | |
| skipping to change at line 41 | | skipping to change at line 41 | |
| /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | | /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | |
| /* OTHER DEALINGS IN THE SOFTWARE. */ | | /* OTHER DEALINGS IN THE SOFTWARE. */ | |
| /* */ | | /* */ | |
| /************************************************************************/ | | /************************************************************************/ | |
| | | | |
| #ifndef VIGRA_MULTI_FFT_HXX | | #ifndef VIGRA_MULTI_FFT_HXX | |
| #define VIGRA_MULTI_FFT_HXX | | #define VIGRA_MULTI_FFT_HXX | |
| | | | |
| #include "fftw3.hxx" | | #include "fftw3.hxx" | |
| #include "multi_array.hxx" | | #include "multi_array.hxx" | |
|
| | | #include "multi_math.hxx" | |
| #include "navigator.hxx" | | #include "navigator.hxx" | |
| #include "copyimage.hxx" | | #include "copyimage.hxx" | |
|
| | | #include "threading.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* Fourier Transform */ | | /* Fourier Transform */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \addtogroup FourierTransform | | /** \addtogroup FourierTransform | |
| | | | |
| skipping to change at line 169 | | skipping to change at line 171 | |
| | | | |
| template <unsigned int N, class T, class C> | | template <unsigned int N, class T, class C> | |
| inline void moveDCToHalfspaceUpperLeft(MultiArrayView<N, T, C> a) | | inline void moveDCToHalfspaceUpperLeft(MultiArrayView<N, T, C> a) | |
| { | | { | |
| detail::moveDCToUpperLeftImpl(a, 1); | | detail::moveDCToUpperLeftImpl(a, 1); | |
| } | | } | |
| | | | |
| namespace detail | | namespace detail | |
| { | | { | |
| | | | |
|
| | | #ifndef VIGRA_SINGLE_THREADED | |
| | | | |
| | | template <int DUMMY=0> | |
| | | class FFTWLock | |
| | | { | |
| | | public: | |
| | | threading::lock_guard<threading::mutex> guard_; | |
| | | | |
| | | FFTWLock() | |
| | | : guard_(plan_mutex_) | |
| | | {} | |
| | | | |
| | | static threading::mutex plan_mutex_; | |
| | | }; | |
| | | | |
| | | template <int DUMMY> | |
| | | threading::mutex FFTWLock<DUMMY>::plan_mutex_; | |
| | | | |
| | | #else // VIGRA_SINGLE_THREADED | |
| | | | |
| | | template <int DUMMY=0> | |
| | | class FFTWLock | |
| | | { | |
| | | public: | |
| | | | |
| | | FFTWLock() | |
| | | {} | |
| | | }; | |
| | | | |
| | | #endif // not VIGRA_SINGLE_THREADED | |
| | | | |
| inline fftw_plan | | inline fftw_plan | |
| fftwPlanCreate(unsigned int N, int* shape, | | fftwPlanCreate(unsigned int N, int* shape, | |
| FFTWComplex<double> * in, int* instrides, int instep, | | FFTWComplex<double> * in, int* instrides, int instep, | |
| FFTWComplex<double> * out, int* outstrides, int outstep, | | FFTWComplex<double> * out, int* outstrides, int outstep, | |
| int sign, unsigned int planner_flags) | | int sign, unsigned int planner_flags) | |
| { | | { | |
| return fftw_plan_many_dft(N, shape, 1, | | return fftw_plan_many_dft(N, shape, 1, | |
| (fftw_complex *)in, instrides, instep, 0, | | (fftw_complex *)in, instrides, instep, 0, | |
| (fftw_complex *)out, outstrides, outstep, 0, | | (fftw_complex *)out, outstrides, outstep, 0, | |
| sign, planner_flags); | | sign, planner_flags); | |
| | | | |
| skipping to change at line 367 | | skipping to change at line 400 | |
| { | | { | |
| fftwl_execute_dft_r2c(plan, in, (fftwl_complex *)out); | | fftwl_execute_dft_r2c(plan, in, (fftwl_complex *)out); | |
| } | | } | |
| | | | |
| inline void | | inline void | |
| fftwPlanExecute(fftwl_plan plan, FFTWComplex<long double> * in, long doubl
e * out) | | fftwPlanExecute(fftwl_plan plan, FFTWComplex<long double> * in, long doubl
e * out) | |
| { | | { | |
| fftwl_execute_dft_c2r(plan, (fftwl_complex *)in, out); | | fftwl_execute_dft_c2r(plan, (fftwl_complex *)in, out); | |
| } | | } | |
| | | | |
|
| inline | | template <int DUMMY> | |
| int fftwPaddingSize(int s) | | struct FFTWPaddingSize | |
| { | | { | |
|
| | | static const int size = 1330; | |
| | | static const int evenSize = 1063; | |
| | | static int goodSizes[size]; | |
| | | static int goodEvenSizes[evenSize]; | |
| | | | |
| | | static inline int find(int s) | |
| | | { | |
| | | if(s <= 0 || s >= goodSizes[size-1]) | |
| | | return s; | |
| | | // find the smallest padding size that is at least as large as 's' | |
| | | int * upperBound = std::upper_bound(goodSizes, goodSizes+size, s); | |
| | | if(upperBound > goodSizes && upperBound[-1] == s) | |
| | | return s; | |
| | | else | |
| | | return *upperBound; | |
| | | } | |
| | | | |
| | | static inline int findEven(int s) | |
| | | { | |
| | | if(s <= 0 || s >= goodEvenSizes[evenSize-1]) | |
| | | return s; | |
| | | // find the smallest padding size that is at least as large as 's' | |
| | | int * upperBound = std::upper_bound(goodEvenSizes, goodEvenSizes+ev | |
| | | enSize, s); | |
| | | if(upperBound > goodEvenSizes && upperBound[-1] == s) | |
| | | return s; | |
| | | else | |
| | | return *upperBound; | |
| | | } | |
| | | }; | |
| | | | |
| // Image sizes where FFTW is fast. The list contains all | | // Image sizes where FFTW is fast. The list contains all | |
| // numbers less than 100000 whose prime decomposition is of the form | | // numbers less than 100000 whose prime decomposition is of the form | |
| // 2^a*3^b*5^c*7^d*11^e*13^f, where e+f is either 0 or 1, and the | | // 2^a*3^b*5^c*7^d*11^e*13^f, where e+f is either 0 or 1, and the | |
| // other exponents are arbitrary | | // other exponents are arbitrary | |
|
| static const int size = 1330; | | template <int DUMMY> | |
| static int goodSizes[size] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1 | | int FFTWPaddingSize<DUMMY>::goodSizes[size] = { | |
| 3, 14, 15, 16, | | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, | |
| 18, 20, 21, 22, 24, 25, 26, 27, 28, 30, 32, 33, 35, 36, 39, 40, 42,
44, 45, 48, | | 18, 20, 21, 22, 24, 25, 26, 27, 28, 30, 32, 33, 35, 36, 39, 40, 42,
44, 45, 48, | |
| 49, 50, 52, 54, 55, 56, 60, 63, 64, 65, 66, 70, 72, 75, 77, 78, 80,
81, | | 49, 50, 52, 54, 55, 56, 60, 63, 64, 65, 66, 70, 72, 75, 77, 78, 80,
81, | |
| 84, 88, 90, 91, 96, 98, 99, 100, 104, 105, 108, 110, 112, 117, 120,
125, | | 84, 88, 90, 91, 96, 98, 99, 100, 104, 105, 108, 110, 112, 117, 120,
125, | |
| 126, 128, 130, 132, 135, 140, 144, 147, 150, 154, 156, 160, 162, 16
5, | | 126, 128, 130, 132, 135, 140, 144, 147, 150, 154, 156, 160, 162, 16
5, | |
| 168, 175, 176, 180, 182, 189, 192, 195, 196, 198, 200, 208, 210, 21
6, | | 168, 175, 176, 180, 182, 189, 192, 195, 196, 198, 200, 208, 210, 21
6, | |
| 220, 224, 225, 231, 234, 240, 243, 245, 250, 252, 256, 260, 264, 27
0, | | 220, 224, 225, 231, 234, 240, 243, 245, 250, 252, 256, 260, 264, 27
0, | |
| 273, 275, 280, 288, 294, 297, 300, 308, 312, 315, 320, 324, 325, 33
0, | | 273, 275, 280, 288, 294, 297, 300, 308, 312, 315, 320, 324, 325, 33
0, | |
| 336, 343, 350, 351, 352, 360, 364, 375, 378, 384, 385, 390, 392, 39
6, | | 336, 343, 350, 351, 352, 360, 364, 375, 378, 384, 385, 390, 392, 39
6, | |
| 400, 405, 416, 420, 432, 440, 441, 448, 450, 455, 462, 468, 480, 48
6, | | 400, 405, 416, 420, 432, 440, 441, 448, 450, 455, 462, 468, 480, 48
6, | |
| 490, 495, 500, 504, 512, 520, 525, 528, 539, 540, 546, 550, 560, 56
7, | | 490, 495, 500, 504, 512, 520, 525, 528, 539, 540, 546, 550, 560, 56
7, | |
| | | | |
| skipping to change at line 494 | | skipping to change at line 558 | |
| 78000, 78125, 78400, 78624, 78732, 78750, 78848, 78975, 79200, 7923
3, | | 78000, 78125, 78400, 78624, 78732, 78750, 78848, 78975, 79200, 7923
3, | |
| 79380, 79625, 79872, 80000, 80190, 80262, 80640, 80850, 81000, 8125
0, | | 79380, 79625, 79872, 80000, 80190, 80262, 80640, 80850, 81000, 8125
0, | |
| 81536, 81648, 81900, 81920, 82320, 82500, 82944, 83160, 83200, 8334
9, | | 81536, 81648, 81900, 81920, 82320, 82500, 82944, 83160, 83200, 8334
9, | |
| 84000, 84035, 84240, 84375, 84480, 84672, 85050, 85293, 85536, 8575
0, | | 84000, 84035, 84240, 84375, 84480, 84672, 85050, 85293, 85536, 8575
0, | |
| 85995, 86016, 86240, 86400, 86436, 86625, 87318, 87360, 87480, 8750
0, | | 85995, 86016, 86240, 86400, 86436, 86625, 87318, 87360, 87480, 8750
0, | |
| 87750, 87808, 88000, 88200, 88452, 88704, 89100, 89180, 89600, 8985
6, | | 87750, 87808, 88000, 88200, 88452, 88704, 89100, 89180, 89600, 8985
6, | |
| 90000, 90112, 90552, 90720, 91000, 91125, 91728, 91854, 91875, 9216
0, | | 90000, 90112, 90552, 90720, 91000, 91125, 91728, 91854, 91875, 9216
0, | |
| 92400, 92610, 93184, 93312, 93555, 93600, 93639, 93750, 94080, 9432
5, | | 92400, 92610, 93184, 93312, 93555, 93600, 93639, 93750, 94080, 9432
5, | |
| 94500, 94770, 95040, 95256, 95550, 96000, 96040, 96228, 96250, 9676
8, | | 94500, 94770, 95040, 95256, 95550, 96000, 96040, 96228, 96250, 9676
8, | |
| 97020, 97200, 97500, 98000, 98280, 98304, 98415, 98560, 98784, 9900
0, | | 97020, 97200, 97500, 98000, 98280, 98304, 98415, 98560, 98784, 9900
0, | |
|
| 99225, 99792, 99840 }; | | 99225, 99792, 99840 | |
| | | }; | |
| if(s <= 0 || s >= goodSizes[size-1]) | | | |
| return s; | | | |
| // find the smallest padding size that is at least as large as 's' | | | |
| int * upperBound = std::upper_bound(goodSizes, goodSizes+size, s); | | | |
| if(upperBound > goodSizes && upperBound[-1] == s) | | | |
| return s; | | | |
| else | | | |
| return *upperBound; | | | |
| } | | | |
| | | | |
|
| inline | | template <int DUMMY> | |
| int fftwEvenPaddingSize(int s) | | int FFTWPaddingSize<DUMMY>::goodEvenSizes[evenSize] = { | |
| { | | 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, | |
| // Image sizes where FFTW is fast. The list contains all even | | | |
| // numbers less than 100000 whose prime decomposition is of the form | | | |
| // 2^a*3^b*5^c*7^d*11^e*13^f, where a >= 1, e+f is either 0 or 1, and t | | | |
| he | | | |
| // other exponents are arbitrary | | | |
| static const int size = 1063; | | | |
| static int goodSizes[size] = { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, | | | |
| 24, 26, 28, 30, 32, 36, 40, 42, 44, 48, 50, 52, 54, 56, 60, 64, 66,
70, | | 24, 26, 28, 30, 32, 36, 40, 42, 44, 48, 50, 52, 54, 56, 60, 64, 66,
70, | |
| 72, 78, 80, 84, 88, 90, 96, 98, 100, 104, 108, 110, 112, 120, 126,
128, | | 72, 78, 80, 84, 88, 90, 96, 98, 100, 104, 108, 110, 112, 120, 126,
128, | |
| 130, 132, 140, 144, 150, 154, 156, 160, 162, 168, 176, 180, 182, 19
2, | | 130, 132, 140, 144, 150, 154, 156, 160, 162, 168, 176, 180, 182, 19
2, | |
| 196, 198, 200, 208, 210, 216, 220, 224, 234, 240, 250, 252, 256, 26
0, | | 196, 198, 200, 208, 210, 216, 220, 224, 234, 240, 250, 252, 256, 26
0, | |
| 264, 270, 280, 288, 294, 300, 308, 312, 320, 324, 330, 336, 350, 35
2, | | 264, 270, 280, 288, 294, 300, 308, 312, 320, 324, 330, 336, 350, 35
2, | |
| 360, 364, 378, 384, 390, 392, 396, 400, 416, 420, 432, 440, 448, 45
0, | | 360, 364, 378, 384, 390, 392, 396, 400, 416, 420, 432, 440, 448, 45
0, | |
| 462, 468, 480, 486, 490, 500, 504, 512, 520, 528, 540, 546, 550, 56
0, | | 462, 468, 480, 486, 490, 500, 504, 512, 520, 528, 540, 546, 550, 56
0, | |
| 576, 588, 594, 600, 616, 624, 630, 640, 648, 650, 660, 672, 686, 70
0, | | 576, 588, 594, 600, 616, 624, 630, 640, 648, 650, 660, 672, 686, 70
0, | |
| 702, 704, 720, 728, 750, 756, 768, 770, 780, 784, 792, 800, 810, 83
2, | | 702, 704, 720, 728, 750, 756, 768, 770, 780, 784, 792, 800, 810, 83
2, | |
| 840, 864, 880, 882, 896, 900, 910, 924, 936, 960, 972, 980, 990, 10
00, | | 840, 864, 880, 882, 896, 900, 910, 924, 936, 960, 972, 980, 990, 10
00, | |
| | | | |
| skipping to change at line 610 | | skipping to change at line 659 | |
| 73500, 73710, 73728, 73920, 74088, 74250, 74844, 74880, 75000, 7526
4, | | 73500, 73710, 73728, 73920, 74088, 74250, 74844, 74880, 75000, 7526
4, | |
| 75460, 75600, 75816, 76032, 76440, 76800, 76832, 77000, 77616, 7776
0, | | 75460, 75600, 75816, 76032, 76440, 76800, 76832, 77000, 77616, 7776
0, | |
| 78000, 78400, 78624, 78732, 78750, 78848, 79200, 79380, 79872, 8000
0, | | 78000, 78400, 78624, 78732, 78750, 78848, 79200, 79380, 79872, 8000
0, | |
| 80190, 80262, 80640, 80850, 81000, 81250, 81536, 81648, 81900, 8192
0, | | 80190, 80262, 80640, 80850, 81000, 81250, 81536, 81648, 81900, 8192
0, | |
| 82320, 82500, 82944, 83160, 83200, 84000, 84240, 84480, 84672, 8505
0, | | 82320, 82500, 82944, 83160, 83200, 84000, 84240, 84480, 84672, 8505
0, | |
| 85536, 85750, 86016, 86240, 86400, 86436, 87318, 87360, 87480, 8750
0, | | 85536, 85750, 86016, 86240, 86400, 86436, 87318, 87360, 87480, 8750
0, | |
| 87750, 87808, 88000, 88200, 88452, 88704, 89100, 89180, 89600, 8985
6, | | 87750, 87808, 88000, 88200, 88452, 88704, 89100, 89180, 89600, 8985
6, | |
| 90000, 90112, 90552, 90720, 91000, 91728, 91854, 92160, 92400, 9261
0, | | 90000, 90112, 90552, 90720, 91000, 91728, 91854, 92160, 92400, 9261
0, | |
| 93184, 93312, 93600, 93750, 94080, 94500, 94770, 95040, 95256, 9555
0, | | 93184, 93312, 93600, 93750, 94080, 94500, 94770, 95040, 95256, 9555
0, | |
| 96000, 96040, 96228, 96250, 96768, 97020, 97200, 97500, 98000, 9828
0, | | 96000, 96040, 96228, 96250, 96768, 97020, 97200, 97500, 98000, 9828
0, | |
|
| 98304, 98560, 98784, 99000, 99792, 99840 }; | | 98304, 98560, 98784, 99000, 99792, 99840 | |
| | | }; | |
| if(s <= 0 || s >= goodSizes[size-1]) | | | |
| return s; | | | |
| // find the smallest padding size that is at least as large as 's' | | | |
| int * upperBound = std::upper_bound(goodSizes, goodSizes+size, s); | | | |
| if(upperBound > goodSizes && upperBound[-1] == s) | | | |
| return s; | | | |
| else | | | |
| return *upperBound; | | | |
| } | | | |
| | | | |
| template <int M> | | template <int M> | |
| struct FFTEmbedKernel | | struct FFTEmbedKernel | |
| { | | { | |
| template <unsigned int N, class Real, class C, class Shape> | | template <unsigned int N, class Real, class C, class Shape> | |
| static void | | static void | |
| exec(MultiArrayView<N, Real, C> & out, Shape const & kernelShape, | | exec(MultiArrayView<N, Real, C> & out, Shape const & kernelShape, | |
| Shape & srcPoint, Shape & destPoint, bool copyIt) | | Shape & srcPoint, Shape & destPoint, bool copyIt) | |
| { | | { | |
| for(srcPoint[M]=0; srcPoint[M]<kernelShape[M]; ++srcPoint[M]) | | for(srcPoint[M]=0; srcPoint[M]<kernelShape[M]; ++srcPoint[M]) | |
| | | | |
| skipping to change at line 734 | | skipping to change at line 774 | |
| } | | } | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| template <class T, int N> | | template <class T, int N> | |
| TinyVector<T, N> | | TinyVector<T, N> | |
| fftwBestPaddedShape(TinyVector<T, N> shape) | | fftwBestPaddedShape(TinyVector<T, N> shape) | |
| { | | { | |
| for(unsigned int k=0; k<N; ++k) | | for(unsigned int k=0; k<N; ++k) | |
|
| shape[k] = detail::fftwPaddingSize(shape[k]); | | shape[k] = detail::FFTWPaddingSize<0>::find(shape[k]); | |
| return shape; | | return shape; | |
| } | | } | |
| | | | |
| template <class T, int N> | | template <class T, int N> | |
| TinyVector<T, N> | | TinyVector<T, N> | |
| fftwBestPaddedShapeR2C(TinyVector<T, N> shape) | | fftwBestPaddedShapeR2C(TinyVector<T, N> shape) | |
| { | | { | |
|
| shape[0] = detail::fftwEvenPaddingSize(shape[0]); | | shape[0] = detail::FFTWPaddingSize<0>::findEven(shape[0]); | |
| for(unsigned int k=1; k<N; ++k) | | for(unsigned int k=1; k<N; ++k) | |
|
| shape[k] = detail::fftwPaddingSize(shape[k]); | | shape[k] = detail::FFTWPaddingSize<0>::find(shape[k]); | |
| return shape; | | return shape; | |
| } | | } | |
| | | | |
| /** \brief Find frequency domain shape for a R2C Fourier transform. | | /** \brief Find frequency domain shape for a R2C Fourier transform. | |
| | | | |
| When a real valued array is transformed to the frequency domain, about
half of the | | When a real valued array is transformed to the frequency domain, about
half of the | |
| Fourier coefficients are redundant. The transform can be optimized as a
<a href="http://www.fftw.org/doc/Multi_002dDimensional-DFTs-of-Real-Data.h
tml">R2C | | Fourier coefficients are redundant. The transform can be optimized as a
<a href="http://www.fftw.org/doc/Multi_002dDimensional-DFTs-of-Real-Data.h
tml">R2C | |
| transform</a> that doesn't compute and store the redundant coefficients
. This function | | transform</a> that doesn't compute and store the redundant coefficients
. This function | |
| computes the appropriate frequency domain shape for a given shape in th
e spatial domain. | | computes the appropriate frequency domain shape for a given shape in th
e spatial domain. | |
| It simply replaces <tt>shape[0]</tt> with <tt>shape[0] / 2 + 1</tt>. | | It simply replaces <tt>shape[0]</tt> with <tt>shape[0] / 2 + 1</tt>. | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_fft.hxx\> | | <b>\#include</b> \<vigra/multi_fft.hxx\><br/> | |
| | | Namespace: vigra | |
| */ | | */ | |
| template <class T, int N> | | template <class T, int N> | |
| TinyVector<T, N> | | TinyVector<T, N> | |
| fftwCorrespondingShapeR2C(TinyVector<T, N> shape) | | fftwCorrespondingShapeR2C(TinyVector<T, N> shape) | |
| { | | { | |
| shape[0] = shape[0] / 2 + 1; | | shape[0] = shape[0] / 2 + 1; | |
| return shape; | | return shape; | |
| } | | } | |
| | | | |
| template <class T, int N> | | template <class T, int N> | |
| | | | |
| skipping to change at line 920 | | skipping to change at line 961 | |
| sign = o.sign; | | sign = o.sign; | |
| o.plan = 0; // act like std::auto_ptr | | o.plan = 0; // act like std::auto_ptr | |
| } | | } | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** \brief Destructor. | | /** \brief Destructor. | |
| */ | | */ | |
| ~FFTWPlan() | | ~FFTWPlan() | |
| { | | { | |
|
| | | detail::FFTWLock<> lock; | |
| detail::fftwPlanDestroy(plan); | | detail::fftwPlanDestroy(plan); | |
| } | | } | |
| | | | |
| /** \brief Init a complex-to-complex transform. | | /** \brief Init a complex-to-complex transform. | |
| | | | |
| See the constructor with the same signature for details. | | See the constructor with the same signature for details. | |
| */ | | */ | |
| template <class C1, class C2> | | template <class C1, class C2> | |
| void init(MultiArrayView<N, FFTWComplex<Real>, C1> in, | | void init(MultiArrayView<N, FFTWComplex<Real>, C1> in, | |
| MultiArrayView<N, FFTWComplex<Real>, C2> out, | | MultiArrayView<N, FFTWComplex<Real>, C2> out, | |
| | | | |
| skipping to change at line 1072 | | skipping to change at line 1114 | |
| newOStrides(outs.stride().begin(), outs.stride().end()), | | newOStrides(outs.stride().begin(), outs.stride().end()), | |
| itotal(ins.shape().begin(), ins.shape().end()), | | itotal(ins.shape().begin(), ins.shape().end()), | |
| ototal(outs.shape().begin(), outs.shape().end()); | | ototal(outs.shape().begin(), outs.shape().end()); | |
| | | | |
| for(unsigned int j=1; j<N; ++j) | | for(unsigned int j=1; j<N; ++j) | |
| { | | { | |
| itotal[j] = ins.stride(j-1) / ins.stride(j); | | itotal[j] = ins.stride(j-1) / ins.stride(j); | |
| ototal[j] = outs.stride(j-1) / outs.stride(j); | | ototal[j] = outs.stride(j-1) / outs.stride(j); | |
| } | | } | |
| | | | |
|
| PlanType newPlan = detail::fftwPlanCreate(N, newShape.begin(), | | { | |
| ins.data(), itotal.begin(), ins.stride(N- | | detail::FFTWLock<> lock; | |
| 1), | | PlanType newPlan = detail::fftwPlanCreate(N, newShape.begin(), | |
| outs.data(), ototal.begin(), outs.stride( | | ins.data(), itotal.begin(), ins.strid | |
| N-1), | | e(N-1), | |
| SIGN, planner_flags); | | outs.data(), ototal.begin(), outs.str | |
| detail::fftwPlanDestroy(plan); | | ide(N-1), | |
| plan = newPlan; | | SIGN, planner_flags); | |
| | | detail::fftwPlanDestroy(plan); | |
| | | plan = newPlan; | |
| | | } | |
| | | | |
| shape.swap(newShape); | | shape.swap(newShape); | |
| instrides.swap(newIStrides); | | instrides.swap(newIStrides); | |
| outstrides.swap(newOStrides); | | outstrides.swap(newOStrides); | |
| sign = SIGN; | | sign = SIGN; | |
| } | | } | |
| | | | |
| template <unsigned int N, class Real> | | template <unsigned int N, class Real> | |
| template <class MI, class MO> | | template <class MI, class MO> | |
| void FFTWPlan<N, Real>::executeImpl(MI ins, MO outs) const | | void FFTWPlan<N, Real>::executeImpl(MI ins, MO outs) const | |
| { | | { | |
| | | | |
| skipping to change at line 1411 | | skipping to change at line 1457 | |
| /** \brief Execute a plan to convolve a real array with a real kern
el. | | /** \brief Execute a plan to convolve a real array with a real kern
el. | |
| | | | |
| The array shapes must be the same as in the corresponding init
function | | The array shapes must be the same as in the corresponding init
function | |
| or constructor. However, execute() can be called several times
on | | or constructor. However, execute() can be called several times
on | |
| the same plan, even with different arrays, as long as they have
the appropriate | | the same plan, even with different arrays, as long as they have
the appropriate | |
| shapes. | | shapes. | |
| */ | | */ | |
| template <class C1, class C2, class C3> | | template <class C1, class C2, class C3> | |
| void execute(MultiArrayView<N, Real, C1> in, | | void execute(MultiArrayView<N, Real, C1> in, | |
| MultiArrayView<N, Real, C2> kernel, | | MultiArrayView<N, Real, C2> kernel, | |
|
| MultiArrayView<N, Real, C3> out); | | MultiArrayView<N, Real, C3> out) | |
| | | { | |
| | | executeImpl(in, kernel, out); | |
| | | } | |
| | | | |
| /** \brief Execute a plan to convolve a real array with a complex k
ernel. | | /** \brief Execute a plan to convolve a real array with a complex k
ernel. | |
| | | | |
| The array shapes must be the same as in the corresponding init
function | | The array shapes must be the same as in the corresponding init
function | |
| or constructor. However, execute() can be called several times
on | | or constructor. However, execute() can be called several times
on | |
| the same plan, even with different arrays, as long as they have
the appropriate | | the same plan, even with different arrays, as long as they have
the appropriate | |
| shapes. | | shapes. | |
| */ | | */ | |
| template <class C1, class C2, class C3> | | template <class C1, class C2, class C3> | |
| void execute(MultiArrayView<N, Real, C1> in, | | void execute(MultiArrayView<N, Real, C1> in, | |
| | | | |
| skipping to change at line 1478 | | skipping to change at line 1527 | |
| bool fourierKernel = IsSameType<KernelValue, Complex>::value; | | bool fourierKernel = IsSameType<KernelValue, Complex>::value; | |
| | | | |
| vigra_precondition(realKernel || fourierKernel, | | vigra_precondition(realKernel || fourierKernel, | |
| "FFTWConvolvePlan::executeMany(): kernels have unsuitable valu
e_type."); | | "FFTWConvolvePlan::executeMany(): kernels have unsuitable valu
e_type."); | |
| vigra_precondition((IsSameType<OutValue, Real>::value), | | vigra_precondition((IsSameType<OutValue, Real>::value), | |
| "FFTWConvolvePlan::executeMany(): outputs have unsuitable valu
e_type."); | | "FFTWConvolvePlan::executeMany(): outputs have unsuitable valu
e_type."); | |
| | | | |
| executeManyImpl(in, kernels, kernelsEnd, outs, UseFourierKernel()); | | executeManyImpl(in, kernels, kernelsEnd, outs, UseFourierKernel()); | |
| } | | } | |
| | | | |
|
| private: | | protected: | |
| | | | |
| template <class KernelIterator, class OutIterator> | | template <class KernelIterator, class OutIterator> | |
| Shape checkShapes(Shape in, | | Shape checkShapes(Shape in, | |
| KernelIterator kernels, KernelIterator kernelsEnd, | | KernelIterator kernels, KernelIterator kernelsEnd, | |
| OutIterator outs); | | OutIterator outs); | |
| | | | |
| template <class KernelIterator, class OutIterator> | | template <class KernelIterator, class OutIterator> | |
| Shape checkShapesFourier(Shape in, | | Shape checkShapesFourier(Shape in, | |
| KernelIterator kernels, KernelIterator kernels
End, | | KernelIterator kernels, KernelIterator kernels
End, | |
| OutIterator outs); | | OutIterator outs); | |
| | | | |
| template <class KernelIterator, class OutIterator> | | template <class KernelIterator, class OutIterator> | |
| Shape checkShapesComplex(Shape in, | | Shape checkShapesComplex(Shape in, | |
| KernelIterator kernels, KernelIterator kernels
End, | | KernelIterator kernels, KernelIterator kernels
End, | |
| OutIterator outs); | | OutIterator outs); | |
| | | | |
|
| | | template <class C1, class C2, class C3> | |
| | | void executeImpl(MultiArrayView<N, Real, C1> in, | |
| | | MultiArrayView<N, Real, C2> kernel, | |
| | | MultiArrayView<N, Real, C3> out, | |
| | | bool do_correlation=false); | |
| | | | |
| template <class C1, class KernelIterator, class OutIterator> | | template <class C1, class KernelIterator, class OutIterator> | |
| void | | void | |
| executeManyImpl(MultiArrayView<N, Real, C1> in, | | executeManyImpl(MultiArrayView<N, Real, C1> in, | |
| KernelIterator kernels, KernelIterator kernelsEnd, | | KernelIterator kernels, KernelIterator kernelsEnd, | |
| OutIterator outs, VigraFalseType /* useFourierKernel*/)
; | | OutIterator outs, VigraFalseType /* useFourierKernel*/)
; | |
| | | | |
| template <class C1, class KernelIterator, class OutIterator> | | template <class C1, class KernelIterator, class OutIterator> | |
| void | | void | |
| executeManyImpl(MultiArrayView<N, Real, C1> in, | | executeManyImpl(MultiArrayView<N, Real, C1> in, | |
| KernelIterator kernels, KernelIterator kernelsEnd, | | KernelIterator kernels, KernelIterator kernelsEnd, | |
| | | | |
| skipping to change at line 1603 | | skipping to change at line 1658 | |
| backward_plan = bplan; | | backward_plan = bplan; | |
| fourierArray.swap(newFourierArray); | | fourierArray.swap(newFourierArray); | |
| fourierKernel.swap(newFourierKernel); | | fourierKernel.swap(newFourierKernel); | |
| } | | } | |
| | | | |
| #ifndef DOXYGEN // doxygen documents these functions as free functions | | #ifndef DOXYGEN // doxygen documents these functions as free functions | |
| | | | |
| template <unsigned int N, class Real> | | template <unsigned int N, class Real> | |
| template <class C1, class C2, class C3> | | template <class C1, class C2, class C3> | |
| void | | void | |
|
| FFTWConvolvePlan<N, Real>::execute(MultiArrayView<N, Real, C1> in, | | FFTWConvolvePlan<N, Real>::executeImpl(MultiArrayView<N, Real, C1> in, | |
| MultiArrayView<N, Real, C2> kernel, | | MultiArrayView<N, Real, C2> kernel, | |
| MultiArrayView<N, Real, C3> out) | | MultiArrayView<N, Real, C3> out, | |
| | | bool do_correlation) | |
| { | | { | |
| vigra_precondition(!useFourierKernel, | | vigra_precondition(!useFourierKernel, | |
| "FFTWConvolvePlan::execute(): plan was generated for Fourier kernel,
got spatial kernel."); | | "FFTWConvolvePlan::execute(): plan was generated for Fourier kernel,
got spatial kernel."); | |
| | | | |
| vigra_precondition(in.shape() == out.shape(), | | vigra_precondition(in.shape() == out.shape(), | |
| "FFTWConvolvePlan::execute(): input and output must have the same s
hape."); | | "FFTWConvolvePlan::execute(): input and output must have the same s
hape."); | |
| | | | |
| Shape paddedShape = fftwBestPaddedShapeR2C(in.shape() + kernel.shape()
- Shape(1)), | | Shape paddedShape = fftwBestPaddedShapeR2C(in.shape() + kernel.shape()
- Shape(1)), | |
| diff = paddedShape - in.shape(), | | diff = paddedShape - in.shape(), | |
| left = div(diff, MultiArrayIndex(2)), | | left = div(diff, MultiArrayIndex(2)), | |
| | | | |
| skipping to change at line 1627 | | skipping to change at line 1683 | |
| | | | |
| vigra_precondition(paddedShape == realArray.shape(), | | vigra_precondition(paddedShape == realArray.shape(), | |
| "FFTWConvolvePlan::execute(): shape mismatch between input and plan.
"); | | "FFTWConvolvePlan::execute(): shape mismatch between input and plan.
"); | |
| | | | |
| detail::fftEmbedArray(in, realArray); | | detail::fftEmbedArray(in, realArray); | |
| forward_plan.execute(realArray, fourierArray); | | forward_plan.execute(realArray, fourierArray); | |
| | | | |
| detail::fftEmbedKernel(kernel, realKernel); | | detail::fftEmbedKernel(kernel, realKernel); | |
| forward_plan.execute(realKernel, fourierKernel); | | forward_plan.execute(realKernel, fourierKernel); | |
| | | | |
|
| fourierArray *= fourierKernel; | | if(do_correlation) | |
| | | { | |
| | | using namespace multi_math; | |
| | | fourierArray *= conj(fourierKernel); | |
| | | } | |
| | | else | |
| | | { | |
| | | fourierArray *= fourierKernel; | |
| | | } | |
| | | | |
| backward_plan.execute(fourierArray, realArray); | | backward_plan.execute(fourierArray, realArray); | |
| | | | |
| out = realArray.subarray(left, right); | | out = realArray.subarray(left, right); | |
| } | | } | |
| | | | |
| template <unsigned int N, class Real> | | template <unsigned int N, class Real> | |
| template <class C1, class C2, class C3> | | template <class C1, class C2, class C3> | |
| void | | void | |
| FFTWConvolvePlan<N, Real>::execute(MultiArrayView<N, Real, C1> in, | | FFTWConvolvePlan<N, Real>::execute(MultiArrayView<N, Real, C1> in, | |
|
| MultiArrayView<N, FFTWComplex<Real>, C2 | | MultiArrayView<N, FFTWComplex<Real>, C2> | |
| > kernel, | | kernel, | |
| MultiArrayView<N, Real, C3> out) | | MultiArrayView<N, Real, C3> out) | |
| { | | { | |
| vigra_precondition(useFourierKernel, | | vigra_precondition(useFourierKernel, | |
| "FFTWConvolvePlan::execute(): plan was generated for spatial kernel,
got Fourier kernel."); | | "FFTWConvolvePlan::execute(): plan was generated for spatial kernel,
got Fourier kernel."); | |
| | | | |
| vigra_precondition(in.shape() == out.shape(), | | vigra_precondition(in.shape() == out.shape(), | |
| "FFTWConvolvePlan::execute(): input and output must have the same s
hape."); | | "FFTWConvolvePlan::execute(): input and output must have the same s
hape."); | |
| | | | |
| vigra_precondition(kernel.shape() == fourierArray.shape(), | | vigra_precondition(kernel.shape() == fourierArray.shape(), | |
| "FFTWConvolvePlan::execute(): shape mismatch between kernel and plan
."); | | "FFTWConvolvePlan::execute(): shape mismatch between kernel and plan
."); | |
| | | | |
| | | | |
| skipping to change at line 1922 | | skipping to change at line 1986 | |
| return kernelShape; | | return kernelShape; | |
| } | | } | |
| else | | else | |
| { | | { | |
| return fftwBestPaddedShape(in + kernelShape - Shape(1)); | | return fftwBestPaddedShape(in + kernelShape - Shape(1)); | |
| } | | } | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
|
| | | /* FFTWCorrelatePlan */ | |
| | | /* */ | |
| | | /********************************************************/ | |
| | | | |
| | | /** Like FFTWConvolvePlan, but performs correlation rather than convolution | |
| | | . | |
| | | | |
| | | See \ref vigra::FFTWConvolvePlan for details. | |
| | | | |
| | | <b> Usage:</b> | |
| | | | |
| | | <b>\#include</b> \<vigra/multi_fft.hxx\><br> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | // convolve a real array with a real kernel | |
| | | MultiArray<2, double> src(Shape2(w, h)), dest(Shape2(w, h)); | |
| | | | |
| | | MultiArray<2, double> spatial_kernel(Shape2(9, 9)); | |
| | | Gaussian<double> gauss(1.0); | |
| | | | |
| | | for(int y=0; y<9; ++y) | |
| | | for(int x=0; x<9; ++x) | |
| | | spatial_kernel(x, y) = gauss(x-4.0)*gauss(y-4.0); | |
| | | | |
| | | // create an optimized plan by measuring the speed of several algorithm va | |
| | | riants | |
| | | FFTWCorrelatePlan<2, double> plan(src, spatial_kernel, dest, FFTW_MEASURE) | |
| | | ; | |
| | | | |
| | | plan.execute(src, spatial_kernel, dest); | |
| | | \endcode | |
| | | */ | |
| | | template <unsigned int N, class Real> | |
| | | class FFTWCorrelatePlan | |
| | | : private FFTWConvolvePlan<N, Real> | |
| | | { | |
| | | typedef FFTWConvolvePlan<N, Real> BaseType; | |
| | | public: | |
| | | | |
| | | typedef typename MultiArrayShape<N>::type Shape; | |
| | | | |
| | | /** \brief Create an empty plan. | |
| | | | |
| | | The plan can be initialized later by one of the init() functions. | |
| | | */ | |
| | | FFTWCorrelatePlan() | |
| | | : BaseType() | |
| | | {} | |
| | | | |
| | | /** \brief Create a plan to correlate a real array with a real kern | |
| | | el. | |
| | | | |
| | | The kernel must be defined in the spatial domain. | |
| | | See \ref correlateFFT() for detailed information on required shape | |
| | | s and internal padding. | |
| | | | |
| | | \arg planner_flags must be a combination of the | |
| | | <a href="http://www.fftw.org/doc/Planner-Flags.html">planner | |
| | | flags</a> defined by the FFTW library. The default <tt>FFTW_ESTIMA | |
| | | TE</tt> will guess | |
| | | optimal algorithm settings or read them from pre-loaded | |
| | | <a href="http://www.fftw.org/doc/Wisdom.html">"wisdom"</a>. | |
| | | */ | |
| | | template <class C1, class C2, class C3> | |
| | | FFTWCorrelatePlan(MultiArrayView<N, Real, C1> in, | |
| | | MultiArrayView<N, Real, C2> kernel, | |
| | | MultiArrayView<N, Real, C3> out, | |
| | | unsigned int planner_flags = FFTW_ESTIMATE) | |
| | | : BaseType(in, kernel, out, planner_flags) | |
| | | {} | |
| | | | |
| | | /** \brief Create a plan from just the shape information. | |
| | | | |
| | | See \ref convolveFFT() for detailed information on required shapes | |
| | | and internal padding. | |
| | | | |
| | | \arg fourierDomainKernel determines if the kernel is defined in th | |
| | | e spatial or | |
| | | Fourier domain. | |
| | | \arg planner_flags must be a combination of the | |
| | | <a href="http://www.fftw.org/doc/Planner-Flags.html">planner | |
| | | flags</a> defined by the FFTW library. The default <tt>FFTW_ESTIMA | |
| | | TE</tt> will guess | |
| | | optimal algorithm settings or read them from pre-loaded | |
| | | <a href="http://www.fftw.org/doc/Wisdom.html">"wisdom"</a>. | |
| | | */ | |
| | | template <class C1, class C2, class C3> | |
| | | FFTWCorrelatePlan(Shape inOut, Shape kernel, | |
| | | bool useFourierKernel = false, | |
| | | unsigned int planner_flags = FFTW_ESTIMATE) | |
| | | : BaseType(inOut, kernel, false, planner_flags) | |
| | | {} | |
| | | | |
| | | /** \brief Init a plan to convolve a real array with a real kernel. | |
| | | | |
| | | See the constructor with the same signature for details. | |
| | | */ | |
| | | template <class C1, class C2, class C3> | |
| | | void init(MultiArrayView<N, Real, C1> in, | |
| | | MultiArrayView<N, Real, C2> kernel, | |
| | | MultiArrayView<N, Real, C3> out, | |
| | | unsigned int planner_flags = FFTW_ESTIMATE) | |
| | | { | |
| | | vigra_precondition(in.shape() == out.shape(), | |
| | | "FFTWCorrelatePlan::init(): input and output mus | |
| | | t have the same shape."); | |
| | | BaseType::init(in.shape(), kernel.shape(), planner_flags); | |
| | | } | |
| | | | |
| | | /** \brief Execute a plan to correlate a real array with a real ker | |
| | | nel. | |
| | | | |
| | | The array shapes must be the same as in the corresponding init fun | |
| | | ction | |
| | | or constructor. However, execute() can be called several times on | |
| | | the same plan, even with different arrays, as long as they have th | |
| | | e appropriate | |
| | | shapes. | |
| | | */ | |
| | | template <class C1, class C2, class C3> | |
| | | void execute(MultiArrayView<N, Real, C1> in, | |
| | | MultiArrayView<N, Real, C2> kernel, | |
| | | MultiArrayView<N, Real, C3> out) | |
| | | { | |
| | | BaseType::executeImpl(in, kernel, out, true); | |
| | | } | |
| | | }; | |
| | | | |
| | | /********************************************************/ | |
| | | /* */ | |
| /* fourierTransform */ | | /* fourierTransform */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <unsigned int N, class Real, class C1, class C2> | | template <unsigned int N, class Real, class C1, class C2> | |
| inline void | | inline void | |
| fourierTransform(MultiArrayView<N, FFTWComplex<Real>, C1> in, | | fourierTransform(MultiArrayView<N, FFTWComplex<Real>, C1> in, | |
| MultiArrayView<N, FFTWComplex<Real>, C2> out) | | MultiArrayView<N, FFTWComplex<Real>, C2> out) | |
| { | | { | |
| FFTWPlan<N, Real>(in, out, FFTW_FORWARD).execute(in, out); | | FFTWPlan<N, Real>(in, out, FFTW_FORWARD).execute(in, out); | |
| | | | |
| skipping to change at line 1996 | | skipping to change at line 2178 | |
| Thanks to the convolution theorem of Fourier theory, a convolution in t
he spatial domain | | Thanks to the convolution theorem of Fourier theory, a convolution in t
he spatial domain | |
| is equivalent to a multiplication in the frequency domain. Thus, for ce
rtain kernels | | is equivalent to a multiplication in the frequency domain. Thus, for ce
rtain kernels | |
| (especially large, non-separable ones), it is advantageous to perform t
he convolution by first | | (especially large, non-separable ones), it is advantageous to perform t
he convolution by first | |
| transforming both array and kernel to the frequency domain, multiplying
the frequency | | transforming both array and kernel to the frequency domain, multiplying
the frequency | |
| representations, and transforming the result back into the spatial doma
in. | | representations, and transforming the result back into the spatial doma
in. | |
| Some kernels have a much simpler definition in the frequency domain, so
that they are readily | | Some kernels have a much simpler definition in the frequency domain, so
that they are readily | |
| computed there directly, avoiding Fourier transformation of those kerne
ls. | | computed there directly, avoiding Fourier transformation of those kerne
ls. | |
| | | | |
| The following functions implement various variants of FFT-based convolu
tion: | | The following functions implement various variants of FFT-based convolu
tion: | |
| | | | |
|
| <DL> | | <DL> | |
| <DT><b>convolveFFT</b><DD> Convolve a real-valued input array with | | <DT><b>convolveFFT</b><DD> Convolve a real-valued input array with a ke | |
| a kernel such that the | | rnel such that the | |
| result is also real-valued. That is, the kernel | | result is also real-valued. That is, the kernel is | |
| is either provided | | either provided | |
| as a real-valued array in the spatial domain, o | | as a real-valued array in the spatial domain, or as | |
| r as a | | a | |
| complex-valued array in the Fourier domain, usi | | complex-valued array in the Fourier domain, using t | |
| ng the half-space format | | he half-space format | |
| of the R2C Fourier transform (see below). | | of the R2C Fourier transform (see below). | |
| <DT><b>convolveFFTMany</b><DD> Like <tt>convolveFFT</tt>, but you m | | <DT><b>convolveFFTMany</b><DD> Like <tt>convolveFFT</tt>, but you may p | |
| ay provide many kernels at once | | rovide many kernels at once | |
| (using an iterator pair specifying the kernel s | | (using an iterator pair specifying the kernel seque | |
| equence). | | nce). | |
| This has the advantage that the forward transfo | | This has the advantage that the forward transform o | |
| rm of the input array needs | | f the input array needs | |
| to be executed only once. | | to be executed only once. | |
| <DT><b>convolveFFTComplex</b><DD> Convolve a complex-valued input a | | <DT><b>convolveFFTComplex</b><DD> Convolve a complex-valued input array | |
| rray with a complex-valued kernel, | | with a complex-valued kernel, | |
| resulting in a complex-valued output array. An | | resulting in a complex-valued output array. An addi | |
| additional flag is used to | | tional flag is used to | |
| specify whether the kernel is defined in the sp | | specify whether the kernel is defined in the spatia | |
| atial or frequency domain. | | l or frequency domain. | |
| <DT><b>convolveFFTComplexMany</b><DD> Like <tt>convolveFFTComplex</ | | <DT><b>convolveFFTComplexMany</b><DD> Like <tt>convolveFFTComplex</tt>, | |
| tt>, but you may provide many kernels at once | | but you may provide many | |
| (using an iterator pair specifying the kernel s | | kernels at once (using an iterator pair specifying | |
| equence). | | the kernel sequence). | |
| This has the advantage that the forward transfo | | This has the advantage that the forward transform o | |
| rm of the input array needs | | f the input array needs | |
| to be executed only once. | | to be executed only once. | |
| </DL> | | </DL> | |
| | | | |
| The output arrays must have the same shape as the input arrays. In the
"Many" variants of the | | The output arrays must have the same shape as the input arrays. In the
"Many" variants of the | |
| convolution functions, the kernels must all have the same shape. | | convolution functions, the kernels must all have the same shape. | |
| | | | |
| The origin of the kernel is always assumed to be in the center of the k
ernel array (precisely, | | The origin of the kernel is always assumed to be in the center of the k
ernel array (precisely, | |
| at the point <tt>floor(kernel.shape() / 2.0)</tt>, except when the half
-space format is used, see below). | | at the point <tt>floor(kernel.shape() / 2.0)</tt>, except when the half
-space format is used, see below). | |
| The function \ref moveDCToUpperLeft() will be called internally to alig
n the kernel with the transformed | | The function \ref moveDCToUpperLeft() will be called internally to alig
n the kernel with the transformed | |
| input as appropriate. | | input as appropriate. | |
| | | | |
| If a real input is combined with a real kernel, the kernel is automatic
ally assumed to be defined | | If a real input is combined with a real kernel, the kernel is automatic
ally assumed to be defined | |
| | | | |
| skipping to change at line 2058 | | skipping to change at line 2240 | |
| of the kernel must be at the point | | of the kernel must be at the point | |
| <tt>(0, floor(fourier_shape[0] / 2.0), ..., floor(fourier_shape[N-1] /
2.0))</tt> | | <tt>(0, floor(fourier_shape[0] / 2.0), ..., floor(fourier_shape[N-1] /
2.0))</tt> | |
| (i.e. as in a regular kernel except for the first dimension). | | (i.e. as in a regular kernel except for the first dimension). | |
| | | | |
| The <tt>Real</tt> type in the declarations can be <tt>double</tt>, <tt>
float</tt>, and | | The <tt>Real</tt> type in the declarations can be <tt>double</tt>, <tt>
float</tt>, and | |
| <tt>long double</tt>. Your program must always link against <tt>libfftw
3</tt>. If you use | | <tt>long double</tt>. Your program must always link against <tt>libfftw
3</tt>. If you use | |
| <tt>float</tt> or <tt>long double</tt> arrays, you must <i>additionally
</i> link against | | <tt>float</tt> or <tt>long double</tt> arrays, you must <i>additionally
</i> link against | |
| <tt>libfftw3f</tt> and <tt>libfftw3l</tt> respectively. | | <tt>libfftw3f</tt> and <tt>libfftw3l</tt> respectively. | |
| | | | |
| The Fourier transform functions internally create <a href="http://www.f
ftw.org/doc/Using-Plans.html">FFTW plans</a> | | The Fourier transform functions internally create <a href="http://www.f
ftw.org/doc/Using-Plans.html">FFTW plans</a> | |
|
| which control the algorithm details. The plans are creates with the fla
g <tt>FFTW_ESTIMATE</tt>, i.e. | | which control the algorithm details. The plans are created with the fla
g <tt>FFTW_ESTIMATE</tt>, i.e. | |
| optimal settings are guessed or read from saved "wisdom" files. If you
need more control over planning, | | optimal settings are guessed or read from saved "wisdom" files. If you
need more control over planning, | |
| you can use the class \ref FFTWConvolvePlan. | | you can use the class \ref FFTWConvolvePlan. | |
| | | | |
| See also \ref applyFourierFilter() for corresponding functionality on t
he basis of the | | See also \ref applyFourierFilter() for corresponding functionality on t
he basis of the | |
| old image iterator interface. | | old image iterator interface. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
| Real-valued convolution with kernel in the spatial domain: | | Real-valued convolution with kernel in the spatial domain: | |
| \code | | \code | |
| | | | |
| skipping to change at line 2234 | | skipping to change at line 2416 | |
| convolveFFTComplexMany(MultiArrayView<N, FFTWComplex<Real>, C1> in, | | convolveFFTComplexMany(MultiArrayView<N, FFTWComplex<Real>, C1> in, | |
| KernelIterator kernels, KernelIterator kernelsEnd, | | KernelIterator kernels, KernelIterator kernelsEnd, | |
| OutIterator outs, | | OutIterator outs, | |
| bool fourierDomainKernel) | | bool fourierDomainKernel) | |
| { | | { | |
| FFTWConvolvePlan<N, Real> plan; | | FFTWConvolvePlan<N, Real> plan; | |
| plan.initMany(in, kernels, kernelsEnd, outs, fourierDomainKernel); | | plan.initMany(in, kernels, kernelsEnd, outs, fourierDomainKernel); | |
| plan.executeMany(in, kernels, kernelsEnd, outs); | | plan.executeMany(in, kernels, kernelsEnd, outs); | |
| } | | } | |
| | | | |
|
| | | /********************************************************/ | |
| | | /* */ | |
| | | /* correlateFFT */ | |
| | | /* */ | |
| | | /********************************************************/ | |
| | | | |
| | | /** \brief Correlate an array with a kernel by means of the Fourier transfo | |
| | | rm. | |
| | | | |
| | | This function correlates a real-valued input array with a real-valued kern | |
| | | el | |
| | | such that the result is also real-valued. Thanks to the correlation theore | |
| | | m of | |
| | | Fourier theory, a correlation in the spatial domain is equivalent to a mul | |
| | | tiplication | |
| | | with the complex conjugate in the frequency domain. Thus, for | |
| | | certain kernels (especially large, non-separable ones), it is advantageous | |
| | | to perform the | |
| | | correlation by first transforming both array and kernel to the frequency d | |
| | | omain, multiplying | |
| | | the frequency representations, and transforming the result back into the s | |
| | | patial domain. | |
| | | | |
| | | The output arrays must have the same shape as the input arrays. | |
| | | | |
| | | See also \ref convolveFFT() for corresponding functionality. | |
| | | | |
| | | <b> Declarations:</b> | |
| | | | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class Real, class C1, class C2, class C3> | |
| | | void | |
| | | correlateFFT(MultiArrayView<N, Real, C1> in, | |
| | | MultiArrayView<N, Real, C2> kernel, | |
| | | MultiArrayView<N, Real, C3> out); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | <b> Usage:</b> | |
| | | | |
| | | <b>\#include</b> \<vigra/multi_fft.hxx\><br> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | // correlate real array with a template to find best matches | |
| | | // (implicitly uses padding by at least 4 pixels) | |
| | | MultiArray<2, double> src(Shape2(w, h)), dest(Shape2(w, h)); | |
| | | | |
| | | MultiArray<2, double> template(Shape2(9, 9)); | |
| | | template = ...; | |
| | | | |
| | | correlateFFT(src, template, dest); | |
| | | \endcode | |
| | | */ | |
| | | doxygen_overloaded_function(template <...> void correlateFFT) | |
| | | | |
| | | template <unsigned int N, class Real, class C1, class C2, class C3> | |
| | | void | |
| | | correlateFFT(MultiArrayView<N, Real, C1> in, | |
| | | MultiArrayView<N, Real, C2> kernel, | |
| | | MultiArrayView<N, Real, C3> out) | |
| | | { | |
| | | FFTWCorrelatePlan<N, Real>(in, kernel, out).execute(in, kernel, out); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_MULTI_FFT_HXX | | #endif // VIGRA_MULTI_FFT_HXX | |
| | | | |
End of changes. 25 change blocks. |
| 90 lines changed or deleted | | 350 lines changed or added | |
|
| multi_iterator_coupled.hxx | | multi_iterator_coupled.hxx | |
| | | | |
| skipping to change at line 36 | | skipping to change at line 36 | |
| /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ | | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ | |
| /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ | | /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ | |
| /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ | | /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ | |
| /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ | | /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ | |
| /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | | /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | |
| /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | | /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | |
| /* OTHER DEALINGS IN THE SOFTWARE. */ | | /* OTHER DEALINGS IN THE SOFTWARE. */ | |
| /* */ | | /* */ | |
| /************************************************************************/ | | /************************************************************************/ | |
| | | | |
|
| #ifndef MULTI_ITERATOR_COUPLED_HXX_ | | #ifndef MULTI_ITERATOR_COUPLED_HXX | |
| #define MULTI_ITERATOR_COUPLED_HXX_ | | #define MULTI_ITERATOR_COUPLED_HXX | |
| | | | |
|
| | | #include "multi_fwd.hxx" | |
| | | #include "multi_shape.hxx" | |
| | | #include "multi_handle.hxx" | |
| #include "metaprogramming.hxx" | | #include "metaprogramming.hxx" | |
|
| #include "multi_iterator.hxx" | | | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup MultiIteratorGroup | | /** \addtogroup MultiIteratorGroup | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
|
| // FIXME: this should go into its separate header file, | | /********************************************************/ | |
| // together with the calculation of neighborhod offsets for Grid | | /* */ | |
| Graph | | /* CoupledScanOrderIterator<N> */ | |
| template <unsigned int N, unsigned int DIMENSION=N-1> | | /* */ | |
| struct NeighborhoodTypeImpl | | /********************************************************/ | |
| { | | | |
| typedef typename MultiArrayShape<N>::type shape_type; | | | |
| | | | |
| static unsigned int exec(shape_type const & point, shape_type const & s | | | |
| hape) | | | |
| { | | | |
| unsigned int res = NeighborhoodTypeImpl<N, DIMENSION-1>::exec(point | | | |
| , shape); | | | |
| if(point[DIMENSION] == 0) | | | |
| res |= (1 << 2*DIMENSION); | | | |
| if(point[DIMENSION] == shape[DIMENSION]-1) | | | |
| res |= (2 << 2*DIMENSION); | | | |
| return res; | | | |
| } | | | |
| }; | | | |
| | | | |
| template <unsigned int N> | | | |
| struct NeighborhoodTypeImpl<N, 0> | | | |
| { | | | |
| typedef typename MultiArrayShape<N>::type shape_type; | | | |
| static const unsigned int DIMENSION = 0; | | | |
| | | | |
| static unsigned int exec(shape_type const & point, shape_type const & s | | | |
| hape) | | | |
| { | | | |
| unsigned int res = 0; | | | |
| if(point[DIMENSION] == 0) | | | |
| res |= (1 << 2*DIMENSION); | | | |
| if(point[DIMENSION] == shape[DIMENSION]-1) | | | |
| res |= (2 << 2*DIMENSION); | | | |
| return res; | | | |
| } | | | |
| }; | | | |
| | | | |
| /** | | | |
| Handle class, used by CoupledScanOrderIterator as the value type to si | | | |
| multaneously itearate over multiple images. | | | |
| */ | | | |
| template <class T, class NEXT> | | | |
| class CoupledHandle | | | |
| : public NEXT | | | |
| { | | | |
| public: | | | |
| typedef NEXT base_type; | | | |
| typedef CoupledHandle<T, NEXT> self_type; | | | |
| | | | |
| static const int index = NEXT::index + 1; // index of | | | |
| this member of the chain | | | |
| static const unsigned int dimensions = NEXT::dimensions; | | | |
| | | | |
| typedef T value_type; | | | |
| typedef T * pointer; | | | |
| typedef T const * const_pointer; | | | |
| typedef T & reference; | | | |
| typedef T const & const_reference; | | | |
| typedef typename base_type::shape_type shape_type; | | | |
| | | | |
| CoupledHandle() | | | |
| : base_type(), | | | |
| pointer_(), | | | |
| strides_() | | | |
| {} | | | |
| | | | |
| CoupledHandle(const_pointer p, shape_type const & strides, NEXT const & | | | |
| next) | | | |
| : base_type(next), | | | |
| pointer_(const_cast<pointer>(p)), | | | |
| strides_(strides) | | | |
| {} | | | |
| | | | |
| template <class Stride> | | | |
| CoupledHandle(MultiArrayView<dimensions, T, Stride> const & v, NEXT con | | | |
| st & next) | | | |
| : base_type(next), | | | |
| pointer_(const_cast<pointer>(v.data())), | | | |
| strides_(v.stride()) | | | |
| { | | | |
| vigra_precondition(v.shape() == this->shape(), "createCoupledIterat | | | |
| or(): shape mismatch."); | | | |
| } | | | |
| | | | |
| template<int DIMENSION> | | | |
| inline void increment() | | | |
| { | | | |
| pointer_ += strides_[DIMENSION]; | | | |
| base_type::template increment<DIMENSION>(); | | | |
| } | | | |
| | | | |
| template<int DIMENSION> | | | |
| inline void decrement() | | | |
| { | | | |
| pointer_ -= strides_[DIMENSION]; | | | |
| base_type::template decrement<DIMENSION>(); | | | |
| } | | | |
| | | | |
| // TODO: test if making the above a default case of the this hurts perf | | | |
| ormance | | | |
| template<int DIMENSION> | | | |
| inline void increment(MultiArrayIndex offset) | | | |
| { | | | |
| pointer_ += offset*strides_[DIMENSION]; | | | |
| base_type::template increment<DIMENSION>(offset); | | | |
| } | | | |
| | | | |
| template<int DIMENSION> | | | |
| inline void decrement(MultiArrayIndex offset) | | | |
| { | | | |
| pointer_ -= offset*strides_[DIMENSION]; | | | |
| base_type::template decrement<DIMENSION>(offset); | | | |
| } | | | |
| | | | |
| void restrictToSubarray(shape_type const & start, shape_type const & en | | | |
| d) | | | |
| { | | | |
| pointer_ += dot(start, strides_); | | | |
| base_type::restrictToSubarray(start, end); | | | |
| } | | | |
| | | | |
| // ptr access | | | |
| reference operator*() | | | |
| { | | | |
| return *pointer_; | | | |
| } | | | |
| | | | |
| const_reference operator*() const | | | |
| { | | | |
| return *pointer_; | | | |
| } | | | |
| | | | |
| pointer operator->() | | | |
| { | | | |
| return pointer_; | | | |
| } | | | |
| | | | |
| const_pointer operator->() const | | | |
| { | | | |
| return pointer_; | | | |
| } | | | |
| | | | |
| pointer ptr() | | | |
| { | | | |
| return pointer_; | | | |
| } | | | |
| | | | |
| const_pointer ptr() const | | | |
| { | | | |
| return pointer_; | | | |
| } | | | |
| | | | |
| shape_type const & strides() const | | | |
| { | | | |
| return strides_; | | | |
| } | | | |
| | | | |
| pointer pointer_; | | | |
| shape_type strides_; | | | |
| }; | | | |
| | | | |
|
| template <int N> | | template <class Iterator> | |
| class CoupledHandle<TinyVector<MultiArrayIndex, N>, void> | | class CoupledDimensionProxy | |
| | | : public Iterator | |
| { | | { | |
|
| public: | | public: | |
| static const int index = 0; // index of this member o | | typedef typename Iterator::value_type value_type; | |
| f the chain | | typedef typename Iterator::difference_type difference_type; | |
| static const unsigned int dimensions = N; | | typedef typename Iterator::reference reference; | |
| | | typedef typename Iterator::const_reference const_reference; | |
| typedef typename MultiArrayShape<N>::type value_type; | | typedef typename Iterator::pointer pointer; | |
| typedef value_type const * pointer; | | typedef CoupledDimensionProxy iterator; | |
| typedef value_type const * const_pointer; | | typedef std::random_access_iterator_tag iterator_category; | |
| typedef value_type const & reference; | | | |
| typedef value_type const & const_reference; | | | |
| typedef value_type shape_type; | | | |
| typedef CoupledHandle<value_type, void> self_type; | | | |
| | | | |
| CoupledHandle() | | | |
| : point_(), | | | |
| shape_(), | | | |
| scanOrderIndex_() | | | |
| {} | | | |
| | | | |
| CoupledHandle(value_type const & shape) | | | |
| : point_(), | | | |
| shape_(shape), | | | |
| scanOrderIndex_() | | | |
| {} | | | |
| | | | |
| CoupledHandle(typename MultiArrayShape<N+1>::type const & shape) | | | |
| : point_(), | | | |
| shape_(shape.begin()), | | | |
| scanOrderIndex_() | | | |
| {} | | | |
| | | | |
| template<int DIMENSION> | | | |
| inline void increment() | | | |
| { | | | |
| ++point_[DIMENSION]; | | | |
| } | | | |
| | | | |
| template<int DIMENSION> | | | |
| inline void decrement() | | | |
| { | | | |
| --point_[DIMENSION]; | | | |
| } | | | |
| | | | |
| // TODO: test if making the above a default case of the this hurts perf | | | |
| ormance | | | |
| template<int DIMENSION> | | | |
| inline void increment(MultiArrayIndex offset) | | | |
| { | | | |
| point_[DIMENSION] += offset; | | | |
| } | | | |
| | | | |
| template<int DIMENSION> | | | |
| inline void decrement(MultiArrayIndex offset) | | | |
| { | | | |
| point_[DIMENSION] -= offset; | | | |
| } | | | |
| | | | |
| void restrictToSubarray(shape_type const & start, shape_type const & en | | | |
| d) | | | |
| { | | | |
| point_ = shape_type(); | | | |
| shape_ = end - start; | | | |
| scanOrderIndex_ = 0; | | | |
| } | | | |
| | | | |
| inline void incrementIndex() | | | |
| { | | | |
| ++scanOrderIndex_; | | | |
| } | | | |
| | | | |
| inline void decrementIndex() | | | |
| { | | | |
| --scanOrderIndex_; | | | |
| } | | | |
| | | | |
| inline void incrementIndex(MultiArrayIndex offset) | | | |
| { | | | |
| scanOrderIndex_ += offset; | | | |
| } | | | |
| | | | |
| inline void decrementIndex(MultiArrayIndex offset) | | | |
| { | | | |
| scanOrderIndex_ -= offset; | | | |
| } | | | |
| | | | |
| // access | | | |
| MultiArrayIndex scanOrderIndex() const | | | |
| { | | | |
| return scanOrderIndex_; | | | |
| } | | | |
| | | | |
| // access | | | |
| const_reference point() const | | | |
| { | | | |
| return point_; | | | |
| } | | | |
| | | | |
| // access | | | |
| const_reference shape() const | | | |
| { | | | |
| return shape_; | | | |
| } | | | |
| | | | |
| const_reference operator*() const | | | |
| { | | | |
| return point_; | | | |
| } | | | |
| | | | |
|
| const_pointer operator->() const | | static const int dimension = Iterator::dimension; | |
| { | | | |
| return &point_; | | | |
| } | | | |
| | | | |
|
| const_pointer ptr() const | | CoupledDimensionProxy & operator++() | |
| { | | { | |
|
| return &point_; | | this->incDim(dimension); | |
| } | | return *this; | |
| | | | |
| unsigned int neighborhoodType() const | | | |
| { | | | |
| return NeighborhoodTypeImpl<N>::exec(point_, shape_); | | | |
| } | | } | |
| | | | |
|
| value_type point_, shape_; | | CoupledDimensionProxy operator++(int) | |
| MultiArrayIndex scanOrderIndex_; | | | |
| }; | | | |
| | | | |
| template <class T> | | | |
| struct Multiband; | | | |
| | | | |
| template <unsigned int N, class T, class StrideTag> | | | |
| class MultiArrayView<N, Multiband<T>, StrideTag> | | | |
| : public MultiArrayView<N, T, StrideTag> | | | |
| { | | | |
| public: | | | |
| MultiArrayView(MultiArrayView<N, T, StrideTag> const & v) | | | |
| : MultiArrayView<N, T, StrideTag>(v) | | | |
| {} | | | |
| }; | | | |
| | | | |
| template <class T, class NEXT> | | | |
| class CoupledHandle<Multiband<T>, NEXT> | | | |
| : public NEXT | | | |
| { | | | |
| public: | | | |
| typedef NEXT base_type; | | | |
| typedef CoupledHandle<Multiband<T>, NEXT> self_type; | | | |
| | | | |
| static const int index = NEXT::index + 1; // in | | | |
| dex of this member of the chain | | | |
| static const unsigned int dimensions = NEXT::dimensions; | | | |
| | | | |
| typedef MultiArrayView<1, T, StridedArrayTag> value_type; | | | |
| typedef value_type * pointer; | | | |
| typedef value_type const * const_pointer; | | | |
| typedef value_type & reference; | | | |
| typedef value_type const & const_reference; | | | |
| typedef typename base_type::shape_type shape_type; | | | |
| | | | |
| CoupledHandle() | | | |
| : base_type(), | | | |
| view_(), | | | |
| strides_() | | | |
| {} | | | |
| | | | |
| CoupledHandle(const_reference p, shape_type const & strides, NEXT const | | | |
| & next) | | | |
| : base_type(next), | | | |
| view_(p), | | | |
| strides_(strides) | | | |
| {} | | | |
| | | | |
| template <class Stride> | | | |
| CoupledHandle(MultiArrayView<dimensions+1, Multiband<T>, Stride> const | | | |
| & v, NEXT const & next) | | | |
| : base_type(next), | | | |
| view_(v.bindInner(shape_type())), | | | |
| strides_(v.bindOuter(0).stride()) | | | |
| { | | { | |
|
| vigra_precondition(v.bindOuter(0).shape() == this->shape(), "create | | CoupledDimensionProxy ret(*this); | |
| CoupledIterator(): shape mismatch."); | | this->incDim(dimension); | |
| | | return ret; | |
| } | | } | |
| | | | |
|
| template<int DIMENSION> | | CoupledDimensionProxy & operator--() | |
| inline void increment() | | | |
| { | | { | |
|
| view_.unsafePtr() += strides_[DIMENSION]; | | this->decDim(dimension); | |
| base_type::template increment<DIMENSION>(); | | return *this; | |
| } | | } | |
| | | | |
|
| template<int DIMENSION> | | CoupledDimensionProxy operator--(int) | |
| inline void decrement() | | | |
| { | | { | |
|
| view_.unsafePtr() -= strides_[DIMENSION]; | | CoupledDimensionProxy ret(*this); | |
| base_type::template decrement<DIMENSION>(); | | this->decDim(dimension); | |
| | | return ret; | |
| } | | } | |
| | | | |
|
| // TODO: test if making the above a default case of the this hurts perf | | CoupledDimensionProxy & operator+=(MultiArrayIndex d) | |
| ormance | | | |
| template<int DIMENSION> | | | |
| inline void increment(MultiArrayIndex offset) | | | |
| { | | { | |
|
| view_.unsafePtr() += offset*strides_[DIMENSION]; | | this->addDim(dimension, d); | |
| base_type::template increment<DIMENSION>(offset); | | return *this; | |
| } | | } | |
| | | | |
|
| template<int DIMENSION> | | CoupledDimensionProxy & operator-=(MultiArrayIndex d) | |
| inline void decrement(MultiArrayIndex offset) | | | |
| { | | { | |
|
| view_.unsafePtr() -= offset*strides_[DIMENSION]; | | this->addDim(dimension, -d); | |
| base_type::template decrement<DIMENSION>(offset); | | return *this; | |
| } | | } | |
| | | | |
|
| void restrictToSubarray(shape_type const & start, shape_type const & en
d) | | value_type operator[](MultiArrayIndex d) const | |
| { | | { | |
|
| view_.unsafePtr() += dot(start, strides_); | | return *(CoupledDimensionProxy(*this) += d); | |
| base_type::restrictToSubarray(start, end); | | | |
| } | | } | |
| | | | |
|
| // ptr access | | CoupledDimensionProxy & operator=(MultiArrayIndex d) | |
| reference operator*() | | | |
| { | | { | |
|
| return view_; | | this->setDim(dimension, d); | |
| | | return *this; | |
| } | | } | |
| | | | |
|
| const_reference operator*() const | | bool operator==(MultiArrayIndex d) const | |
| { | | { | |
|
| return view_; | | return this->point(dimension) == d; | |
| } | | } | |
| | | | |
|
| pointer operator->() | | bool operator!=(MultiArrayIndex d) const | |
| { | | { | |
|
| return &view_; | | return this->point(dimension) != d; | |
| } | | } | |
| | | | |
|
| const_pointer operator->() const | | bool operator<(MultiArrayIndex d) const | |
| { | | { | |
|
| return &view_; | | return this->point(dimension) < d; | |
| } | | } | |
| | | | |
|
| pointer ptr() | | bool operator<=(MultiArrayIndex d) const | |
| { | | { | |
|
| return &view_; | | return this->point(dimension) <= d; | |
| } | | } | |
| | | | |
|
| const_pointer ptr() const | | bool operator>(MultiArrayIndex d) const | |
| { | | { | |
|
| return &view_; | | return this->point(dimension) > d; | |
| } | | } | |
| | | | |
|
| shape_type const & strides() const | | bool operator>=(MultiArrayIndex d) const | |
| { | | { | |
|
| return strides_; | | return this->point(dimension) >= d; | |
| } | | } | |
|
| | | | |
| value_type view_; | | | |
| shape_type strides_; | | | |
| }; | | | |
| | | | |
| template <unsigned TARGET_INDEX> | | | |
| struct Error__CoupledHandle_index_out_of_range; | | | |
| | | | |
| namespace detail { | | | |
| | | | |
| template <unsigned TARGET_INDEX, class Handle, bool isValid, unsigned int I | | | |
| NDEX=Handle::index> | | | |
| struct CoupledHandleCastImpl | | | |
| { | | | |
| typedef typename CoupledHandleCastImpl<TARGET_INDEX, typename Handle::b | | | |
| ase_type, isValid>::type type; | | | |
| }; | | | |
| | | | |
| template <unsigned TARGET_INDEX, class Handle, unsigned int INDEX> | | | |
| struct CoupledHandleCastImpl<TARGET_INDEX, Handle, false, INDEX> | | | |
| { | | | |
| typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> type; | | | |
| }; | | | |
| | | | |
| template <unsigned TARGET_INDEX, class Handle> | | | |
| struct CoupledHandleCastImpl<TARGET_INDEX, Handle, true, TARGET_INDEX> | | | |
| { | | | |
| typedef Handle type; | | | |
| }; | | | |
| | | | |
| } // namespace detail | | | |
| | | | |
| template <unsigned TARGET_INDEX, class Handle, unsigned int INDEX=Handle::i | | | |
| ndex> | | | |
| struct CoupledHandleCast | | | |
| : public detail::CoupledHandleCastImpl<TARGET_INDEX, Handle, (TARGET_INDEX | | | |
| <= INDEX), INDEX> | | | |
| {}; | | | |
| | | | |
| template <unsigned int TARGET_INDEX, class Handle> | | | |
| typename CoupledHandleCast<TARGET_INDEX, Handle>::type & | | | |
| cast(Handle & handle) | | | |
| { | | | |
| return handle; | | | |
| }; | | | |
| | | | |
| template <unsigned int TARGET_INDEX, class Handle> | | | |
| typename CoupledHandleCast<TARGET_INDEX, Handle>::type const & | | | |
| cast(Handle const & handle) | | | |
| { | | | |
| return handle; | | | |
| }; | | | |
| | | | |
| /** Returns reference to the element in the band of the handle with index | | | |
| TARGET_INDEX. | | | |
| */ | | | |
| template <unsigned int TARGET_INDEX, class Handle> | | | |
| typename CoupledHandleCast<TARGET_INDEX, Handle>::type::reference | | | |
| get(Handle & handle) | | | |
| { | | | |
| return *cast<TARGET_INDEX>(handle); | | | |
| }; | | | |
| | | | |
| /** Returns a constant reference to the element in the band of the handle | | | |
| with index TARGET_INDEX. | | | |
| */ | | | |
| template <unsigned int TARGET_INDEX, class Handle> | | | |
| typename CoupledHandleCast<TARGET_INDEX, Handle>::type::const_reference | | | |
| get(Handle const & handle) | | | |
| { | | | |
| return *cast<TARGET_INDEX>(handle); | | | |
| }; | | }; | |
| | | | |
|
| /********************************************************/ | | | |
| /* */ | | | |
| /* CoupledScanOrderIterator<N> */ | | | |
| /* */ | | | |
| /********************************************************/ | | | |
| | | | |
| /** \brief Iterate over multiple images simultaneously in scan order. | | /** \brief Iterate over multiple images simultaneously in scan order. | |
| | | | |
| The value type of this iterator is an instance of the handle class Coup
ledHandle. This allows to iterate over multiple arrays simultaneously. The
coordinates can be accessed as a special band (index 0) in the handle. The
scan-order is defined such that dimensions are iterated from front to back
(first to last). | | The value type of this iterator is an instance of the handle class Coup
ledHandle. This allows to iterate over multiple arrays simultaneously. The
coordinates can be accessed as a special band (index 0) in the handle. The
scan-order is defined such that dimensions are iterated from front to back
(first to last). | |
| | | | |
| Instances of this class are usually constructed by calling createCouple
dIterator() . | | Instances of this class are usually constructed by calling createCouple
dIterator() . | |
| | | | |
| To get the type of a CoupledScanOrderIterator for arrays of a certain d
imension and element types use CoupledIteratorType::type. | | To get the type of a CoupledScanOrderIterator for arrays of a certain d
imension and element types use CoupledIteratorType::type. | |
| | | | |
| The iterator supports all functions listed in the STL documentation for | | The iterator supports all functions listed in the STL documentation for | |
|
| <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Ran | | <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Ran | |
| dom | | dom Access Iterators</a>. | |
| Access Iterators</a>. | | | |
| | | | |
| Example of use: | | Example of use: | |
| \code | | \code | |
| using namespace vigra; | | using namespace vigra; | |
| MultiArray<2, double> image1(Shape2(5, 5)); | | MultiArray<2, double> image1(Shape2(5, 5)); | |
| MultiArray<2, double> image2(Shape2(5, 5)); | | MultiArray<2, double> image2(Shape2(5, 5)); | |
| // fill image with data ... | | // fill image with data ... | |
| | | | |
| typedef CoupledIteratorType<2, double, double>::type Iterator; // the t
ype of the CoupledScanOrderIterator | | typedef CoupledIteratorType<2, double, double>::type Iterator; // the t
ype of the CoupledScanOrderIterator | |
| | | | |
| | | | |
| skipping to change at line 557 | | skipping to change at line 185 | |
| std::cout << "coordinates: " << it.get<0>() << std::endl; | | std::cout << "coordinates: " << it.get<0>() << std::endl; | |
| std::cout << "image1: " << it.get<1>() << std::endl; | | std::cout << "image1: " << it.get<1>() << std::endl; | |
| std::cout << "image2: " << it.get<2>() << std::endl; | | std::cout << "image2: " << it.get<2>() << std::endl; | |
| } | | } | |
| | | | |
| //random access: | | //random access: | |
| Iterator::value_type handle = start[15]; | | Iterator::value_type handle = start[15]; | |
| std::cout << "image1: " << get<1>(handle) << std::endl; | | std::cout << "image1: " << get<1>(handle) << std::endl; | |
| \endcode | | \endcode | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_iterator_coupled.hxx\> | | <b>\#include</b> \<vigra/multi_iterator_coupled.hxx\> <br/> | |
| | | Namespace: vigra | |
| Namespace: vigra | | | |
| */ | | */ | |
| | | | |
| template <unsigned int N, | | template <unsigned int N, | |
| class HANDLES, | | class HANDLES, | |
|
| int DIMENSION = N-1> | | int DIMENSION> // NOTE: default template arguments are defined i
n multi_fwd.hxx | |
| class CoupledScanOrderIterator | | class CoupledScanOrderIterator | |
| #ifndef DOXYGEN // doxygen doesn't understand this inheritance | | #ifndef DOXYGEN // doxygen doesn't understand this inheritance | |
|
| : protected CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> | | : public CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> | |
| #endif | | #endif | |
| { | | { | |
| typedef CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> base_type; | | typedef CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> base_type; | |
|
| static const int dimension = DIMENSION; | | | |
| | | | |
| public: | | public: | |
|
| | | static const int dimension = DIMENSION; | |
| | | | |
|
| typedef typename MultiArrayShape<dimension+1>::type shape_type; | | | |
| typedef MultiArrayIndex difference_type; | | typedef MultiArrayIndex difference_type; | |
| typedef CoupledScanOrderIterator iterator; | | typedef CoupledScanOrderIterator iterator; | |
| typedef std::random_access_iterator_tag iterator_category; | | typedef std::random_access_iterator_tag iterator_category; | |
| | | | |
| typedef typename base_type::value_type value_type; | | typedef typename base_type::value_type value_type; | |
| | | | |
| #ifdef DOXYGEN | | #ifdef DOXYGEN | |
| /** The type of the CoupledHandle. | | /** The type of the CoupledHandle. | |
| */ | | */ | |
| typedef HANDLES value_type; | | typedef HANDLES value_type; | |
| #endif | | #endif | |
| | | | |
|
| | | typedef typename base_type::shape_type shape_type; | |
| typedef typename base_type::reference reference; | | typedef typename base_type::reference reference; | |
| typedef typename base_type::const_reference const_reference; // FIXME:
do we need both? | | typedef typename base_type::const_reference const_reference; // FIXME:
do we need both? | |
| typedef typename base_type::pointer pointer; | | typedef typename base_type::pointer pointer; | |
|
| | | typedef CoupledDimensionProxy<iterator> dimension_proxy; | |
| | | | |
|
| CoupledScanOrderIterator(value_type const & handles = value_type()) | | explicit CoupledScanOrderIterator(value_type const & handles = value_ty
pe()) | |
| : base_type(handles) | | : base_type(handles) | |
| {} | | {} | |
| | | | |
|
| value_type operator[](MultiArrayIndex i) const | | | |
| { | | | |
| return *(CoupledScanOrderIterator(*this) += i); | | | |
| } | | | |
| | | | |
| CoupledScanOrderIterator & operator++() | | CoupledScanOrderIterator & operator++() | |
| { | | { | |
| base_type::operator++(); | | base_type::operator++(); | |
| if(this->point()[dimension-1] == this->shape()[dimension-1]) | | if(this->point()[dimension-1] == this->shape()[dimension-1]) | |
| { | | { | |
|
| base_type::reset(); | | resetAndIncrement(); | |
| this->handles_.template increment<dimension>(); | | | |
| } | | } | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator operator++(int) | | CoupledScanOrderIterator operator++(int) | |
| { | | { | |
| CoupledScanOrderIterator res(*this); | | CoupledScanOrderIterator res(*this); | |
| ++*this; | | ++*this; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator & operator+=(MultiArrayIndex i) | | CoupledScanOrderIterator & operator+=(MultiArrayIndex i) | |
| { | | { | |
|
| // FIXME: this looks very expensive | | base_type::operator+=(i); | |
| shape_type coordOffset; | | | |
| detail::ScanOrderToCoordinate<N>::exec(i+scanOrderIndex(), this->sh | | | |
| ape(), coordOffset); | | | |
| coordOffset -= point(); | | | |
| moveRelative(coordOffset); | | | |
| this->handles_.scanOrderIndex_ += i; | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator & operator+=(const shape_type &coordOffset) | | CoupledScanOrderIterator & operator+=(const shape_type &coordOffset) | |
| { | | { | |
|
| moveRelative(coordOffset); | | base_type::operator+=(coordOffset); | |
| this->handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>: | | | |
| :exec(this->shape(), coordOffset); | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator & operator--() | | CoupledScanOrderIterator & operator--() | |
| { | | { | |
| base_type::operator--(); | | base_type::operator--(); | |
| if(this->point()[dimension-1] == -1) | | if(this->point()[dimension-1] == -1) | |
| { | | { | |
|
| base_type::inverseReset(); | | resetAndDecrement(); | |
| this->handles_.template decrement<dimension>(); | | | |
| } | | } | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator operator--(int) | | CoupledScanOrderIterator operator--(int) | |
| { | | { | |
| CoupledScanOrderIterator res(*this); | | CoupledScanOrderIterator res(*this); | |
| --*this; | | --*this; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| skipping to change at line 665 | | skipping to change at line 280 | |
| CoupledScanOrderIterator & operator-=(MultiArrayIndex i) | | CoupledScanOrderIterator & operator-=(MultiArrayIndex i) | |
| { | | { | |
| return operator+=(-i); | | return operator+=(-i); | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator & operator-=(const shape_type &coordOffset) | | CoupledScanOrderIterator & operator-=(const shape_type &coordOffset) | |
| { | | { | |
| return operator+=(-coordOffset); | | return operator+=(-coordOffset); | |
| } | | } | |
| | | | |
|
| /** Returns CoupledScanOrderIterator pointing beyond the last element. | | /** Returns CoupledScanOrderIterator pointing beyond the last eleme | |
| */ | | nt. | |
| | | */ | |
| CoupledScanOrderIterator getEndIterator() const | | CoupledScanOrderIterator getEndIterator() const | |
| { | | { | |
|
| return operator+(prod(this->shape())); | | return operator+(prod(this->shape()) - this->scanOrderIndex()); | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator operator+(MultiArrayIndex d) const | | CoupledScanOrderIterator operator+(MultiArrayIndex d) const | |
| { | | { | |
| return CoupledScanOrderIterator(*this) += d; | | return CoupledScanOrderIterator(*this) += d; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator operator-(MultiArrayIndex d) const | | CoupledScanOrderIterator operator-(MultiArrayIndex d) const | |
| { | | { | |
| return CoupledScanOrderIterator(*this) -= d; | | return CoupledScanOrderIterator(*this) -= d; | |
| | | | |
| skipping to change at line 697 | | skipping to change at line 312 | |
| CoupledScanOrderIterator operator-(const shape_type &coordOffset) const | | CoupledScanOrderIterator operator-(const shape_type &coordOffset) const | |
| { | | { | |
| return CoupledScanOrderIterator(*this) -= coordOffset; | | return CoupledScanOrderIterator(*this) -= coordOffset; | |
| } | | } | |
| | | | |
| MultiArrayIndex operator-(CoupledScanOrderIterator const & r) const | | MultiArrayIndex operator-(CoupledScanOrderIterator const & r) const | |
| { | | { | |
| return base_type::operator-(r); | | return base_type::operator-(r); | |
| } | | } | |
| | | | |
|
| bool operator==(CoupledScanOrderIterator const & r) | | CoupledScanOrderIterator & | |
| | | restrictToSubarray(shape_type const & start, shape_type const & end) | |
| { | | { | |
|
| return base_type::operator==(r); | | base_type::restrictToSubarray(start, end); | |
| } | | return *this; | |
| | | | |
| bool operator!=(CoupledScanOrderIterator const & r) const | | | |
| { | | | |
| return base_type::operator!=(r); | | | |
| } | | | |
| | | | |
| bool operator<(CoupledScanOrderIterator const & r) const | | | |
| { | | | |
| return base_type::operator<(r); | | | |
| } | | | |
| | | | |
| bool operator<=(CoupledScanOrderIterator const & r) const | | | |
| { | | | |
| return base_type::operator<=(r); | | | |
| } | | | |
| | | | |
| bool operator>(CoupledScanOrderIterator const & r) const | | | |
| { | | | |
| return base_type::operator>(r); | | | |
| } | | } | |
| | | | |
|
| bool operator>=(CoupledScanOrderIterator const & r) const | | #ifdef DOXYGEN | |
| { | | | |
| return base_type::operator>=(r); | | | |
| } | | | |
| | | | |
|
| using base_type::operator*; | | /** Returns reference to the element in the band with index TARGET_ | |
| using base_type::point; | | INDEX. | |
| using base_type::shape; | | */ | |
| using base_type::scanOrderIndex; | | template<unsigned int TARGET_INDEX> | |
| using base_type::atBorder; | | typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference | |
| using base_type::neighborhoodType; | | get(); | |
| using base_type::get; | | | |
| | | | |
|
| #ifdef DOXYGEN | | /** Returns constant reference to the element in the band with inde | |
| | | x TARGET_INDEX. | |
| | | */ | |
| | | template<unsigned int TARGET_INDEX> | |
| | | typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_refer | |
| | | ence | |
| | | get() const; | |
| | | | |
|
| /** Returns reference to the element in the band with index TARGET_INDEX. | | | |
| */ | | | |
| template<unsigned int TARGET_INDEX> | | | |
| typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference | | | |
| get() | | | |
| { | | | |
| return vigra::get<TARGET_INDEX>(handles_); | | | |
| } | | | |
| | | | |
| /** Returns constant reference to the element in the band with index TARG | | | |
| ET_INDEX. | | | |
| */ | | | |
| template<unsigned int TARGET_INDEX> | | | |
| typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_referen | | | |
| ce | | | |
| get() const | | | |
| { | | | |
| return vigra::get<TARGET_INDEX>(handles_); | | | |
| } | | | |
| #endif | | #endif | |
| | | | |
| protected: | | protected: | |
|
| | | // placing these functions out-of-line prevents MSVC | |
| | | // from stupid optimizations | |
| | | void resetAndIncrement(); | |
| | | void resetAndDecrement(); | |
| | | | |
| void reset() | | void reset() | |
| { | | { | |
| this->handles_.template decrement<dimension>(this->shape()[dimensio
n]); | | this->handles_.template decrement<dimension>(this->shape()[dimensio
n]); | |
| } | | } | |
| | | | |
| void inverseReset() | | void inverseReset() | |
| { | | { | |
| this->handles_.template increment<dimension>(this->shape()[dimensio
n]); | | this->handles_.template increment<dimension>(this->shape()[dimensio
n]); | |
| } | | } | |
|
| | | | |
| void moveRelative(typename value_type::shape_type const & coordOffset) | | | |
| { | | | |
| base_type::moveRelative(coordOffset); | | | |
| this->handles_.template increment<dimension>(coordOffset[dimension] | | | |
| ); | | | |
| } | | | |
| }; | | }; | |
| | | | |
|
| | | template <unsigned int N, class HANDLES, int DIMENSION> | |
| | | void CoupledScanOrderIterator<N, HANDLES, DIMENSION>::resetAndIncrement() | |
| | | { | |
| | | base_type::reset(); | |
| | | this->handles_.template increment<dimension>(); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class HANDLES, int DIMENSION> | |
| | | void CoupledScanOrderIterator<N, HANDLES, DIMENSION>::resetAndDecrement() | |
| | | { | |
| | | base_type::inverseReset(); | |
| | | this->handles_.template decrement<dimension>(); | |
| | | } | |
| | | | |
| template <unsigned int N, class HANDLES> | | template <unsigned int N, class HANDLES> | |
| class CoupledScanOrderIterator<N, HANDLES, 0> | | class CoupledScanOrderIterator<N, HANDLES, 0> | |
| { | | { | |
|
| static const int dimension = 0; | | | |
| | | | |
| public: | | public: | |
| | | | |
|
| | | static const int dimension = 0; | |
| | | | |
| typedef CoupledScanOrderIterator<N, HANDLES, 0> self_type; | | typedef CoupledScanOrderIterator<N, HANDLES, 0> self_type; | |
| typedef HANDLES value_type; | | typedef HANDLES value_type; | |
| typedef MultiArrayIndex difference_type; | | typedef MultiArrayIndex difference_type; | |
| typedef value_type & reference; | | typedef value_type & reference; | |
| typedef value_type const & const_reference; | | typedef value_type const & const_reference; | |
| typedef value_type * pointer; | | typedef value_type * pointer; | |
|
| typedef typename MultiArrayShape<1>::type shape_type; | | typedef typename MultiArrayShape<N>::type shape_type; | |
| typedef CoupledScanOrderIterator iterator; | | typedef CoupledScanOrderIterator iterator; | |
| typedef std::random_access_iterator_tag iterator_category; | | typedef std::random_access_iterator_tag iterator_category; | |
|
| | | typedef CoupledDimensionProxy<iterator> dimension_proxy; | |
| | | | |
| | | template <unsigned int TARGET_INDEX> | |
| | | struct Reference | |
| | | { | |
| | | typedef typename CoupledHandleCast<TARGET_INDEX, HANDLES>::referenc | |
| | | e type; | |
| | | }; | |
| | | | |
| | | template <unsigned int TARGET_INDEX> | |
| | | struct ConstReference | |
| | | { | |
| | | typedef typename CoupledHandleCast<TARGET_INDEX, HANDLES>::const_re | |
| | | ference type; | |
| | | }; | |
| | | | |
|
| CoupledScanOrderIterator(value_type const & handles = value_type()) | | explicit CoupledScanOrderIterator(value_type const & handles = value_ty | |
| : handles_(handles) | | pe()) | |
| | | : handles_(handles), | |
| | | strides_(detail::defaultStride(handles_.shape())) | |
| {} | | {} | |
| | | | |
|
| | | template <unsigned int DIM> | |
| | | typename CoupledScanOrderIterator<N, HANDLES, DIM>::dimension_proxy & | |
| | | dim() | |
| | | { | |
| | | typedef CoupledScanOrderIterator<N, HANDLES, DIM> Iter; | |
| | | typedef typename Iter::dimension_proxy Proxy; | |
| | | return static_cast<Proxy &>(static_cast<Iter &>(*this)); | |
| | | } | |
| | | | |
| | | template <unsigned int DIM> | |
| | | typename CoupledScanOrderIterator<N, HANDLES, DIM>::dimension_proxy con | |
| | | st & | |
| | | dim() const | |
| | | { | |
| | | typedef CoupledScanOrderIterator<N, HANDLES, DIM> Iter; | |
| | | typedef typename Iter::dimension_proxy Proxy; | |
| | | return static_cast<Proxy const &>(static_cast<Iter const &>(*this)) | |
| | | ; | |
| | | } | |
| | | | |
| | | void incDim(int dim) | |
| | | { | |
| | | handles_.incDim(dim); | |
| | | handles_.incrementIndex(strides_[dim]); | |
| | | } | |
| | | | |
| | | void decDim(int dim) | |
| | | { | |
| | | handles_.decDim(dim); | |
| | | handles_.decrementIndex(strides_[dim]); | |
| | | } | |
| | | | |
| | | void addDim(int dim, MultiArrayIndex d) | |
| | | { | |
| | | handles_.addDim(dim, d); | |
| | | handles_.incrementIndex(d*strides_[dim]); | |
| | | } | |
| | | | |
| | | void setDim(int dim, MultiArrayIndex d) | |
| | | { | |
| | | d -= point(dim); | |
| | | handles_.addDim(dim, d); | |
| | | handles_.incrementIndex(d*strides_[dim]); | |
| | | } | |
| | | | |
| | | void resetDim(int dim) | |
| | | { | |
| | | MultiArrayIndex d = -point(dim); | |
| | | handles_.addDim(dim, d); | |
| | | handles_.incrementIndex(d*strides_[dim]); | |
| | | } | |
| | | | |
| CoupledScanOrderIterator & operator++() | | CoupledScanOrderIterator & operator++() | |
| { | | { | |
| handles_.template increment<dimension>(); | | handles_.template increment<dimension>(); | |
| handles_.incrementIndex(); | | handles_.incrementIndex(); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator operator++(int) | | CoupledScanOrderIterator operator++(int) | |
| { | | { | |
| CoupledScanOrderIterator res(*this); | | CoupledScanOrderIterator res(*this); | |
| ++*this; | | ++*this; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator & operator+=(MultiArrayIndex i) | | CoupledScanOrderIterator & operator+=(MultiArrayIndex i) | |
| { | | { | |
|
| | | // FIXME: this looks very expensive | |
| shape_type coordOffset; | | shape_type coordOffset; | |
|
| detail::ScanOrderToCoordinate<N>::exec(i, shape(), coordOffset); | | detail::ScanOrderToCoordinate<N>::exec(i+scanOrderIndex(), shape(), | |
| moveRelative(coordOffset); | | coordOffset); | |
| | | coordOffset -= point(); | |
| | | handles_.add(coordOffset); | |
| handles_.scanOrderIndex_ += i; | | handles_.scanOrderIndex_ += i; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator & operator+=(const shape_type &coordOffset) | | CoupledScanOrderIterator & operator+=(const shape_type &coordOffset) | |
| { | | { | |
|
| moveRelative(coordOffset); | | handles_.add(coordOffset); | |
| handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(
shape(), coordOffset); | | handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(
shape(), coordOffset); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| CoupledScanOrderIterator & operator-=(const shape_type &coordOffset) | | | |
| { | | | |
| return operator+=(-coordOffset); | | | |
| } | | | |
| | | | |
| CoupledScanOrderIterator & operator--() | | CoupledScanOrderIterator & operator--() | |
| { | | { | |
| handles_.template decrement<dimension>(); | | handles_.template decrement<dimension>(); | |
| handles_.decrementIndex(); | | handles_.decrementIndex(); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator operator--(int) | | CoupledScanOrderIterator operator--(int) | |
| { | | { | |
| CoupledScanOrderIterator res(*this); | | CoupledScanOrderIterator res(*this); | |
| --this; | | --this; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator & operator-=(MultiArrayIndex i) | | CoupledScanOrderIterator & operator-=(MultiArrayIndex i) | |
| { | | { | |
| return operator+=(-i); | | return operator+=(-i); | |
| } | | } | |
| | | | |
|
| | | CoupledScanOrderIterator & operator-=(const shape_type &coordOffset) | |
| | | { | |
| | | return operator+=(-coordOffset); | |
| | | } | |
| | | | |
| value_type operator[](MultiArrayIndex i) const | | value_type operator[](MultiArrayIndex i) const | |
| { | | { | |
| return *(CoupledScanOrderIterator(*this) += i); | | return *(CoupledScanOrderIterator(*this) += i); | |
| } | | } | |
| | | | |
|
| | | value_type operator[](const shape_type& coordOffset) const | |
| | | { | |
| | | return *(CoupledScanOrderIterator(*this) += coordOffset); | |
| | | } | |
| | | | |
| CoupledScanOrderIterator | | CoupledScanOrderIterator | |
| operator+(MultiArrayIndex d) const | | operator+(MultiArrayIndex d) const | |
| { | | { | |
| return CoupledScanOrderIterator(*this) += d; | | return CoupledScanOrderIterator(*this) += d; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator | | CoupledScanOrderIterator | |
| operator-(MultiArrayIndex d) const | | operator-(MultiArrayIndex d) const | |
| { | | { | |
| return CoupledScanOrderIterator(*this) -= d; | | return CoupledScanOrderIterator(*this) -= d; | |
| | | | |
| skipping to change at line 882 | | skipping to change at line 545 | |
| { | | { | |
| return CoupledScanOrderIterator(*this) -= coordOffset; | | return CoupledScanOrderIterator(*this) -= coordOffset; | |
| } | | } | |
| | | | |
| MultiArrayIndex | | MultiArrayIndex | |
| operator-(CoupledScanOrderIterator const & r) const | | operator-(CoupledScanOrderIterator const & r) const | |
| { | | { | |
| return scanOrderIndex() - r.scanOrderIndex(); | | return scanOrderIndex() - r.scanOrderIndex(); | |
| } | | } | |
| | | | |
|
| bool | | bool operator==(CoupledScanOrderIterator const & r) const | |
| operator==(CoupledScanOrderIterator const & r) | | | |
| { | | { | |
| return scanOrderIndex() == r.scanOrderIndex(); | | return scanOrderIndex() == r.scanOrderIndex(); | |
| } | | } | |
| | | | |
|
| bool | | bool operator!=(CoupledScanOrderIterator const & r) const | |
| operator!=(CoupledScanOrderIterator const & r) const | | | |
| { | | { | |
| return scanOrderIndex() != r.scanOrderIndex(); | | return scanOrderIndex() != r.scanOrderIndex(); | |
| } | | } | |
| | | | |
|
| bool | | bool operator<(CoupledScanOrderIterator const & r) const | |
| operator<(CoupledScanOrderIterator const & r) const | | | |
| { | | { | |
| return scanOrderIndex() < r.scanOrderIndex(); | | return scanOrderIndex() < r.scanOrderIndex(); | |
| } | | } | |
| | | | |
|
| bool | | bool operator<=(CoupledScanOrderIterator const & r) const | |
| operator<=(CoupledScanOrderIterator const & r) const | | | |
| { | | { | |
| return scanOrderIndex() <= r.scanOrderIndex(); | | return scanOrderIndex() <= r.scanOrderIndex(); | |
| } | | } | |
| | | | |
|
| bool | | bool operator>(CoupledScanOrderIterator const & r) const | |
| operator>(CoupledScanOrderIterator const & r) const | | | |
| { | | { | |
| return scanOrderIndex() > r.scanOrderIndex(); | | return scanOrderIndex() > r.scanOrderIndex(); | |
| } | | } | |
| | | | |
|
| bool | | bool operator>=(CoupledScanOrderIterator const & r) const | |
| operator>=(CoupledScanOrderIterator const & r) const | | | |
| { | | { | |
| return scanOrderIndex() >= r.scanOrderIndex(); | | return scanOrderIndex() >= r.scanOrderIndex(); | |
| } | | } | |
| | | | |
|
| | | bool isValid() const | |
| | | { | |
| | | return handles_.scanOrderIndex() < prod(shape()); | |
| | | } | |
| | | | |
| | | bool atEnd() const | |
| | | { | |
| | | return handles_.scanOrderIndex() >= prod(shape()); | |
| | | } | |
| | | | |
| MultiArrayIndex scanOrderIndex() const | | MultiArrayIndex scanOrderIndex() const | |
| { | | { | |
| return handles_.scanOrderIndex(); | | return handles_.scanOrderIndex(); | |
| } | | } | |
| | | | |
|
| typename value_type::shape_type const & point() const | | shape_type const & coord() const | |
| { | | { | |
| return handles_.point(); | | return handles_.point(); | |
| } | | } | |
| | | | |
|
| typename value_type::shape_type const & shape() const | | MultiArrayIndex coord(unsigned int dim) const | |
| | | { | |
| | | return coord()[dim]; | |
| | | } | |
| | | | |
| | | shape_type const & point() const | |
| | | { | |
| | | return handles_.point(); | |
| | | } | |
| | | | |
| | | MultiArrayIndex point(unsigned int dim) const | |
| | | { | |
| | | return point()[dim]; | |
| | | } | |
| | | | |
| | | shape_type const & shape() const | |
| { | | { | |
| return handles_.shape(); | | return handles_.shape(); | |
| } | | } | |
| | | | |
|
| | | MultiArrayIndex shape(unsigned int dim) const | |
| | | { | |
| | | return handles_.shape()[dim]; | |
| | | } | |
| | | | |
| reference operator*() | | reference operator*() | |
| { | | { | |
| return handles_; | | return handles_; | |
| } | | } | |
| | | | |
| const_reference operator*() const | | const_reference operator*() const | |
| { | | { | |
| return handles_; | | return handles_; | |
| } | | } | |
| | | | |
|
| void restrictToSubarray(shape_type const & start, shape_type const & en | | CoupledScanOrderIterator & | |
| d) const | | restrictToSubarray(shape_type const & start, shape_type const & end) | |
| { | | { | |
| operator+=(-point()); | | operator+=(-point()); | |
|
| handles_.restricToSubarray(start, end); | | handles_.restrictToSubarray(start, end); | |
| | | strides_ = detail::defaultStride(shape()); | |
| | | return *this; | |
| } | | } | |
| | | | |
| CoupledScanOrderIterator getEndIterator() const | | CoupledScanOrderIterator getEndIterator() const | |
| { | | { | |
|
| return operator+(prod(shape())); | | return operator+(prod(shape())-scanOrderIndex()); | |
| } | | } | |
| | | | |
| bool atBorder() const | | bool atBorder() const | |
| { | | { | |
|
| return (handles_.neighborhoodType() != 0); | | return (handles_.borderType() != 0); | |
| } | | } | |
| | | | |
|
| unsigned int neighborhoodType() const | | unsigned int borderType() const | |
| { | | { | |
|
| return handles_.neighborhoodType(); | | return handles_.borderType(); | |
| } | | } | |
| | | | |
| template<unsigned int TARGET_INDEX> | | template<unsigned int TARGET_INDEX> | |
|
| typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference | | typename Reference<TARGET_INDEX>::type | |
| get() | | get() | |
| { | | { | |
| return vigra::get<TARGET_INDEX>(handles_); | | return vigra::get<TARGET_INDEX>(handles_); | |
| } | | } | |
| | | | |
| template<unsigned int TARGET_INDEX> | | template<unsigned int TARGET_INDEX> | |
|
| typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_refer
ence | | typename ConstReference<TARGET_INDEX>::type | |
| get() const | | get() const | |
| { | | { | |
| return vigra::get<TARGET_INDEX>(handles_); | | return vigra::get<TARGET_INDEX>(handles_); | |
| } | | } | |
| | | | |
|
| protected: | | reference handles() | |
| void reset() | | | |
| { | | | |
| handles_.template decrement<dimension>(shape()[dimension]); | | | |
| } | | | |
| | | | |
| void inverseReset() | | | |
| { | | | |
| handles_.template increment<dimension>(shape()[dimension]); | | | |
| } | | | |
| | | | |
| void moveRelative(typename value_type::shape_type const & coordOffset) | | | |
| { | | { | |
|
| handles_.template increment<dimension>(coordOffset[dimension]); | | return handles_; | |
| } | | } | |
| | | | |
|
| value_type handles_; | | const_reference handles() const | |
| }; | | | |
| | | | |
| template <unsigned int N, class List> | | | |
| struct ComposeCoupledHandle; | | | |
| | | | |
| template <unsigned int N, class T, class TAIL> | | | |
| struct ComposeCoupledHandle<N, TypeList<T, TAIL> > | | | |
| { | | | |
| typedef typename ComposeCoupledHandle<N, TAIL>::type BaseType; | | | |
| typedef typename MultiArrayShape<N>::type shape_type; | | | |
| typedef CoupledHandle<T, BaseType> type; | | | |
| | | | |
| template <class S> | | | |
| type exec(MultiArrayView<N, T, S> const & m, | | | |
| shape_type const & start, shape_type const & end, | | | |
| BaseType const & base) | | | |
| { | | { | |
|
| return type(m.subarray(start, end).data(), m.stride(), base); | | return handles_; | |
| } | | } | |
| | | | |
|
| template <class S> | | protected: | |
| type exec(MultiArrayView<N, T, S> const & m, BaseType const & base) | | void reset() | |
| { | | { | |
|
| return type(m.data(), m.stride(), base); | | handles_.template decrement<dimension>(shape()[dimension]); | |
| } | | } | |
|
| }; | | | |
| | | | |
|
| template <unsigned int N> | | void inverseReset() | |
| struct ComposeCoupledHandle<N, void> | | | |
| { | | | |
| typedef typename MultiArrayShape<N>::type shape_type; | | | |
| typedef CoupledHandle<shape_type, void> type; | | | |
| | | | |
| type exec(shape_type const & shape) | | | |
| { | | { | |
|
| return type(shape); | | handles_.template increment<dimension>(shape()[dimension]); | |
| } | | } | |
| | | | |
|
| type exec(shape_type const & start, shape_type const & end) | | value_type handles_; | |
| { | | shape_type strides_; | |
| return type(end-start); | | | |
| } | | | |
| }; | | }; | |
| | | | |
|
| template <unsigned int N, class T1=void, class T2=void, class T3=void, clas | | template <unsigned int TARGET_INDEX, | |
| s T4=void, class T5=void> | | unsigned int N, | |
| struct CoupledHandleType | | class HANDLES, | |
| | | int DIM> | |
| | | typename CoupledScanOrderIterator<N, HANDLES, DIM>::template Reference<TARG | |
| | | ET_INDEX>::type | |
| | | get(CoupledScanOrderIterator<N, HANDLES, DIM> & i) | |
| { | | { | |
|
| // reverse the order to get the desired index order | | return vigra::get<TARGET_INDEX>(*i); | |
| typedef typename MakeTypeList<T5, T4, T3, T2, T1>::type TypeList; | | } | |
| typedef typename ComposeCoupledHandle<N, TypeList>::type type; | | | |
| }; | | | |
| | | | |
|
| template <unsigned int N, class T1, class T2, class T3, class T4, class T5> | | template <unsigned int TARGET_INDEX, | |
| struct CoupledHandleType<N, Multiband<T1>, T2, T3, T4, T5> | | unsigned int N, | |
| | | class HANDLES, | |
| | | int DIM> | |
| | | typename CoupledScanOrderIterator<N, HANDLES, DIM>::template ConstReference | |
| | | <TARGET_INDEX>::type | |
| | | get(CoupledScanOrderIterator<N, HANDLES, DIM> const & i) | |
| { | | { | |
|
| // reverse the order to get the desired index order | | return vigra::get<TARGET_INDEX>(*i); | |
| typedef typename MakeTypeList<T5, T4, T3, T2, Multiband<T1> >::type Typ | | } | |
| eList; | | | |
| typedef typename ComposeCoupledHandle<N-1, TypeList>::type type; | | | |
| }; | | | |
| | | | |
| /** Helper class to easliy get the type of a CoupledScanOrderIterator (and
corresponding CoupledHandle) for up to five arrays of dimension N with elem
ent types T1,...,T5. | | /** Helper class to easliy get the type of a CoupledScanOrderIterator (and
corresponding CoupledHandle) for up to five arrays of dimension N with elem
ent types T1,...,T5. | |
| */ | | */ | |
| template <unsigned int N, class T1=void, class T2=void, class T3=void, clas
s T4=void, class T5=void> | | template <unsigned int N, class T1=void, class T2=void, class T3=void, clas
s T4=void, class T5=void> | |
| struct CoupledIteratorType | | struct CoupledIteratorType | |
| { | | { | |
| /** Type of the CoupledHandle.*/ | | /** Type of the CoupledHandle.*/ | |
| typedef typename CoupledHandleType<N, T1, T2, T3, T4, T5>::type HandleT
ype; | | typedef typename CoupledHandleType<N, T1, T2, T3, T4, T5>::type HandleT
ype; | |
| | | | |
| /** Type of the CoupledScanOrderIterator.*/ | | /** Type of the CoupledScanOrderIterator.*/ | |
|
| typedef CoupledScanOrderIterator<HandleType::dimensions, HandleType> ty | | typedef CoupledScanOrderIterator<HandleType::dimensions, HandleType> It | |
| pe; | | eratorType; | |
| | | typedef IteratorType ty | |
| | | pe; | |
| }; | | }; | |
| | | | |
|
| | | /** Alias for \ref vigra::CoupledIteratorType (maybe easier to remember). | |
| | | */ | |
| | | template <unsigned int N, class T1=void, class T2=void, class T3=void, clas | |
| | | s T4=void, class T5=void> | |
| | | struct CoupledArrays | |
| | | : public CoupledIteratorType<N, T1, T2, T3, T4, T5> | |
| | | {}; | |
| | | | |
| /** Returns a CoupledScanOrderIterator from shape to iterate over coordinat
es. | | /** Returns a CoupledScanOrderIterator from shape to iterate over coordinat
es. | |
| */ | | */ | |
| template <int N> | | template <int N> | |
| typename CoupledIteratorType<N>::type | | typename CoupledIteratorType<N>::type | |
| createCoupledIterator(TinyVector<MultiArrayIndex, N> const & shape) | | createCoupledIterator(TinyVector<MultiArrayIndex, N> const & shape) | |
| { | | { | |
| typedef typename CoupledHandleType<N>::type P0; | | typedef typename CoupledHandleType<N>::type P0; | |
| typedef CoupledScanOrderIterator<N, P0> IteratorType; | | typedef CoupledScanOrderIterator<N, P0> IteratorType; | |
| | | | |
| return IteratorType(P0(shape)); | | return IteratorType(P0(shape)); | |
| | | | |
| skipping to change at line 1189 | | skipping to change at line 855 | |
| typedef CoupledScanOrderIterator<P1::dimensions, P5> IteratorType; | | typedef CoupledScanOrderIterator<P1::dimensions, P5> IteratorType; | |
| | | | |
| return IteratorType(P5(m5, | | return IteratorType(P5(m5, | |
| P4(m4, | | P4(m4, | |
| P3(m3, | | P3(m3, | |
| P2(m2, | | P2(m2, | |
| P1(m1, | | P1(m1, | |
| P0(m1.shape()))))))); | | P0(m1.shape()))))))); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class A, class B> | |
| | | CoupledScanOrderIterator<N, typename ZipCoupledHandles<A, B>::type> | |
| | | zip(CoupledScanOrderIterator<N, A> const & a, CoupledScanOrderIterator<N, B | |
| | | > const & b) | |
| | | { | |
| | | vigra_precondition(a.shape() == b.shape() && a.scanOrderIndex() == b.sc | |
| | | anOrderIndex(), | |
| | | "zip(CoupledScanOrderIterator): iterators must have identical shap | |
| | | e and position."); | |
| | | | |
| | | typedef typename ZipCoupledHandles<A, B>::type Handle; | |
| | | typedef CoupledScanOrderIterator<N, Handle> IteratorType; | |
| | | return IteratorType(ZipCoupledHandles<A, B>::construct(*a, *b)); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
|
| #endif /* MULTI_ITERATOR_COUPLED_HXX_ */ | | namespace std { | |
| | | | |
| | | template <unsigned int N, class HANDLES, int DIMENSION> | |
| | | ostream & operator<<(ostream & o, vigra::CoupledScanOrderIterator<N, HANDLE | |
| | | S, DIMENSION> const & i) | |
| | | { | |
| | | o << i.point(); | |
| | | return o; | |
| | | } | |
| | | | |
| | | } // namespace std | |
| | | | |
| | | #endif /* MULTI_ITERATOR_COUPLED_HXX */ | |
| | | | |
End of changes. 111 change blocks. |
| 647 lines changed or deleted | | 309 lines changed or added | |
|
| multi_pointoperators.hxx | | multi_pointoperators.hxx | |
| | | | |
| skipping to change at line 59 | | skipping to change at line 59 | |
| namespace vigra | | namespace vigra | |
| { | | { | |
| | | | |
| /** \addtogroup MultiPointoperators Point operators for multi-dimensional a
rrays. | | /** \addtogroup MultiPointoperators Point operators for multi-dimensional a
rrays. | |
| | | | |
| Copy, transform, and inspect arbitrary dimensional arrays which are rep
resented | | Copy, transform, and inspect arbitrary dimensional arrays which are rep
resented | |
| by iterators compatible to \ref MultiIteratorPage. Note that are range
is here | | by iterators compatible to \ref MultiIteratorPage. Note that are range
is here | |
| specified by a pair: an iterator referring to the first point of the ar
ray | | specified by a pair: an iterator referring to the first point of the ar
ray | |
| and a shape object specifying the size of the (rectangular) ROI. | | and a shape object specifying the size of the (rectangular) ROI. | |
| | | | |
|
| <b>\#include</b> \<vigra/multi_pointoperators.hxx\> | | <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br/> | |
| | | Namespace: vigra | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* initMultiArray */ | | /* initMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class Iterator, class Shape, class Accessor, | | template <class Iterator, class Shape, class Accessor, | |
| | | | |
| skipping to change at line 90 | | skipping to change at line 91 | |
| initMultiArrayImpl(Iterator s, Shape const & shape, Accessor a, | | initMultiArrayImpl(Iterator s, Shape const & shape, Accessor a, | |
| VALUETYPE const & v, MetaInt<N>) | | VALUETYPE const & v, MetaInt<N>) | |
| { | | { | |
| Iterator send = s + shape[N]; | | Iterator send = s + shape[N]; | |
| for(; s < send; ++s) | | for(; s < send; ++s) | |
| { | | { | |
| initMultiArrayImpl(s.begin(), shape, a, v, MetaInt<N-1>()); | | initMultiArrayImpl(s.begin(), shape, a, v, MetaInt<N-1>()); | |
| } | | } | |
| } | | } | |
| | | | |
|
| /** \brief Write a value to every pixel in a multi-dimensional array. | | /** \brief Write a value to every element in a multi-dimensional array. | |
| | | | |
| This function can be used to init the array which must be represented b | | | |
| y | | | |
| a pair of iterators compatible to \ref vigra::MultiIterator. | | | |
| It uses an accessor to access the data elements. Note that the iterator | | | |
| range | | | |
| must be specified by a shape object, because otherwise we could not con | | | |
| trol | | | |
| the range simultaneously in all dimensions (this is a necessary consequ | | | |
| ence | | | |
| of the \ref vigra::MultiIterator design). | | | |
| | | | |
| The initial value can either be a constant of appropriate type (compati
ble with | | The initial value can either be a constant of appropriate type (compati
ble with | |
| the destination's value_type), or a functor with compatible result_type
. These two | | the destination's value_type), or a functor with compatible result_type
. These two | |
| cases are automatically distinguished when <tt>FunctorTraits<FUNCTOR>::
isInitializer</tt> | | cases are automatically distinguished when <tt>FunctorTraits<FUNCTOR>::
isInitializer</tt> | |
| yields <tt>VigraTrueType</tt>. Since the functor is passed by <tt>const
</tt> reference, its | | yields <tt>VigraTrueType</tt>. Since the functor is passed by <tt>const
</tt> reference, its | |
| <tt>operator()</tt> must be const, and its internal state may need to b
e <tt>mutable</tt>. | | <tt>operator()</tt> must be const, and its internal state may need to b
e <tt>mutable</tt>. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T, class S, class VALUETYPE> | |
| | | void | |
| | | initMultiArray(MultiArrayView<N, T, S> s, VALUETYPE const & v); | |
| | | | |
| | | template <unsigned int N, class T, class S, class FUNCTOR> | |
| | | void | |
| | | initMultiArray(MultiArrayView<N, T, S> s, FUNCTOR const & f); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{initMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Iterator, class Shape, class Accessor, class VALUET
YPE> | | template <class Iterator, class Shape, class Accessor, class VALUET
YPE> | |
| void | | void | |
| initMultiArray(Iterator s, Shape const & shape, Accessor a, VALUET
YPE const & v); | | initMultiArray(Iterator s, Shape const & shape, Accessor a, VALUET
YPE const & v); | |
| | | | |
| template <class Iterator, class Shape, class Accessor, class FUNCTO
R> | | template <class Iterator, class Shape, class Accessor, class FUNCTO
R> | |
| void | | void | |
| initMultiArray(Iterator s, Shape const & shape, Accessor a, FUNCTO
R const & f); | | initMultiArray(Iterator s, Shape const & shape, Accessor a, FUNCTO
R const & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Iterator, class Shape, class Accessor, class VALUET
YPE> | | template <class Iterator, class Shape, class Accessor, class VALUET
YPE> | |
| void | | void | |
| initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETY
PE const & v); | | initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETY
PE const & v); | |
| | | | |
| template <class Iterator, class Shape, class Accessor, class FUNCTO
R> | | template <class Iterator, class Shape, class Accessor, class FUNCTO
R> | |
| void | | void | |
| initMultiArray(triple<Iterator, Shape, Accessor> const & s, FUNCTOR
const & f); | | initMultiArray(triple<Iterator, Shape, Accessor> const & s, FUNCTOR
const & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | | <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| typedef vigra::MultiArray<3, int> Array; | | MultiArray<3, unsigned int> array(Shape3(100, 200, 50)); | |
| Array array(Array::size_type(100, 200, 50)); | | | |
| | | // make an array of all ones | |
| | | initMultiArray(array, 1); | |
| | | | |
| | | // equivalent calls: | |
| | | array = 1; | |
| | | array.init(1); | |
| | | | |
|
| // zero the array | | // fill the array with random numbers | |
| vigra::initMultiArray(destMultiArrayRange(array), 0); | | #include <vigra/random.hxx> | |
| | | | |
| | | initMultiArray(array, MersenneTwister()); | |
| \endcode | | \endcode | |
| | | | |
|
| <b> Required Interface:</b> | | \deprecatedUsage{initMultiArray} | |
| | | \code | |
| | | MultiArray<3, int> array(Shape3(100, 200, 50)); | |
| | | | |
|
| | | // make an array of all twos | |
| | | vigra::initMultiArray(destMultiArrayRange(array), 2); | |
| | | \endcode | |
| | | <b> Required Interface:</b> | |
| The function accepts either a value that is copied into every destinati
on element: | | The function accepts either a value that is copied into every destinati
on element: | |
|
| | | | |
| \code | | \code | |
| MultiIterator begin; | | MultiIterator begin; | |
| | | | |
| Accessor accessor; | | Accessor accessor; | |
| VALUETYPE v; | | VALUETYPE v; | |
| | | | |
| accessor.set(v, begin); | | accessor.set(v, begin); | |
| \endcode | | \endcode | |
|
| | | | |
| or a functor that is called (without argument) at every location, | | or a functor that is called (without argument) at every location, | |
| and the result is written into the current element. Internally, | | and the result is written into the current element. Internally, | |
| functors are recognized by the meta function | | functors are recognized by the meta function | |
| <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> yielding <tt>VigraTrueTy
pe</tt>. | | <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> yielding <tt>VigraTrueTy
pe</tt>. | |
| Make sure that your functor correctly defines <tt>FunctorTraits</tt> be
cause | | Make sure that your functor correctly defines <tt>FunctorTraits</tt> be
cause | |
| otherwise the code will not compile. | | otherwise the code will not compile. | |
|
| | | | |
| \code | | \code | |
| MultiIterator begin; | | MultiIterator begin; | |
| Accessor accessor; | | Accessor accessor; | |
| | | | |
| FUNCTOR f; | | FUNCTOR f; | |
| assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTru
eType)); | | assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTru
eType)); | |
| | | | |
| accessor.set(f(), begin); | | accessor.set(f(), begin); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void initMultiArray) | | doxygen_overloaded_function(template <...> void initMultiArray) | |
| | | | |
| template <class Iterator, class Shape, class Accessor, class VALUETYPE> | | template <class Iterator, class Shape, class Accessor, class VALUETYPE> | |
| inline void | | inline void | |
| initMultiArray(Iterator s, Shape const & shape, Accessor a, VALUETYPE cons
t & v) | | initMultiArray(Iterator s, Shape const & shape, Accessor a, VALUETYPE cons
t & v) | |
| { | | { | |
| initMultiArrayImpl(s, shape, a, v, MetaInt<Iterator::level>()); | | initMultiArrayImpl(s, shape, a, v, MetaInt<Iterator::level>()); | |
| } | | } | |
| | | | |
| template <class Iterator, class Shape, class Accessor, class VALUETYPE> | | template <class Iterator, class Shape, class Accessor, class VALUETYPE> | |
|
| inline | | inline void | |
| void | | | |
| initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETYPE const
& v) | | initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETYPE const
& v) | |
| { | | { | |
|
| initMultiArray(s.first, s.second, s.third, v); | | initMultiArrayImpl(s.first, s.second, s.third, v, MetaInt<Iterator::le | |
| | | vel>()); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T, class S, class VALUETYPE> | |
| | | inline void | |
| | | initMultiArray(MultiArrayView<N, T, S> s, VALUETYPE const & v) | |
| | | { | |
| | | initMultiArray(destMultiArrayRange(s), v); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* initMultiArrayBorder */ | | /* initMultiArrayBorder */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
|
| /** \brief Write value to the specified border values in the array. | | /** \brief Write values to the specified border values in the array. | |
| | | | |
| | | This functions is similar to \ref initMultiArray(), but it initializes | |
| | | only | |
| | | the array elements whose distance from any array border is at most \a b | |
| | | order_width. | |
| | | | |
| | | <b> Declarations:</b> | |
| | | | |
| | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // init equal borders on all array sides | |
| | | template <unsigned int N, class T, class S, | |
| | | class VALUETYPE> | |
| | | void | |
| | | initMultiArrayBorder( MultiArrayView<N, T, S> array, | |
| | | MultiArrayIndex border_width, VALUETYPE const | |
| | | & v); | |
| | | | |
| | | template <unsigned int N, class T, class S, | |
| | | class FUNCTOR> | |
| | | void | |
| | | initMultiArrayBorder( MultiArrayView<N, T, S> array, | |
| | | MultiArrayIndex border_width, FUNCTOR const & | |
| | | v); | |
| | | | |
| | | // specify border width individually for all array sides | |
| | | template <unsigned int N, class T, class S, | |
| | | class VALUETYPE> | |
| | | void | |
| | | initMultiArrayBorder( MultiArrayView<N, T, S> array, | |
| | | typename MultiArrayShape<N>::type const & low | |
| | | er_border, | |
| | | typename MultiArrayShape<N>::type const & upp | |
| | | er_border, | |
| | | VALUETYPE const & v); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{initMultiArrayBorder} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class Iterator, class Diff_type, class Accessor, | |
| | | class VALUETYPE> | |
| | | void | |
| | | initMultiArrayBorder(Iterator upperleft, Diff_type shape, Accessor | |
| | | a, | |
| | | MultiArrayIndex border_width, VALUETYPE const | |
| | | & v); | |
| | | } | |
| | | \endcode | |
| | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class Iterator, class Diff_type, class Accessor, | |
| | | class VALUETYPE> | |
| | | inline void | |
| | | initMultiArrayBorder( triple<Iterator, Diff_type, Accessor> multiAr | |
| | | ray, | |
| | | MultiArrayIndex border_width, VALUETYPE const | |
| | | & v); | |
| | | } | |
| | | \endcode | |
| | | \deprecatedEnd | |
| | | | |
| | | <b> Usage:</b> | |
| | | | |
| | | <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<3, unsigned int> array(Shape3(100, 200, 50)); | |
| | | | |
| | | int border_width = 5; | |
| | | | |
|
| */template <class Iterator, class Diff_type, class Accessor, class VALUETYP | | // init the array interior to 1, the border to 2 | |
| E> | | initMultiArray(array.subarray(Shape3(border_width), Shape3(-border_widt | |
| inline void initMultiArrayBorder( Iterator upperleft, Diff_type shape, | | h)), 1); | |
| Accessor a, int border_width, VALUETYPE | | initMultiArrayBorder(array, border_width, 2); | |
| v) | | \endcode | |
| | | */ | |
| | | doxygen_overloaded_function(template <...> void initMultiArrayBorder) | |
| | | | |
| | | template <class Iterator, class Diff_type, class Accessor, | |
| | | class VALUETYPE> | |
| | | void | |
| | | initMultiArrayBorder(Iterator upperleft, Diff_type shape, Accessor a, | |
| | | Diff_type lower_border, Diff_type upper_border, | |
| | | VALUETYPE const & v) | |
| { | | { | |
|
| Diff_type border(shape); | | for(unsigned int dim=0; dim<shape.size(); dim++) | |
| for(unsigned int dim=0; dim<shape.size(); dim++){ | | { | |
| border[dim] = (border_width > shape[dim]) ? shape[dim] : border_wid | | lower_border[dim] = (lower_border[dim] > shape[dim]) ? shape[dim] : | |
| th; | | lower_border[dim]; | |
| | | upper_border[dim] = (upper_border[dim] > shape[dim]) ? shape[dim] : | |
| | | upper_border[dim]; | |
| } | | } | |
| | | | |
|
| for(unsigned int dim=0; dim<shape.size(); dim++){ | | for(unsigned int dim=0; dim<shape.size(); dim++) | |
| Diff_type start(shape), | | { | |
| | | Diff_type start, | |
| offset(shape); | | offset(shape); | |
|
| start = start-shape; | | offset[dim] = lower_border[dim]; | |
| offset[dim]=border[dim]; | | | |
| | | | |
| initMultiArray(upperleft+start, offset, a, v); | | initMultiArray(upperleft+start, offset, a, v); | |
| | | | |
|
| start[dim]=shape[dim]-border[dim]; | | start[dim] = shape[dim] - upper_border[dim]; | |
| | | offset[dim] = upper_border[dim]; | |
| initMultiArray(upperleft+start, offset, a, v); | | initMultiArray(upperleft+start, offset, a, v); | |
| } | | } | |
| } | | } | |
| | | | |
|
| template <class Iterator, class Diff_type, class Accessor, class VALUETYPE> | | template <class Iterator, class Diff_type, class Accessor, | |
| inline void initMultiArrayBorder( triple<Iterator, Diff_type, Accessor> mul | | class VALUETYPE> | |
| tiArray, | | inline void | |
| int border_width, VALUETYPE v) | | initMultiArrayBorder(Iterator upperleft, Diff_type shape, Accessor a, | |
| | | MultiArrayIndex border_width, VALUETYPE const & v) | |
| | | { | |
| | | initMultiArrayBorder(upperleft, shape, a, | |
| | | Diff_type(border_width), Diff_type(border_width), | |
| | | v); | |
| | | } | |
| | | | |
| | | template <class Iterator, class Diff_type, class Accessor, | |
| | | class VALUETYPE> | |
| | | inline void | |
| | | initMultiArrayBorder( triple<Iterator, Diff_type, Accessor> multiArray, | |
| | | MultiArrayIndex border_width, VALUETYPE const & v) | |
| { | | { | |
| initMultiArrayBorder(multiArray.first, multiArray.second, multiArray.th
ird, border_width, v); | | initMultiArrayBorder(multiArray.first, multiArray.second, multiArray.th
ird, border_width, v); | |
| } | | } | |
| | | | |
|
| | | template <class Iterator, class Diff_type, class Accessor, | |
| | | class VALUETYPE> | |
| | | inline void | |
| | | initMultiArrayBorder( triple<Iterator, Diff_type, Accessor> multiArray, | |
| | | Diff_type const & lower_border, Diff_type const & upp | |
| | | er_border, | |
| | | VALUETYPE const & v) | |
| | | { | |
| | | initMultiArrayBorder(multiArray.first, multiArray.second, multiArray.th | |
| | | ird, | |
| | | lower_border, upper_border, v); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T, class S, | |
| | | class VALUETYPE> | |
| | | inline void | |
| | | initMultiArrayBorder( MultiArrayView<N, T, S> array, | |
| | | MultiArrayIndex border_width, VALUETYPE const & v) | |
| | | { | |
| | | initMultiArrayBorder(destMultiArrayRange(array), border_width, v); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T, class S, | |
| | | class VALUETYPE> | |
| | | inline void | |
| | | initMultiArrayBorder( MultiArrayView<N, T, S> array, | |
| | | typename MultiArrayShape<N>::type const & lower_borde | |
| | | r, | |
| | | typename MultiArrayShape<N>::type const & upper_borde | |
| | | r, | |
| | | VALUETYPE const & v) | |
| | | { | |
| | | initMultiArrayBorder(destMultiArrayRange(array), lower_border, upper_bo | |
| | | rder, v); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* copyMultiArray */ | | /* copyMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestShape, class DestAccessor> | | class DestIterator, class DestShape, class DestAccessor> | |
| void | | void | |
| copyMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src, | | copyMultiArrayImpl(SrcIterator s, SrcShape const & sshape, SrcAccessor src, | |
| | | | |
| skipping to change at line 300 | | skipping to change at line 445 | |
| The given row is automatically repeated for every row of the destin
ation image. | | The given row is automatically repeated for every row of the destin
ation image. | |
| Again, type conversion os performed if necessary. | | Again, type conversion os performed if necessary. | |
| </DL> | | </DL> | |
| | | | |
| The arrays must be represented by | | The arrays must be represented by | |
| iterators compatible with \ref vigra::MultiIterator, and the iteration
range | | iterators compatible with \ref vigra::MultiIterator, and the iteration
range | |
| is specified by means of shape objects. If only the source shape is giv
en | | is specified by means of shape objects. If only the source shape is giv
en | |
| the destination array is assumed to have the same shape, and standard m
ode | | the destination array is assumed to have the same shape, and standard m
ode | |
| is applied. If two shapes are given, the size of corresponding dimensio
ns | | is applied. If two shapes are given, the size of corresponding dimensio
ns | |
| must be either equal (standard copy), or the source length must be 1 | | must be either equal (standard copy), or the source length must be 1 | |
|
| (expanding copy). The function uses accessors to access the data elemen
ts. | | (expanding copy). | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
| <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | | <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | copyMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{copyMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| copyMultiArray(SrcIterator s, | | copyMultiArray(SrcIterator s, | |
| SrcShape const & shape, SrcAccessor src, | | SrcShape const & shape, SrcAccessor src, | |
| DestIterator d, DestAccessor dest); | | DestIterator d, DestAccessor dest); | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestShape, class DestAccessor> | | class DestIterator, class DestShape, class DestAccessor> | |
| void | | void | |
| copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor
src, | | copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor
src, | |
| DestIterator d, DestShape const & dshape, DestAccess
or dest); | | DestIterator d, DestShape const & dshape, DestAccess
or dest); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & s
rc, | | copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & s
rc, | |
| pair<DestIterator, DestAccessor> const & dest); | | pair<DestIterator, DestAccessor> const & dest); | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestShape, class DestAccessor> | | class DestIterator, class DestShape, class DestAccessor> | |
| void | | void | |
| copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & s
rc, | | copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & s
rc, | |
| triple<DestIterator, DestShape, DestAccessor> const
& dest); | | triple<DestIterator, DestShape, DestAccessor> const
& dest); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage - Standard Mode:</b> | | <b> Usage - Standard Mode:</b> | |
| | | | |
| \code | | \code | |
|
| typedef vigra::MultiArray<3, int> Array; | | MultiArray<3, int> src(Shape3(100, 200, 50)), | |
| Array src(Array::size_type(100, 200, 50)), | | dest(Shape3(100, 200, 50)); | |
| dest(Array::size_type(100, 200, 50)); | | | |
| ... | | ... | |
| | | | |
|
| vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArray(dest)); | | copyMultiArray(src, dest); | |
| | | | |
| | | // equivalent to | |
| | | dest = src; | |
| | | | |
| | | // copy only the red channel (i.e. channl 0) of an RGB array | |
| | | MultiArray<3, RGBValue<int> > rgb_src(Shape3(100, 200, 50)); | |
| | | | |
| | | copyMultiArray(rgb_src.bindElementChannel(0), dest); | |
| | | | |
| | | // equivalent to | |
| | | dest = rgb_src.bindElementChannel(0); | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage - Expanding Mode:</b> | | <b> Usage - Expanding Mode:</b> | |
| | | | |
|
| The source array is only 2D (it has depth 1). Thus, the destination | | The source array is effectively only a 2D image (it has a 3D shape, but | |
| will contain 50 identical copies of this image. Note that the destinati | | 'depth' is a | |
| on shape | | singleton dimension with length 1). Thus, the destination will contain | |
| must be passed to the algorithm for the expansion to work, so we use | | 50 identical | |
| <tt>destMultiArrayRange()</tt> rather than <tt>destMultiArray()</tt>. | | copies of this image: | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<3, int> src(Shape2(100, 200)), | |
| | | dest(Shape3(100, 200, 50)); | |
| | | ... | |
| | | | |
| | | copyMultiArray(src.insertSingletonDimension(2), dest); | |
| | | | |
| | | // create an RGB image with three identical color bands | |
| | | MultiArray<3, RGBValue<int> > rgb_dest(Shape2(100, 200)); | |
| | | | |
| | | copyMultiArray(src.insertSingletonDimension(2), rgb_dest.expandElements | |
| | | (2)); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{copyMultiArray} | |
| | | \code | |
| typedef vigra::MultiArray<3, int> Array; | | typedef vigra::MultiArray<3, int> Array; | |
|
| Array src(Array::size_type(100, 200, 1)), | | Array src(Array::size_type(100, 200, 50)), | |
| dest(Array::size_type(100, 200, 50)); | | dest(Array::size_type(100, 200, 50)); | |
| ... | | ... | |
| | | | |
|
| vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArrayRange(dest
)); | | vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArray(dest)); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| MultiIterator src_begin, dest_begin; | | MultiIterator src_begin, dest_begin; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| dest_accessor.set(src_accessor(src_begin), dest_begin); | | dest_accessor.set(src_accessor(src_begin), dest_begin); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void copyMultiArray) | | doxygen_overloaded_function(template <...> void copyMultiArray) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| copyMultiArray(SrcIterator s, | | copyMultiArray(SrcIterator s, | |
| SrcShape const & shape, SrcAccessor src, | | SrcShape const & shape, SrcAccessor src, | |
| DestIterator d, DestAccessor dest) | | DestIterator d, DestAccessor dest) | |
| { | | { | |
| copyMultiArrayImpl(s, shape, src, d, shape, dest, MetaInt<SrcIterator::
level>()); | | copyMultiArrayImpl(s, shape, src, d, shape, dest, MetaInt<SrcIterator::
level>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
|
| class DestIterator, class DestAccessor> | | | |
| inline void | | | |
| copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src, | | | |
| pair<DestIterator, DestAccessor> const & dest) | | | |
| { | | | |
| | | | |
| copyMultiArray(src.first, src.second, src.third, dest.first, dest.secon | | | |
| d); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | | |
| class DestIterator, class DestShape, class DestAccessor> | | class DestIterator, class DestShape, class DestAccessor> | |
| void | | void | |
| copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src, | | copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src, | |
| DestIterator d, DestShape const & dshape, DestAccessor dest) | | DestIterator d, DestShape const & dshape, DestAccessor dest) | |
| { | | { | |
| vigra_precondition(sshape.size() == dshape.size(), | | vigra_precondition(sshape.size() == dshape.size(), | |
| "copyMultiArray(): dimensionality of source and destination array d
iffer"); | | "copyMultiArray(): dimensionality of source and destination array d
iffer"); | |
| for(unsigned int i=0; i<sshape.size(); ++i) | | for(unsigned int i=0; i<sshape.size(); ++i) | |
| vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i], | | vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i], | |
| "copyMultiArray(): mismatch between source and destination shap
es:\n" | | "copyMultiArray(): mismatch between source and destination shap
es:\n" | |
| "length of each source dimension must either be 1 or equal to t
he corresponding " | | "length of each source dimension must either be 1 or equal to t
he corresponding " | |
| "destination length."); | | "destination length."); | |
| copyMultiArrayImpl(s, sshape, src, d, dshape, dest, MetaInt<SrcIterator
::level>()); | | copyMultiArrayImpl(s, sshape, src, d, dshape, dest, MetaInt<SrcIterator
::level>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
|
| | | class DestIterator, class DestAccessor> | |
| | | inline void | |
| | | copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src, | |
| | | pair<DestIterator, DestAccessor> const & dest) | |
| | | { | |
| | | | |
| | | copyMultiArray(src.first, src.second, src.third, dest.first, dest.secon | |
| | | d); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestShape, class DestAccessor> | | class DestIterator, class DestShape, class DestAccessor> | |
| inline void | | inline void | |
| copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src, | | copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src, | |
| triple<DestIterator, DestShape, DestAccessor> const & dest) | | triple<DestIterator, DestShape, DestAccessor> const & dest) | |
| { | | { | |
| | | | |
| copyMultiArray(src.first, src.second, src.third, dest.first, dest.secon
d, dest.third); | | copyMultiArray(src.first, src.second, src.third, dest.first, dest.secon
d, dest.third); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | copyMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest) | |
| | | { | |
| | | for(int k=0; k<N; ++k) | |
| | | vigra_precondition(source.shape(k) == dest.shape(k) || source.shape | |
| | | (k) == 1 || 1 == dest.shape(k), | |
| | | "copyMultiArray(): shape mismatch between input and output."); | |
| | | if(source.shape() == dest.shape()) | |
| | | copyMultiArray(srcMultiArrayRange(source), destMultiArray(dest)); | |
| | | else | |
| | | copyMultiArray(srcMultiArrayRange(source), destMultiArrayRange(dest | |
| | | )); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* transformMultiArray */ | | /* transformMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| | | | |
| skipping to change at line 559 | | skipping to change at line 751 | |
| vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i], | | vigra_precondition(sshape[i] == 1 || sshape[i] == dshape[i], | |
| "transformMultiArray(): mismatch between source and destination
shapes:\n" | | "transformMultiArray(): mismatch between source and destination
shapes:\n" | |
| "In 'expand'-mode, the length of each source dimension must eit
her be 1\n" | | "In 'expand'-mode, the length of each source dimension must eit
her be 1\n" | |
| "or equal to the corresponding destination length."); | | "or equal to the corresponding destination length."); | |
| transformMultiArrayExpandImpl(s, sshape, src, d, dshape, dest, | | transformMultiArrayExpandImpl(s, sshape, src, d, dshape, dest, | |
| f, MetaInt<SrcIterator::level>()); | | f, MetaInt<SrcIterator::level>()); | |
| } | | } | |
| | | | |
| /** \brief Transform a multi-dimensional array with a unary function or fun
ctor. | | /** \brief Transform a multi-dimensional array with a unary function or fun
ctor. | |
| | | | |
|
| | | Note: The effect of this function can often be achieved in a simpler an | |
| | | d | |
| | | more readable way by means of \ref MultiMathModule "array experessions" | |
| | | . | |
| | | | |
| This function can be applied in three modes: | | This function can be applied in three modes: | |
| | | | |
| <DL> | | <DL> | |
| <DT><b>Standard Mode:</b> | | <DT><b>Standard Mode:</b> | |
| <DD>If the source and destination arrays have the same size, | | <DD>If the source and destination arrays have the same size, | |
| the transformation given by the functor is applied to every source | | the transformation given by the functor is applied to every source | |
| element and the result written into the corresponding destination e
lement. | | element and the result written into the corresponding destination e
lement. | |
| Unary functions, unary functors from the STL and the functors speci
fically | | Unary functions, unary functors from the STL and the functors speci
fically | |
| defined in \ref TransformFunctor can be used in standard mode. | | defined in \ref TransformFunctor can be used in standard mode. | |
| Creation of new functors is easiest by using \ref FunctorExpression
s. | | Creation of new functors is easiest by using \ref FunctorExpression
s. | |
| | | | |
| skipping to change at line 588 | | skipping to change at line 783 | |
| <DT><b>Reducing Mode:</b> | | <DT><b>Reducing Mode:</b> | |
| <DD>If the destination array has length 1 along some (or even all)
dimensions, | | <DD>If the destination array has length 1 along some (or even all)
dimensions, | |
| the source values in these dimensions are reduced to single values
by means | | the source values in these dimensions are reduced to single values
by means | |
| of a suitable functor (e.g. \ref vigra::ReduceFunctor), which suppo
rts two | | of a suitable functor (e.g. \ref vigra::ReduceFunctor), which suppo
rts two | |
| function call operators: one | | function call operators: one | |
| with a single argument to collect the values, and without argument
to | | with a single argument to collect the values, and without argument
to | |
| obtain the final (reduced) result. This behavior is a multi-dimensi
onal | | obtain the final (reduced) result. This behavior is a multi-dimensi
onal | |
| generalization of the C++ standard function <tt>std::accumulate()</
tt>. | | generalization of the C++ standard function <tt>std::accumulate()</
tt>. | |
| </DL> | | </DL> | |
| | | | |
|
| The arrays must be represented by | | The arrays must be represented by MultiArrayViews. If source and destin | |
| iterators compatible with \ref vigra::MultiIterator, and the iteration | | ation shapes | |
| range | | match, standard mode is applied. If the shapes differ, the size of corr | |
| is specified by means of shape objects. If only the source shape is giv | | esponding | |
| en | | dimensions must either be equal, or the source length must be 1 | |
| the destination array is assumed to have the same shape, and standard m | | | |
| ode | | | |
| is applied. If two shapes are given, the size of corresponding dimensio | | | |
| ns | | | |
| must be either equal (standard copy), or the source length must be 1 | | | |
| (expand mode), or the destination length must be 1 (reduce mode). Howev
er, | | (expand mode), or the destination length must be 1 (reduce mode). Howev
er, | |
| reduction and expansion cannot be executed at the same time, so the lat
ter | | reduction and expansion cannot be executed at the same time, so the lat
ter | |
| conditions are mutual exclusive, even if they apply to different dimens
ions. | | conditions are mutual exclusive, even if they apply to different dimens
ions. | |
| | | | |
|
| The function uses accessors to access the data elements. | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
| <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | | <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | void | |
| | | transformMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, Functor const & | |
| | | f); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{transformMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAcces
sor src, | | transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAcces
sor src, | |
| DestIterator d, DestAccessor dest, Functor cons
t & f); | | DestIterator d, DestAccessor dest, Functor cons
t & f); | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAcce
ssor src, | | transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAcce
ssor src, | |
| DestIterator d, DestShape const & dshape, DestA
ccessor dest, | | DestIterator d, DestShape const & dshape, DestA
ccessor dest, | |
| Functor const & f); | | Functor const & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & src, | | transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & src, | |
| pair<DestIterator, DestAccessor> const & dest,
Functor const & f); | | pair<DestIterator, DestAccessor> const & dest,
Functor const & f); | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & src, | | transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> cons
t & src, | |
| triple<DestIterator, DestShape, DestAccessor> c
onst & dest, | | triple<DestIterator, DestShape, DestAccessor> c
onst & dest, | |
| Functor const & f) | | Functor const & f) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage - Standard Mode:</b> | | <b> Usage - Standard Mode:</b> | |
| | | | |
| Source and destination array have the same size. | | Source and destination array have the same size. | |
| | | | |
| \code | | \code | |
| #include <cmath> // for sqrt() | | #include <cmath> // for sqrt() | |
| | | | |
|
| typedef vigra::MultiArray<3, float> Array; | | MultiArray<3, float> src(Shape3(100, 200, 50)), | |
| Array src(Array::size_type(100, 200, 50)), | | dest(Shape3(100, 200, 50)); | |
| dest(Array::size_type(100, 200, 50)); | | | |
| ... | | ... | |
| | | | |
|
| vigra::transformMultiArray(srcMultiArrayRange(src), | | transformMultiArray(src, dest, &std::sqrt ); | |
| destMultiArray(dest), | | | |
| (float(*)(float))&std::sqrt ); | | | |
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage - Expand Mode:</b> | | <b> Usage - Expand Mode:</b> | |
| | | | |
|
| The source array is only 2D (it has depth 1). Thus, the destination | | The source array is effectively only a 2D image(it has a 3D shape, but | |
| will contain 50 identical copies of the transformed source array. | | depth is a singleton dimension | |
| Note that the destination shape must be passed to the algorithm for | | with length 1). Thus, the destination will contain 50 identical copies | |
| the expansion to work, so we use <tt>destMultiArrayRange()</tt> | | of the transformed source image. | |
| rather than <tt>destMultiArray()</tt>. | | | |
| | | | |
| \code | | \code | |
| #include <cmath> // for sqrt() | | #include <cmath> // for sqrt() | |
| | | | |
|
| typedef vigra::MultiArray<3, float> Array; | | MultiArray<3, float> src(Shape3(100, 200, 1)), | |
| Array src(Array::size_type(100, 200, 1)), | | dest(Shape3(100, 200, 50)); | |
| dest(Array::size_type(100, 200, 50)); | | | |
| ... | | ... | |
| | | | |
|
| vigra::transformMultiArray(srcMultiArrayRange(src), | | transformMultiArray(src, dest, &std::sqrt ); | |
| destMultiArrayRange(dest), | | | |
| (float(*)(float))&std::sqrt ); | | | |
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage - Reduce Mode:</b> | | <b> Usage - Reduce Mode:</b> | |
| | | | |
|
| The destination array is only 1D (it's width and height are 1). | | The destination array is effectively only 1D (it's width and height are
singleton dimensions). | |
| Thus, it will contain accumulated data for every slice of the source vo
lume | | Thus, it will contain accumulated data for every slice of the source vo
lume | |
| (or for every frame, if the source is interpreted as an image sequence)
. | | (or for every frame, if the source is interpreted as an image sequence)
. | |
| In the example, we use the functor \ref vigra::FindAverage to calculate | | In the example, we use the functor \ref vigra::FindAverage to calculate | |
|
| the average gray value of every slice. Note that the destination shape | | the average gray value of every slice. | |
| must also be passed for the reduction to work, so we use | | | |
| <tt>destMultiArrayRange()</tt> rather than <tt>destMultiArray()</tt>. | | | |
| | | | |
| \code | | \code | |
|
| typedef vigra::MultiArray<3, float> Array; | | MultiArray<3, float> src(Shape3(100, 200, 50)), | |
| Array src(Array::size_type(100, 200, 50)), | | dest(Shape3(1, 1, 50)); | |
| dest(Array::size_type(1, 1, 50)); | | | |
| ... | | ... | |
| | | | |
|
| vigra::transformMultiArray(srcMultiArrayRange(src), | | transformMultiArray(src, dest, | |
| destMultiArrayRange(dest), | | FindAverage<float>() ); | |
| vigra::FindAverage<float>() ); | | | |
| | | | |
| \endcode | | \endcode | |
| | | | |
| Note that the functor must define the appropriate traits described belo
w in order to be | | Note that the functor must define the appropriate traits described belo
w in order to be | |
| recognized as a reduce functor. This is most easily achieved by derivin
g from | | recognized as a reduce functor. This is most easily achieved by derivin
g from | |
| <tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits). | | <tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits). | |
| | | | |
|
| <b> Required Interface:</b> | | \deprecatedUsage{transformMultiArray} | |
| | | | |
| In standard and expand mode, the functor must be a model of UnaryFuncti | | | |
| on | | | |
| (i.e. support function call with one argument and a return value | | | |
| <tt>res = functor(arg)</tt>): | | | |
| | | | |
| \code | | \code | |
|
| MultiIterator src_begin, src_end, dest_begin; | | #include <cmath> // for sqrt() | |
| | | | |
|
| SrcAccessor src_accessor; | | typedef vigra::MultiArray<3, float> Array; | |
| DestAccessor dest_accessor; | | Array src(Shape3(100, 200, 50)), | |
| Functor functor; | | dest(Shape3(100, 200, 50)); | |
| | | ... | |
| | | | |
| | | vigra::transformMultiArray(srcMultiArrayRange(src), | |
| | | destMultiArray(dest), | |
| | | (float(*)(float))&std::sqrt ); | |
| | | | |
|
| dest_accessor.set(functor(src_accessor(src_begin)), dest_begin); | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| | | <b> Required Interface:</b> | |
| | | | |
| | | In standard and expand mode, the functor must be a model of UnaryFuncti | |
| | | on | |
| | | (i.e. support one-argument function call which accepts values of type | |
| | | <tt>T1</tt> and a return value that is convertible into <tt>T2</tt>. | |
| | | | |
| In reduce mode, it must be a model of UnaryAnalyser (i.e. support funct
ion call | | In reduce mode, it must be a model of UnaryAnalyser (i.e. support funct
ion call | |
| with one argument and no return value <tt>functor(arg)</tt>) and Initia
lizer | | with one argument and no return value <tt>functor(arg)</tt>) and Initia
lizer | |
| (i.e. support function call with no argument, but return value | | (i.e. support function call with no argument, but return value | |
| <tt>res = functor()</tt>). Internally, such functors are recognized by
the | | <tt>res = functor()</tt>). Internally, such functors are recognized by
the | |
| meta functions <tt>FunctorTraits<FUNCTOR>::isUnaryAnalyser</tt> and | | meta functions <tt>FunctorTraits<FUNCTOR>::isUnaryAnalyser</tt> and | |
| <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield | | <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield | |
| <tt>VigraTrueType</tt>. Make sure that your functor correctly defines | | <tt>VigraTrueType</tt>. Make sure that your functor correctly defines | |
| <tt>FunctorTraits</tt> because otherwise reduce mode will not work. | | <tt>FunctorTraits</tt> because otherwise reduce mode will not work. | |
| This is most easily achieved by deriving the functor from | | This is most easily achieved by deriving the functor from | |
| <tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits). | | <tt>UnaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits). | |
| In addition, the functor must be copy constructible in order to start e
ach reduction | | In addition, the functor must be copy constructible in order to start e
ach reduction | |
| with a fresh functor. | | with a fresh functor. | |
| | | | |
|
| \code | | \see TransformFunctor, MultiMathModule, \ref FunctorExpressions | |
| MultiIterator src_begin, src_end, dest_begin; | | | |
| | | | |
| SrcAccessor src_accessor; | | | |
| DestAccessor dest_accessor; | | | |
| | | | |
| FUNCTOR initial_functor, functor(initial_functor); | | | |
| assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTru | | | |
| eType)); | | | |
| assert(typeid(FunctorTraits<FUNCTOR>::isUnaryAnalyser) == typeid(VigraT | | | |
| rueType)); | | | |
| | | | |
| functor(src_accessor(src_begin)); | | | |
| dest_accessor.set(functor(), dest_begin); | | | |
| \endcode | | | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void transformMultiArray) | | doxygen_overloaded_function(template <...> void transformMultiArray) | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Functor> | | class Functor> | |
| inline void | | inline void | |
| transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAccessor src, | | transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAccessor src, | |
| DestIterator d, DestAccessor dest, Functor const & f) | | DestIterator d, DestAccessor dest, Functor const & f) | |
| { | | { | |
| transformMultiArrayExpandImpl(s, shape, src, d, shape, dest, | | transformMultiArrayExpandImpl(s, shape, src, d, shape, dest, | |
| f, MetaInt<SrcIterator::level>()); | | f, MetaInt<SrcIterator::level>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
|
| class DestIterator, class DestAccessor, | | | |
| class Functor> | | | |
| inline void | | | |
| transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src, | | | |
| pair<DestIterator, DestAccessor> const & dest, Functor const | | | |
| & f) | | | |
| { | | | |
| | | | |
| transformMultiArray(src.first, src.second, src.third, | | | |
| dest.first, dest.second, f); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src
, | | transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src
, | |
| DestIterator d, DestShape const & dshape, DestAccessor dest, | | DestIterator d, DestShape const & dshape, DestAccessor dest, | |
| Functor const & f) | | Functor const & f) | |
| { | | { | |
| vigra_precondition(sshape.size() == dshape.size(), | | vigra_precondition(sshape.size() == dshape.size(), | |
| "transformMultiArray(): dimensionality of source and destination ar
ray differ"); | | "transformMultiArray(): dimensionality of source and destination ar
ray differ"); | |
| typedef FunctorTraits<Functor> FT; | | typedef FunctorTraits<Functor> FT; | |
| typedef typename | | typedef typename | |
| And<typename FT::isInitializer, typename FT::isUnaryAnalyser>::resu
lt | | And<typename FT::isInitializer, typename FT::isUnaryAnalyser>::resu
lt | |
| isAnalyserInitializer; | | isAnalyserInitializer; | |
| transformMultiArrayImpl(s, sshape, src, d, dshape, dest, | | transformMultiArrayImpl(s, sshape, src, d, dshape, dest, | |
| f, isAnalyserInitializer()); | | f, isAnalyserInitializer()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcShape, class SrcAccessor, | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
|
| | | class DestIterator, class DestAccessor, | |
| | | class Functor> | |
| | | inline void | |
| | | transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src, | |
| | | pair<DestIterator, DestAccessor> const & dest, Functor | |
| | | const & f) | |
| | | { | |
| | | | |
| | | transformMultiArray(src.first, src.second, src.third, | |
| | | dest.first, dest.second, f); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcShape, class SrcAccessor, | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| inline void | | inline void | |
| transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src, | | transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src, | |
| triple<DestIterator, DestShape, DestAccessor> const & dest, | | triple<DestIterator, DestShape, DestAccessor> const & dest, | |
| Functor const & f) | | Functor const & f) | |
| { | | { | |
| transformMultiArray(src.first, src.second, src.third, | | transformMultiArray(src.first, src.second, src.third, | |
| dest.first, dest.second, dest.third, f); | | dest.first, dest.second, dest.third, f); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | transformMultiArrayImpl(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | Functor const & f, VigraFalseType) | |
| | | { | |
| | | if(source.shape() == dest.shape()) | |
| | | transformMultiArray(srcMultiArrayRange(source), destMultiArray(dest | |
| | | ), f); | |
| | | else | |
| | | transformMultiArray(srcMultiArrayRange(source), destMultiArrayRange | |
| | | (dest), f); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | transformMultiArrayImpl(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | Functor const & f, VigraTrueType) | |
| | | { | |
| | | transformMultiArray(srcMultiArrayRange(source), destMultiArrayRange(des | |
| | | t), f); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | transformMultiArray(MultiArrayView<N, T1, S1> const & source, | |
| | | MultiArrayView<N, T2, S2> dest, Functor const & f) | |
| | | { | |
| | | for(unsigned int k=0; k<N; ++k) | |
| | | vigra_precondition(source.shape(k) == dest.shape(k) || source.shape | |
| | | (k) == 1 || 1 == dest.shape(k), | |
| | | "transformMultiArray(): shape mismatch between input and output | |
| | | ."); | |
| | | | |
| | | typedef FunctorTraits<Functor> FT; | |
| | | typedef typename | |
| | | And<typename FT::isInitializer, typename FT::isUnaryAnalyser>::resu | |
| | | lt | |
| | | isAnalyserInitializer; | |
| | | transformMultiArrayImpl(source, dest, f, isAnalyserInitializer()); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* combineTwoMultiArrays */ | | /* combineTwoMultiArrays */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| class SrcIterator2, class SrcAccessor2, | | class SrcIterator2, class SrcAccessor2, | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| | | | |
| skipping to change at line 973 | | skipping to change at line 1196 | |
| "combineTwoMultiArrays(): mismatch between source and destinati
on shapes:\n" | | "combineTwoMultiArrays(): mismatch between source and destinati
on shapes:\n" | |
| "In 'expand'-mode, the length of each source dimension must eit
her be 1\n" | | "In 'expand'-mode, the length of each source dimension must eit
her be 1\n" | |
| "or equal to the corresponding destination length."); | | "or equal to the corresponding destination length."); | |
| combineTwoMultiArraysExpandImpl(s1, sshape1, src1, s2, sshape2, src2, | | combineTwoMultiArraysExpandImpl(s1, sshape1, src1, s2, sshape2, src2, | |
| d, dshape, dest, | | d, dshape, dest, | |
| f, MetaInt<SrcIterator1::level>()); | | f, MetaInt<SrcIterator1::level>()); | |
| } | | } | |
| | | | |
| /** \brief Combine two multi-dimensional arrays into one using a binary fun
ction or functor. | | /** \brief Combine two multi-dimensional arrays into one using a binary fun
ction or functor. | |
| | | | |
|
| | | Note: The effect of this function can often be achieved in a simpler an | |
| | | d | |
| | | more readable way by means of \ref MultiMathModule "array experessions" | |
| | | . | |
| | | | |
| This function can be applied in three modes: | | This function can be applied in three modes: | |
| | | | |
| <DL> | | <DL> | |
| <DT><b>Standard Mode:</b> | | <DT><b>Standard Mode:</b> | |
| <DD>If the source and destination arrays have the same size, | | <DD>If the source and destination arrays have the same size, | |
| the transformation given by the functor is applied to every pair of | | the transformation given by the functor is applied to every pair of | |
| corresponding source elements and the result written into the corre
sponding | | corresponding source elements and the result written into the corre
sponding | |
| destination element. | | destination element. | |
| Binary functions, binary functors from the STL and the functors spe
cifically | | Binary functions, binary functors from the STL and the functors spe
cifically | |
| defined in \ref CombineFunctor can be used in standard mode. | | defined in \ref CombineFunctor can be used in standard mode. | |
| | | | |
| skipping to change at line 1005 | | skipping to change at line 1231 | |
| The same functors as in standard mode can be applied. | | The same functors as in standard mode can be applied. | |
| <DT><b>Reducing Mode:</b> | | <DT><b>Reducing Mode:</b> | |
| <DD>If the destination array has length 1 along some (or even all)
dimensions, | | <DD>If the destination array has length 1 along some (or even all)
dimensions, | |
| the source values in these dimensions are reduced to single values
by means | | the source values in these dimensions are reduced to single values
by means | |
| of a suitable functor which supports two function call operators: o
ne | | of a suitable functor which supports two function call operators: o
ne | |
| with two arguments to collect the values, and one without argument
to | | with two arguments to collect the values, and one without argument
to | |
| obtain the final (reduced) result. This behavior is a multi-dimensi
onal | | obtain the final (reduced) result. This behavior is a multi-dimensi
onal | |
| generalization of the C++ standard function <tt>std::accumulate()</
tt>. | | generalization of the C++ standard function <tt>std::accumulate()</
tt>. | |
| </DL> | | </DL> | |
| | | | |
|
| The arrays must be represented by | | The arrays must be represented by MultiArrayViews. If all shapes are id | |
| iterators compatible with \ref vigra::MultiIterator, and the iteration | | entical, | |
| range | | standard mode is applied. If the shapes differ, the size of correspondi | |
| is specified by means of shape objects. If only a single source shape i | | ng dimensions | |
| s given | | must either be equal, or the length of this dimension must be 1 in one | |
| the destination array is assumed to have the same shape, and standard m | | or both source | |
| ode | | arrays (expand mode), or the destination length must be 1 (reduce mode) | |
| is applied. If three shapes are given, the size of corresponding dimens | | . However, | |
| ions | | | |
| must be either equal (standard copy), or the length of this dimension m | | | |
| ust | | | |
| be 1 in one or both source arrays | | | |
| (expand mode), or the destination length must be 1 (reduce mode). Howev | | | |
| er, | | | |
| reduction and expansion cannot be executed at the same time, so the lat
ter | | reduction and expansion cannot be executed at the same time, so the lat
ter | |
| conditions are mutual exclusive, even if they apply to different dimens
ions. | | conditions are mutual exclusive, even if they apply to different dimens
ions. | |
| | | | |
|
| The function uses accessors to access the data elements. | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
| <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | | <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T11, class S11, | |
| | | class T12, class S12, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | void | |
| | | combineTwoMultiArrays(MultiArrayView<N, T11, S11> const & source1, | |
| | | MultiArrayView<N, T12, S12> const & source2, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | Functor const & f); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{combineTwoMultiArrays} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| class SrcIterator2, class SrcAccessor2, | | class SrcIterator2, class SrcAccessor2, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void combineTwoMultiArrays( | | void combineTwoMultiArrays( | |
| SrcIterator1 s1, SrcShape const & shape, SrcAccessor
1 src1, | | SrcIterator1 s1, SrcShape const & shape, SrcAccessor
1 src1, | |
| SrcIterator2 s2, SrcAccessor2 src2, | | SrcIterator2 s2, SrcAccessor2 src2, | |
| DestIterator d, DestAccessor dest, Functor const & f
); | | DestIterator d, DestAccessor dest, Functor const & f
); | |
| | | | |
| skipping to change at line 1046 | | skipping to change at line 1282 | |
| class SrcIterator2, class SrcShape2, class SrcAccessor2, | | class SrcIterator2, class SrcShape2, class SrcAccessor2, | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void combineTwoMultiArrays( | | void combineTwoMultiArrays( | |
| SrcIterator1 s1, SrcShape1 const & sshape1, SrcAcces
sor1 src1, | | SrcIterator1 s1, SrcShape1 const & sshape1, SrcAcces
sor1 src1, | |
| SrcIterator2 s2, SrcShape2 const & sshape2, SrcAcces
sor2 src2, | | SrcIterator2 s2, SrcShape2 const & sshape2, SrcAcces
sor2 src2, | |
| DestIterator d, DestShape const & dshape, DestAccess
or dest, | | DestIterator d, DestShape const & dshape, DestAccess
or dest, | |
| Functor const & f); | | Functor const & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| class SrcIterator2, class SrcAccessor2, | | class SrcIterator2, class SrcAccessor2, | |
| class DestIterator, class DestAccessor, class Functor> | | class DestIterator, class DestAccessor, class Functor> | |
| void combineTwoMultiArrays( | | void combineTwoMultiArrays( | |
| triple<SrcIterator1, SrcShape, SrcAccessor1> const &
src1, | | triple<SrcIterator1, SrcShape, SrcAccessor1> const &
src1, | |
| pair<SrcIterator2, SrcAccessor2> const & src2, | | pair<SrcIterator2, SrcAccessor2> const & src2, | |
| pair<DestIterator, DestAccessor> const & dest, Funct
or const & f); | | pair<DestIterator, DestAccessor> const & dest, Funct
or const & f); | |
| | | | |
| skipping to change at line 1069 | | skipping to change at line 1304 | |
| class SrcIterator2, class SrcShape2, class SrcAccessor2, | | class SrcIterator2, class SrcShape2, class SrcAccessor2, | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void combineTwoMultiArrays( | | void combineTwoMultiArrays( | |
| triple<SrcIterator1, SrcShape1, SrcAccessor1> const
& src1, | | triple<SrcIterator1, SrcShape1, SrcAccessor1> const
& src1, | |
| triple<SrcIterator2, SrcShape2, SrcAccessor2> const
& src2, | | triple<SrcIterator2, SrcShape2, SrcAccessor2> const
& src2, | |
| triple<DestIterator, DestShape, DestAccessor> const
& dest, | | triple<DestIterator, DestShape, DestAccessor> const
& dest, | |
| Functor const & f); | | Functor const & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage - Standard Mode:</b> | | <b> Usage - Standard Mode:</b> | |
| | | | |
| Source and destination arrays have the same size. | | Source and destination arrays have the same size. | |
| | | | |
| \code | | \code | |
| #include <functional> // for std::plus | | #include <functional> // for std::plus | |
| | | | |
|
| typedef vigra::MultiArray<3, int> Array; | | MultiArray<3, int> src1(Shape3(100, 200, 50)), | |
| Array src1(Array::size_type(100, 200, 50)), | | src2(Shape3(100, 200, 50)), | |
| src2(Array::size_type(100, 200, 50)), | | dest(Shape3(100, 200, 50)); | |
| dest(Array::size_type(100, 200, 50)); | | | |
| ... | | ... | |
| | | | |
|
| vigra::combineTwoMultiArrays( | | combineTwoMultiArrays(src1, src2, dest, | |
| srcMultiArrayRange(src1), | | std::plus<int>()); | |
| srcMultiArray(src2), | | | |
| destMultiArray(dest), | | | |
| std::plus<int>()); | | | |
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage - Expand Mode:</b> | | <b> Usage - Expand Mode:</b> | |
| | | | |
|
| One source array is only 2D (it has depth 1). This image will be added | | One source array is effectively only a 2D image (it has depth 1). This | |
| to every slice of the other source array, and the result | | image will be added | |
| if written into the corresponding destination slice. Note that the shap | | to every slice of the other source array, and the result is written int | |
| es | | o the | |
| of all arrays must be passed to the algorithm, so we use | | corresponding destination slice. | |
| <tt>srcMultiArrayRange()</tt> and <tt>destMultiArrayRange()</tt> | | | |
| rather than <tt>srcMultiArray()</tt> and <tt>destMultiArray()</tt>. | | | |
| | | | |
| \code | | \code | |
| #include <functional> // for std::plus | | #include <functional> // for std::plus | |
| | | | |
|
| typedef vigra::MultiArray<3, int> Array; | | MultiArray<3, int> src1(Shape3(100, 200, 1)), | |
| Array src1(Array::size_type(100, 200, 1)), | | src2(Shape3(100, 200, 50)), | |
| src2(Array::size_type(100, 200, 50)), | | dest(Shape3(100, 200, 50)); | |
| dest(Array::size_type(100, 200, 50)); | | | |
| ... | | ... | |
| | | | |
|
| vigra::combineTwoMultiArrays( | | combineTwoMultiArrays(src1, src2, dest, | |
| srcMultiArrayRange(src1), | | std::plus<int>()); | |
| srcMultiArray(src2), | | | |
| destMultiArray(dest), | | | |
| std::plus<int>()); | | | |
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage - Reduce Mode:</b> | | <b> Usage - Reduce Mode:</b> | |
| | | | |
|
| The destination array is only 1D (it's width and height are 1). | | The destination array is only 1D (it's width and height are singleton d
imensions). | |
| Thus, it will contain accumulated data for every slice of the source vo
lumes | | Thus, it will contain accumulated data for every slice of the source vo
lumes | |
| (or for every frame, if the sources are interpreted as image sequences)
. | | (or for every frame, if the sources are interpreted as image sequences)
. | |
| In the example, we use \ref vigra::ReduceFunctor together with a functo
r | | In the example, we use \ref vigra::ReduceFunctor together with a functo
r | |
|
| expression (see \ref FunctorExpressions) | | expression (see \ref FunctorExpressions) to calculate the total absolut | |
| to calculate the total absolute difference of the gray values in every | | e difference | |
| pair of | | of the gray values in every pair of source slices. | |
| source slices. Note that the shapes of all arrays must be passed | | | |
| to the algorithm in order for the reduction to work, so we use | | | |
| <tt>srcMultiArrayRange()</tt> and <tt>destMultiArrayRange()</tt> | | | |
| rather than <tt>srcMultiArray()</tt> and <tt>destMultiArray()</tt>. | | | |
| | | | |
| \code | | \code | |
| #include <vigra/functorexpression.hxx> | | #include <vigra/functorexpression.hxx> | |
| using namespace vigra::functor; | | using namespace vigra::functor; | |
| | | | |
|
| typedef vigra::MultiArray<3, int> Array; | | MultiArray<3, int> src1(Shape3(100, 200, 50)), | |
| Array src1(Array::size_type(100, 200, 50)), | | src2(Shape3(100, 200, 50)), | |
| src2(Array::size_type(100, 200, 50)), | | dest(Shape3(1, 1, 50)); | |
| dest(Array::size_type(1, 1, 50)); | | | |
| ... | | ... | |
| | | | |
|
| vigra::combineTwoMultiArrays( | | combineTwoMultiArrays(src1, src2, dest, | |
| srcMultiArrayRange(src1), | | reduceFunctor(Arg1() + abs(Arg2() - Arg3()), 0) ) | |
| srcMultiArray(src2), | | ; | |
| destMultiArray(dest), | | // Arg1() is the sum accumulated so far, initiali | |
| reduceFunctor(Arg1() + abs(Arg2() - Arg3()), 0) ); | | zed with 0 | |
| // Arg1() is the sum accumulated so far, initialized with 0 | | | |
| | | | |
| \endcode | | \endcode | |
| | | | |
| Note that the functor must define the appropriate traits described belo
w in order to be | | Note that the functor must define the appropriate traits described belo
w in order to be | |
| recognized as a reduce functor. This is most easily achieved by derivin
g from | | recognized as a reduce functor. This is most easily achieved by derivin
g from | |
| <tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits). | | <tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits). | |
| | | | |
|
| <b> Required Interface:</b> | | \deprecatedUsage{combineTwoMultiArrays} | |
| | | | |
| In standard and expand mode, the functor must be a model of BinaryFunct | | | |
| ion | | | |
| (i.e. support function call with two arguments and a return value | | | |
| <tt>res = functor(arg1, arg2)</tt>): | | | |
| | | | |
| \code | | \code | |
|
| MultiIterator src1_begin, src2_begin, dest_begin; | | #include <functional> // for std::plus | |
| | | | |
|
| SrcAccessor1 src1_accessor; | | typedef vigra::MultiArray<3, int> Array; | |
| SrcAccessor2 src2_accessor; | | Array src1(Shape3(100, 200, 50)), | |
| DestAccessor dest_accessor; | | src2(Shape3(100, 200, 50)), | |
| | | dest(Shape3(100, 200, 50)); | |
| | | ... | |
| | | | |
|
| Functor functor; | | vigra::combineTwoMultiArrays( | |
| | | srcMultiArrayRange(src1), | |
| | | srcMultiArray(src2), | |
| | | destMultiArray(dest), | |
| | | std::plus<int>()); | |
| | | \endcode | |
| | | \deprecatedEnd | |
| | | | |
|
| dest_accessor.set( | | <b> Required Interface:</b> | |
| functor(src1_accessor(src1_begin), src2_accessor(src2_begin)), | | | |
| dest_begin); | | | |
| | | | |
|
| \endcode | | In standard and expand mode, the functor must be a model of BinaryFunct | |
| | | ion | |
| | | (i.e. support function call with two arguments and a return value which | |
| | | is convertible | |
| | | into <tt>T2</tt>: <tt>T2 res = functor(arg1, arg2)</tt>): | |
| | | | |
| In reduce mode, it must be a model of BinaryAnalyser (i.e. support func
tion call | | In reduce mode, it must be a model of BinaryAnalyser (i.e. support func
tion call | |
| with two arguments and no return value <tt>functor(arg1, arg2)</tt>) an
d Initializer | | with two arguments and no return value <tt>functor(arg1, arg2)</tt>) an
d Initializer | |
| (i.e. support function call with no argument, but return value | | (i.e. support function call with no argument, but return value | |
| <tt>res = functor()</tt>). Internally, such functors are recognized by
the | | <tt>res = functor()</tt>). Internally, such functors are recognized by
the | |
| meta functions <tt>FunctorTraits<FUNCTOR>::isBinaryAnalyser</tt> and | | meta functions <tt>FunctorTraits<FUNCTOR>::isBinaryAnalyser</tt> and | |
| <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield | | <tt>FunctorTraits<FUNCTOR>::isInitializer</tt> which must both yield | |
| <tt>VigraTrueType</tt>. Make sure that your functor correctly defines | | <tt>VigraTrueType</tt>. Make sure that your functor correctly defines | |
| <tt>FunctorTraits</tt> because otherwise reduce mode will not work. | | <tt>FunctorTraits</tt> because otherwise reduce mode will not work. | |
| This is most easily achieved by deriving the functor from | | This is most easily achieved by deriving the functor from | |
| <tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits). | | <tt>BinaryReduceFunctorTag</tt> (see \ref vigra::FunctorTraits). | |
| In addition, the functor must be copy constructible in order to start e
ach reduction | | In addition, the functor must be copy constructible in order to start e
ach reduction | |
| with a fresh functor. | | with a fresh functor. | |
| | | | |
|
| \code | | \see TransformFunctor, MultiMathModule, \ref FunctorExpressions | |
| MultiIterator src1_begin, src2_begin, dest_begin; | | | |
| | | | |
| SrcAccessor1 src1_accessor; | | | |
| SrcAccessor2 src2_accessor; | | | |
| DestAccessor dest_accessor; | | | |
| | | | |
| FUNCTOR initial_functor, functor(initial_functor); | | | |
| assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTru | | | |
| eType)); | | | |
| assert(typeid(FunctorTraits<FUNCTOR>::isBinaryAnalyser) == typeid(Vigra | | | |
| TrueType)); | | | |
| | | | |
| functor(src1_accessor(src1_begin), src2_accessor(src2_begin)); | | | |
| dest_accessor.set(functor(), dest_begin); | | | |
| \endcode | | | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void combineTwoMultiArrays) | | doxygen_overloaded_function(template <...> void combineTwoMultiArrays) | |
| | | | |
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| class SrcIterator2, class SrcAccessor2, | | class SrcIterator2, class SrcAccessor2, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Functor> | | class Functor> | |
| inline void | | inline void | |
| combineTwoMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1
src1, | | combineTwoMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1
src1, | |
| SrcIterator2 s2, SrcAccessor2 src2, | | SrcIterator2 s2, SrcAccessor2 src2, | |
| DestIterator d, DestAccessor dest, Functor const & f) | | DestIterator d, DestAccessor dest, Functor const & f) | |
| { | | { | |
| combineTwoMultiArraysExpandImpl(s1, shape, src1, s2, shape, src2, d, sh
ape, dest, f, | | combineTwoMultiArraysExpandImpl(s1, shape, src1, s2, shape, src2, d, sh
ape, dest, f, | |
| MetaInt<SrcIterator1::level>()); | | MetaInt<SrcIterator1::level>()); | |
| } | | } | |
| | | | |
|
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | | |
| class SrcIterator2, class SrcAccessor2, | | | |
| class DestIterator, class DestAccessor, class Functor> | | | |
| inline void | | | |
| combineTwoMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & | | | |
| src1, | | | |
| pair<SrcIterator2, SrcAccessor2> const & src2, | | | |
| pair<DestIterator, DestAccessor> const & dest, Functor const | | | |
| & f) | | | |
| { | | | |
| | | | |
| combineTwoMultiArrays( | | | |
| src1.first, src1.second, src1.third, | | | |
| src2.first, src2.second, dest.first, dest.second, f); | | | |
| } | | | |
| | | | |
| template <class SrcIterator1, class SrcShape1, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape1, class SrcAccessor1, | |
| class SrcIterator2, class SrcShape2, class SrcAccessor2, | | class SrcIterator2, class SrcShape2, class SrcAccessor2, | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| combineTwoMultiArrays( | | combineTwoMultiArrays( | |
| SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src
1, | | SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src
1, | |
| SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src
2, | | SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src
2, | |
| DestIterator d, DestShape const & dshape, DestAccessor dest, | | DestIterator d, DestShape const & dshape, DestAccessor dest, | |
| Functor const & f) | | Functor const & f) | |
| | | | |
| skipping to change at line 1254 | | skipping to change at line 1443 | |
| "combineTwoMultiArrays(): dimensionality of source and destination
arrays differ"); | | "combineTwoMultiArrays(): dimensionality of source and destination
arrays differ"); | |
| | | | |
| typedef FunctorTraits<Functor> FT; | | typedef FunctorTraits<Functor> FT; | |
| typedef typename | | typedef typename | |
| And<typename FT::isInitializer, typename FT::isBinaryAnalyser>::res
ult | | And<typename FT::isInitializer, typename FT::isBinaryAnalyser>::res
ult | |
| isAnalyserInitializer; | | isAnalyserInitializer; | |
| combineTwoMultiArraysImpl(s1, sshape1, src1, s2, sshape2, src2, d, dsha
pe, dest, | | combineTwoMultiArraysImpl(s1, sshape1, src1, s2, sshape2, src2, d, dsha
pe, dest, | |
| f, isAnalyserInitializer()); | | f, isAnalyserInitializer()); | |
| } | | } | |
| | | | |
|
| | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| | | class SrcIterator2, class SrcAccessor2, | |
| | | class DestIterator, class DestAccessor, class Functor> | |
| | | inline void | |
| | | combineTwoMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & | |
| | | src1, | |
| | | pair<SrcIterator2, SrcAccessor2> const & src2, | |
| | | pair<DestIterator, DestAccessor> const & dest, | |
| | | Functor const & f) | |
| | | { | |
| | | | |
| | | combineTwoMultiArrays( | |
| | | src1.first, src1.second, src1.third, | |
| | | src2.first, src2.second, dest.first, dest.second, f); | |
| | | } | |
| | | | |
| template <class SrcIterator1, class SrcShape1, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape1, class SrcAccessor1, | |
| class SrcIterator2, class SrcShape2, class SrcAccessor2, | | class SrcIterator2, class SrcShape2, class SrcAccessor2, | |
| class DestIterator, class DestShape, class DestAccessor, | | class DestIterator, class DestShape, class DestAccessor, | |
| class Functor> | | class Functor> | |
| inline void | | inline void | |
|
| combineTwoMultiArrays( | | combineTwoMultiArrays(triple<SrcIterator1, SrcShape1, SrcAccessor1> const & | |
| triple<SrcIterator1, SrcShape1, SrcAccessor1> const & src1, | | src1, | |
| triple<SrcIterator2, SrcShape2, SrcAccessor2> const & src2, | | triple<SrcIterator2, SrcShape2, SrcAccessor2> const & | |
| triple<DestIterator, DestShape, DestAccessor> const & dest, | | src2, | |
| Functor const & f) | | triple<DestIterator, DestShape, DestAccessor> const & | |
| | | dest, | |
| | | Functor const & f) | |
| { | | { | |
| combineTwoMultiArrays(src1.first, src1.second, src1.third, | | combineTwoMultiArrays(src1.first, src1.second, src1.third, | |
| src2.first, src2.second, src2.third, | | src2.first, src2.second, src2.third, | |
| dest.first, dest.second, dest.third, f); | | dest.first, dest.second, dest.third, f); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T11, class S11, | |
| | | class T12, class S12, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | combineTwoMultiArraysImpl(MultiArrayView<N, T11, S11> const & source1, | |
| | | MultiArrayView<N, T12, S12> const & source2, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | Functor const & f, VigraFalseType) | |
| | | { | |
| | | | |
| | | if(source1.shape() == source2.shape() && source1.shape() == dest.shape( | |
| | | )) | |
| | | combineTwoMultiArrays(srcMultiArrayRange(source1), | |
| | | srcMultiArray(source2), destMultiArray(dest), | |
| | | f); | |
| | | else | |
| | | combineTwoMultiArrays(srcMultiArrayRange(source1), | |
| | | srcMultiArrayRange(source2), | |
| | | destMultiArrayRange(dest), f); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T11, class S11, | |
| | | class T12, class S12, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | combineTwoMultiArraysImpl(MultiArrayView<N, T11, S11> const & source1, | |
| | | MultiArrayView<N, T12, S12> const & source2, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | Functor const & f, VigraTrueType) | |
| | | { | |
| | | | |
| | | combineTwoMultiArrays(srcMultiArrayRange(source1), | |
| | | srcMultiArrayRange(source2), | |
| | | destMultiArrayRange(dest), f); | |
| | | } | |
| | | | |
| | | template <unsigned int N, class T11, class S11, | |
| | | class T12, class S12, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | combineTwoMultiArrays(MultiArrayView<N, T11, S11> const & source1, | |
| | | MultiArrayView<N, T12, S12> const & source2, | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | Functor const & f) | |
| | | { | |
| | | for(unsigned int k=0; k<N; ++k) | |
| | | vigra_precondition((source1.shape(k) == source2.shape(k) || source1 | |
| | | .shape(k) == 1 || 1 == source2.shape(k)) && | |
| | | (source1.shape(k) == dest.shape(k) || source1.sh | |
| | | ape(k) == 1 || 1 == dest.shape(k)), | |
| | | "combineTwoMultiArrays(): shape mismatch between inputs and/or | |
| | | output."); | |
| | | | |
| | | typedef FunctorTraits<Functor> FT; | |
| | | typedef typename | |
| | | And<typename FT::isInitializer, typename FT::isBinaryAnalyser>::res | |
| | | ult | |
| | | isAnalyserInitializer; | |
| | | combineTwoMultiArraysImpl(source1, source2, dest, f, isAnalyserInitiali | |
| | | zer()); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* combineThreeMultiArrays */ | | /* combineThreeMultiArrays */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| class SrcIterator2, class SrcAccessor2, | | class SrcIterator2, class SrcAccessor2, | |
| class SrcIterator3, class SrcAccessor3, | | class SrcIterator3, class SrcAccessor3, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| | | | |
| skipping to change at line 1314 | | skipping to change at line 1575 | |
| { | | { | |
| combineThreeMultiArraysImpl(s1.begin(), shape, src1, | | combineThreeMultiArraysImpl(s1.begin(), shape, src1, | |
| s2.begin(), src2, s3.begin(), src3, d.beg
in(), dest, | | s2.begin(), src2, s3.begin(), src3, d.beg
in(), dest, | |
| f, MetaInt<N-1>()); | | f, MetaInt<N-1>()); | |
| } | | } | |
| } | | } | |
| | | | |
| /** \brief Combine three multi-dimensional arrays into one using a | | /** \brief Combine three multi-dimensional arrays into one using a | |
| ternary function or functor. | | ternary function or functor. | |
| | | | |
|
| | | Note: The effect of this function can often be achieved in a simpler an | |
| | | d | |
| | | more readable way by means of \ref MultiMathModule "array experessions" | |
| | | . | |
| | | | |
| Except for the fact that it operates on three input arrays, this functi
on is | | Except for the fact that it operates on three input arrays, this functi
on is | |
|
| identical to \ref combineTwoMultiArrays(). | | identical to the standard mode of \ref combineTwoMultiArrays() (reduce | |
| | | and expand | |
| | | modes are not supported). | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T11, class S11, | |
| | | class T12, class S12, | |
| | | class T13, class S13, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | void | |
| | | combineThreeMultiArrays(MultiArrayView<N, T11, S11> const & source1 | |
| | | , | |
| | | MultiArrayView<N, T12, S12> const & source2 | |
| | | , | |
| | | MultiArrayView<N, T13, S13> const & source3 | |
| | | , | |
| | | MultiArrayView<N, T2, S2> dest, | |
| | | Functor const & f); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{combineThreeMultiArrays} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| class SrcIterator2, class SrcAccessor2, | | class SrcIterator2, class SrcAccessor2, | |
| class SrcIterator3, class SrcAccessor3, | | class SrcIterator3, class SrcAccessor3, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Functor> | | class Functor> | |
| void | | void | |
| combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, Sr
cAccessor1 src1, | | combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, Sr
cAccessor1 src1, | |
| SrcIterator2 s2, SrcAccessor2 src2, | | SrcIterator2 s2, SrcAccessor2 src2, | |
| SrcIterator3 s3, SrcAccessor3 src3, | | SrcIterator3 s3, SrcAccessor3 src3, | |
| DestIterator d, DestAccessor dest, Functor const & f
); | | DestIterator d, DestAccessor dest, Functor const & f
); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| class SrcIterator2, class SrcAccessor2, | | class SrcIterator2, class SrcAccessor2, | |
| class SrcIterator3, class SrcAccessor3, | | class SrcIterator3, class SrcAccessor3, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Functor> | | class Functor> | |
| inline void | | inline void | |
| combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1
> const & src1, | | combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1
> const & src1, | |
| pair<SrcIterator2, SrcAccessor2> const & src2, | | pair<SrcIterator2, SrcAccessor2> const & src2, | |
| pair<SrcIterator3, SrcAccessor3> const & src3, | | pair<SrcIterator3, SrcAccessor3> const & src3, | |
| pair<DestIterator, DestAccessor> const & dest, Funct
or const & f); | | pair<DestIterator, DestAccessor> const & dest, Funct
or const & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | | <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | #include <vigra/functorexpression.hxx> | |
| | | | |
| | | MultiArray<3, int> src1(Shape3(100, 200, 50)), | |
| | | src2(Shape3(100, 200, 50)), | |
| | | src3(Shape3(100, 200, 50)), | |
| | | dest(Shape3(100, 200, 50)); | |
| | | ... | |
| | | | |
| | | using namespace vigra::functor; // activate VIGRA's lambda library | |
| | | | |
| | | combineThreeMultiArrays(src1, src2, src3, dest, | |
| | | Arg1()*exp(-abs(Arg2()-Arg3()))); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{combineThreeMultiArrays} | |
| | | \code | |
| #include <functional> // for plus | | #include <functional> // for plus | |
| | | | |
| typedef vigra::MultiArray<3, int> Array; | | typedef vigra::MultiArray<3, int> Array; | |
|
| Array src1(Array::size_type(100, 200, 50)), | | Array src1(Shape3(100, 200, 50)), | |
| src2(Array::size_type(100, 200, 50)), | | src2(Shape3(100, 200, 50)), | |
| src3(Array::size_type(100, 200, 50)), | | src3(Shape3(100, 200, 50)), | |
| dest(Array::size_type(100, 200, 50)); | | dest(Shape3(100, 200, 50)); | |
| ... | | ... | |
| | | | |
| vigra::combineThreeMultiArrays( | | vigra::combineThreeMultiArrays( | |
| srcMultiArrayRange(src1), | | srcMultiArrayRange(src1), | |
| srcMultiArray(src2), | | srcMultiArray(src2), | |
| srcMultiArray(src3), | | srcMultiArray(src3), | |
| destMultiArray(dest), | | destMultiArray(dest), | |
| SomeThreeArgumentFunctor()); | | SomeThreeArgumentFunctor()); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| | | \see TransformFunctor, MultiMathModule, \ref FunctorExpressions | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void combineThreeMultiArrays) | | doxygen_overloaded_function(template <...> void combineThreeMultiArrays) | |
| | | | |
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| class SrcIterator2, class SrcAccessor2, | | class SrcIterator2, class SrcAccessor2, | |
| class SrcIterator3, class SrcAccessor3, | | class SrcIterator3, class SrcAccessor3, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Functor> | | class Functor> | |
| inline void | | inline void | |
| combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccesso
r1 src1, | | combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccesso
r1 src1, | |
| | | | |
| skipping to change at line 1399 | | skipping to change at line 1700 | |
| MetaInt<SrcIterator1::level>()); | | MetaInt<SrcIterator1::level>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator1, class SrcShape, class SrcAccessor1, | | template <class SrcIterator1, class SrcShape, class SrcAccessor1, | |
| class SrcIterator2, class SrcAccessor2, | | class SrcIterator2, class SrcAccessor2, | |
| class SrcIterator3, class SrcAccessor3, | | class SrcIterator3, class SrcAccessor3, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Functor> | | class Functor> | |
| inline void | | inline void | |
| combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const
& src1, | | combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const
& src1, | |
|
| pair<SrcIterator2, SrcAccessor2> const & src2, | | pair<SrcIterator2, SrcAccessor2> const & src2, | |
| pair<SrcIterator3, SrcAccessor3> const & src3, | | pair<SrcIterator3, SrcAccessor3> const & src3, | |
| pair<DestIterator, DestAccessor> const & dest, Functor const | | pair<DestIterator, DestAccessor> const & dest, Func | |
| & f) | | tor const & f) | |
| { | | { | |
| | | | |
| combineThreeMultiArrays( | | combineThreeMultiArrays( | |
| src1.first, src1.second, src1.third, | | src1.first, src1.second, src1.third, | |
| src2.first, src2.second, src3.first, src3.second, dest.first, de
st.second, f); | | src2.first, src2.second, src3.first, src3.second, dest.first, de
st.second, f); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T11, class S11, | |
| | | class T12, class S12, | |
| | | class T13, class S13, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | combineThreeMultiArrays(MultiArrayView<N, T11, S11> const & source1, | |
| | | MultiArrayView<N, T12, S12> const & source2, | |
| | | MultiArrayView<N, T13, S13> const & source3, | |
| | | MultiArrayView<N, T2, S2> dest, Functor const & f) | |
| | | { | |
| | | vigra_precondition(source1.shape() == source2.shape() && source1.shape( | |
| | | ) == source3.shape() && source1.shape() == dest.shape(), | |
| | | "combineThreeMultiArrays(): shape mismatch between inputs and/or ou | |
| | | tput."); | |
| | | | |
| | | combineThreeMultiArrays( | |
| | | srcMultiArrayRange(source1), | |
| | | srcMultiArray(source2), srcMultiArray(source3), destMultiArray(d | |
| | | est), f); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* inspectMultiArray */ | | /* inspectMultiArray */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class Iterator, class Shape, class Accessor, class Functor> | | template <class Iterator, class Shape, class Accessor, class Functor> | |
| inline void | | inline void | |
| inspectMultiArrayImpl(Iterator s, Shape const & shape, Accessor a, Functor
& f, MetaInt<0>) | | inspectMultiArrayImpl(Iterator s, Shape const & shape, Accessor a, Functor
& f, MetaInt<0>) | |
| { | | { | |
| | | | |
| skipping to change at line 1437 | | skipping to change at line 1757 | |
| for(; s < send; ++s) | | for(; s < send; ++s) | |
| { | | { | |
| inspectMultiArrayImpl(s.begin(), shape, a, f, MetaInt<N-1>()); | | inspectMultiArrayImpl(s.begin(), shape, a, f, MetaInt<N-1>()); | |
| } | | } | |
| } | | } | |
| | | | |
| /** \brief Call an analyzing functor at every element of a multi-dimensiona
l array. | | /** \brief Call an analyzing functor at every element of a multi-dimensiona
l array. | |
| | | | |
| This function can be used to collect statistics of the array etc. | | This function can be used to collect statistics of the array etc. | |
| The results must be stored in the functor, which serves as a return | | The results must be stored in the functor, which serves as a return | |
|
| value. The arrays must be represented by | | value (therefore, it is passed to the function by reference). The array | |
| iterators compatible with \ref vigra::MultiIterator. | | must be | |
| The function uses an accessor to access the pixel data. Note that the i | | represented as a MultiArrayView. | |
| terator range | | | |
| must be specified by a shape object, because otherwise we could not con | | For many common statistics, the use of \ref vigra::acc::extractFeature | |
| trol | | s() in combination with | |
| the range simultaneously in all dimensions (this is a necessary consequ | | \ref FeatureAccumulators is more convenient. | |
| ence | | | |
| of the \ref vigra::MultiIterator design). | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T, class S, | |
| | | class Functor> | |
| | | void | |
| | | inspectMultiArray(MultiArrayView<N, T, S> const & s, | |
| | | Functor & f); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{inspectMultiArray} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Iterator, class Shape, class Accessor, class Functo
r> | | template <class Iterator, class Shape, class Accessor, class Functo
r> | |
| void | | void | |
| inspectMultiArray(Iterator s, Shape const & shape, Accessor a, Fun
ctor & f); | | inspectMultiArray(Iterator s, Shape const & shape, Accessor a, Fun
ctor & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Iterator, class Shape, class Accessor, class Functo
r> | | template <class Iterator, class Shape, class Accessor, class Functo
r> | |
| void | | void | |
| inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Func
tor & f); | | inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Func
tor & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | | <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<3, int> array(Shape3(100, 200, 50)); | |
| | | ... // fill array | |
| | | | |
| | | // init functor | |
| | | FindMinMax<int> minmax; | |
| | | | |
| | | inspectMultiArray(array, minmax); | |
| | | | |
| | | cout << "Min: " << minmax.min << " Max: " << minmax.max; | |
| | | \endcode | |
| | | The functor must support function call with one argument. | |
| | | | |
| | | \deprecatedUsage{inspectMultiArray} | |
| | | \code | |
| typedef vigra::MultiArray<3, int> Array; | | typedef vigra::MultiArray<3, int> Array; | |
|
| Array array(Array::size_type(100, 200, 50)); | | Array array(Shape3(100, 200, 50)); | |
| | | | |
| // init functor | | // init functor | |
| vigra::FindMinMax<int> minmax; | | vigra::FindMinMax<int> minmax; | |
| | | | |
| vigra::inspectMultiArray(srcMultiArrayRange(array), minmax); | | vigra::inspectMultiArray(srcMultiArrayRange(array), minmax); | |
| | | | |
| cout << "Min: " << minmax.min << " Max: " << minmax.max; | | cout << "Min: " << minmax.min << " Max: " << minmax.max; | |
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| MultiIterator src_begin; | | MultiIterator src_begin; | |
| | | | |
| Accessor accessor; | | Accessor accessor; | |
| Functor functor; | | Functor functor; | |
| | | | |
| functor(accessor(src_begin)); | | functor(accessor(src_begin)); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void inspectMultiArray) | | doxygen_overloaded_function(template <...> void inspectMultiArray) | |
| | | | |
| template <class Iterator, class Shape, class Accessor> | | template <class Iterator, class Shape, class Accessor> | |
| struct inspectMultiArray_binder | | struct inspectMultiArray_binder | |
| { | | { | |
| Iterator s; | | Iterator s; | |
| const Shape & shape; | | const Shape & shape; | |
| Accessor a; | | Accessor a; | |
| inspectMultiArray_binder(Iterator s_, const Shape & shape_, Accessor a_
) | | inspectMultiArray_binder(Iterator s_, const Shape & shape_, Accessor a_
) | |
| | | | |
| skipping to change at line 1526 | | skipping to change at line 1869 | |
| detail::extra_passes_select(g, f); | | detail::extra_passes_select(g, f); | |
| } | | } | |
| | | | |
| template <class Iterator, class Shape, class Accessor, class Functor> | | template <class Iterator, class Shape, class Accessor, class Functor> | |
| inline void | | inline void | |
| inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f) | | inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f) | |
| { | | { | |
| inspectMultiArray(s.first, s.second, s.third, f); | | inspectMultiArray(s.first, s.second, s.third, f); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T, class S, class Functor> | |
| | | inline void | |
| | | inspectMultiArray(MultiArrayView<N, T, S> const & s, Functor & f) | |
| | | { | |
| | | inspectMultiArray(srcMultiArrayRange(s), f); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* inspectTwoMultiArrays */ | | /* inspectTwoMultiArrays */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class Iterator1, class Shape, class Accessor1, | | template <class Iterator1, class Shape, class Accessor1, | |
| class Iterator2, class Accessor2, | | class Iterator2, class Accessor2, | |
| class Functor> | | class Functor> | |
| inline void | | inline void | |
| | | | |
| skipping to change at line 1562 | | skipping to change at line 1912 | |
| for(; s1 < s1end; ++s1, ++s2) | | for(; s1 < s1end; ++s1, ++s2) | |
| { | | { | |
| inspectTwoMultiArraysImpl(s1.begin(), shape, a1, | | inspectTwoMultiArraysImpl(s1.begin(), shape, a1, | |
| s2.begin(), a2, f, MetaInt<N-1>()); | | s2.begin(), a2, f, MetaInt<N-1>()); | |
| } | | } | |
| } | | } | |
| | | | |
| /** \brief Call an analyzing functor at all corresponding elements of | | /** \brief Call an analyzing functor at all corresponding elements of | |
| two multi-dimensional arrays. | | two multi-dimensional arrays. | |
| | | | |
|
| This function can be used to collect statistics of the array etc. | | This function can be used to collect statistics over tow arrays. | |
| | | For example, one can holde data, and the other region labels or weights | |
| | | . | |
| The results must be stored in the functor, which serves as a return | | The results must be stored in the functor, which serves as a return | |
|
| value. The arrays must be represented by | | value (and is therefore passed by reference). The arrays must be repres | |
| iterators compatible with \ref vigra::MultiIterator. | | ented by | |
| The function uses an accessor to access the pixel data. Note that the i | | MultiArrayViews. | |
| terator range | | | |
| must be specified by a shape object, because otherwise we could not con | | For many common statistics, the use of \ref vigra::acc::extractFeature | |
| trol | | s() in combination with | |
| the range simultaneously in all dimensions (this is a necessary consequ | | \ref FeatureAccumulators is more convenient. | |
| ence | | | |
| of the \ref vigra::MultiIterator design). | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass arbitrary-dimensional array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | void | |
| | | inspectTwoMultiArrays(MultiArrayView<N, T1, S1> const & s1, | |
| | | MultiArrayView<N, T2, S2> const & s2, | |
| | | Functor & f); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{inspectTwoMultiArrays} | |
| | | pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Iterator1, class Shape, class Accessor1, | | template <class Iterator1, class Shape, class Accessor1, | |
| class Iterator2, class Accessor2, | | class Iterator2, class Accessor2, | |
| class Functor> | | class Functor> | |
| void | | void | |
| inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1
a1, | | inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1
a1, | |
| Iterator2 s2, Accessor2 a2, Functor & f); | | Iterator2 s2, Accessor2 a2, Functor & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Iterator1, class Shape1, class Accessor1, | | template <class Iterator1, class Shape1, class Accessor1, | |
| class Iterator2, class Accessor2, | | class Iterator2, class Accessor2, | |
| class Functor> | | class Functor> | |
| void | | void | |
| inspectTwoMultiArrays(triple<Iterator1, Shape1, Accessor1> const &
s1, | | inspectTwoMultiArrays(triple<Iterator1, Shape1, Accessor1> const &
s1, | |
| pair<Iterator2, Accessor2> const & s2, Functo
r & f); | | pair<Iterator2, Accessor2> const & s2, Functo
r & f); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | | <b>\#include</b> \<vigra/multi_pointoperators.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| typedef vigra::MultiArray<3, int> Array; | | MultiArray<3, int> array1(Shape3(100, 200, 50)), | |
| Array array1(Array::size_type(100, 200, 50)), | | array2(Shape3(100, 200, 50)); | |
| array2(Array::size_type(100, 200, 50)); | | | |
| | | | |
| // init functor | | // init functor | |
| SomeStatisticsFunctor stats(..); | | SomeStatisticsFunctor stats(..); | |
| | | | |
|
| vigra::inspectTwoMultiArrays(srcMultiArrayRange(array1), srcMultiArray( | | inspectTwoMultiArrays(array1, array2, stats); | |
| array2), stats); | | | |
| | | | |
| \endcode | | \endcode | |
|
| | | The functor must support function call with two arguments. | |
| | | | |
|
| <b> Required Interface:</b> | | \deprecatedUsage{inspectTwoMultiArrays} | |
| | | \code | |
| | | MultiArray<3, int> array1(Shape3(100, 200, 50)), | |
| | | array2(Shape3(100, 200, 50)); | |
| | | | |
|
| | | // init functor | |
| | | SomeStatisticsFunctor stats(..); | |
| | | | |
| | | vigra::inspectTwoMultiArrays(srcMultiArrayRange(array1), srcMultiArray( | |
| | | array2), stats); | |
| | | \endcode | |
| | | <b> Required Interface:</b> | |
| \code | | \code | |
| MultiIterator src1_begin, src2_begin; | | MultiIterator src1_begin, src2_begin; | |
| | | | |
| Accessor a1, a2; | | Accessor a1, a2; | |
| Functor functor; | | Functor functor; | |
| | | | |
| functor(a1(src1_begin), a2(src2_begin)); | | functor(a1(src1_begin), a2(src2_begin)); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void inspectTwoMultiArrays) | | doxygen_overloaded_function(template <...> void inspectTwoMultiArrays) | |
| | | | |
| template <class Iterator1, class Shape, class Accessor1, | | template <class Iterator1, class Shape, class Accessor1, | |
| class Iterator2, class Accessor2> | | class Iterator2, class Accessor2> | |
| struct inspectTwoMultiArrays_binder | | struct inspectTwoMultiArrays_binder | |
| { | | { | |
| Iterator1 s1; | | Iterator1 s1; | |
| const Shape & shape; | | const Shape & shape; | |
| Accessor1 a1; | | Accessor1 a1; | |
| | | | |
| skipping to change at line 1664 | | skipping to change at line 2036 | |
| { | | { | |
| inspectTwoMultiArrays_binder<Iterator1, Shape, Accessor1, | | inspectTwoMultiArrays_binder<Iterator1, Shape, Accessor1, | |
| Iterator2, Accessor2> | | Iterator2, Accessor2> | |
| g(s1, shape, a1, s2, a2); | | g(s1, shape, a1, s2, a2); | |
| detail::extra_passes_select(g, f); | | detail::extra_passes_select(g, f); | |
| } | | } | |
| | | | |
| template <class Iterator1, class Shape, class Accessor1, | | template <class Iterator1, class Shape, class Accessor1, | |
| class Iterator2, class Accessor2, | | class Iterator2, class Accessor2, | |
| class Functor> | | class Functor> | |
|
| inline | | inline void | |
| void | | | |
| inspectTwoMultiArrays(triple<Iterator1, Shape, Accessor1> const & s1, | | inspectTwoMultiArrays(triple<Iterator1, Shape, Accessor1> const & s1, | |
| pair<Iterator2, Accessor2> const & s2, Functor & f) | | pair<Iterator2, Accessor2> const & s2, Functor & f) | |
| { | | { | |
| inspectTwoMultiArrays(s1.first, s1.second, s1.third, | | inspectTwoMultiArrays(s1.first, s1.second, s1.third, | |
| s2.first, s2.second, f); | | s2.first, s2.second, f); | |
| } | | } | |
| | | | |
|
| | | template <unsigned int N, class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Functor> | |
| | | inline void | |
| | | inspectTwoMultiArrays(MultiArrayView<N, T1, S1> const & s1, | |
| | | MultiArrayView<N, T2, S2> const & s2, Functor & f) | |
| | | { | |
| | | vigra_precondition(s1.shape() == s2.shape(), | |
| | | "inspectTwoMultiArrays(): shape mismatch between inputs."); | |
| | | | |
| | | inspectTwoMultiArrays(srcMultiArrayRange(s1), | |
| | | srcMultiArray(s2), f); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } //-- namespace vigra | | } //-- namespace vigra | |
| | | | |
| #endif //-- VIGRA_MULTI_POINTOPERATORS_H | | #endif //-- VIGRA_MULTI_POINTOPERATORS_H | |
| | | | |
End of changes. 124 change blocks. |
| 327 lines changed or deleted | | 754 lines changed or added | |
|
| noise_normalization.hxx | | noise_normalization.hxx | |
| | | | |
| skipping to change at line 51 | | skipping to change at line 51 | |
| #include "stdimage.hxx" | | #include "stdimage.hxx" | |
| #include "transformimage.hxx" | | #include "transformimage.hxx" | |
| #include "combineimages.hxx" | | #include "combineimages.hxx" | |
| #include "localminmax.hxx" | | #include "localminmax.hxx" | |
| #include "functorexpression.hxx" | | #include "functorexpression.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "separableconvolution.hxx" | | #include "separableconvolution.hxx" | |
| #include "linear_solve.hxx" | | #include "linear_solve.hxx" | |
| #include "array_vector.hxx" | | #include "array_vector.hxx" | |
| #include "static_assert.hxx" | | #include "static_assert.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| #include <algorithm> | | #include <algorithm> | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /** \addtogroup NoiseNormalization Noise Normalization | | /** \addtogroup NoiseNormalization Noise Normalization | |
| Estimate noise with intensity-dependent variance and transform it into
additive Gaussian noise. | | Estimate noise with intensity-dependent variance and transform it into
additive Gaussian noise. | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| skipping to change at line 74 | | skipping to change at line 76 | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Pass options to one of the noise normalization functions. | | /** \brief Pass options to one of the noise normalization functions. | |
| | | | |
| <tt>NoiseNormalizationOptions</tt> is an argument object that holds va
rious optional | | <tt>NoiseNormalizationOptions</tt> is an argument object that holds va
rious optional | |
| parameters used by the noise normalization functions. If a parameter is
not explicitly | | parameters used by the noise normalization functions. If a parameter is
not explicitly | |
| set, a suitable default will be used. | | set, a suitable default will be used. | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | | <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| vigra::BImage src(w,h); | | MultiArray<2, float> src(w,h); | |
| std::vector<vigra::TinyVector<double, 2> > result; | | std::vector<TinyVector<double, 2> > result; | |
| | | | |
| ... | | ... | |
|
| vigra::noiseVarianceEstimation(srcImageRange(src), result, | | noiseVarianceEstimation(src, result, | |
| vigra::NoiseNormalizationOptions().window | | NoiseNormalizationOptions().windowRadius(9).noi | |
| Radius(9).noiseVarianceInitialGuess(25.0)); | | seVarianceInitialGuess(25.0)); | |
| \endcode | | \endcode | |
| */ | | */ | |
| class NoiseNormalizationOptions | | class NoiseNormalizationOptions | |
| { | | { | |
| public: | | public: | |
| | | | |
| /** Initialize all options with default values. | | /** Initialize all options with default values. | |
| */ | | */ | |
| NoiseNormalizationOptions() | | NoiseNormalizationOptions() | |
| : window_radius(6), | | : window_radius(6), | |
| | | | |
| skipping to change at line 547 | | skipping to change at line 549 | |
| void | | void | |
| findHomogeneousRegionsFoerstner( | | findHomogeneousRegionsFoerstner( | |
| SrcIterator sul, SrcIterator slr, SrcAccessor src, | | SrcIterator sul, SrcIterator slr, SrcAccessor src, | |
| DestIterator dul, DestAccessor dest, | | DestIterator dul, DestAccessor dest, | |
| unsigned int windowRadius = 6, double homogeneityThreshold = 40.0) | | unsigned int windowRadius = 6, double homogeneityThreshold = 40.0) | |
| { | | { | |
| using namespace vigra::functor; | | using namespace vigra::functor; | |
| int w = slr.x - sul.x; | | int w = slr.x - sul.x; | |
| int h = slr.y - sul.y; | | int h = slr.y - sul.y; | |
| | | | |
|
| typedef typename NumericTraits<typename SrcAccessor::value_type>::RealP | | | |
| romote TmpType; | | | |
| typedef BasicImage<TmpType> TmpImage; | | | |
| | | | |
| BImage btmp(w, h); | | BImage btmp(w, h); | |
| transformImage(srcIterRange(sul, slr, src), destImage(btmp), | | transformImage(srcIterRange(sul, slr, src), destImage(btmp), | |
| ifThenElse(Arg1() <= Param(homogeneityThreshold), Param
(1), Param(0))); | | ifThenElse(Arg1() <= Param(homogeneityThreshold), Param
(1), Param(0))); | |
| | | | |
| // Erosion | | // Erosion | |
| discErosion(srcImageRange(btmp), destIter(dul, dest), windowRadius); | | discErosion(srcImageRange(btmp), destIter(dul, dest), windowRadius); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| | | | |
| skipping to change at line 977 | | skipping to change at line 976 | |
| i.e. so that intensity changes due to edges do not bias the estimate. T
he source value type | | i.e. so that intensity changes due to edges do not bias the estimate. T
he source value type | |
| (<TT>SrcAccessor::value_type</TT>) must be a scalar type which is conve
rtible to <tt>double</tt>. | | (<TT>SrcAccessor::value_type</TT>) must be a scalar type which is conve
rtible to <tt>double</tt>. | |
| The result is written into the \a result sequence, whose <tt>value_type
</tt> must be constructible | | The result is written into the \a result sequence, whose <tt>value_type
</tt> must be constructible | |
| from two <tt>double</tt> values. The following options can be set via t
he \a options object | | from two <tt>double</tt> values. The following options can be set via t
he \a options object | |
| (see \ref vigra::NoiseNormalizationOptions for details):<br><br> | | (see \ref vigra::NoiseNormalizationOptions for details):<br><br> | |
| | | | |
| <tt>useGradient</tt>, <tt>windowRadius</tt>, <tt>noiseEstimationQuantil
e</tt>, <tt>noiseVarianceInitialGuess</tt> | | <tt>useGradient</tt>, <tt>windowRadius</tt>, <tt>noiseEstimationQuantil
e</tt>, <tt>noiseVarianceInitialGuess</tt> | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, class BackInsertable> | |
| | | void | |
| | | noiseVarianceEstimation(MultiArrayView<2, T1, S1> const & src, | |
| | | BackInsertable & result, | |
| | | NoiseNormalizationOptions const & options = | |
| | | NoiseNormalizationOptions()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{noiseVarianceEstimation} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void noiseVarianceEstimation(SrcIterator sul, SrcIterator slr, SrcA
ccessor src, | | void noiseVarianceEstimation(SrcIterator sul, SrcIterator slr, SrcA
ccessor src, | |
| BackInsertable & result, | | BackInsertable & result, | |
| NoiseNormalizationOptions const & opti
ons = NoiseNormalizationOptions()); | | NoiseNormalizationOptions const & opti
ons = NoiseNormalizationOptions()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void noiseVarianceEstimation(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | | void noiseVarianceEstimation(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | |
| BackInsertable & result, | | BackInsertable & result, | |
| NoiseNormalizationOptions const & opti
ons = NoiseNormalizationOptions()); | | NoiseNormalizationOptions const & opti
ons = NoiseNormalizationOptions()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | | <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h); | |
| | | std::vector<TinyVector<double, 2> > result; | |
| | | | |
| | | ... | |
| | | noiseVarianceEstimation(src, result, | |
| | | NoiseNormalizationOptions().windowRadius(9).noi | |
| | | seVarianceInitialGuess(25.0)); | |
| | | | |
| | | // print the intensity / variance pairs found | |
| | | for(int k=0; k<result.size(); ++k) | |
| | | std::cout << "Intensity: " << result[k][0] << ", estimated variance | |
| | | : " << result[k][1] << std::endl; | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{noiseVarianceEstimation} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| std::vector<vigra::TinyVector<double, 2> > result; | | std::vector<vigra::TinyVector<double, 2> > result; | |
| | | | |
| ... | | ... | |
| vigra::noiseVarianceEstimation(srcImageRange(src), result, | | vigra::noiseVarianceEstimation(srcImageRange(src), result, | |
| vigra::NoiseNormalizationOptions().window
Radius(9).noiseVarianceInitialGuess(25.0)); | | vigra::NoiseNormalizationOptions().window
Radius(9).noiseVarianceInitialGuess(25.0)); | |
| | | | |
| // print the intensity / variance pairs found | | // print the intensity / variance pairs found | |
| for(int k=0; k<result.size(); ++k) | | for(int k=0; k<result.size(); ++k) | |
| std::cout << "Intensity: " << result[k][0] << ", estimated variance
: " << result[k][1] << std::endl; | | std::cout << "Intensity: " << result[k][0] << ", estimated variance
: " << result[k][1] << std::endl; | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcIterator upperleft, lowerright; | | SrcIterator upperleft, lowerright; | |
| SrcAccessor src; | | SrcAccessor src; | |
| | | | |
| typedef SrcAccessor::value_type SrcType; | | typedef SrcAccessor::value_type SrcType; | |
| typedef NumericTraits<SrcType>::isScalar isScalar; | | typedef NumericTraits<SrcType>::isScalar isScalar; | |
| assert(isScalar::asBool == true); | | assert(isScalar::asBool == true); | |
| | | | |
| double value = src(uperleft); | | double value = src(uperleft); | |
| | | | |
| BackInsertable result; | | BackInsertable result; | |
| typedef BackInsertable::value_type ResultType; | | typedef BackInsertable::value_type ResultType; | |
| double intensity, variance; | | double intensity, variance; | |
| result.push_back(ResultType(intensity, variance)); | | result.push_back(ResultType(intensity, variance)); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void noiseVarianceEstimation) | | doxygen_overloaded_function(template <...> void noiseVarianceEstimation) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
| inline | | inline | |
| void noiseVarianceEstimation(SrcIterator sul, SrcIterator slr, SrcAccessor
src, | | void noiseVarianceEstimation(SrcIterator sul, SrcIterator slr, SrcAccessor
src, | |
| BackInsertable & result, | | BackInsertable & result, | |
| NoiseNormalizationOptions const & options = Nois
eNormalizationOptions()) | | NoiseNormalizationOptions const & options = Nois
eNormalizationOptions()) | |
| { | | { | |
|
| typedef typename BackInsertable::value_type ResultType; | | | |
| typedef typename SrcAccessor::value_type SrcType; | | typedef typename SrcAccessor::value_type SrcType; | |
| typedef typename NumericTraits<SrcType>::isScalar isScalar; | | typedef typename NumericTraits<SrcType>::isScalar isScalar; | |
| | | | |
| VIGRA_STATIC_ASSERT(( | | VIGRA_STATIC_ASSERT(( | |
| noiseVarianceEstimation_can_only_work_on_scalar_images<(isScalar::a
sBool)>)); | | noiseVarianceEstimation_can_only_work_on_scalar_images<(isScalar::a
sBool)>)); | |
| | | | |
| detail::noiseVarianceEstimationImpl(sul, slr, src, result, options); | | detail::noiseVarianceEstimationImpl(sul, slr, src, result, options); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
|
| inline | | inline void | |
| void noiseVarianceEstimation(triple<SrcIterator, SrcIterator, SrcAccessor> | | noiseVarianceEstimation(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| src, | | BackInsertable & result, | |
| BackInsertable & result, | | NoiseNormalizationOptions const & options = NoiseNo | |
| NoiseNormalizationOptions const & options = Nois | | rmalizationOptions()) | |
| eNormalizationOptions()) | | | |
| { | | { | |
| noiseVarianceEstimation(src.first, src.second, src.third, result, optio
ns); | | noiseVarianceEstimation(src.first, src.second, src.third, result, optio
ns); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, class BackInsertable> | |
| | | inline void | |
| | | noiseVarianceEstimation(MultiArrayView<2, T1, S1> const & src, | |
| | | BackInsertable & result, | |
| | | NoiseNormalizationOptions const & options = NoiseNo | |
| | | rmalizationOptions()) | |
| | | { | |
| | | noiseVarianceEstimation(srcImageRange(src), result, options); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* noiseVarianceClustering */ | | /* noiseVarianceClustering */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Determine the noise variance as a function of the image intensit
y and cluster the results. | | /** \brief Determine the noise variance as a function of the image intensit
y and cluster the results. | |
| | | | |
| This operator first calls \ref noiseVarianceEstimation() to obtain a se
quence of intensity/variance pairs, | | This operator first calls \ref noiseVarianceEstimation() to obtain a se
quence of intensity/variance pairs, | |
| which are then clustered using the median cut algorithm. Then the clust
er centers (i.e. average variance vs. | | which are then clustered using the median cut algorithm. Then the clust
er centers (i.e. average variance vs. | |
| average intensity) are determined and returned in the \a result sequenc
e. | | average intensity) are determined and returned in the \a result sequenc
e. | |
| | | | |
| In addition to the options valid for \ref noiseVarianceEstimation(), th
e following options can be set via | | In addition to the options valid for \ref noiseVarianceEstimation(), th
e following options can be set via | |
| the \a options object (see \ref vigra::NoiseNormalizationOptions for de
tails):<br><br> | | the \a options object (see \ref vigra::NoiseNormalizationOptions for de
tails):<br><br> | |
| | | | |
| <tt>clusterCount</tt>, <tt>averagingQuantile</tt> | | <tt>clusterCount</tt>, <tt>averagingQuantile</tt> | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, class BackInsertable> | |
| | | void | |
| | | noiseVarianceClustering(MultiArrayView<2, T1, S1> const & src, | |
| | | BackInsertable & result, | |
| | | NoiseNormalizationOptions const & options = | |
| | | NoiseNormalizationOptions()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{noiseVarianceClustering} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void noiseVarianceClustering(SrcIterator sul, SrcIterator slr, SrcA
ccessor src, | | void noiseVarianceClustering(SrcIterator sul, SrcIterator slr, SrcA
ccessor src, | |
| BackInsertable & result, | | BackInsertable & result, | |
| NoiseNormalizationOptions const & options =
NoiseNormalizationOptions()); | | NoiseNormalizationOptions const & options =
NoiseNormalizationOptions()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | | template <class SrcIterator, class SrcAccessor, class BackInsertabl
e> | |
| void noiseVarianceClustering(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | | void noiseVarianceClustering(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | |
| BackInsertable & result, | | BackInsertable & result, | |
| NoiseNormalizationOptions const & options =
NoiseNormalizationOptions()); | | NoiseNormalizationOptions const & options =
NoiseNormalizationOptions()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | | <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h); | |
| | | std::vector<TinyVector<double, 2> > result; | |
| | | | |
| | | ... | |
| | | noiseVarianceClustering(src, result, | |
| | | NoiseNormalizationOptions().windowRadius(9).noi | |
| | | seVarianceInitialGuess(25.0). | |
| | | clusterCount(15)); | |
| | | | |
| | | // print the intensity / variance pairs representing the cluster center | |
| | | s | |
| | | for(int k=0; k<result.size(); ++k) | |
| | | std::cout << "Cluster: " << k << ", intensity: " << result[k][0] << | |
| | | ", estimated variance: " << result[k][1] << std::endl; | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{noiseVarianceClustering} | |
| | | \code | |
| vigra::BImage src(w,h); | | vigra::BImage src(w,h); | |
| std::vector<vigra::TinyVector<double, 2> > result; | | std::vector<vigra::TinyVector<double, 2> > result; | |
| | | | |
| ... | | ... | |
| vigra::noiseVarianceClustering(srcImageRange(src), result, | | vigra::noiseVarianceClustering(srcImageRange(src), result, | |
| vigra::NoiseNormalizationOptions().window
Radius(9).noiseVarianceInitialGuess(25.0). | | vigra::NoiseNormalizationOptions().window
Radius(9).noiseVarianceInitialGuess(25.0). | |
| clusterCount(15)); | | clusterCount(15)); | |
| | | | |
| // print the intensity / variance pairs representing the cluster center
s | | // print the intensity / variance pairs representing the cluster center
s | |
| for(int k=0; k<result.size(); ++k) | | for(int k=0; k<result.size(); ++k) | |
| std::cout << "Cluster: " << k << ", intensity: " << result[k][0] <<
", estimated variance: " << result[k][1] << std::endl; | | std::cout << "Cluster: " << k << ", intensity: " << result[k][0] <<
", estimated variance: " << result[k][1] << std::endl; | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| same as \ref noiseVarianceEstimation() | | same as \ref noiseVarianceEstimation() | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void noiseVarianceClustering) | | doxygen_overloaded_function(template <...> void noiseVarianceClustering) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
| inline | | inline | |
| void noiseVarianceClustering(SrcIterator sul, SrcIterator slr, SrcAccessor
src, | | void noiseVarianceClustering(SrcIterator sul, SrcIterator slr, SrcAccessor
src, | |
| BackInsertable & result, | | BackInsertable & result, | |
| NoiseNormalizationOptions const & options = Nois
eNormalizationOptions()) | | NoiseNormalizationOptions const & options = Nois
eNormalizationOptions()) | |
| { | | { | |
| ArrayVector<TinyVector<double, 2> > variance; | | ArrayVector<TinyVector<double, 2> > variance; | |
| noiseVarianceEstimation(sul, slr, src, variance, options); | | noiseVarianceEstimation(sul, slr, src, variance, options); | |
| detail::noiseVarianceClusteringImpl(variance, result, options.cluster_c
ount, options.averaging_quantile); | | detail::noiseVarianceClusteringImpl(variance, result, options.cluster_c
ount, options.averaging_quantile); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class BackInsertable> | | template <class SrcIterator, class SrcAccessor, class BackInsertable> | |
|
| inline | | inline void | |
| void noiseVarianceClustering(triple<SrcIterator, SrcIterator, SrcAccessor> | | noiseVarianceClustering(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| src, | | BackInsertable & result, | |
| BackInsertable & result, | | NoiseNormalizationOptions const & options = NoiseNo | |
| NoiseNormalizationOptions const & options = Nois | | rmalizationOptions()) | |
| eNormalizationOptions()) | | | |
| { | | { | |
| noiseVarianceClustering(src.first, src.second, src.third, result, optio
ns); | | noiseVarianceClustering(src.first, src.second, src.third, result, optio
ns); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, class BackInsertable> | |
| | | inline void | |
| | | noiseVarianceClustering(MultiArrayView<2, T1, S1> const & src, | |
| | | BackInsertable & result, | |
| | | NoiseNormalizationOptions const & options = NoiseNo | |
| | | rmalizationOptions()) | |
| | | { | |
| | | noiseVarianceClustering(srcImageRange(src), result, options); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* nonparametricNoiseNormalization */ | | /* nonparametricNoiseNormalization */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Noise normalization by means of an estimated non-parametric nois
e model. | | /** \brief Noise normalization by means of an estimated non-parametric nois
e model. | |
| | | | |
| The original image is assumed to be corrupted by noise whose variance d
epends on the intensity in an unknown way. | | The original image is assumed to be corrupted by noise whose variance d
epends on the intensity in an unknown way. | |
| The present functions first calls \ref noiseVarianceClustering() to obt
ain a sequence of intensity/variance pairs | | The present functions first calls \ref noiseVarianceClustering() to obt
ain a sequence of intensity/variance pairs | |
| | | | |
| skipping to change at line 1171 | | skipping to change at line 1238 | |
| The inverted formula defines a pixel-wise intensity transformation whos
e application turns the original image | | The inverted formula defines a pixel-wise intensity transformation whos
e application turns the original image | |
| into one that is corrupted by additive Gaussian noise with unit varianc
e. Most subsequent algorithms will be able | | into one that is corrupted by additive Gaussian noise with unit varianc
e. Most subsequent algorithms will be able | |
| to handle this type of noise much better than the original noise. | | to handle this type of noise much better than the original noise. | |
| | | | |
| RGB and other multiband images will be processed one band at a time. Th
e function returns <tt>true</tt> on success. | | RGB and other multiband images will be processed one band at a time. Th
e function returns <tt>true</tt> on success. | |
| Noise normalization will fail if the original image does not contain su
fficiently homogeneous regions that | | Noise normalization will fail if the original image does not contain su
fficiently homogeneous regions that | |
| allow robust estimation of the noise variance. | | allow robust estimation of the noise variance. | |
| | | | |
| The \a options object may use all options described in \ref vigra::Nois
eNormalizationOptions. | | The \a options object may use all options described in \ref vigra::Nois
eNormalizationOptions. | |
| | | | |
|
| | | The function returns <tt>false</tt> if the noise estimation failed, so | |
| | | that no normalization could be performed. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | bool | |
| | | nonparametricNoiseNormalization(MultiArrayView<2, T1, S1> const & s | |
| | | rc, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | NoiseNormalizationOptions const & o | |
| | | ptions = NoiseNormalizationOptions()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{nonparametricNoiseNormalization} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| bool nonparametricNoiseNormalization(SrcIterator sul, SrcIterator s
lr, SrcAccessor src, | | bool nonparametricNoiseNormalization(SrcIterator sul, SrcIterator s
lr, SrcAccessor src, | |
| DestIterator dul, DestAccessor
dest, | | DestIterator dul, DestAccessor
dest, | |
| NoiseNormalizationOptions cons
t & options = NoiseNormalizationOptions()); | | NoiseNormalizationOptions cons
t & options = NoiseNormalizationOptions()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| bool nonparametricNoiseNormalization(triple<SrcIterator, SrcIterato
r, SrcAccessor> src, | | bool nonparametricNoiseNormalization(triple<SrcIterator, SrcIterato
r, SrcAccessor> src, | |
| pair<DestIterator, DestAccesso
r> dest, | | pair<DestIterator, DestAccesso
r> dest, | |
| NoiseNormalizationOptions cons
t & options = NoiseNormalizationOptions()); | | NoiseNormalizationOptions cons
t & options = NoiseNormalizationOptions()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | | <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, RGBValue<float> > src(w,h), dest(w, h); | |
| | | | |
| | | ... | |
| | | nonparametricNoiseNormalization(src, dest, | |
| | | NoiseNormalizationOptions().windowRadiu | |
| | | s(9).noiseVarianceInitialGuess(25.0). | |
| | | clusterCount(15)); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{nonparametricNoiseNormalization} | |
| | | \code | |
| vigra::BRGBImage src(w,h), dest(w, h); | | vigra::BRGBImage src(w,h), dest(w, h); | |
| | | | |
| ... | | ... | |
| vigra::nonparametricNoiseNormalization(srcImageRange(src), destImage(de
st), | | vigra::nonparametricNoiseNormalization(srcImageRange(src), destImage(de
st), | |
| vigra::NoiseNormalizationOptions
().windowRadius(9).noiseVarianceInitialGuess(25.0). | | vigra::NoiseNormalizationOptions
().windowRadius(9).noiseVarianceInitialGuess(25.0). | |
| clusterCount(15)); | | clusterCount(15)); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| same as \ref noiseVarianceEstimation() | | same as \ref noiseVarianceEstimation() | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> bool nonparametricNoiseNormaliza
tion) | | doxygen_overloaded_function(template <...> bool nonparametricNoiseNormaliza
tion) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline bool | | inline bool | |
| nonparametricNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccess
or src, | | nonparametricNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccess
or src, | |
| DestIterator dul, DestAccessor dest, | | DestIterator dul, DestAccessor dest, | |
| NoiseNormalizationOptions const & options =
NoiseNormalizationOptions()) | | NoiseNormalizationOptions const & options =
NoiseNormalizationOptions()) | |
| { | | { | |
| typedef typename SrcAccessor::value_type SrcType; | | typedef typename SrcAccessor::value_type SrcType; | |
| | | | |
| return detail::nonparametricNoiseNormalizationImpl(sul, slr, src, dul,
dest, options, | | return detail::nonparametricNoiseNormalizationImpl(sul, slr, src, dul,
dest, options, | |
| typename NumericTraits<SrcType>::i
sScalar()); | | typename NumericTraits<SrcType>::i
sScalar()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline bool | |
| bool nonparametricNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAc | | nonparametricNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccesso | |
| cessor> src, | | r> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| NoiseNormalizationOptions const & opti | | NoiseNormalizationOptions const & options = | |
| ons = NoiseNormalizationOptions()) | | NoiseNormalizationOptions()) | |
| { | | { | |
| return nonparametricNoiseNormalization(src.first, src.second, src.third
, dest.first, dest.second, options); | | return nonparametricNoiseNormalization(src.first, src.second, src.third
, dest.first, dest.second, options); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline bool | |
| | | nonparametricNoiseNormalization(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | NoiseNormalizationOptions const & options = | |
| | | NoiseNormalizationOptions()) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "nonparametricNoiseNormalization(): shape mismatch between input an | |
| | | d output."); | |
| | | return nonparametricNoiseNormalization(srcImageRange(src), destImage(de | |
| | | st), options); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* quadraticNoiseNormalization */ | | /* quadraticNoiseNormalization */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
|
| /** \brief Noise normalization by means of an estimated quadratic noise mod
el. | | /** \brief Noise normalization by means of an estimated or given quadratic
noise model. | |
| | | | |
|
| This function works in the same way as \ref nonparametricNoiseNormaliza | | This function works like \ref nonparametricNoiseNormalization() excapt | |
| tion() with the exception of the | | that the model for the | |
| model for the dependency between intensity and noise variance: it assum | | dependency between intensity and noise variance is assumed to be a | |
| es that this dependency is a | | quadratic function rather than a piecewise linear function. If the data | |
| quadratic function rather than a piecewise linear function. If the quad | | conform to the quadratic model, | |
| ratic model is applicable, it leads | | this leads to a somewhat smoother transformation. The function returns | |
| to a somewhat smoother transformation. | | <tt>false</tt> if the noise | |
| | | estimation failed, so that no normalization could be performed. | |
| | | | |
| | | In the second variant of the function, the parameters of the quadratic | |
| | | model are not estimated, | |
| | | but explicitly given according to: | |
| | | \code | |
| | | variance = a0 + a1 * intensity + a2 * sq(intensity) | |
| | | \endcode | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| | | // estimate and apply a quadratic noise model | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | bool | |
| | | quadraticNoiseNormalization(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | NoiseNormalizationOptions const & optio | |
| | | ns = NoiseNormalizationOptions()); | |
| | | | |
| | | // apply a given quadratic noise model | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | quadraticNoiseNormalization(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double a0, double a1, double a2); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{quadraticNoiseNormalization} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| | | \code | |
| | | namespace vigra { | |
| | | // estimate and apply a quadratic noise model | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| bool quadraticNoiseNormalization(SrcIterator sul, SrcIterator slr,
SrcAccessor src, | | bool quadraticNoiseNormalization(SrcIterator sul, SrcIterator slr,
SrcAccessor src, | |
| DestIterator dul, DestAccessor des
t, | | DestIterator dul, DestAccessor des
t, | |
| NoiseNormalizationOptions const &
options = NoiseNormalizationOptions()); | | NoiseNormalizationOptions const &
options = NoiseNormalizationOptions()); | |
|
| | | | |
| | | // apply a given quadratic noise model | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor> | |
| | | void quadraticNoiseNormalization(SrcIterator sul, SrcIterator slr, | |
| | | SrcAccessor src, | |
| | | DestIterator dul, DestAccessor des | |
| | | t, | |
| | | double a0, double a1, double a2); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| | | // estimate and apply a quadratic noise model | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| bool quadraticNoiseNormalization(triple<SrcIterator, SrcIterator, S
rcAccessor> src, | | bool quadraticNoiseNormalization(triple<SrcIterator, SrcIterator, S
rcAccessor> src, | |
| pair<DestIterator, DestAccessor> d
est, | | pair<DestIterator, DestAccessor> d
est, | |
| NoiseNormalizationOptions const &
options = NoiseNormalizationOptions()); | | NoiseNormalizationOptions const &
options = NoiseNormalizationOptions()); | |
|
| | | | |
| | | // apply a given quadratic noise model | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor> | |
| | | void quadraticNoiseNormalization(triple<SrcIterator, SrcIterator, S | |
| | | rcAccessor> src, | |
| | | pair<DestIterator, DestAccessor> d | |
| | | est, | |
| | | double a0, double a1, double a2); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | | <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, RGBValue<float> > src(w,h), dest(w, h); | |
| | | | |
| | | ... | |
| | | // estimate the noise model and apply it to normalize the noise varianc | |
| | | e | |
| | | bool success = quadraticNoiseNormalization(src, dest, | |
| | | NoiseNormalizationOptions().windowRadius(9) | |
| | | .noiseVarianceInitialGuess(25.0). | |
| | | clusterCount(15)); | |
| | | vigra_postcondition(success, "quadraticNoiseNormalization(): Unable to | |
| | | estimate noise model."); | |
| | | | |
| | | // apply a pre-computed noise model | |
| | | quadraticNoiseNormalization(src, dest, 100, 0.02, 1e-6); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{quadraticNoiseNormalization} | |
| | | \code | |
| vigra::BRGBImage src(w,h), dest(w, h); | | vigra::BRGBImage src(w,h), dest(w, h); | |
| | | | |
| ... | | ... | |
|
| | | // estimate the noise model and apply it to normalize the noise varianc
e | |
| vigra::quadraticNoiseNormalization(srcImageRange(src), destImage(dest), | | vigra::quadraticNoiseNormalization(srcImageRange(src), destImage(dest), | |
| vigra::NoiseNormalizationOptions().w
indowRadius(9).noiseVarianceInitialGuess(25.0). | | vigra::NoiseNormalizationOptions().w
indowRadius(9).noiseVarianceInitialGuess(25.0). | |
| clusterCount(15)); | | clusterCount(15)); | |
|
| | | | |
| | | // apply a pre-computed noise model | |
| | | vigra::quadraticNoiseNormalization(srcImageRange(src), destImage(dest), | |
| | | 100, 0.02, 1e-6); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
| | | | |
|
| same as \ref noiseVarianceEstimation() | | The source value type must be convertible to <tt>double</tt> or must be | |
| | | a vector whose elements | |
| | | are convertible to <tt>double</tt>. Likewise, the destination type must | |
| | | be assignable from <tt>double</tt> | |
| | | or a vector whose elements are assignable from <tt>double</tt>. | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> bool quadraticNoiseNormalization
) | | doxygen_overloaded_function(template <...> bool quadraticNoiseNormalization
) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline bool | | inline bool | |
| quadraticNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor s
rc, | | quadraticNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor s
rc, | |
|
| DestIterator dul, DestAccessor dest, | | DestIterator dul, DestAccessor dest, | |
| NoiseNormalizationOptions const & options = | | NoiseNormalizationOptions const & options) | |
| NoiseNormalizationOptions()) | | | |
| { | | { | |
| typedef typename SrcAccessor::value_type SrcType; | | typedef typename SrcAccessor::value_type SrcType; | |
| | | | |
| return detail::quadraticNoiseNormalizationImpl(sul, slr, src, dul, dest
, options, | | return detail::quadraticNoiseNormalizationImpl(sul, slr, src, dul, dest
, options, | |
| typename NumericTraits<SrcType>::i
sScalar()); | | typename NumericTraits<SrcType>::i
sScalar()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline bool | |
| bool quadraticNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccess | | quadraticNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccessor> s | |
| or> src, | | rc, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| NoiseNormalizationOptions const & opti | | NoiseNormalizationOptions const & options = Noi | |
| ons = NoiseNormalizationOptions()) | | seNormalizationOptions()) | |
| { | | { | |
| return quadraticNoiseNormalization(src.first, src.second, src.third, de
st.first, dest.second, options); | | return quadraticNoiseNormalization(src.first, src.second, src.third, de
st.first, dest.second, options); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline bool | |
| | | quadraticNoiseNormalization(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | NoiseNormalizationOptions const & options = Noi | |
| | | seNormalizationOptions()) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "quadraticNoiseNormalization(): shape mismatch between input and ou | |
| | | tput."); | |
| | | return quadraticNoiseNormalization(srcImageRange(src), destImage(dest), | |
| | | options); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* quadraticNoiseNormalization */ | | /* quadraticNoiseNormalization */ | |
|
| | | /* (variant) */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
|
| /** \brief Noise normalization by means of a given quadratic noise model. | | | |
| | | | |
| This function works similar to \ref nonparametricNoiseNormalization() w | | | |
| ith the exception that the | | | |
| functional dependency of the noise variance from the intensity is given | | | |
| (by a quadratic function) | | | |
| rather than estimated: | | | |
| | | | |
| \code | | | |
| variance = a0 + a1 * intensity + a2 * sq(intensity) | | | |
| \endcode | | | |
| | | | |
| <b> Declarations:</b> | | | |
| | | | |
| pass arguments explicitly: | | | |
| \code | | | |
| namespace vigra { | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | | |
| void quadraticNoiseNormalization(SrcIterator sul, SrcIterator slr, | | | |
| SrcAccessor src, | | | |
| DestIterator dul, DestAccessor des | | | |
| t, | | | |
| double a0, double a1, double a2); | | | |
| } | | | |
| \endcode | | | |
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | | |
| \code | | | |
| namespace vigra { | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | | |
| void quadraticNoiseNormalization(triple<SrcIterator, SrcIterator, S | | | |
| rcAccessor> src, | | | |
| pair<DestIterator, DestAccessor> de | | | |
| st, | | | |
| double a0, double a1, double a2); | | | |
| } | | | |
| \endcode | | | |
| | | | |
| <b> Usage:</b> | | | |
| | | | |
| <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | | | |
| Namespace: vigra | | | |
| | | | |
| \code | | | |
| vigra::BRGBImage src(w,h), dest(w, h); | | | |
| | | | |
| ... | | | |
| vigra::quadraticNoiseNormalization(srcImageRange(src), destImage(dest), | | | |
| 100, 0.02, 1e-6); | | | |
| \endcode | | | |
| | | | |
| <b> Required Interface:</b> | | | |
| | | | |
| The source value type must be convertible to <tt>double</tt> or must be | | | |
| a vector whose elements | | | |
| are convertible to <tt>double</tt>. Likewise, the destination type must | | | |
| be assignable from <tt>double</tt> | | | |
| or a vector whose elements are assignable from <tt>double</tt>. | | | |
| */ | | | |
| doxygen_overloaded_function(template <...> void quadraticNoiseNormalization | | | |
| ) | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| quadraticNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor s
rc, | | quadraticNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor s
rc, | |
| DestIterator dul, DestAccessor dest, | | DestIterator dul, DestAccessor dest, | |
| double a0, double a1, double a2) | | double a0, double a1, double a2) | |
| { | | { | |
| typedef typename SrcAccessor::value_type SrcType; | | typedef typename SrcAccessor::value_type SrcType; | |
| | | | |
| detail::quadraticNoiseNormalizationImpl(sul, slr, src, dul, dest, a0, a
1, a2, | | detail::quadraticNoiseNormalizationImpl(sul, slr, src, dul, dest, a0, a
1, a2, | |
| typename NumericTraits<SrcType>::i
sScalar()); | | typename NumericTraits<SrcType>::i
sScalar()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline void | |
| void quadraticNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccess | | quadraticNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccessor> s | |
| or> src, | | rc, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| double a0, double a1, double a2) | | double a0, double a1, double a2) | |
| { | | { | |
| quadraticNoiseNormalization(src.first, src.second, src.third, dest.firs
t, dest.second, a0, a1, a2); | | quadraticNoiseNormalization(src.first, src.second, src.third, dest.firs
t, dest.second, a0, a1, a2); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | quadraticNoiseNormalization(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double a0, double a1, double a2) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "quadraticNoiseNormalization(): shape mismatch between input and ou | |
| | | tput."); | |
| | | quadraticNoiseNormalization(srcImageRange(src), destImage(dest), a0, a1 | |
| | | , a2); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* linearNoiseNormalization */ | | /* linearNoiseNormalization */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
|
| /** \brief Noise normalization by means of an estimated linear noise model. | | /** \brief Noise normalization by means of an estimated or given linear noi
se model. | |
| | | | |
|
| This function works in the same way as \ref nonparametricNoiseNormaliza | | This function works like \ref nonparametricNoiseNormalization() excapt | |
| tion() with the exception of the | | that the model for the | |
| model for the dependency between intensity and noise variance: it assum | | dependency between intensity and noise variance is assumed to be a | |
| es that this dependency is a | | linear function rather than a piecewise linear function. If the data co | |
| linear function rather than a piecewise linear function. If the linear | | nform to the linear model, | |
| model is applicable, it leads | | this leads to a very simple transformation which is similar to the fami | |
| to a very simple transformation which is similar to the familiar gamma | | liar gamma correction. | |
| correction. | | The function returns <tt>false</tt> if the noise estimation failed, so | |
| | | that no | |
| | | normalization could be performed. | |
| | | | |
| | | In the second variant of the function, the parameters of the linear mod | |
| | | el are not estimated, | |
| | | but explicitly given according to: | |
| | | \code | |
| | | variance = a0 + a1 * intensity | |
| | | \endcode | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // estimate and apply a linear noise model | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | bool | |
| | | linearNoiseNormalization(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | NoiseNormalizationOptions const & options | |
| | | = NoiseNormalizationOptions()); | |
| | | | |
| | | // apply a given linear noise model | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | linearNoiseNormalization(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double a0, double a1); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{linearNoiseNormalization} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| | | // estimate and apply a linear noise model | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| bool linearNoiseNormalization(SrcIterator sul, SrcIterator slr, Src
Accessor src, | | bool linearNoiseNormalization(SrcIterator sul, SrcIterator slr, Src
Accessor src, | |
| DestIterator dul, DestAccessor dest, | | DestIterator dul, DestAccessor dest, | |
| NoiseNormalizationOptions const & opt
ions = NoiseNormalizationOptions()); | | NoiseNormalizationOptions const & opt
ions = NoiseNormalizationOptions()); | |
|
| | | | |
| | | // apply a given linear noise model | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor> | |
| | | void linearNoiseNormalization(SrcIterator sul, SrcIterator slr, Src | |
| | | Accessor src, | |
| | | DestIterator dul, DestAccessor dest, | |
| | | double a0, double a1); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
|
| | | // estimate and apply a linear noise model | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| bool linearNoiseNormalization(triple<SrcIterator, SrcIterator, SrcA
ccessor> src, | | bool linearNoiseNormalization(triple<SrcIterator, SrcIterator, SrcA
ccessor> src, | |
| pair<DestIterator, DestAccessor> dest
, | | pair<DestIterator, DestAccessor> dest
, | |
| NoiseNormalizationOptions const & opt
ions = NoiseNormalizationOptions()); | | NoiseNormalizationOptions const & opt
ions = NoiseNormalizationOptions()); | |
|
| | | | |
| | | // apply a given linear noise model | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor> | |
| | | void linearNoiseNormalization(triple<SrcIterator, SrcIterator, SrcA | |
| | | ccessor> src, | |
| | | pair<DestIterator, DestAccessor> dest | |
| | | , | |
| | | double a0, double a1); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | | <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vigra::BRGBImage src(w,h), dest(w, h); | | vigra::BRGBImage src(w,h), dest(w, h); | |
| | | | |
| ... | | ... | |
|
| | | // estimate the noise model and apply it to normalize the noise varianc | |
| | | e | |
| | | bool success = linearNoiseNormalization(src, dest, | |
| | | NoiseNormalizationOptions().windowRadius(9).no | |
| | | iseVarianceInitialGuess(25.0). | |
| | | clusterCount(15)); | |
| | | vigra_postcondition(success, "linearNoiseNormalization(): Unable to est | |
| | | imate noise model."); | |
| | | | |
| | | // apply a pre-computed noise model | |
| | | linearNoiseNormalization(src, dest, 100, 0.02); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{linearNoiseNormalization} | |
| | | \code | |
| | | vigra::BRGBImage src(w,h), dest(w, h); | |
| | | | |
| | | ... | |
| | | // estimate the noise model and apply it to normalize the noise varianc | |
| | | e | |
| vigra::linearNoiseNormalization(srcImageRange(src), destImage(dest), | | vigra::linearNoiseNormalization(srcImageRange(src), destImage(dest), | |
| vigra::NoiseNormalizationOptions().wind
owRadius(9).noiseVarianceInitialGuess(25.0). | | vigra::NoiseNormalizationOptions().wind
owRadius(9).noiseVarianceInitialGuess(25.0). | |
| clusterCount(15)); | | clusterCount(15)); | |
|
| | | | |
| | | // apply a pre-computed noise model | |
| | | vigra::linearNoiseNormalization(srcImageRange(src), destImage(dest), | |
| | | 100, 0.02); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
| | | | |
|
| same as \ref noiseVarianceEstimation() | | The source value type must be convertible to <tt>double</tt> or must be | |
| | | a vector whose elements | |
| | | are convertible to <tt>double</tt>. Likewise, the destination type must | |
| | | be assignable from <tt>double</tt> | |
| | | or a vector whose elements are assignable from <tt>double</tt>. | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> bool linearNoiseNormalization) | | doxygen_overloaded_function(template <...> bool linearNoiseNormalization) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline bool | | inline bool | |
| linearNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor src, | | linearNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor src, | |
| DestIterator dul, DestAccessor dest, | | DestIterator dul, DestAccessor dest, | |
| NoiseNormalizationOptions const & options =
NoiseNormalizationOptions()) | | NoiseNormalizationOptions const & options =
NoiseNormalizationOptions()) | |
| { | | { | |
| typedef typename SrcAccessor::value_type SrcType; | | typedef typename SrcAccessor::value_type SrcType; | |
| | | | |
| return detail::linearNoiseNormalizationImpl(sul, slr, src, dul, dest, o
ptions, | | return detail::linearNoiseNormalizationImpl(sul, slr, src, dul, dest, o
ptions, | |
| typename NumericTraits<SrcType>::i
sScalar()); | | typename NumericTraits<SrcType>::i
sScalar()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline bool | |
| bool linearNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccessor> | | linearNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| src, | | pair<DestIterator, DestAccessor> dest, | |
| pair<DestIterator, DestAccessor> dest, | | NoiseNormalizationOptions const & options = NoiseN | |
| NoiseNormalizationOptions const & opti | | ormalizationOptions()) | |
| ons = NoiseNormalizationOptions()) | | | |
| { | | { | |
| return linearNoiseNormalization(src.first, src.second, src.third, dest.
first, dest.second, options); | | return linearNoiseNormalization(src.first, src.second, src.third, dest.
first, dest.second, options); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline bool | |
| | | linearNoiseNormalization(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | NoiseNormalizationOptions const & options = NoiseN | |
| | | ormalizationOptions()) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "linearNoiseNormalization(): shape mismatch between input and outpu | |
| | | t."); | |
| | | return linearNoiseNormalization(srcImageRange(src), destImage(dest), op | |
| | | tions); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* linearNoiseNormalization */ | | /* linearNoiseNormalization */ | |
|
| | | /* (variant) */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
|
| /** \brief Noise normalization by means of a given linear noise model. | | | |
| | | | |
| This function works similar to \ref nonparametricNoiseNormalization() w | | | |
| ith the exception that the | | | |
| functional dependency of the noise variance from the intensity is given | | | |
| (as a linear function) | | | |
| rather than estimated: | | | |
| | | | |
| \code | | | |
| variance = a0 + a1 * intensity | | | |
| \endcode | | | |
| | | | |
| <b> Declarations:</b> | | | |
| | | | |
| pass arguments explicitly: | | | |
| \code | | | |
| namespace vigra { | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | | |
| void linearNoiseNormalization(SrcIterator sul, SrcIterator slr, Src | | | |
| Accessor src, | | | |
| DestIterator dul, DestAccessor dest, | | | |
| double a0, double a1); | | | |
| } | | | |
| \endcode | | | |
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | | |
| \code | | | |
| namespace vigra { | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | | |
| void linearNoiseNormalization(triple<SrcIterator, SrcIterator, SrcA | | | |
| ccessor> src, | | | |
| pair<DestIterator, DestAccessor> dest | | | |
| , | | | |
| double a0, double a1); | | | |
| } | | | |
| \endcode | | | |
| | | | |
| <b> Usage:</b> | | | |
| | | | |
| <b>\#include</b> \<vigra/noise_normalization.hxx\><br> | | | |
| Namespace: vigra | | | |
| | | | |
| \code | | | |
| vigra::BRGBImage src(w,h), dest(w, h); | | | |
| | | | |
| ... | | | |
| vigra::linearNoiseNormalization(srcImageRange(src), destImage(dest), | | | |
| 100, 0.02); | | | |
| \endcode | | | |
| | | | |
| <b> Required Interface:</b> | | | |
| | | | |
| The source value type must be convertible to <tt>double</tt> or must be | | | |
| a vector whose elements | | | |
| are convertible to <tt>double</tt>. Likewise, the destination type must | | | |
| be assignable from <tt>double</tt> | | | |
| or a vector whose elements are assignable from <tt>double</tt>. | | | |
| */ | | | |
| doxygen_overloaded_function(template <...> void linearNoiseNormalization) | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline | | inline | |
| void linearNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor
src, | | void linearNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor
src, | |
| DestIterator dul, DestAccessor dest, | | DestIterator dul, DestAccessor dest, | |
| double a0, double a1) | | double a0, double a1) | |
| { | | { | |
| typedef typename SrcAccessor::value_type SrcType; | | typedef typename SrcAccessor::value_type SrcType; | |
| | | | |
| detail::linearNoiseNormalizationImpl(sul, slr, src, dul, dest, a0, a1, | | detail::linearNoiseNormalizationImpl(sul, slr, src, dul, dest, a0, a1, | |
| typename NumericTraits<SrcType>::i
sScalar()); | | typename NumericTraits<SrcType>::i
sScalar()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline void | |
| void linearNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccessor> | | linearNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| src, | | pair<DestIterator, DestAccessor> dest, | |
| pair<DestIterator, DestAccessor> dest, | | double a0, double a1) | |
| double a0, double a1) | | | |
| { | | { | |
| linearNoiseNormalization(src.first, src.second, src.third, dest.first,
dest.second, a0, a1); | | linearNoiseNormalization(src.first, src.second, src.third, dest.first,
dest.second, a0, a1); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | linearNoiseNormalization(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double a0, double a1) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "linearNoiseNormalization(): shape mismatch between input and outpu | |
| | | t."); | |
| | | linearNoiseNormalization(srcImageRange(src), destImage(dest), a0, a1); | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_NOISE_NORMALIZATION_HXX | | #endif // VIGRA_NOISE_NORMALIZATION_HXX | |
| | | | |
End of changes. 79 change blocks. |
| 220 lines changed or deleted | | 425 lines changed or added | |
|
| polygon.hxx | | polygon.hxx | |
| | | | |
| skipping to change at line 45 | | skipping to change at line 45 | |
| | | | |
| #ifndef VIGRA_POLYGON_HXX | | #ifndef VIGRA_POLYGON_HXX | |
| #define VIGRA_POLYGON_HXX | | #define VIGRA_POLYGON_HXX | |
| | | | |
| #include <cmath> | | #include <cmath> | |
| #include <cstdlib> | | #include <cstdlib> | |
| #include <iterator> | | #include <iterator> | |
| #include <algorithm> | | #include <algorithm> | |
| #include "config.hxx" | | #include "config.hxx" | |
| #include "error.hxx" | | #include "error.hxx" | |
|
| | | #include "tinyvector.hxx" | |
| #include "array_vector.hxx" | | #include "array_vector.hxx" | |
|
| | | #include "gaussians.hxx" | |
| | | #include "splines.hxx" | |
| | | #include "linear_solve.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
|
| /** \addtogroup MathFunctions | | | |
| */ | | | |
| //@{ | | | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| template < class Point > | | template < class Point > | |
|
| bool sortPoints(Point const & p1, Point const & p2) | | bool pointYXOrdering(Point const & p1, Point const & p2) | |
| { | | { | |
|
| return (p1[0]<p2[0]) || (p1[0] == p2[0] && p1[1] < p2[1]); | | return (p1[1]<p2[1]) || (p1[1] == p2[1] && p1[0] < p2[0]); | |
| } | | } | |
| | | | |
| template < class Point > | | template < class Point > | |
| bool orderedClockwise(const Point &O, const Point &A, const Point &B) | | bool orderedClockwise(const Point &O, const Point &A, const Point &B) | |
| { | | { | |
| return (A[0] - O[0]) * (B[1] - O[1]) - (A[1] - O[1]) * (B[0] - O[0]) <=
0; | | return (A[0] - O[0]) * (B[1] - O[1]) - (A[1] - O[1]) * (B[0] - O[0]) <=
0; | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| | | /** \addtogroup Geometry | |
| | | */ | |
| | | //@{ | |
| | | | |
| | | /** Polygons in two and higher dimenions. | |
| | | | |
| | | */ | |
| | | template<class POINT=TinyVector<double, 2> > | |
| | | class Polygon | |
| | | : protected ArrayVector<POINT> | |
| | | { | |
| | | public: | |
| | | typedef ArrayVector<POINT> Base; | |
| | | | |
| | | typedef POINT Point; | |
| | | typedef typename Base::value_type value_type; | |
| | | typedef typename Base::reference reference; | |
| | | typedef typename Base::const_reference const_reference; | |
| | | typedef typename Base::pointer pointer; | |
| | | typedef typename Base::const_pointer const_pointer; | |
| | | typedef typename Base::iterator iterator; | |
| | | typedef typename Base::const_iterator const_iterator; | |
| | | typedef typename Base::reverse_iterator reverse_iterator; | |
| | | typedef typename Base::const_reverse_iterator const_reverse_iterator; | |
| | | typedef typename Base::size_type size_type; | |
| | | typedef typename Base::difference_type difference_type; | |
| | | typedef typename POINT::value_type coordinate_type; | |
| | | | |
| | | using Base::size; | |
| | | using Base::empty; | |
| | | using Base::begin; | |
| | | using Base::end; | |
| | | using Base::cbegin; | |
| | | using Base::cend; | |
| | | using Base::rbegin; | |
| | | using Base::rend; | |
| | | using Base::crbegin; | |
| | | using Base::crend; | |
| | | | |
| | | // use default copy constructor | |
| | | | |
| | | Polygon() | |
| | | : length_(0.0), | |
| | | lengthValid_(false), | |
| | | partialArea_(0.0), | |
| | | partialAreaValid_(false) | |
| | | {} | |
| | | | |
| | | Polygon(size_type n) | |
| | | : Base(n, Point()), | |
| | | lengthValid_(false), | |
| | | partialAreaValid_(false) | |
| | | {} | |
| | | | |
| | | template <class InputIterator> | |
| | | Polygon(InputIterator b, InputIterator e) | |
| | | : Base(b, e), | |
| | | lengthValid_(false), | |
| | | partialAreaValid_(false) | |
| | | {} | |
| | | | |
| | | void clear() | |
| | | { | |
| | | invalidateProperties(); | |
| | | Base::clear(); | |
| | | } | |
| | | | |
| | | void invalidateProperties() | |
| | | { | |
| | | lengthValid_ = false; | |
| | | partialAreaValid_ = false; | |
| | | } | |
| | | | |
| | | double length() const | |
| | | { | |
| | | if(!lengthValid_) | |
| | | { | |
| | | length_ = 0.0; | |
| | | for(unsigned int i = 1; i < size(); ++i) | |
| | | length_ += ((*this)[i] - (*this)[i-1]).magnitude(); | |
| | | lengthValid_ = true; | |
| | | } | |
| | | return length_; | |
| | | } | |
| | | | |
| | | double partialArea() const | |
| | | { | |
| | | if(!partialAreaValid_) | |
| | | { | |
| | | partialArea_ = 0.0; | |
| | | for(unsigned int i = 1; i < size(); ++i) | |
| | | partialArea_ += ((*this)[i][0]*(*this)[i-1][1] - | |
| | | (*this)[i][1]*(*this)[i-1][0]); | |
| | | partialArea_ *= 0.5; | |
| | | partialAreaValid_ = true; | |
| | | } | |
| | | return partialArea_; | |
| | | } | |
| | | | |
| | | double area() const | |
| | | { | |
| | | vigra_precondition(closed(), | |
| | | "Polygon::area() requires polygon to be closed!" | |
| | | ); | |
| | | return abs(partialArea()); | |
| | | } | |
| | | | |
| | | /// Returns true iff the last and first points are equal or the pol | |
| | | ygon is empty. | |
| | | bool closed() const | |
| | | { | |
| | | return size() <= 1 || back() == front(); | |
| | | } | |
| | | | |
| | | /** Linearly interpolate at <tt>offset</tt> between knots | |
| | | <tt>index</tt> and <tt>index+1</tt>. | |
| | | | |
| | | Preconditions: <tt>0 <= index < size()-1</tt> and <tt>0 <= offs | |
| | | et <= 1</tt>. | |
| | | */ | |
| | | Point interpolate(unsigned int index, double offset) const | |
| | | { | |
| | | if(index < size() - 1) | |
| | | return (1.0 - offset) * (*this)[index] + offset * (*this)[index | |
| | | +1]; | |
| | | else | |
| | | return (*this)[index]; | |
| | | } | |
| | | | |
| | | /** | |
| | | * Tests whether the given point lies within this polygon. | |
| | | * Requires that this polygon is closed. | |
| | | | |
| | | * Points which lie directly on the polylines or coincide with a kn | |
| | | ot | |
| | | * are considered inside (this behavior is consistent with fillPoly | |
| | | gon()). | |
| | | * Parameter \a tolerance (interpreted as an absolute error bound) | |
| | | * controls the numerical accuracy of this test. | |
| | | */ | |
| | | bool contains(const_reference point, coordinate_type tolerance) const; | |
| | | | |
| | | bool contains(const_reference point) const | |
| | | { | |
| | | return contains(point, 2.0*NumericTraits<coordinate_type>::epsilon( | |
| | | )); | |
| | | } | |
| | | | |
| | | void push_back(const_reference v) | |
| | | { | |
| | | if(size()) | |
| | | { | |
| | | if(lengthValid_) | |
| | | length_ += (v - back()).magnitude(); | |
| | | if(partialAreaValid_) | |
| | | partialArea_ += 0.5*(v[0]*back()[1] - v[1]*back()[0]); | |
| | | } | |
| | | push_back_unsafe(v); | |
| | | } | |
| | | | |
| | | void push_back_unsafe(const_reference v) | |
| | | { | |
| | | Base::push_back(v); | |
| | | } | |
| | | | |
| | | void extend(const Polygon &other) | |
| | | { | |
| | | if(!other.size()) | |
| | | return; | |
| | | | |
| | | const_iterator otherBegin(other.begin()); | |
| | | if(size()) | |
| | | { | |
| | | if(*otherBegin == Base::back()) | |
| | | { | |
| | | // don't copy first pixel | |
| | | ++otherBegin; | |
| | | } | |
| | | else | |
| | | { | |
| | | if(lengthValid_) | |
| | | length_ += (other.front() - Base::back()).magnitude(); | |
| | | if(partialAreaValid_) | |
| | | partialArea_ += (other.front()[0]*Base::back()[1] - | |
| | | other.front()[1]*Base::back()[0]); | |
| | | } | |
| | | } | |
| | | if(lengthValid_) | |
| | | length_ += other.length(); | |
| | | if(partialAreaValid_) | |
| | | partialArea_ += other.partialArea(); | |
| | | Base::insert(Base::end(), otherBegin, other.end()); | |
| | | } | |
| | | | |
| | | void setPoint(unsigned int pos, const_reference x) | |
| | | { | |
| | | invalidateProperties(); | |
| | | Base::operator[](pos) = x; | |
| | | } | |
| | | | |
| | | // doesn't call invalidateProperties() | |
| | | void setPointUnsafe(unsigned int pos, const_reference x) | |
| | | { | |
| | | Base::operator[](pos) = x; | |
| | | } | |
| | | | |
| | | // alternative, but it will also invalidate if the caller only read | |
| | | s | |
| | | // reads the return value. | |
| | | // reference operator[](unsigned int pos) | |
| | | // { | |
| | | // invalidateProperties(); | |
| | | // return Base::operator[](pos); | |
| | | // } | |
| | | | |
| | | const_reference operator[](unsigned int pos) const | |
| | | { | |
| | | return Base::operator[](pos); | |
| | | } | |
| | | | |
| | | const_reference front() const | |
| | | { | |
| | | return Base::front(); | |
| | | } | |
| | | | |
| | | const_reference back() const | |
| | | { | |
| | | return Base::back(); | |
| | | } | |
| | | | |
| | | iterator begin() | |
| | | { | |
| | | invalidateProperties(); | |
| | | return Base::begin(); | |
| | | } | |
| | | | |
| | | iterator end() | |
| | | { | |
| | | invalidateProperties(); | |
| | | return Base::end(); | |
| | | } | |
| | | | |
| | | reverse_iterator rbegin() | |
| | | { | |
| | | invalidateProperties(); | |
| | | return Base::rbegin(); | |
| | | } | |
| | | | |
| | | reverse_iterator rend() | |
| | | { | |
| | | invalidateProperties(); | |
| | | return Base::rend(); | |
| | | } | |
| | | | |
| | | void erase(iterator pos) | |
| | | { | |
| | | invalidateProperties(); | |
| | | Base::erase(pos); | |
| | | } | |
| | | | |
| | | void erase(iterator pos, iterator end) | |
| | | { | |
| | | invalidateProperties(); | |
| | | Base::erase(pos, end); | |
| | | } | |
| | | | |
| | | iterator insert(iterator pos, const_reference x) | |
| | | { | |
| | | invalidateProperties(); | |
| | | return Base::insert(pos, x); | |
| | | } | |
| | | | |
| | | template <class InputIterator> | |
| | | iterator insert(iterator pos, InputIterator i, InputIterator end) | |
| | | { | |
| | | invalidateProperties(); | |
| | | return Base::insert(pos, i, end); | |
| | | } | |
| | | | |
| | | Polygon split(unsigned int pos) | |
| | | { | |
| | | Polygon result; | |
| | | if(pos == 0) | |
| | | { | |
| | | swap(result); | |
| | | } | |
| | | else if(pos < size()) | |
| | | { | |
| | | result.insert(result.begin(), begin() + pos, end()); | |
| | | erase(begin() + pos, end()); | |
| | | } | |
| | | return result; | |
| | | } | |
| | | | |
| | | template <class Sequence> | |
| | | void arcLengthList(Sequence & arcLengths) const | |
| | | { | |
| | | double length = 0.0; | |
| | | arcLengths.push_back(0.0); | |
| | | for(unsigned int i = 1; i < size(); ++i) | |
| | | { | |
| | | length += ((*this)[i] - (*this)[i-1]).magnitude(); | |
| | | arcLengths.push_back(length); | |
| | | } | |
| | | } | |
| | | | |
| | | /** Find the point on the polygon that corresponds to the given qua | |
| | | ntile. | |
| | | | |
| | | \a quantile must be in <tt>[0.0, 1.0]</tt>. The result of this | |
| | | function | |
| | | can be used as input to <tt>interpolate()</tt>. For example, | |
| | | the following code computes the point in the middle of the poly | |
| | | gon: | |
| | | | |
| | | \code | |
| | | double c = poly.arcLengthQuantile(0.5); | |
| | | Point center = poly.interpolate((int)floor(c), c - floor(c)); | |
| | | \endcode | |
| | | */ | |
| | | double arcLengthQuantile(double quantile) const | |
| | | { | |
| | | vigra_precondition(this->size() > 0, | |
| | | "Polygon:.arcLengthQuantile(): polygon is empty."); | |
| | | if(quantile == 0.0 || this->size() == 1) | |
| | | return 0.0; | |
| | | if(quantile == 1.0) | |
| | | return this->size() - 1.0; | |
| | | vigra_precondition(0.0 < quantile && quantile < 1.0, | |
| | | "Polygon:.arcLengthQuantile(): quantile must be between 0 and 1 | |
| | | ."); | |
| | | ArrayVector<double> arcLength; | |
| | | arcLength.reserve(this->size()); | |
| | | arcLengthList(arcLength); | |
| | | double length = quantile*arcLength.back(); | |
| | | unsigned int k=0; | |
| | | for(; k<this->size(); ++k) | |
| | | if(arcLength[k] >= length) | |
| | | break; | |
| | | --k; | |
| | | return k + (length - arcLength[k]) / (arcLength[k+1] - arcLength[k] | |
| | | ); | |
| | | } | |
| | | | |
| | | void swap(Polygon &rhs) | |
| | | { | |
| | | Base::swap(rhs); | |
| | | std::swap(length_, rhs.length_); | |
| | | std::swap(lengthValid_, rhs.lengthValid_); | |
| | | std::swap(partialArea_, rhs.partialArea_); | |
| | | std::swap(partialAreaValid_, rhs.partialAreaValid_); | |
| | | } | |
| | | | |
| | | void reverse() | |
| | | { | |
| | | std::reverse(Base::begin(), Base::end()); | |
| | | if(partialAreaValid_) | |
| | | partialArea_ = -partialArea_; | |
| | | } | |
| | | | |
| | | POINT nearestPoint(const_reference p) const; | |
| | | | |
| | | Polygon & operator+=(POINT const & offset) | |
| | | { | |
| | | if(!closed()) | |
| | | partialAreaValid_ = false; | |
| | | for(unsigned int i = 0; i < size(); ++i) | |
| | | Base::operator[](i) += offset; | |
| | | return *this; | |
| | | } | |
| | | | |
| | | Polygon & operator-=(POINT const & offset) | |
| | | { | |
| | | if(!closed()) | |
| | | partialAreaValid_ = false; | |
| | | for(unsigned int i = 0; i < size(); ++i) | |
| | | Base::operator[](i) -= offset; | |
| | | return *this; | |
| | | } | |
| | | | |
| | | Polygon & operator*=(double scale) | |
| | | { | |
| | | partialArea_ *= sq(scale); | |
| | | length_ *= scale; | |
| | | for(unsigned int i = 0; i < size(); ++i) | |
| | | Base::operator[](i) *= scale; | |
| | | return *this; | |
| | | } | |
| | | | |
| | | Polygon & operator/=(double scale) | |
| | | { | |
| | | partialArea_ /= sq(scale); | |
| | | length_ /= scale; | |
| | | for(unsigned int i = 0; i < size(); ++i) | |
| | | Base::operator[](i) /= scale; | |
| | | return *this; | |
| | | } | |
| | | | |
| | | bool operator==(Polygon const & rhs) const | |
| | | { | |
| | | if(size() != rhs.size()) | |
| | | return false; | |
| | | for(size_type k=0; k<size(); ++k) | |
| | | if((*this)[k] != rhs[k]) | |
| | | return false; | |
| | | return true; | |
| | | } | |
| | | | |
| | | bool operator!=(Polygon const & rhs) const | |
| | | { | |
| | | return !((*this) == rhs); | |
| | | } | |
| | | | |
| | | protected: | |
| | | | |
| | | mutable double length_; | |
| | | mutable bool lengthValid_; | |
| | | mutable double partialArea_; | |
| | | mutable bool partialAreaValid_; | |
| | | }; | |
| | | | |
| | | template <class POINT> | |
| | | POINT Polygon<POINT>::nearestPoint(const_reference p) const | |
| | | { | |
| | | double dist = NumericTraits<double>::max(); | |
| | | POINT r; | |
| | | for(unsigned int k=1; k<size(); ++k) | |
| | | { | |
| | | POINT dp = (*this)[k] - (*this)[k-1]; | |
| | | POINT dc = p - (*this)[k-1]; | |
| | | double t = dot(dp, dc); | |
| | | if(t != 0.0) | |
| | | t /= squaredNorm(dp); | |
| | | if(t > 1.0) | |
| | | { | |
| | | double d = norm((*this)[k]-p); | |
| | | if (d < dist) | |
| | | { | |
| | | dist = d; | |
| | | r = (*this)[k]; | |
| | | } | |
| | | } | |
| | | else if(t < 0.0) | |
| | | { | |
| | | double d = norm((*this)[k-1]-p); | |
| | | if (d < dist) | |
| | | { | |
| | | dist = d; | |
| | | r = (*this)[k-1]; | |
| | | } | |
| | | } | |
| | | else | |
| | | { | |
| | | POINT pp = (*this)[k-1] + t*dp; | |
| | | double d = norm(pp-p); | |
| | | if (d < dist) | |
| | | { | |
| | | dist = d; | |
| | | r = pp; | |
| | | } | |
| | | } | |
| | | } | |
| | | return r; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | bool | |
| | | Polygon<POINT>::contains(const_reference point, | |
| | | coordinate_type tolerance) const | |
| | | { | |
| | | typedef typename Polygon<POINT>::Base Base; | |
| | | vigra_precondition(closed(), | |
| | | "Polygon::contains() requires polygon to be closed!" | |
| | | ); | |
| | | | |
| | | // NOTE: the following code is very similar to detail::createScanInterv | |
| | | als() | |
| | | // to ensure consistent results. | |
| | | | |
| | | Polygon p = (*this) - point; // shift the polygon so that we only need | |
| | | to test | |
| | | // for intersections with scanline 0 | |
| | | int n = p.size(); | |
| | | for(int k=0; k<n; ++k) | |
| | | if(closeAtTolerance(p[k][1], 0.0, tolerance)) | |
| | | ((Base&)p)[k][1] = 0.0; | |
| | | | |
| | | int result = 0; | |
| | | bool drop_next_start_point = false; | |
| | | int first_point_maybe_dropped = -1; | |
| | | for(int k=0; k<n-1; ++k) | |
| | | { | |
| | | Point const & p1 = p[k]; | |
| | | Point const & p2 = p[k+1]; | |
| | | | |
| | | if(p1[1] == p2[1]) // ignore horizontal lines | |
| | | continue; | |
| | | | |
| | | double t = (p2[0] - p1[0]) / (p2[1] - p1[1]); | |
| | | double y, yend, dy; | |
| | | if(p1[1] < p2[1]) | |
| | | { | |
| | | y = ceil(p1[1]); | |
| | | yend = floor(p2[1]); | |
| | | dy = 1.0; | |
| | | } | |
| | | else | |
| | | { | |
| | | y = floor(p1[1]); | |
| | | yend = ceil(p2[1]); | |
| | | dy = -1.0; | |
| | | } | |
| | | if(yend != p2[1]) | |
| | | yend += dy; | |
| | | if(drop_next_start_point) | |
| | | { | |
| | | y += dy; | |
| | | drop_next_start_point = false; | |
| | | } | |
| | | if(first_point_maybe_dropped == -1) | |
| | | { | |
| | | if(y == 0.0 && p1[0] - p1[1]*t < 0.0) | |
| | | first_point_maybe_dropped = 1; | |
| | | else | |
| | | first_point_maybe_dropped = 0; | |
| | | } | |
| | | if(y*dy <= 0.0 && yend*dy > 0.0) // intersects scanline 0 | |
| | | { | |
| | | double x = p1[0] - p1[1]*t; | |
| | | if(closeAtTolerance(x, 0.0, tolerance)) | |
| | | return true; | |
| | | if(x < 0.0) | |
| | | ++result; | |
| | | } | |
| | | else if(p2[1] == 0.0) // degenerate case | |
| | | { | |
| | | int j = (k+2)%n; | |
| | | bool convex = detail::orderedClockwise(p1, p2, p[j]); | |
| | | if(convex) | |
| | | { | |
| | | double x = p2[0] - p2[1]*t; | |
| | | if(closeAtTolerance(x, 0.0, tolerance)) | |
| | | return true; | |
| | | if(x < 0.0) | |
| | | ++result; | |
| | | } | |
| | | for(; j != k+1; j = (j+1)%n) | |
| | | { | |
| | | double bend = dy*(p[j][1] - yend); | |
| | | if(bend == 0.0) | |
| | | continue; | |
| | | // Drop startpoint of next segment when the polygon after a | |
| | | convex | |
| | | // degenerate knot eventually crosses the scanline, or when | |
| | | it | |
| | | // returns to the original side of the scanline after a con | |
| | | cave | |
| | | // degenerate knot. | |
| | | if((convex && bend > 0.0) || (!convex && bend < 0.0)) | |
| | | drop_next_start_point = true; | |
| | | break; | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| | | if(drop_next_start_point && first_point_maybe_dropped == 1) | |
| | | --result; | |
| | | | |
| | | return (result % 2) != 0; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> round(Polygon<POINT> const & p) | |
| | | { | |
| | | Polygon<POINT> result(p.size()); | |
| | | for(unsigned int i = 0; i < p.size(); ++i) | |
| | | { | |
| | | result.setPointUnsafe(i, round(p[i])); | |
| | | } | |
| | | return result; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<TinyVector<std::ptrdiff_t, 2> > roundi(Polygon<POINT> const | |
| | | & p) | |
| | | { | |
| | | Polygon<TinyVector<std::ptrdiff_t, 2> > result(p.size()); | |
| | | for(unsigned int i = 0; i < p.size(); ++i) | |
| | | { | |
| | | result.setPointUnsafe(i,roundi(p[i])); | |
| | | } | |
| | | return result; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> | |
| | | operator+(Polygon<POINT> const & p, POINT const & offset) | |
| | | { | |
| | | return Polygon<POINT>(p) += offset; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> | |
| | | operator+(POINT const & offset, Polygon<POINT> const & p) | |
| | | { | |
| | | return Polygon<POINT>(p) += offset; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> | |
| | | operator-(Polygon<POINT> const & p) | |
| | | { | |
| | | Polygon<POINT> result(p.size()); | |
| | | for(unsigned int i = 0; i < p.size(); ++i) | |
| | | result.setPointUnsafe(i, -p[i]); | |
| | | return result; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> | |
| | | operator-(Polygon<POINT> const & p, POINT const & offset) | |
| | | { | |
| | | return Polygon<POINT>(p) -= offset; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> | |
| | | operator*(Polygon<POINT> const & p, double scale) | |
| | | { | |
| | | return Polygon<POINT>(p) *= scale; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> | |
| | | operator*(double scale, Polygon<POINT> const & p) | |
| | | { | |
| | | return Polygon<POINT>(p) *= scale; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> | |
| | | operator/(Polygon<POINT> const & p, double scale) | |
| | | { | |
| | | return Polygon<POINT>(p) /= scale; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> | |
| | | transpose(Polygon<POINT> const & p) | |
| | | { | |
| | | Polygon<POINT> result(p.size()); | |
| | | for(unsigned int i = 0; i < p.size(); ++i) | |
| | | { | |
| | | result.setPointUnsafe(i, POINT(p[i][1], p[i][0])); | |
| | | } | |
| | | return result; | |
| | | } | |
| | | | |
| | | template <class POINT> | |
| | | inline Polygon<POINT> | |
| | | reverse(Polygon<POINT> const & p) | |
| | | { | |
| | | Polygon<POINT> result(p); | |
| | | result.reverse(); | |
| | | return result; | |
| | | } | |
| | | | |
| | | template<class Point> | |
| | | Point centroid(const Polygon<Point> &polygon) | |
| | | { | |
| | | vigra_precondition(polygon.closed(), | |
| | | "centroid() expects a closed polygon"); | |
| | | double a = 0.0; | |
| | | TinyVector<double, 2> result; | |
| | | for(unsigned int i = 1; i < polygon.size(); ++i) | |
| | | { | |
| | | double pa = (polygon[i-1][0]*polygon[i][1] - | |
| | | polygon[i-1][1]*polygon[i][0]); | |
| | | a += pa; | |
| | | result += (polygon[i-1] + polygon[i])*pa; | |
| | | } | |
| | | return result / (3.0*a); | |
| | | } | |
| | | | |
| | | } // namespace vigra | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | namespace std { | |
| | | | |
| | | template<class T> | |
| | | void swap(vigra::Polygon<T> &a, vigra::Polygon<T> &b) | |
| | | { | |
| | | a.swap(b); | |
| | | } | |
| | | | |
| | | } // namespace std | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | namespace vigra { | |
| | | | |
| | | /** \brief Create a polygon from the interpixel contour of a labeled region | |
| | | . | |
| | | | |
| | | The point \a anchor_point must be in the region whose contour we want t | |
| | | o extract, | |
| | | and must be adjacent to the contour. The algorithm uses the 'left hand | |
| | | on the wall' | |
| | | algorithm to trace the connected component whose label equals the label | |
| | | of the | |
| | | \a anchor_point. The contour is returned in \a countour_points as a clo | |
| | | sed polygon | |
| | | that circles the region counter-clockwise in the image coordinate syste | |
| | | m (i.e. the | |
| | | coordinate system where x points to the right and y points downwards). | |
| | | Since the | |
| | | resulting polygon represents the interpixel contour, all points will ha | |
| | | ve one integer | |
| | | and one half-integer coordinate. | |
| | | */ | |
| | | template<class T, class S, class PointArray> | |
| | | void | |
| | | extractContour(MultiArrayView<2, T, S> const &label_image, | |
| | | Shape2 const & anchor_point, | |
| | | PointArray & contour_points) | |
| | | { | |
| | | typedef typename PointArray::value_type Point; | |
| | | | |
| | | Shape2 step[4] = { Shape2(0, -1), Shape2(1, 0), Shape2(0, 1), Shape2(-1 | |
| | | , 0) }; | |
| | | Point contour_offsets[4] = { Point(-0.5, 0), Point(0, -0.5), Point(0.5, | |
| | | 0), Point(0, 0.5) }; | |
| | | | |
| | | T foreground = label_image[anchor_point]; | |
| | | | |
| | | int direction; | |
| | | Shape2 position; | |
| | | // find a position outside the object from which we place the hand | |
| | | for(direction = 3; direction >= 0; --direction) | |
| | | { | |
| | | position = anchor_point + step[(direction + 1) % 4]; | |
| | | if(!label_image.isInside(position) || label_image[position] != fore | |
| | | ground) | |
| | | break; | |
| | | } | |
| | | | |
| | | vigra_precondition(direction >= 0, | |
| | | "extractContour(): the anchor point must be at the region border.") | |
| | | ; | |
| | | | |
| | | int initial_direction = direction; | |
| | | Shape2 initial_position = position; | |
| | | | |
| | | // go around the object | |
| | | do | |
| | | { | |
| | | contour_points.push_back(position + contour_offsets[direction]); | |
| | | | |
| | | Shape2 next_position = position + step[direction]; | |
| | | | |
| | | if(label_image.isInside(next_position) && | |
| | | label_image[next_position] == foreground) | |
| | | { | |
| | | // we have bumped into a wall => turn right to touch the wall a | |
| | | gain | |
| | | direction = (direction + 1) % 4; | |
| | | } | |
| | | else | |
| | | { | |
| | | position = next_position; | |
| | | int next_direction = (direction + 3) % 4; | |
| | | next_position += step[next_direction]; | |
| | | if(!label_image.isInside(next_position) || | |
| | | label_image[next_position] != foreground) | |
| | | { | |
| | | // we have lost the wall => turn left and move forward to t | |
| | | ouch the wall again | |
| | | direction = next_direction; | |
| | | position = next_position; | |
| | | } | |
| | | } | |
| | | } | |
| | | while (position != initial_position || direction != initial_direction); | |
| | | | |
| | | contour_points.push_back(contour_points.front()); // make it a closed p | |
| | | olygon | |
| | | } | |
| | | | |
| /** \brief Compute convex hull of a 2D polygon. | | /** \brief Compute convex hull of a 2D polygon. | |
| | | | |
| The input array \a points contains a (not necessarily ordered) set of 2
D points | | The input array \a points contains a (not necessarily ordered) set of 2
D points | |
| whose convex hull is to be computed. The array's <tt>value_type</tt> (i
.e. the point type) | | whose convex hull is to be computed. The array's <tt>value_type</tt> (i
.e. the point type) | |
| must be compatible with std::vector (in particular, it must support ind
exing, | | must be compatible with std::vector (in particular, it must support ind
exing, | |
| copying, and have <tt>size() == 2</tt>). The points of the convex hull
will be appended | | copying, and have <tt>size() == 2</tt>). The points of the convex hull
will be appended | |
| to the output array \a convex_hull (which must support <tt>std::back_in
serter(convex_hull)</tt>). | | to the output array \a convex_hull (which must support <tt>std::back_in
serter(convex_hull)</tt>). | |
| Since the convex hull is a closed polygon, the first and last point of
the output will | | Since the convex hull is a closed polygon, the first and last point of
the output will | |
| be the same (i.e. the first point will simply be inserted at the end ag
ain). The points | | be the same (i.e. the first point will simply be inserted at the end ag
ain). The points | |
| of the convex hull will be ordered counter-clockwise, starting with the
leftmost point | | of the convex hull will be ordered counter-clockwise, starting with the
leftmost point | |
| | | | |
| skipping to change at line 91 | | skipping to change at line 845 | |
| template<class PointArray1, class PointArray2> | | template<class PointArray1, class PointArray2> | |
| void convexHull(const PointArray1 &points, PointArray2 & convex_hull) | | void convexHull(const PointArray1 &points, PointArray2 & convex_hull) | |
| { | | { | |
| vigra_precondition(points.size() >= 2, | | vigra_precondition(points.size() >= 2, | |
| "convexHull(): at least two input points are needed.
"); | | "convexHull(): at least two input points are needed.
"); | |
| vigra_precondition(points[0].size() == 2, | | vigra_precondition(points[0].size() == 2, | |
| "convexHull(): 2-dimensional points required."); | | "convexHull(): 2-dimensional points required."); | |
| | | | |
| typedef typename PointArray1::value_type Point; | | typedef typename PointArray1::value_type Point; | |
| | | | |
|
| ArrayVector<Point> ordered(points.begin(), points.end()); | | typename PointArray1::const_iterator begin = points.begin(); | |
| std::sort(ordered.begin(), ordered.end(), detail::sortPoints<Point>); | | if(points.front() == points.back()) // closed polygon | |
| | | ++begin; // => remove redundant start point | |
| | | ArrayVector<Point> ordered(begin, points.end()); | |
| | | std::sort(ordered.begin(), ordered.end(), detail::pointYXOrdering<Point | |
| | | >); | |
| | | | |
| ArrayVector<Point> H; | | ArrayVector<Point> H; | |
| | | | |
|
| int n = points.size(), k=0; | | int n = ordered.size(), k=0; | |
| | | | |
| // Build lower hull | | // Build lower hull | |
| for (int i = 0; i < n; i++) | | for (int i = 0; i < n; i++) | |
| { | | { | |
| while (k >= 2 && detail::orderedClockwise(H[k-2], H[k-1], ordered[i
])) | | while (k >= 2 && detail::orderedClockwise(H[k-2], H[k-1], ordered[i
])) | |
| { | | { | |
| H.pop_back(); | | H.pop_back(); | |
| --k; | | --k; | |
| } | | } | |
| H.push_back(ordered[i]); | | H.push_back(ordered[i]); | |
| | | | |
| skipping to change at line 122 | | skipping to change at line 879 | |
| { | | { | |
| while (k >= t && detail::orderedClockwise(H[k-2], H[k-1], ordered[i
])) | | while (k >= t && detail::orderedClockwise(H[k-2], H[k-1], ordered[i
])) | |
| { | | { | |
| H.pop_back(); | | H.pop_back(); | |
| --k; | | --k; | |
| } | | } | |
| H.push_back(ordered[i]); | | H.push_back(ordered[i]); | |
| ++k; | | ++k; | |
| } | | } | |
| | | | |
|
| std::copy(H.begin(), H.begin()+k, std::back_inserter(convex_hull)); | | for(int i=k-1; i>=0; --i) | |
| | | convex_hull.push_back(H[i]); | |
| } | | } | |
| | | | |
|
| | | /********************************************************************/ | |
| | | /* */ | |
| | | /* polygon drawing */ | |
| | | /* */ | |
| | | /********************************************************************/ | |
| | | | |
| | | namespace detail { | |
| | | | |
| | | /* | |
| | | * Find and sort all intersection points of the polygon with scanlines. | |
| | | * Polygons are considered as closed set, i.e. pixels on the polygon | |
| | | * contour are included. The function handles degenerate cases (i.e. | |
| | | * knots on scanlines) correctly. | |
| | | */ | |
| | | template<class Point, class Array> | |
| | | void createScanIntervals(Polygon<Point> const &p, Array & result) | |
| | | { | |
| | | bool drop_next_start_point = false; | |
| | | int n = p.size(); | |
| | | for(int k=0; k<n-1; ++k) | |
| | | { | |
| | | Point const & p1 = p[k]; | |
| | | Point const & p2 = p[k+1]; | |
| | | | |
| | | if(p1[1] == p2[1]) // ignore horizontal lines | |
| | | continue; | |
| | | | |
| | | double t = (p2[0] - p1[0]) / (p2[1] - p1[1]); | |
| | | double y, yend, dy; | |
| | | if(p1[1] < p2[1]) | |
| | | { | |
| | | y = ceil(p1[1]); | |
| | | yend = floor(p2[1]); | |
| | | dy = 1.0; | |
| | | } | |
| | | else | |
| | | { | |
| | | y = floor(p1[1]); | |
| | | yend = ceil(p2[1]); | |
| | | dy = -1.0; | |
| | | } | |
| | | if(yend != p2[1]) // in general don't include the segment's endpoin | |
| | | t | |
| | | yend += dy; // (since it is also the start point of the next | |
| | | segment) | |
| | | if(drop_next_start_point) // handle degeneracy from previous iterat | |
| | | ion | |
| | | { | |
| | | y += dy; | |
| | | drop_next_start_point = false; | |
| | | } | |
| | | for(; (y-yend)*dy < 0.0; y += dy) // compute scanline intersection | |
| | | s | |
| | | { | |
| | | double x = p1[0] + (y - p1[1])*t; | |
| | | result.push_back(Point(x,y)); | |
| | | } | |
| | | if(yend == p2[1]) // degenerate case: p2 is exactly on a scanline ( | |
| | | yend is integer) | |
| | | { | |
| | | int j = (k+2)%n; | |
| | | bool convex = detail::orderedClockwise(p1, p2, p[j]); | |
| | | if(convex) // include the segment's endpoint p2 when it is a co | |
| | | nvex knot | |
| | | { | |
| | | result.push_back(p2); | |
| | | } | |
| | | for(; j != k+1; j = (j+1)%n) | |
| | | { | |
| | | double bend = dy*(p[j][1] - yend); | |
| | | if(bend == 0.0) | |
| | | continue; | |
| | | // Drop startpoint of next segment when the polygon after a | |
| | | convex | |
| | | // degenerate knot eventually crosses the scanline, or when | |
| | | it | |
| | | // returns to the original side of the scanline after a con | |
| | | cave | |
| | | // degenerate knot. | |
| | | if((convex && bend > 0.0) || (!convex && bend < 0.0)) | |
| | | drop_next_start_point = true; | |
| | | break; | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| | | if(drop_next_start_point) | |
| | | result.erase(result.begin()); | |
| | | | |
| | | vigra_invariant((result.size() & 1) == 0, | |
| | | "createScanIntervals(): internal error - should return an even numb | |
| | | er of points."); | |
| | | sort(result.begin(), result.end(), pointYXOrdering<Point>); | |
| | | } | |
| | | | |
| | | } // namespace detail | |
| | | | |
| | | template<class Point, class FUNCTOR> | |
| | | bool | |
| | | inspectPolygon(Polygon<Point> const &p, | |
| | | FUNCTOR const & f) | |
| | | { | |
| | | vigra_precondition(p.closed(), | |
| | | "inspectPolygon(): polygon must be closed (i.e. first point == last | |
| | | point)."); | |
| | | | |
| | | std::vector<Point> scan_intervals; | |
| | | detail::createScanIntervals(p, scan_intervals); | |
| | | | |
| | | for(unsigned int k=0; k < scan_intervals.size(); k+=2) | |
| | | { | |
| | | Shape2 p((MultiArrayIndex)ceil(scan_intervals[k][0]), | |
| | | (MultiArrayIndex)scan_intervals[k][1]); | |
| | | MultiArrayIndex xend = (MultiArrayIndex)floor(scan_intervals[k+1][0 | |
| | | ]) + 1; | |
| | | for(; p[0] < xend; ++p[0]) | |
| | | if(!f(p)) | |
| | | return false; | |
| | | } | |
| | | return true; | |
| | | } | |
| | | | |
| | | /** \brief Render closed polygon \a p into the image \a output_image. | |
| | | | |
| | | All pixels on the polygon's contour and in its interior are | |
| | | set to the given \a value. Parts of the polygon outside the image | |
| | | region are clipped. The function uses a robust X-intersection array | |
| | | algorithm that is able to handle all corner cases (concave and | |
| | | self-intersecting polygons, knots on integer coordinates). | |
| | | */ | |
| | | template<class Point, class T, class S, class Value> | |
| | | void fillPolygon(Polygon<Point> const &p, | |
| | | MultiArrayView<2, T, S> &output_image, | |
| | | Value value) | |
| | | { | |
| | | vigra_precondition(p.closed(), | |
| | | "fillPolygon(): polygon must be closed (i.e. first point == last po | |
| | | int)."); | |
| | | | |
| | | std::vector<Point> scan_intervals; | |
| | | detail::createScanIntervals(p, scan_intervals); | |
| | | | |
| | | for(unsigned int k=0; k < scan_intervals.size(); k+=2) | |
| | | { | |
| | | MultiArrayIndex x = (MultiArrayIndex)ceil(scan_intervals[k][0]), | |
| | | y = (MultiArrayIndex)scan_intervals[k][1], | |
| | | xend = (MultiArrayIndex)floor(scan_intervals[k+1][0 | |
| | | ]) + 1; | |
| | | vigra_invariant(y == scan_intervals[k+1][1], | |
| | | "fillPolygon(): internal error - scan interval should have same | |
| | | y value."); | |
| | | // clipping | |
| | | if(y < 0) | |
| | | continue; | |
| | | if(y >= output_image.shape(1)) | |
| | | break; | |
| | | if(x < 0) | |
| | | x = 0; | |
| | | if(xend > output_image.shape(0)) | |
| | | xend = output_image.shape(0); | |
| | | // drawing | |
| | | for(; x < xend; ++x) | |
| | | output_image(x,y) = value; | |
| | | } | |
| | | } | |
| | | | |
| | | #if 0 | |
| | | | |
| | | // the following sophisticated polygon resampling functions have no tests y | |
| | | et | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | template<bool useMaxStep, class PointIterator, class TargetArray> | |
| | | void simplifyPolygonHelper( | |
| | | const PointIterator &polyBegin, const PointIterator &polyEnd, | |
| | | TargetArray &simple, double epsilon, | |
| | | double maxStep2 = vigra::NumericTraits<double>::max()) | |
| | | { | |
| | | if(polyEnd - polyBegin <= 2) | |
| | | return; // no splitpoint necessary / possible | |
| | | | |
| | | PointIterator splitPos(polyEnd), lastPoint(polyEnd); | |
| | | --lastPoint; | |
| | | | |
| | | double maxDist = epsilon; | |
| | | | |
| | | // calculate normal of straight end point connection | |
| | | typename TargetArray::value_type | |
| | | straight(*lastPoint - *polyBegin); | |
| | | double straightLength2 = straight.squaredMagnitude(); | |
| | | | |
| | | // search splitpoint | |
| | | if(straightLength2 > 1e-16) | |
| | | { | |
| | | typename TargetArray::value_type | |
| | | normal(straight[1], -straight[0]); | |
| | | | |
| | | normal /= std::sqrt(straightLength2); | |
| | | | |
| | | // iterate over points *between* first and last point: | |
| | | PointIterator it(polyBegin); | |
| | | for(++it; it != lastPoint; ++it) | |
| | | { | |
| | | double dist = fabs(dot(*it - *polyBegin, normal)); | |
| | | if(dist > maxDist) | |
| | | { | |
| | | splitPos = it; | |
| | | maxDist = dist; | |
| | | } | |
| | | } | |
| | | } | |
| | | else | |
| | | { | |
| | | // start- and end-points identical?! -> look for most distant point | |
| | | PointIterator it(polyBegin); | |
| | | for(++it; it != lastPoint; ++it) | |
| | | { | |
| | | double dist = (*it - *polyBegin).magnitude(); | |
| | | if(dist > maxDist) | |
| | | { | |
| | | splitPos = it; | |
| | | maxDist = dist; | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| | | if(useMaxStep && (straightLength2 > maxStep2) && (splitPos == polyEnd)) | |
| | | { | |
| | | PointIterator it(polyBegin); | |
| | | ++it; | |
| | | double bestD2D = std::fabs((*it - *polyBegin).squaredMagnitude() | |
| | | - (*it - *lastPoint).squaredMagnitude()) | |
| | | ; | |
| | | splitPos = it; | |
| | | for(++it; it != lastPoint; ++it) | |
| | | { | |
| | | double dist2Diff = std::fabs((*it - *polyBegin).squaredMagnitud | |
| | | e() | |
| | | - (*it - *lastPoint).squaredMagnit | |
| | | ude()); | |
| | | if(dist2Diff < bestD2D) | |
| | | { | |
| | | bestD2D = dist2Diff; | |
| | | splitPos = it; | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| | | if(splitPos != polyEnd) | |
| | | { | |
| | | simplifyPolygonHelper<useMaxStep>( | |
| | | polyBegin, splitPos + 1, simple, epsilon, maxStep2); | |
| | | simple.push_back(*splitPos); | |
| | | simplifyPolygonHelper<useMaxStep>( | |
| | | splitPos, polyEnd, simple, epsilon, maxStep2); | |
| | | } | |
| | | } | |
| | | | |
| | | template<class PointArray> | |
| | | void simplifyPolygon( | |
| | | const PointArray &poly, PointArray &simple, double epsilon) | |
| | | { | |
| | | simple.push_back(poly[0]); | |
| | | simplifyPolygonHelper<false>(poly.begin(), poly.end(), simple, epsilon) | |
| | | ; | |
| | | simple.push_back(poly[poly.size()-1]); | |
| | | } | |
| | | | |
| | | template<class PointArray> | |
| | | void simplifyPolygon( | |
| | | const PointArray &poly, PointArray &simple, double epsilon, double maxS | |
| | | tep) | |
| | | { | |
| | | simple.push_back(poly[0]); | |
| | | simplifyPolygonHelper<true>(poly.begin(), poly.end(), | |
| | | simple, epsilon, maxStep*maxStep); | |
| | | simple.push_back(poly[poly.size()-1]); | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | namespace detail { | |
| | | | |
| | | template <class Point> | |
| | | Point digitalLineIntersection(TinyVector<double, 3> const & l1, TinyVector< | |
| | | double, 3> const & l2) | |
| | | { | |
| | | double d = l1[0]*l2[1] - l1[1]*l2[0]; | |
| | | return Point((l1[1]*l2[2] - l1[2]*l2[1]) / d, (l1[2]*l2[0] - l1[0]*l2[2 | |
| | | ]) / d); | |
| | | } | |
| | | | |
| | | } // namespace detail | |
| | | | |
| | | template<class PointArray> | |
| | | void simplifyPolygonDigitalLine( | |
| | | const PointArray &poly, PointArray &simple, int connectivity) | |
| | | { | |
| | | typedef typename PointArray::value_type Point; | |
| | | | |
| | | int size = poly.size(); | |
| | | if(size <= 2) | |
| | | { | |
| | | simple = poly; | |
| | | return; | |
| | | } | |
| | | | |
| | | vigra_precondition(connectivity == 4 || connectivity == 8, | |
| | | "simplifyPolygonDigitalLine(): connectivity must be 4 or 8."); | |
| | | | |
| | | bool isOpenPolygon = poly[size-1] != poly[0]; | |
| | | | |
| | | ArrayVector<TinyVector<double, 3> > lines; | |
| | | Point l1 = poly[0], | |
| | | r1 = l1, | |
| | | l2 = poly[1], | |
| | | r2 = l2; | |
| | | double a = l2[1] - l1[1], | |
| | | b = l1[0] - l2[0], | |
| | | c = -a*l2[0] - b*l2[1]; | |
| | | for(int k=2; k < size; ++k) | |
| | | { | |
| | | double ab = (connectivity == 4) | |
| | | ? std::fabs(a) + std::fabs(b) | |
| | | : std::max(std::fabs(a), std::fabs(b)); | |
| | | double d = a*poly[k][0] + b*poly[k][1] + c; | |
| | | if(d < -1.0 || d > ab) | |
| | | { | |
| | | // finish current segment | |
| | | c = (c - a*r2[0] - b*r2[1]) / 2.0; | |
| | | lines.push_back(TinyVector<double, 3>(a, b, c)); | |
| | | // initialize new segment | |
| | | l1 = poly[k-1]; | |
| | | r1 = l1; | |
| | | l2 = poly[k]; | |
| | | r2 = l2; | |
| | | a = l2[1] - l1[1]; | |
| | | b = l1[0] - l2[0]; | |
| | | c = -a*l2[0] - b*l2[1]; | |
| | | } | |
| | | else if(d <= 0.0) | |
| | | { | |
| | | l2 = poly[k]; | |
| | | if(d < 0.0) | |
| | | { | |
| | | r1 = r2; | |
| | | a = l2[1] - l1[1]; | |
| | | b = l1[0] - l2[0]; | |
| | | c = -a*l2[0] - b*l2[1]; | |
| | | } | |
| | | } | |
| | | else if(d >= ab - 1.0) | |
| | | { | |
| | | r2 = poly[k]; | |
| | | if(d > ab - 1.0) | |
| | | { | |
| | | l1 = l2; | |
| | | a = r2[1] - r1[1]; | |
| | | b = r1[0] - r2[0]; | |
| | | c = -a*l2[0] - b*l2[1]; | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| | | c = (c - a*r2[0] - b*r2[1]) / 2.0; | |
| | | lines.push_back(TinyVector<double, 3>(a, b, c)); | |
| | | int segments = lines.size(); | |
| | | | |
| | | if(isOpenPolygon) | |
| | | simple.push_back(poly[0]); | |
| | | else | |
| | | simple.push_back(detail::digitalLineIntersection<Point>(lines[0], l | |
| | | ines[segments-1])); | |
| | | | |
| | | for(int k=1; k<segments; ++k) | |
| | | simple.push_back(detail::digitalLineIntersection<Point>(lines[k-1], | |
| | | lines[k])); | |
| | | | |
| | | if(isOpenPolygon) | |
| | | simple.push_back(poly[size-1]); | |
| | | else | |
| | | simple.push_back(detail::digitalLineIntersection<Point>(lines[0], l | |
| | | ines[segments-1])); | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | template<class PointArray> | |
| | | void resamplePolygon( | |
| | | const PointArray &poly, PointArray &simple, double desiredPointDistance | |
| | | ) | |
| | | { | |
| | | typedef typename PointArray::value_type Point; | |
| | | | |
| | | int size = poly.size(); | |
| | | bool isOpenPolygon = !poly.closed(); | |
| | | | |
| | | ArrayVector<double> arcLength; | |
| | | poly.arcLengthList(arcLength); | |
| | | int segmentCount = int(std::ceil(arcLength[size-1] / desiredPointDistan | |
| | | ce)); | |
| | | if(segmentCount < 2) | |
| | | { | |
| | | simple.push_back(poly[0]); | |
| | | if(!isOpenPolygon) | |
| | | { | |
| | | Point p = poly[1]; | |
| | | double dist = (p - poly[0]).magnitude(); | |
| | | for(int k=2; k < size-1; ++k) | |
| | | { | |
| | | double d = (poly[k] - poly[0]).magnitude(); | |
| | | if(d > dist) | |
| | | { | |
| | | dist = d; | |
| | | p = poly[k]; | |
| | | } | |
| | | } | |
| | | simple.push_back(p); | |
| | | } | |
| | | simple.push_back(poly[size-1]); | |
| | | return; | |
| | | } | |
| | | | |
| | | for(int k=0; k<size; ++k) | |
| | | arcLength[k] *= segmentCount / arcLength[size-1]; | |
| | | | |
| | | ArrayVector<Point> integrals(segmentCount+1, Point(0.0, 0.0)); | |
| | | Point p1 = poly[0]; | |
| | | double t1 = 0.0; | |
| | | int l = 1; | |
| | | for(int k=1; k<size; ++k) | |
| | | { | |
| | | double d = arcLength[k]; | |
| | | while(d >= l && l <= segmentCount) | |
| | | { | |
| | | double t2 = 1.0; | |
| | | double dt = t2 - t1; | |
| | | Point p2 = poly.interpolate(k-1, (l - arcLength[k-1]) / (d - ar | |
| | | cLength[k-1])); | |
| | | Point sum1 = 0.5 * dt * (p1 + p2); | |
| | | Point sumt = dt / 6.0 * (p1*(2.0*t1+t2) + p2*(t1+2.0*t2)); | |
| | | integrals[l-1] += sum1 - sumt; | |
| | | integrals[l] += sumt; | |
| | | if(isOpenPolygon && l==1) | |
| | | { | |
| | | integrals[0] += poly[0] - integrals[1]; | |
| | | } | |
| | | p1 = p2; | |
| | | t1 = 0.0; | |
| | | ++l; | |
| | | if(isOpenPolygon && l==segmentCount) | |
| | | { | |
| | | integrals[segmentCount] += integrals[segmentCount-1]; | |
| | | } | |
| | | } | |
| | | if(d < l && l <= segmentCount) | |
| | | { | |
| | | double t2 = std::fmod(d, 1.0); | |
| | | double dt = t2 - t1; | |
| | | Point p2 = poly[k]; | |
| | | Point sum1 = 0.5 * dt * (p1 + p2); | |
| | | Point sumt = dt / 6.0 * (p1*(2.0*t1+t2) + p2*(t1+2.0*t2)); | |
| | | integrals[l-1] += sum1 - sumt; | |
| | | integrals[l] += sumt; | |
| | | p1 = p2; | |
| | | t1 = t2; | |
| | | } | |
| | | } | |
| | | | |
| | | if(isOpenPolygon) | |
| | | { | |
| | | integrals[segmentCount] += poly[size-1] - integrals[segmentCount-1] | |
| | | ; | |
| | | integrals[1] -= integrals[0] / 6.0; | |
| | | integrals[segmentCount-1] -= integrals[segmentCount] / 6.0; | |
| | | | |
| | | ArrayVector<double> g(segmentCount); | |
| | | double b = 2.0 / 3.0; | |
| | | simple.push_back(poly[0]); | |
| | | simple.push_back(integrals[1] / b); | |
| | | for(int k=2; k<segmentCount; ++k) | |
| | | { | |
| | | g[k] = 1.0 / 6.0 / b; | |
| | | b = 2.0 / 3.0 - g[k] / 6.0; | |
| | | simple.push_back((integrals[k] - simple[k-1] / 6.0) / b); | |
| | | } | |
| | | for(int k = segmentCount-2; k >= 1; --k) | |
| | | { | |
| | | simple[k] -= g[k+1] * simple[k+1]; | |
| | | } | |
| | | | |
| | | simple.push_back(poly[size-1]); | |
| | | } | |
| | | else | |
| | | { | |
| | | integrals[0] += integrals[segmentCount]; | |
| | | | |
| | | int initializationSteps = std::min(segmentCount, 5); | |
| | | ArrayVector<Point> p(segmentCount+2*initializationSteps); | |
| | | double b = 0.6220084679281461, | |
| | | g = 0.26794919243112275; | |
| | | p[0] = integrals[0] / b; | |
| | | | |
| | | for(int k=1; k<segmentCount+2*initializationSteps; ++k) | |
| | | { | |
| | | p[k] = (integrals[k % segmentCount] - p[k-1] / 6.0) / b; | |
| | | } | |
| | | for(int k = segmentCount+2*initializationSteps-2; k >= initializati | |
| | | onSteps; --k) | |
| | | { | |
| | | p[k] -= g * p[k+1]; | |
| | | } | |
| | | | |
| | | for(int k=segmentCount; k<segmentCount+initializationSteps; ++k) | |
| | | simple.push_back(p[k]); | |
| | | for(int k=initializationSteps; k<=segmentCount; ++k) | |
| | | simple.push_back(p[k]); | |
| | | } | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | template<class PointArray> | |
| | | void resamplePolygonLinearInterpolation( | |
| | | const PointArray &poly, PointArray &simple, double desiredPointDistance | |
| | | ) | |
| | | { | |
| | | int size = poly.size(); | |
| | | if(size <= 2) | |
| | | { | |
| | | simple = poly; | |
| | | return; | |
| | | } | |
| | | | |
| | | ArrayVector<double> arcLengths; | |
| | | poly.arcLengthList(arcLengths); | |
| | | | |
| | | int steps = int(std::ceil(arcLengths[size-1] / desiredPointDistance)); | |
| | | double newStep = arcLengths[size-1] / steps; | |
| | | | |
| | | simple.push_back(poly[0]); | |
| | | int l = 1; | |
| | | for(int k=1; k<steps; ++k) | |
| | | { | |
| | | double currentArcLength = k*newStep; | |
| | | for(; l < size; ++l) | |
| | | { | |
| | | if(arcLengths[l] >= currentArcLength) | |
| | | break; | |
| | | } | |
| | | double o = (arcLengths[l] - currentArcLength) / (arcLengths[l] - ar | |
| | | cLengths[l-1]); | |
| | | simple.push_back(o*poly[l-1] + (1.0-o)*poly[l]); | |
| | | } | |
| | | simple.push_back(poly[size-1]); | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | template<class PointArray> | |
| | | void resamplePolygonExponentialFilter( | |
| | | const PointArray &poly, PointArray &simple, double scale, double desire | |
| | | dPointDistance) | |
| | | { | |
| | | int size = poly.size(); | |
| | | if(size <= 2) | |
| | | { | |
| | | simple = poly; | |
| | | return; | |
| | | } | |
| | | | |
| | | bool isOpenPolygon = !poly.closed(); | |
| | | | |
| | | typedef typename PointArray::value_type Point; | |
| | | ArrayVector<Point> pforward(size), pbackward(size); | |
| | | ArrayVector<double> wforward(size), wbackward(size), weights(size-1); | |
| | | for(int k=0; k < size - 1; ++k) | |
| | | weights[k] = std::exp(-(poly[k] - poly[k+1]).magnitude()/scale); | |
| | | | |
| | | // init recursion with cyclic boundary conditions | |
| | | Point p = poly[0]; | |
| | | double w = 1.0; | |
| | | for(int k=1; k < size; ++k) | |
| | | { | |
| | | p = poly[k] + weights[k-1]*p; | |
| | | w = 1.0 + weights[k-1]*w; | |
| | | } | |
| | | pforward[0] = p; | |
| | | wforward[0] = w; | |
| | | | |
| | | p = poly[size-1]; | |
| | | w = 1.0; | |
| | | for(int k=size-2; k>=0; --k) | |
| | | { | |
| | | p = poly[k] + weights[k]*p; | |
| | | w = 1.0 + weights[k]*w; | |
| | | } | |
| | | pbackward[size-1] = p; | |
| | | wbackward[size-1] = w; | |
| | | | |
| | | if(isOpenPolygon) | |
| | | { | |
| | | // change initialization into anti-reflective boundary conditions f | |
| | | or open polygons | |
| | | std::swap(wbackward[size-1], wforward[0]); | |
| | | std::swap(pbackward[size-1], pforward[0]); | |
| | | pforward[0] = 2.0*wforward[0]*poly[0] - pforward[0]; | |
| | | pbackward[size-1] = 2.0*wbackward[size-1]*poly[size-1] - pbackward[ | |
| | | size-1]; | |
| | | } | |
| | | | |
| | | // forward and backward pass of the recursive filter | |
| | | for(int k=1; k < size; ++k) | |
| | | { | |
| | | pforward[k] = poly[k] + weights[k-1]*pforward[k-1]; | |
| | | wforward[k] = 1.0 + weights[k-1]*wforward[k-1]; | |
| | | } | |
| | | for(int k=size-2; k >= 0; --k) | |
| | | { | |
| | | pbackward[k] = poly[k] + weights[k]*pbackward[k+1]; | |
| | | wbackward[k] = 1.0 + weights[k]*wbackward[k+1]; | |
| | | } | |
| | | | |
| | | // measure the arc length of the new polygon (after possible shrinkage) | |
| | | p = (pforward[0]+weights[0]*pbackward[1]) / (wforward[0] + weights[0]*w | |
| | | backward[1]); | |
| | | simple.push_back(p); | |
| | | | |
| | | Point pend = isOpenPolygon | |
| | | ? (weights[size-2]*pforward[size-2]+pbackward[size-1]) / | |
| | | (weights[size-2]*wforward[size-2] + wbackward[size-1]) | |
| | | : p; | |
| | | | |
| | | ArrayVector<double> arcLength; | |
| | | double length = 0.0; | |
| | | arcLength.push_back(length); | |
| | | for(int k=1; k<size-1; ++k) | |
| | | { | |
| | | Point pc = (pforward[k]+weights[k]*pbackward[k+1]) / (wforward[k] + | |
| | | weights[k]*wbackward[k+1]); | |
| | | length += (pc - p).magnitude(); | |
| | | arcLength.push_back(length); | |
| | | p = pc; | |
| | | } | |
| | | length += (p-pend).magnitude(); | |
| | | arcLength.push_back(length); | |
| | | | |
| | | // alternative: use the arc lenth of the original polygon | |
| | | // poly.arcLengthList(arcLength); | |
| | | | |
| | | int steps = int(std::floor(arcLength[size-1] / desiredPointDistance+0.5 | |
| | | )); | |
| | | double newStep = arcLength[size-1] / steps; | |
| | | | |
| | | int l = 1; | |
| | | for(int k=1; k < steps; ++k) | |
| | | { | |
| | | double currentArcLength = k*newStep; | |
| | | for(; l < size; ++l) | |
| | | { | |
| | | if(arcLength[l] >= currentArcLength) | |
| | | break; | |
| | | } | |
| | | double w = weights[l-1]; | |
| | | double o = (arcLength[l] - currentArcLength) / (arcLength[l] - arcL | |
| | | ength[l-1]); | |
| | | double wl = std::pow(w, 1.0-o); | |
| | | double wr = std::pow(w, o); | |
| | | simple.push_back((wl*pforward[l-1]+wr*pbackward[l]) / (wl*wforward[ | |
| | | l-1] + wr*wbackward[l])); | |
| | | } | |
| | | simple.push_back(pend); | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | namespace detail { | |
| | | | |
| | | template<class ArcLengthList, class PointList> | |
| | | typename PointList::value_type | |
| | | singleGaussianConvolvePolygonReflective( | |
| | | const ArcLengthList &arcLengthList, | |
| | | const PointList &pointList, | |
| | | int i, double arcLengthPos, | |
| | | const Gaussian<double> &g) | |
| | | { | |
| | | typedef typename PointList::value_type ValueType; | |
| | | | |
| | | ValueType sum(vigra::NumericTraits<ValueType>::zero()); | |
| | | double norm = 0.0; | |
| | | | |
| | | int size = arcLengthList.size(), | |
| | | lastIndex = size - 1; | |
| | | double reflectLength = 2.0*arcLengthList[lastIndex]; | |
| | | | |
| | | ValueType reflectPoint = 2.0*pointList[lastIndex]; | |
| | | for(int j = i; true; ++j) | |
| | | { | |
| | | int k = (j > lastIndex) | |
| | | ? 2*lastIndex - j | |
| | | : j; | |
| | | double pos = arcLengthList[k]; | |
| | | ValueType point = pointList[k]; | |
| | | if(j > lastIndex) | |
| | | { | |
| | | pos = reflectLength - pos; | |
| | | point = reflectPoint - point; | |
| | | } | |
| | | double diff = pos - arcLengthPos; | |
| | | if(diff > g.radius()) | |
| | | break; | |
| | | double w(g(diff)); | |
| | | sum += w*point; | |
| | | norm += w; | |
| | | } | |
| | | | |
| | | reflectPoint = 2.0*pointList[0]; | |
| | | for(int j = i - 1; true; --j) | |
| | | { | |
| | | int k = std::abs(j); | |
| | | double pos = arcLengthList[k]; | |
| | | ValueType point = pointList[k]; | |
| | | if(j < 0) | |
| | | { | |
| | | pos = -pos; | |
| | | point = reflectPoint - point; | |
| | | } | |
| | | double diff = pos - arcLengthPos; | |
| | | if(diff < -g.radius()) | |
| | | break; | |
| | | double w(g(diff)); | |
| | | sum += w*point; | |
| | | norm += w; | |
| | | } | |
| | | | |
| | | return sum / norm; | |
| | | } | |
| | | | |
| | | template<class ArcLengthList, class PointList> | |
| | | typename PointList::value_type | |
| | | singleGaussianConvolvePolygonCyclic( | |
| | | const ArcLengthList &arcLengthList, | |
| | | const PointList &pointList, | |
| | | int i, double arcLengthPos, | |
| | | const Gaussian<double> &g) | |
| | | { | |
| | | typedef typename PointList::value_type ValueType; | |
| | | | |
| | | ValueType sum(vigra::NumericTraits<ValueType>::zero()); | |
| | | double norm = 0.0; | |
| | | | |
| | | int size = arcLengthList.size() - 1, | |
| | | lastIndex = size - 1; | |
| | | double totalLength = arcLengthList[size]; | |
| | | | |
| | | for(int j = i; true; ++j) | |
| | | { | |
| | | int k = j % size; | |
| | | double pos = j > lastIndex | |
| | | ? arcLengthList[k] + totalLength | |
| | | : arcLengthList[k]; | |
| | | ValueType point = pointList[k]; | |
| | | double diff = pos - arcLengthPos; | |
| | | if(diff > g.radius()) | |
| | | break; | |
| | | double w(g(diff)); | |
| | | sum += w*point; | |
| | | norm += w; | |
| | | } | |
| | | | |
| | | for(int j = i - 1; true; --j) | |
| | | { | |
| | | int k = (j + size) % size; | |
| | | double pos = j < 0 | |
| | | ? arcLengthList[k] - totalLength | |
| | | : arcLengthList[k]; | |
| | | ValueType point = pointList[k]; | |
| | | double diff = pos - arcLengthPos; | |
| | | if(diff < -g.radius()) | |
| | | break; | |
| | | double w(g(diff)); | |
| | | sum += w*point; | |
| | | norm += w; | |
| | | } | |
| | | | |
| | | return sum / norm; | |
| | | } | |
| | | | |
| | | } // namespace detail | |
| | | | |
| | | template<class PointArray> | |
| | | void resamplePolygonGaussianFilter( | |
| | | const PointArray &poly, PointArray &simple, double scale, double desire | |
| | | dPointDistance) | |
| | | { | |
| | | int size = poly.size(); | |
| | | if(size <= 2) | |
| | | { | |
| | | simple = poly; | |
| | | return; | |
| | | } | |
| | | | |
| | | ArrayVector<double> arcLengths; | |
| | | poly.arcLengthList(arcLengths); | |
| | | | |
| | | Gaussian<double> g(scale); | |
| | | | |
| | | vigra_precondition(arcLengths[size-1] > g.radius(), | |
| | | "resamplePolygonGaussianFilter(): Filter longer than polygon."); | |
| | | | |
| | | bool isOpenPolygon = !poly.closed(); | |
| | | | |
| | | int steps = int(std::ceil(arcLengths[size-1] / desiredPointDistance)); | |
| | | double newStep = arcLengths[size-1] / steps; | |
| | | | |
| | | int l = 0; | |
| | | for(int k=0; k<steps; ++k) | |
| | | { | |
| | | double currentArcLength = k*newStep; | |
| | | for(; l < size; ++l) | |
| | | { | |
| | | if(arcLengths[l] >= currentArcLength) | |
| | | break; | |
| | | } | |
| | | if(isOpenPolygon) | |
| | | simple.push_back(detail::singleGaussianConvolvePolygonReflectiv | |
| | | e(arcLengths, poly, l, currentArcLength, g)); | |
| | | else | |
| | | simple.push_back(detail::singleGaussianConvolvePolygonCyclic(ar | |
| | | cLengths, poly, l, currentArcLength, g)); | |
| | | } | |
| | | if(isOpenPolygon) | |
| | | simple.push_back(detail::singleGaussianConvolvePolygonReflective(ar | |
| | | cLengths, poly, size-1, arcLengths[size-1], g)); | |
| | | else | |
| | | simple.push_back(simple[0]); | |
| | | } | |
| | | | |
| | | /********************************************************************/ | |
| | | | |
| | | namespace detail { | |
| | | | |
| | | template<class Point> | |
| | | Point spline3Integral(Point const & p1, Point const & p2, double t1, double | |
| | | t2) | |
| | | { | |
| | | StaticPolynomial<5, double> p[2]; | |
| | | p[0][0] = p[1][0] = 0.0; | |
| | | if(t1 >= 1.0) | |
| | | { | |
| | | return (t1 - t2) / 120.0 * | |
| | | (p1 * (-80.0 + t1*(80.0 + 2.0*t2*(t2 - 10.0) + t1*(3.0*t2 - | |
| | | 30.0 + 4.0*t1)) + t2*(40.0 + t2*(t2 - 10.0))) + | |
| | | p2 * (-80.0 + t1*(40.0 + t2*(3.0*t2 - 20.0) + t1*(2.0*t2 - | |
| | | 10.0 + t1)) + t2*(80.0 + t2*(4.0*t2 - 30.0)))); | |
| | | } | |
| | | else | |
| | | { | |
| | | return (t2 - t1) / 120.0 * | |
| | | (p1 * (40.0 + t1*(2.0*t2*(3.0*t2 - 10.0) + t1*(9.0*t2 - 30.0 | |
| | | + 12.0*t1)) + t2*t2*(3.0*t2 - 10.0)) + | |
| | | p2 * (40.0 + t1*(t2*(9.0*t2 - 20.0) + t1*(6.0*t2 - 10.0 + 3 | |
| | | .0*t1)) + t2*t2*(12.0*t2 - 30.0))); | |
| | | } | |
| | | } | |
| | | | |
| | | template<class ArcLengthList, class PointList> | |
| | | typename PointList::value_type | |
| | | singleSpline3ConvolvePolygon( | |
| | | const ArcLengthList &arcLengthList, | |
| | | const PointList &pointList, | |
| | | int left, int center, int right) | |
| | | { | |
| | | typedef typename PointList::value_type ValueType; | |
| | | | |
| | | ValueType sum(vigra::NumericTraits<ValueType>::zero()); | |
| | | double arcLengthPos = arcLengthList[center]; | |
| | | for(int j = center + 1; j <= right; ++j) | |
| | | { | |
| | | double t1 = arcLengthList[j-1] - arcLengthPos, | |
| | | t2 = arcLengthList[j] - arcLengthPos; | |
| | | sum += spline3Integral(pointList[j-1], pointList[j], t1, t2); | |
| | | } | |
| | | for(int j = center - 1; j >= left; --j) | |
| | | { | |
| | | double t1 = arcLengthPos - arcLengthList[j+1], | |
| | | t2 = arcLengthPos - arcLengthList[j]; | |
| | | sum -= spline3Integral(-pointList[j+1], -pointList[j], t1, t2); | |
| | | } | |
| | | | |
| | | return sum; | |
| | | } | |
| | | | |
| | | } // namespace detail | |
| | | | |
| | | template<class PointArray> | |
| | | void polygonSplineControlPoints( | |
| | | const PointArray &poly, PointArray &splinePoints, int segmentCount) | |
| | | { | |
| | | typedef typename PointArray::value_type Point; | |
| | | | |
| | | int size = poly.size(); | |
| | | vigra_precondition(size >= 4, | |
| | | "polygonSplineControlPoints(): Polygon must have at least 4 points. | |
| | | "); | |
| | | | |
| | | bool isOpenPolygon = !poly.closed(); | |
| | | | |
| | | ArrayVector<double> arcLength; | |
| | | poly.arcLengthList(arcLength); | |
| | | double totalLength = segmentCount / arcLength[size-1]; | |
| | | for(int k=0; k<size; ++k) | |
| | | arcLength[k] *= totalLength; | |
| | | | |
| | | PointArray augmentedPoly; | |
| | | augmentedPoly.push_back(poly[0]); | |
| | | | |
| | | ArrayVector<double> augmentedArcLength; | |
| | | augmentedArcLength.push_back(0.0); | |
| | | | |
| | | ArrayVector<int> splineIndices(segmentCount + 1); | |
| | | splineIndices[0] = 0; | |
| | | int l = 1; | |
| | | for(int k=1; k<size-1; ++k) | |
| | | { | |
| | | double d = arcLength[k]; | |
| | | while(d > l) | |
| | | { | |
| | | augmentedPoly.push_back(poly.interpolate(k-1, (l - arcLength[k- | |
| | | 1]) / (d - arcLength[k-1]))); | |
| | | augmentedArcLength.push_back(l); | |
| | | splineIndices[l] = augmentedPoly.size()-1; | |
| | | ++l; | |
| | | } | |
| | | augmentedPoly.push_back(poly[k]); | |
| | | augmentedArcLength.push_back(d); | |
| | | if(d == l) | |
| | | { | |
| | | splineIndices[l] = augmentedPoly.size()-1; | |
| | | ++l; | |
| | | } | |
| | | } | |
| | | augmentedPoly.push_back(poly[size-1]); | |
| | | augmentedArcLength.push_back(segmentCount); | |
| | | splineIndices[segmentCount] = augmentedPoly.size()-1; | |
| | | size = augmentedPoly.size(); | |
| | | | |
| | | ArrayVector<Point> integrals(segmentCount+1); | |
| | | if(isOpenPolygon) | |
| | | { | |
| | | integrals[0] = augmentedPoly[0]; | |
| | | PointArray reflectedPoly; | |
| | | Point reflectPoint = 2.0*poly[0]; | |
| | | ArrayVector<double> reflectedArcLength; | |
| | | for(int k=-splineIndices[1]; k <= splineIndices[3]; ++k) | |
| | | { | |
| | | if(k < 0) | |
| | | { | |
| | | reflectedPoly.push_back(reflectPoint - augmentedPoly[-k]); | |
| | | reflectedArcLength.push_back(-augmentedArcLength[-k]); | |
| | | } | |
| | | else | |
| | | { | |
| | | reflectedPoly.push_back(augmentedPoly[k]); | |
| | | reflectedArcLength.push_back(augmentedArcLength[k]); | |
| | | } | |
| | | } | |
| | | integrals[1] = detail::singleSpline3ConvolvePolygon(reflectedArcLen | |
| | | gth, reflectedPoly, | |
| | | 0, 2*splineIndices[1], splineIndices[1] | |
| | | + splineIndices[3]); | |
| | | | |
| | | reflectPoint = 2.0*augmentedPoly[size-1]; | |
| | | for(int k=size-2; k>=splineIndices[segmentCount-1]; --k) | |
| | | { | |
| | | augmentedPoly.push_back(reflectPoint - augmentedPoly[k]); | |
| | | augmentedArcLength.push_back(2.0*segmentCount - augmentedArcLen | |
| | | gth[k]); | |
| | | } | |
| | | integrals[segmentCount-1] = detail::singleSpline3ConvolvePolygon(au | |
| | | gmentedArcLength, augmentedPoly, | |
| | | splineIndices[segmentCount-3], splineIndices[segmentCount-1] | |
| | | , | |
| | | 2*splineIndices[segmentCount] - splineIndices[segmentCount-1 | |
| | | ]); | |
| | | integrals[segmentCount] = augmentedPoly[size-1]; | |
| | | } | |
| | | else | |
| | | { | |
| | | PointArray wrappedPoly; | |
| | | ArrayVector<double> wrappedArcLength; | |
| | | for(int k=splineIndices[segmentCount-1]; k < splineIndices[segmentC | |
| | | ount]; ++k) | |
| | | { | |
| | | wrappedPoly.push_back(augmentedPoly[k]); | |
| | | wrappedArcLength.push_back(augmentedArcLength[k] - segmentCount | |
| | | ); | |
| | | } | |
| | | int indexShift = wrappedPoly.size(); | |
| | | for(int k=0; k <= splineIndices[3]; ++k) | |
| | | { | |
| | | wrappedPoly.push_back(augmentedPoly[k]); | |
| | | wrappedArcLength.push_back(augmentedArcLength[k]); | |
| | | } | |
| | | integrals[1] = detail::singleSpline3ConvolvePolygon(wrappedArcLengt | |
| | | h, wrappedPoly, | |
| | | 0, splineIndices[1] + indexShift, splineIndice | |
| | | s[3] + indexShift); | |
| | | | |
| | | for(int k=1; k <= splineIndices[2]; ++k) | |
| | | { | |
| | | augmentedPoly.push_back(augmentedPoly[k]); | |
| | | augmentedArcLength.push_back(segmentCount + augmentedArcLength[ | |
| | | k]); | |
| | | } | |
| | | integrals[segmentCount-1] = detail::singleSpline3ConvolvePolygon(au | |
| | | gmentedArcLength, augmentedPoly, | |
| | | splineIndices[segmentCount-3], splineIndices[segmentCount-1] | |
| | | , | |
| | | splineIndices[segmentCount] + splineIndices[1]); | |
| | | integrals[0] = detail::singleSpline3ConvolvePolygon(augmentedArcLen | |
| | | gth, augmentedPoly, | |
| | | splineIndices[segmentCount-2], splineIndices[segmentCount], | |
| | | splineIndices[segmentCount] + splineIndices[2]); | |
| | | } | |
| | | | |
| | | for(int k=2; k <= segmentCount-2; ++k) | |
| | | integrals[k] = detail::singleSpline3ConvolvePolygon(augmentedArcLen | |
| | | gth, augmentedPoly, | |
| | | splineIndices[k-2], splineIndices[k], s | |
| | | plineIndices[k+2]); | |
| | | | |
| | | BSpline<7, double> spline7; | |
| | | if(isOpenPolygon) | |
| | | { | |
| | | int solutionSize = segmentCount + 1; | |
| | | Matrix<double> m(solutionSize, solutionSize), | |
| | | rhs(solutionSize, 2), | |
| | | solution(solutionSize, 2); | |
| | | for(int k=0; k<solutionSize; ++k) | |
| | | { | |
| | | for(int l=-3; l<=3; ++l) | |
| | | { | |
| | | if(k + l < 0) | |
| | | { | |
| | | m(k, 0) += 2.0*spline7(l); | |
| | | m(k, abs(k+l)) -= spline7(l); | |
| | | } | |
| | | else if(k + l >= solutionSize) | |
| | | { | |
| | | m(k, solutionSize - 1) += 2.0*spline7(l); | |
| | | m(k, 2*solutionSize - k - l - 2) -= spline7(l); | |
| | | } | |
| | | else | |
| | | m(k,k+l) += spline7(l); | |
| | | } | |
| | | rhs(k, 0) = integrals[k][0]; | |
| | | rhs(k, 1) = integrals[k][1]; | |
| | | } | |
| | | | |
| | | linearSolve(m, rhs, solution); | |
| | | | |
| | | for(int k=0; k<solutionSize; ++k) | |
| | | { | |
| | | splinePoints.push_back(Point(solution(k,0), solution(k,1))); | |
| | | } | |
| | | splinePoints.push_back(2.0*splinePoints[solutionSize-1] - splinePoi | |
| | | nts[solutionSize-2]); | |
| | | splinePoints.insert(splinePoints.begin(), 2.0*splinePoints[0] - spl | |
| | | inePoints[1]); | |
| | | } | |
| | | else | |
| | | { | |
| | | int solutionSize = segmentCount; | |
| | | Matrix<double> m(solutionSize, solutionSize), | |
| | | rhs(solutionSize, 2), | |
| | | solution(solutionSize, 2); | |
| | | for(int k=0; k<solutionSize; ++k) | |
| | | { | |
| | | for(int l=-3; l<=3; ++l) | |
| | | m(k, (k+l+solutionSize) % solutionSize) = spline7(l); | |
| | | rhs(k, 0) = integrals[k][0]; | |
| | | rhs(k, 1) = integrals[k][1]; | |
| | | } | |
| | | linearSolve(m, rhs, solution); | |
| | | | |
| | | for(int k=0; k<solutionSize; ++k) | |
| | | { | |
| | | splinePoints.push_back(Point(solution(k,0), solution(k,1))); | |
| | | } | |
| | | splinePoints.push_back(splinePoints[0]); | |
| | | } | |
| | | } | |
| | | | |
| | | #endif | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
|
| | | namespace std { | |
| | | | |
| | | template <class T> | |
| | | ostream & operator<<(ostream & s, vigra::Polygon<T> const & a) | |
| | | { | |
| | | for(std::size_t k=0; k<a.size()-1; ++k) | |
| | | s << a[k] << ", "; | |
| | | if(a.size()) | |
| | | s << a.back(); | |
| | | return s; | |
| | | } | |
| | | | |
| | | } // namespace std | |
| | | | |
| #endif /* VIGRA_POLYGON_HXX */ | | #endif /* VIGRA_POLYGON_HXX */ | |
| | | | |
End of changes. 11 change blocks. |
| 10 lines changed or deleted | | 1915 lines changed or added | |
|
| recursiveconvolution.hxx | | recursiveconvolution.hxx | |
| | | | |
| skipping to change at line 46 | | skipping to change at line 46 | |
| #ifndef VIGRA_RECURSIVECONVOLUTION_HXX | | #ifndef VIGRA_RECURSIVECONVOLUTION_HXX | |
| #define VIGRA_RECURSIVECONVOLUTION_HXX | | #define VIGRA_RECURSIVECONVOLUTION_HXX | |
| | | | |
| #include <cmath> | | #include <cmath> | |
| #include <vector> | | #include <vector> | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "imageiteratoradapter.hxx" | | #include "imageiteratoradapter.hxx" | |
| #include "bordertreatment.hxx" | | #include "bordertreatment.hxx" | |
| #include "array_vector.hxx" | | #include "array_vector.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* Recursive convolution functions */ | | /* Recursive convolution functions */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \addtogroup RecursiveConvolution Recursive convolution functions | | /** \addtogroup RecursiveConvolution Recursive convolution functions | |
| | | | |
| skipping to change at line 125 | | skipping to change at line 126 | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| vector<float> src, dest; | | vector<float> src, dest; | |
| ... | | ... | |
| | | | |
|
| vigra::DefaultAccessor<vector<float>::iterator, float> FAccessor; | | DefaultAccessor<vector<float>::iterator, float> FAccessor; | |
| | | | |
|
| vigra::recursiveFilterLine(src.begin(), src.end(), FAccessor(), | | recursiveFilterLine(src.begin(), src.end(), FAccessor(), | |
| dest.begin(), FAccessor(), | | dest.begin(), FAccessor(), | |
| 0.5, BORDER_TREATMENT_REFLECT); | | 0.5, BORDER_TREATMENT_REFLECT); | |
| \endcode | | \endcode | |
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
| | | | |
| \code | | \code | |
| RandomAccessIterator is, isend; | | RandomAccessIterator is, isend; | |
| RandomAccessIterator id; | | RandomAccessIterator id; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | | NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | |
| double d; | | double d; | |
| | | | |
| s = s + s; | | s = s + s; | |
| s = d * s; | | s = d * s; | |
| | | | |
| dest_accessor.set( | | dest_accessor.set( | |
| NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | | NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | |
|
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| -1 < b < 1 | | -1 < b < 1 | |
| \endcode | | \endcode | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveFilterLine) | | doxygen_overloaded_function(template <...> void recursiveFilterLine) | |
| | | | |
| skipping to change at line 273 | | skipping to change at line 273 | |
| if(border == BORDER_TREATMENT_CLIP) | | if(border == BORDER_TREATMENT_CLIP) | |
| { | | { | |
| // correction factors for b | | // correction factors for b | |
| double bright = b; | | double bright = b; | |
| double bleft = VIGRA_CSTD::pow(b, w); | | double bleft = VIGRA_CSTD::pow(b, w); | |
| | | | |
| for(x=w-1; x>=0; --x, --is, --id) | | for(x=w-1; x>=0; --x, --is, --id) | |
| { | | { | |
| TempType f = TempType(b * old); | | TempType f = TempType(b * old); | |
| old = as(is) + f; | | old = as(is) + f; | |
|
| double norm = (1.0 - b) / (1.0 + b - bleft - bright); | | norm = (1.0 - b) / (1.0 + b - bleft - bright); | |
| bleft /= b; | | bleft /= b; | |
| bright *= b; | | bright *= b; | |
| ad.set(norm * (line[x] + f), id); | | ad.set(norm * (line[x] + f), id); | |
| } | | } | |
| } | | } | |
| else if(border == BORDER_TREATMENT_AVOID) | | else if(border == BORDER_TREATMENT_AVOID) | |
| { | | { | |
| for(x=w-1; x >= kernelw; --x, --is, --id) | | for(x=w-1; x >= kernelw; --x, --is, --id) | |
| { | | { | |
| TempType f = TempType(b * old); | | TempType f = TempType(b * old); | |
| | | | |
| skipping to change at line 316 | | skipping to change at line 316 | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as, | | void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as, | |
| DestIterator id, DestAccessor ad, double b1, doubl
e b2) | | DestIterator id, DestAccessor ad, double b1, doubl
e b2) | |
| { | | { | |
| int w = isend - is; | | int w = isend - is; | |
| int x; | | int x; | |
| | | | |
| typedef typename | | typedef typename | |
| NumericTraits<typename SrcAccessor::value_type>::RealPromote TempTy
pe; | | NumericTraits<typename SrcAccessor::value_type>::RealPromote TempTy
pe; | |
|
| typedef NumericTraits<typename DestAccessor::value_type> DestTraits; | | | |
| | | | |
| // speichert den Ergebnis der linkseitigen Filterung. | | // speichert den Ergebnis der linkseitigen Filterung. | |
| std::vector<TempType> vline(w+1); | | std::vector<TempType> vline(w+1); | |
| typename std::vector<TempType>::iterator line = vline.begin(); | | typename std::vector<TempType>::iterator line = vline.begin(); | |
| | | | |
| double norm = 1.0 - b1 - b2; | | double norm = 1.0 - b1 - b2; | |
| double norm1 = (1.0 - b1 - b2) / (1.0 + b1 + b2); | | double norm1 = (1.0 - b1 - b2) / (1.0 + b1 + b2); | |
| double norm2 = norm * norm; | | double norm2 = norm * norm; | |
| | | | |
| // init left side of filter | | // init left side of filter | |
| | | | |
| skipping to change at line 429 | | skipping to change at line 428 | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | | NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | |
| double d; | | double d; | |
| | | | |
| s = s + s; | | s = s + s; | |
| s = d * s; | | s = d * s; | |
| | | | |
| dest_accessor.set( | | dest_accessor.set( | |
| NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | | NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | |
|
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| 0 <= sigma (absolute values are used for negative sigma) | | 0 <= sigma (absolute values are used for negative sigma) | |
| \endcode | | \endcode | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveGaussianFilterLine
) | | doxygen_overloaded_function(template <...> void recursiveGaussianFilterLine
) | |
| | | | |
| skipping to change at line 468 | | skipping to change at line 466 | |
| int w = isend - is; | | int w = isend - is; | |
| vigra_precondition(w >= 4, | | vigra_precondition(w >= 4, | |
| "recursiveGaussianFilterLine(): line must have at least length 4.")
; | | "recursiveGaussianFilterLine(): line must have at least length 4.")
; | |
| | | | |
| int kernelw = std::min(w-4, (int)(4.0*sigma)); | | int kernelw = std::min(w-4, (int)(4.0*sigma)); | |
| | | | |
| int x; | | int x; | |
| | | | |
| typedef typename | | typedef typename | |
| NumericTraits<typename SrcAccessor::value_type>::RealPromote TempTy
pe; | | NumericTraits<typename SrcAccessor::value_type>::RealPromote TempTy
pe; | |
|
| typedef NumericTraits<typename DestAccessor::value_type> DestTraits; | | | |
| | | | |
| // speichert das Ergebnis der linkseitigen Filterung. | | // speichert das Ergebnis der linkseitigen Filterung. | |
| std::vector<TempType> yforward(w); | | std::vector<TempType> yforward(w); | |
| | | | |
| std::vector<TempType> ybackward(w, 0.0); | | std::vector<TempType> ybackward(w, 0.0); | |
| | | | |
| // initialise the filter for reflective boundary conditions | | // initialise the filter for reflective boundary conditions | |
| for(x=kernelw; x>=0; --x) | | for(x=kernelw; x>=0; --x) | |
| { | | { | |
| ybackward[x] = detail::RequiresExplicitCast<TempType>::cast(B*as(is
, x) + (b1*ybackward[x+1]+b2*ybackward[x+2]+b3*ybackward[x+3])); | | ybackward[x] = detail::RequiresExplicitCast<TempType>::cast(B*as(is
, x) + (b1*ybackward[x+1]+b2*ybackward[x+2]+b3*ybackward[x+3])); | |
| | | | |
| skipping to change at line 570 | | skipping to change at line 567 | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | | NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | |
| double d; | | double d; | |
| | | | |
| s = s + s; | | s = s + s; | |
| s = d * s; | | s = d * s; | |
| | | | |
| dest_accessor.set( | | dest_accessor.set( | |
| NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | | NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | |
|
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| \endcode | | \endcode | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveSmoothLine) | | doxygen_overloaded_function(template <...> void recursiveSmoothLine) | |
| | | | |
| skipping to change at line 657 | | skipping to change at line 653 | |
| | | | |
| NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | | NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | |
| double d; | | double d; | |
| | | | |
| s = s + s; | | s = s + s; | |
| s = -s; | | s = -s; | |
| s = d * s; | | s = d * s; | |
| | | | |
| dest_accessor.set( | | dest_accessor.set( | |
| NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | | NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | |
|
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| \endcode | | \endcode | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveFirstDerivativeLin
e) | | doxygen_overloaded_function(template <...> void recursiveFirstDerivativeLin
e) | |
| | | | |
| skipping to change at line 776 | | skipping to change at line 771 | |
| | | | |
| NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | | NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is
); | |
| double d; | | double d; | |
| | | | |
| s = s + s; | | s = s + s; | |
| s = s - s; | | s = s - s; | |
| s = d * s; | | s = d * s; | |
| | | | |
| dest_accessor.set( | | dest_accessor.set( | |
| NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | | NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id); | |
|
| | | | |
| \endcode | | \endcode | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| scale > 0 | | scale > 0 | |
| \endcode | | \endcode | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveSecondDerivativeLi
ne) | | doxygen_overloaded_function(template <...> void recursiveSecondDerivativeLi
ne) | |
| | | | |
| skipping to change at line 851 | | skipping to change at line 845 | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Performs 1 dimensional recursive filtering (1st and 2nd order) i
n x direction. | | /** \brief Performs 1 dimensional recursive filtering (1st and 2nd order) i
n x direction. | |
| | | | |
| It calls \ref recursiveFilterLine() for every row of the | | It calls \ref recursiveFilterLine() for every row of the | |
| image. See \ref recursiveFilterLine() for more information about | | image. See \ref recursiveFilterLine() for more information about | |
| required interfaces and vigra_preconditions. | | required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // first order filter | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveFilterX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double b, BorderTreatmentMode border); | |
| | | | |
| | | // second order filter | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveFilterX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double b1, double b2); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveFilterX} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // first order filter | | // first order filter | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterX(SrcImageIterator supperleft, | | void recursiveFilterX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as
, | | SrcImageIterator slowerright, SrcAccessor as
, | |
| DestImageIterator dupperleft, DestAccessor a
d, | | DestImageIterator dupperleft, DestAccessor a
d, | |
| double b, BorderTreatmentMode border); | | double b, BorderTreatmentMode border); | |
| | | | |
| // second order filter | | // second order filter | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterX(SrcImageIterator supperleft, | | void recursiveFilterX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as
, | | SrcImageIterator slowerright, SrcAccessor as
, | |
| DestImageIterator dupperleft, DestAccessor a
d, | | DestImageIterator dupperleft, DestAccessor a
d, | |
| double b1, double b2); | | double b1, double b2); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // first order filter | | // first order filter | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterX( | | void recursiveFilterX( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double b, BorderTreatmentMode border); | | double b, BorderTreatmentMode border); | |
| | | | |
| // second order filter | | // second order filter | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterX( | | void recursiveFilterX( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double b1, double b2); | | double b1, double b2); | |
|
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | // apply a first-order filter to the x-axis | |
| | | recursiveFilterX(src, dest, 0.5, BORDER_TREATMENT_REFLECT); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveFilterX} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
|
| vigra::recursiveSmoothX(srcImageRange(src), destImage(dest), | | vigra::recursiveFilterX(srcImageRange(src), destImage(dest), | |
| 0.5, BORDER_TREATMENT_REFLECT); | | 0.5, BORDER_TREATMENT_REFLECT); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveFilterX) | | doxygen_overloaded_function(template <...> void recursiveFilterX) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterX(SrcImageIterator supperleft, | | void recursiveFilterX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double b, BorderTreatmentMode border) | | double b, BorderTreatmentMode border) | |
| { | | { | |
| | | | |
| skipping to change at line 935 | | skipping to change at line 959 | |
| typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | | typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | |
| | | | |
| recursiveFilterLine(rs, rs+w, as, | | recursiveFilterLine(rs, rs+w, as, | |
| rd, ad, | | rd, ad, | |
| b, border); | | b, border); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveFilterX( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveFilterX(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> sr | |
| pair<DestImageIterator, DestAccessor> dest, | | c, | |
| double b, BorderTreatmentMode border) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double b, BorderTreatmentMode border) | |
| { | | { | |
| recursiveFilterX(src.first, src.second, src.third, | | recursiveFilterX(src.first, src.second, src.third, | |
|
| dest.first, dest.second, b, border); | | dest.first, dest.second, b, border); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveFilterX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double b, BorderTreatmentMode border) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveFilterX(): shape mismatch between input and output."); | |
| | | recursiveFilterX(srcImageRange(src), | |
| | | destImage(dest), b, border); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveFilterX (2nd order) */ | | /* recursiveFilterX (2nd order) */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| | | | |
| skipping to change at line 975 | | skipping to change at line 1012 | |
| typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | | typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | |
| | | | |
| recursiveFilterLine(rs, rs+w, as, | | recursiveFilterLine(rs, rs+w, as, | |
| rd, ad, | | rd, ad, | |
| b1, b2); | | b1, b2); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveFilterX( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveFilterX(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> sr | |
| pair<DestImageIterator, DestAccessor> dest, | | c, | |
| double b1, double b2) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double b1, double b2) | |
| { | | { | |
| recursiveFilterX(src.first, src.second, src.third, | | recursiveFilterX(src.first, src.second, src.third, | |
|
| dest.first, dest.second, b1, b2); | | dest.first, dest.second, b1, b2); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveFilterX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double b1, double b2) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveFilterX(): shape mismatch between input and output."); | |
| | | recursiveFilterX(srcImageRange(src), | |
| | | destImage(dest), b1, b2); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveGaussianFilterX */ | | /* recursiveGaussianFilterX */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| // AUTHOR: Sebastian Boppel | | // AUTHOR: Sebastian Boppel | |
| | | | |
| /** \brief Compute 1 dimensional recursive approximation of Gaussian smooth
ing in y direction. | | /** \brief Compute 1 dimensional recursive approximation of Gaussian smooth
ing in y direction. | |
| | | | |
| It calls \ref recursiveGaussianFilterLine() for every column of the | | It calls \ref recursiveGaussianFilterLine() for every column of the | |
| image. See \ref recursiveGaussianFilterLine() for more information abou
t | | image. See \ref recursiveGaussianFilterLine() for more information abou
t | |
| required interfaces and vigra_preconditions. | | required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveGaussianFilterX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double sigma); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveGaussianFilterX} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| recursiveGaussianFilterX(SrcImageIterator supperleft, SrcImageItera
tor slowerright, SrcAccessor as, | | recursiveGaussianFilterX(SrcImageIterator supperleft, SrcImageItera
tor slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor
ad, | | DestImageIterator dupperleft, DestAccessor
ad, | |
| double sigma); | | double sigma); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| recursiveGaussianFilterX(triple<SrcImageIterator, SrcImageIterator,
SrcAccessor> src, | | recursiveGaussianFilterX(triple<SrcImageIterator, SrcImageIterator,
SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest
, | | pair<DestImageIterator, DestAccessor> dest
, | |
| double sigma); | | double sigma); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | recursiveGaussianFilterX(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveGaussianFilterX} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| vigra::recursiveGaussianFilterX(srcImageRange(src), destImage(dest), 3.
0); | | vigra::recursiveGaussianFilterX(srcImageRange(src), destImage(dest), 3.
0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveGaussianFilterX) | | doxygen_overloaded_function(template <...> void recursiveGaussianFilterX) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| recursiveGaussianFilterX(SrcImageIterator supperleft, SrcImageIterator slow
erright, SrcAccessor as, | | recursiveGaussianFilterX(SrcImageIterator supperleft, SrcImageIterator slow
erright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double sigma) | | double sigma) | |
| { | | { | |
| | | | |
| skipping to change at line 1074 | | skipping to change at line 1144 | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| inline void | | inline void | |
| recursiveGaussianFilterX(triple<SrcImageIterator, SrcImageIterator, SrcAcce
ssor> src, | | recursiveGaussianFilterX(triple<SrcImageIterator, SrcImageIterator, SrcAcce
ssor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double sigma) | | double sigma) | |
| { | | { | |
| recursiveGaussianFilterX(src.first, src.second, src.third, | | recursiveGaussianFilterX(src.first, src.second, src.third, | |
| dest.first, dest.second, sigma); | | dest.first, dest.second, sigma); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveGaussianFilterX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double sigma) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveGaussianFilterX(): shape mismatch between input and outpu | |
| | | t."); | |
| | | recursiveGaussianFilterX(srcImageRange(src), | |
| | | destImage(dest), sigma); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveSmoothX */ | | /* recursiveSmoothX */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Performs 1 dimensional recursive smoothing in x direction. | | /** \brief Performs 1 dimensional recursive smoothing in x direction. | |
| | | | |
| It calls \ref recursiveSmoothLine() for every row of the | | It calls \ref recursiveSmoothLine() for every row of the | |
| image. See \ref recursiveSmoothLine() for more information about | | image. See \ref recursiveSmoothLine() for more information about | |
| required interfaces and vigra_preconditions. | | required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveSmoothX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveSmoothX} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSmoothX(SrcImageIterator supperleft, | | void recursiveSmoothX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSmoothX( | | void recursiveSmoothX( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | recursiveSmoothX(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveGaussianFilterX} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| vigra::recursiveSmoothX(srcImageRange(src), destImage(dest), 3.0); | | vigra::recursiveSmoothX(srcImageRange(src), destImage(dest), 3.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveSmoothX) | | doxygen_overloaded_function(template <...> void recursiveSmoothX) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSmoothX(SrcImageIterator supperleft, | | void recursiveSmoothX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| { | | { | |
| | | | |
| skipping to change at line 1153 | | skipping to change at line 1256 | |
| typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | | typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | |
| | | | |
| recursiveSmoothLine(rs, rs+w, as, | | recursiveSmoothLine(rs, rs+w, as, | |
| rd, ad, | | rd, ad, | |
| scale); | | scale); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveSmoothX( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveSmoothX(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> sr | |
| pair<DestImageIterator, DestAccessor> dest, | | c, | |
| double scale) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double scale) | |
| { | | { | |
| recursiveSmoothX(src.first, src.second, src.third, | | recursiveSmoothX(src.first, src.second, src.third, | |
|
| dest. first, dest.second, scale); | | dest.first, dest.second, scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveSmoothX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveSmoothX(): shape mismatch between input and output."); | |
| | | recursiveSmoothX(srcImageRange(src), | |
| | | destImage(dest), scale); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveFilterY */ | | /* recursiveFilterY */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Performs 1 dimensional recursive filtering (1st and 2nd order) i
n y direction. | | /** \brief Performs 1 dimensional recursive filtering (1st and 2nd order) i
n y direction. | |
| | | | |
| It calls \ref recursiveFilterLine() for every column of the | | It calls \ref recursiveFilterLine() for every column of the | |
| image. See \ref recursiveFilterLine() for more information about | | image. See \ref recursiveFilterLine() for more information about | |
| required interfaces and vigra_preconditions. | | required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | // first order filter | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveFilterY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double b, BorderTreatmentMode border); | |
| | | | |
| | | // second order filter | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveFilterY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double b1, double b2); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveFilterY} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // first order filter | | // first order filter | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterY(SrcImageIterator supperleft, | | void recursiveFilterY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as
, | | SrcImageIterator slowerright, SrcAccessor as
, | |
| DestImageIterator dupperleft, DestAccessor a
d, | | DestImageIterator dupperleft, DestAccessor a
d, | |
| double b, BorderTreatmentMode border); | | double b, BorderTreatmentMode border); | |
| | | | |
| // second order filter | | // second order filter | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterY(SrcImageIterator supperleft, | | void recursiveFilterY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as
, | | SrcImageIterator slowerright, SrcAccessor as
, | |
| DestImageIterator dupperleft, DestAccessor a
d, | | DestImageIterator dupperleft, DestAccessor a
d, | |
| double b1, double b2); | | double b1, double b2); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| // first order filter | | // first order filter | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterY( | | void recursiveFilterY( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double b, BorderTreatmentMode border); | | double b, BorderTreatmentMode border); | |
| | | | |
| // second order filter | | // second order filter | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterY( | | void recursiveFilterY( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor>
src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double b1, double b2); | | double b1, double b2); | |
|
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | // apply a second-order filter to the y-axis | |
| | | recursiveFilterY(src, dest, -0.6, -0.06); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveFilterY} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| vigra::recursiveFilterY(srcImageRange(src), destImage(dest), -0.6, -0.0
6); | | vigra::recursiveFilterY(srcImageRange(src), destImage(dest), -0.6, -0.0
6); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveFilterY) | | doxygen_overloaded_function(template <...> void recursiveFilterY) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFilterY(SrcImageIterator supperleft, | | void recursiveFilterY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double b, BorderTreatmentMode border) | | double b, BorderTreatmentMode border) | |
| { | | { | |
| | | | |
| skipping to change at line 1259 | | skipping to change at line 1405 | |
| typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | | typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | |
| | | | |
| recursiveFilterLine(cs, cs+h, as, | | recursiveFilterLine(cs, cs+h, as, | |
| cd, ad, | | cd, ad, | |
| b, border); | | b, border); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveFilterY( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveFilterY(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> sr | |
| pair<DestImageIterator, DestAccessor> dest, | | c, | |
| double b, BorderTreatmentMode border) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double b, BorderTreatmentMode border) | |
| { | | { | |
| recursiveFilterY(src.first, src.second, src.third, | | recursiveFilterY(src.first, src.second, src.third, | |
|
| dest.first, dest.second, b, border); | | dest.first, dest.second, b, border); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveFilterY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double b, BorderTreatmentMode border) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveFilterY(): shape mismatch between input and output."); | |
| | | recursiveFilterY(srcImageRange(src), | |
| | | destImage(dest), b, border); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveFilterY (2nd order) */ | | /* recursiveFilterY (2nd order) */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| | | | |
| skipping to change at line 1299 | | skipping to change at line 1458 | |
| typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | | typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | |
| | | | |
| recursiveFilterLine(cs, cs+h, as, | | recursiveFilterLine(cs, cs+h, as, | |
| cd, ad, | | cd, ad, | |
| b1, b2); | | b1, b2); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveFilterY( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveFilterY(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> sr | |
| pair<DestImageIterator, DestAccessor> dest, | | c, | |
| double b1, double b2) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double b1, double b2) | |
| { | | { | |
| recursiveFilterY(src.first, src.second, src.third, | | recursiveFilterY(src.first, src.second, src.third, | |
|
| dest.first, dest.second, b1, b2); | | dest.first, dest.second, b1, b2); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveFilterY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double b1, double b2) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveFilterY(): shape mismatch between input and output."); | |
| | | recursiveFilterY(srcImageRange(src), | |
| | | destImage(dest), b1, b2); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveGaussianFilterY */ | | /* recursiveGaussianFilterY */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| // AUTHOR: Sebastian Boppel | | // AUTHOR: Sebastian Boppel | |
| | | | |
| /** \brief Compute 1 dimensional recursive approximation of Gaussian smooth
ing in y direction. | | /** \brief Compute 1 dimensional recursive approximation of Gaussian smooth
ing in y direction. | |
| | | | |
| It calls \ref recursiveGaussianFilterLine() for every column of the | | It calls \ref recursiveGaussianFilterLine() for every column of the | |
| image. See \ref recursiveGaussianFilterLine() for more information abou
t | | image. See \ref recursiveGaussianFilterLine() for more information abou
t | |
| required interfaces and vigra_preconditions. | | required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveGaussianFilterY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double sigma); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveGaussianFilterY} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| recursiveGaussianFilterY(SrcImageIterator supperleft, SrcImageItera
tor slowerright, SrcAccessor as, | | recursiveGaussianFilterY(SrcImageIterator supperleft, SrcImageItera
tor slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor
ad, | | DestImageIterator dupperleft, DestAccessor
ad, | |
| double sigma); | | double sigma); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| recursiveGaussianFilterY(triple<SrcImageIterator, SrcImageIterator,
SrcAccessor> src, | | recursiveGaussianFilterY(triple<SrcImageIterator, SrcImageIterator,
SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest
, | | pair<DestImageIterator, DestAccessor> dest
, | |
| double sigma); | | double sigma); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | recursiveGaussianFilterY(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveGaussianFilterY} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| vigra::recursiveGaussianFilterY(srcImageRange(src), destImage(dest), 3.
0); | | vigra::recursiveGaussianFilterY(srcImageRange(src), destImage(dest), 3.
0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveGaussianFilterY) | | doxygen_overloaded_function(template <...> void recursiveGaussianFilterY) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| recursiveGaussianFilterY(SrcImageIterator supperleft, SrcImageIterator slow
erright, SrcAccessor as, | | recursiveGaussianFilterY(SrcImageIterator supperleft, SrcImageIterator slow
erright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double sigma) | | double sigma) | |
| { | | { | |
| | | | |
| skipping to change at line 1398 | | skipping to change at line 1590 | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| inline void | | inline void | |
| recursiveGaussianFilterY(triple<SrcImageIterator, SrcImageIterator, SrcAcce
ssor> src, | | recursiveGaussianFilterY(triple<SrcImageIterator, SrcImageIterator, SrcAcce
ssor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double sigma) | | double sigma) | |
| { | | { | |
| recursiveGaussianFilterY(src.first, src.second, src.third, | | recursiveGaussianFilterY(src.first, src.second, src.third, | |
| dest.first, dest.second, sigma); | | dest.first, dest.second, sigma); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveGaussianFilterY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double sigma) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveGaussianFilterY(): shape mismatch between input and outpu | |
| | | t."); | |
| | | recursiveGaussianFilterY(srcImageRange(src), | |
| | | destImage(dest), sigma); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveSmoothY */ | | /* recursiveSmoothY */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Performs 1 dimensional recursive smoothing in y direction. | | /** \brief Performs 1 dimensional recursive smoothing in y direction. | |
| | | | |
| It calls \ref recursiveSmoothLine() for every column of the | | It calls \ref recursiveSmoothLine() for every column of the | |
| image. See \ref recursiveSmoothLine() for more information about | | image. See \ref recursiveSmoothLine() for more information about | |
| required interfaces and vigra_preconditions. | | required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveSmoothY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveSmoothY} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSmoothY(SrcImageIterator supperleft, | | void recursiveSmoothY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSmoothY( | | void recursiveSmoothY( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | recursiveSmoothY(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveSmoothY} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| vigra::recursiveSmoothY(srcImageRange(src), destImage(dest), 3.0); | | vigra::recursiveSmoothY(srcImageRange(src), destImage(dest), 3.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveSmoothY) | | doxygen_overloaded_function(template <...> void recursiveSmoothY) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSmoothY(SrcImageIterator supperleft, | | void recursiveSmoothY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| { | | { | |
| | | | |
| skipping to change at line 1477 | | skipping to change at line 1702 | |
| typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | | typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | |
| | | | |
| recursiveSmoothLine(cs, cs+h, as, | | recursiveSmoothLine(cs, cs+h, as, | |
| cd, ad, | | cd, ad, | |
| scale); | | scale); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveSmoothY( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveSmoothY(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> sr | |
| pair<DestImageIterator, DestAccessor> dest, | | c, | |
| double scale) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double scale) | |
| { | | { | |
| recursiveSmoothY(src.first, src.second, src.third, | | recursiveSmoothY(src.first, src.second, src.third, | |
|
| dest. first, dest.second, scale); | | dest.first, dest.second, scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveSmoothY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveSmoothY(): shape mismatch between input and output."); | |
| | | recursiveSmoothY(srcImageRange(src), | |
| | | destImage(dest), scale); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveFirstDerivativeX */ | | /* recursiveFirstDerivativeX */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Recursively calculates the 1 dimensional first derivative in x | | /** \brief Recursively calculates the 1 dimensional first derivative in x | |
| direction. | | direction. | |
| | | | |
| It calls \ref recursiveFirstDerivativeLine() for every | | It calls \ref recursiveFirstDerivativeLine() for every | |
| row of the image. See \ref recursiveFirstDerivativeLine() for more | | row of the image. See \ref recursiveFirstDerivativeLine() for more | |
| information about required interfaces and vigra_preconditions. | | information about required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveFirstDerivativeX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveFirstDerivativeX} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFirstDerivativeX(SrcImageIterator supperleft, | | void recursiveFirstDerivativeX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFirstDerivativeX( | | void recursiveFirstDerivativeX( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | recursiveFirstDerivativeX(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveFirstDerivativeX} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| vigra::recursiveFirstDerivativeX(srcImageRange(src), destImage(dest), 3
.0); | | vigra::recursiveFirstDerivativeX(srcImageRange(src), destImage(dest), 3
.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveFirstDerivativeX) | | doxygen_overloaded_function(template <...> void recursiveFirstDerivativeX) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFirstDerivativeX(SrcImageIterator supperleft, | | void recursiveFirstDerivativeX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| { | | { | |
| | | | |
| skipping to change at line 1566 | | skipping to change at line 1824 | |
| typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | | typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | |
| | | | |
| recursiveFirstDerivativeLine(rs, rs+w, as, | | recursiveFirstDerivativeLine(rs, rs+w, as, | |
| rd, ad, | | rd, ad, | |
| scale); | | scale); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveFirstDerivativeX( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveFirstDerivativeX(triple<SrcImageIterator, SrcImageIterator, SrcAcc | |
| pair<DestImageIterator, DestAccessor> dest, | | essor> src, | |
| double scale) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double scale) | |
| { | | { | |
| recursiveFirstDerivativeX(src.first, src.second, src.third, | | recursiveFirstDerivativeX(src.first, src.second, src.third, | |
|
| dest. first, dest.second, scale); | | dest.first, dest.second, scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveFirstDerivativeX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveFirstDerivativeX(): shape mismatch between input and outp | |
| | | ut."); | |
| | | recursiveFirstDerivativeX(srcImageRange(src), | |
| | | destImage(dest), scale); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveFirstDerivativeY */ | | /* recursiveFirstDerivativeY */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Recursively calculates the 1 dimensional first derivative in y | | /** \brief Recursively calculates the 1 dimensional first derivative in y | |
| direction. | | direction. | |
| | | | |
| It calls \ref recursiveFirstDerivativeLine() for every | | It calls \ref recursiveFirstDerivativeLine() for every | |
| column of the image. See \ref recursiveFirstDerivativeLine() for more | | column of the image. See \ref recursiveFirstDerivativeLine() for more | |
| information about required interfaces and vigra_preconditions. | | information about required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveFirstDerivativeY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveFirstDerivativeY} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFirstDerivativeY(SrcImageIterator supperleft, | | void recursiveFirstDerivativeY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFirstDerivativeY( | | void recursiveFirstDerivativeY( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | recursiveFirstDerivativeY(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveFirstDerivativeY} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| vigra::recursiveFirstDerivativeY(srcImageRange(src), destImage(dest), 3
.0); | | vigra::recursiveFirstDerivativeY(srcImageRange(src), destImage(dest), 3
.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveFirstDerivativeY) | | doxygen_overloaded_function(template <...> void recursiveFirstDerivativeY) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveFirstDerivativeY(SrcImageIterator supperleft, | | void recursiveFirstDerivativeY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| { | | { | |
| | | | |
| skipping to change at line 1655 | | skipping to change at line 1946 | |
| typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | | typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | |
| | | | |
| recursiveFirstDerivativeLine(cs, cs+h, as, | | recursiveFirstDerivativeLine(cs, cs+h, as, | |
| cd, ad, | | cd, ad, | |
| scale); | | scale); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveFirstDerivativeY( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveFirstDerivativeY(triple<SrcImageIterator, SrcImageIterator, SrcAcc | |
| pair<DestImageIterator, DestAccessor> dest, | | essor> src, | |
| double scale) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double scale) | |
| { | | { | |
| recursiveFirstDerivativeY(src.first, src.second, src.third, | | recursiveFirstDerivativeY(src.first, src.second, src.third, | |
|
| dest. first, dest.second, scale); | | dest.first, dest.second, scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveFirstDerivativeY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveFirstDerivativeY(): shape mismatch between input and outp | |
| | | ut."); | |
| | | recursiveFirstDerivativeY(srcImageRange(src), | |
| | | destImage(dest), scale); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveSecondDerivativeX */ | | /* recursiveSecondDerivativeX */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Recursively calculates the 1 dimensional second derivative in x | | /** \brief Recursively calculates the 1 dimensional second derivative in x | |
| direction. | | direction. | |
| | | | |
| It calls \ref recursiveSecondDerivativeLine() for every | | It calls \ref recursiveSecondDerivativeLine() for every | |
| row of the image. See \ref recursiveSecondDerivativeLine() for more | | row of the image. See \ref recursiveSecondDerivativeLine() for more | |
| information about required interfaces and vigra_preconditions. | | information about required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveSecondDerivativeX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveSecondDerivativeX} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSecondDerivativeX(SrcImageIterator supperleft, | | void recursiveSecondDerivativeX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSecondDerivativeX( | | void recursiveSecondDerivativeX( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | recursiveSecondDerivativeX(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveSecondDerivativeX} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| vigra::recursiveSecondDerivativeX(srcImageRange(src), destImage(dest),
3.0); | | vigra::recursiveSecondDerivativeX(srcImageRange(src), destImage(dest),
3.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveSecondDerivativeX) | | doxygen_overloaded_function(template <...> void recursiveSecondDerivativeX) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSecondDerivativeX(SrcImageIterator supperleft, | | void recursiveSecondDerivativeX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| { | | { | |
| | | | |
| skipping to change at line 1744 | | skipping to change at line 2068 | |
| typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | | typename DestImageIterator::row_iterator rd = dupperleft.rowIterato
r(); | |
| | | | |
| recursiveSecondDerivativeLine(rs, rs+w, as, | | recursiveSecondDerivativeLine(rs, rs+w, as, | |
| rd, ad, | | rd, ad, | |
| scale); | | scale); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveSecondDerivativeX( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveSecondDerivativeX(triple<SrcImageIterator, SrcImageIterator, SrcAc | |
| pair<DestImageIterator, DestAccessor> dest, | | cessor> src, | |
| double scale) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double scale) | |
| { | | { | |
| recursiveSecondDerivativeX(src.first, src.second, src.third, | | recursiveSecondDerivativeX(src.first, src.second, src.third, | |
|
| dest. first, dest.second, scale); | | dest.first, dest.second, scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveSecondDerivativeX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveSecondDerivativeX(): shape mismatch between input and out | |
| | | put."); | |
| | | recursiveSecondDerivativeX(srcImageRange(src), | |
| | | destImage(dest), scale); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* recursiveSecondDerivativeY */ | | /* recursiveSecondDerivativeY */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Recursively calculates the 1 dimensional second derivative in y | | /** \brief Recursively calculates the 1 dimensional second derivative in y | |
| direction. | | direction. | |
| | | | |
| It calls \ref recursiveSecondDerivativeLine() for every | | It calls \ref recursiveSecondDerivativeLine() for every | |
| column of the image. See \ref recursiveSecondDerivativeLine() for more | | column of the image. See \ref recursiveSecondDerivativeLine() for more | |
| information about required interfaces and vigra_preconditions. | | information about required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | recursiveSecondDerivativeY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{recursiveSecondDerivativeY} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSecondDerivativeY(SrcImageIterator supperleft, | | void recursiveSecondDerivativeY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSecondDerivativeY( | | void recursiveSecondDerivativeY( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| double scale) | | double scale) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | | <b>\#include</b> \<vigra/recursiveconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | recursiveSecondDerivativeY(src, dest, 3.0); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{recursiveSecondDerivativeY} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| vigra::recursiveSecondDerivativeY(srcImageRange(src), destImage(dest),
3.0); | | vigra::recursiveSecondDerivativeY(srcImageRange(src), destImage(dest),
3.0); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void recursiveSecondDerivativeY) | | doxygen_overloaded_function(template <...> void recursiveSecondDerivativeY) | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void recursiveSecondDerivativeY(SrcImageIterator supperleft, | | void recursiveSecondDerivativeY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor as, | | SrcImageIterator slowerright, SrcAccessor as, | |
| DestImageIterator dupperleft, DestAccessor ad, | | DestImageIterator dupperleft, DestAccessor ad, | |
| double scale) | | double scale) | |
| { | | { | |
| | | | |
| skipping to change at line 1833 | | skipping to change at line 2190 | |
| typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | | typename DestImageIterator::column_iterator cd = dupperleft.columnI
terator(); | |
| | | | |
| recursiveSecondDerivativeLine(cs, cs+h, as, | | recursiveSecondDerivativeLine(cs, cs+h, as, | |
| cd, ad, | | cd, ad, | |
| scale); | | scale); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
|
| inline void recursiveSecondDerivativeY( | | inline void | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | recursiveSecondDerivativeY(triple<SrcImageIterator, SrcImageIterator, SrcAc | |
| pair<DestImageIterator, DestAccessor> dest, | | cessor> src, | |
| double scale) | | pair<DestImageIterator, DestAccessor> dest, | |
| | | double scale) | |
| { | | { | |
| recursiveSecondDerivativeY(src.first, src.second, src.third, | | recursiveSecondDerivativeY(src.first, src.second, src.third, | |
|
| dest. first, dest.second, scale); | | dest.first, dest.second, scale); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | recursiveSecondDerivativeY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | double scale) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "recursiveSecondDerivativeY(): shape mismatch between input and out | |
| | | put."); | |
| | | recursiveSecondDerivativeY(srcImageRange(src), | |
| | | destImage(dest), scale); | |
| } | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_RECURSIVECONVOLUTION_HXX | | #endif // VIGRA_RECURSIVECONVOLUTION_HXX | |
| | | | |
End of changes. 96 change blocks. |
| 105 lines changed or deleted | | 491 lines changed or added | |
|
| regression.hxx | | regression.hxx | |
| /************************************************************************/ | | /************************************************************************/ | |
| /* */ | | /* */ | |
|
| /* Copyright 2008 by Ullrich Koethe */ | | /* Copyright 2008-2013 by Ullrich Koethe */ | |
| /* */ | | /* */ | |
| /* This file is part of the VIGRA computer vision library. */ | | /* This file is part of the VIGRA computer vision library. */ | |
| /* The VIGRA Website is */ | | /* The VIGRA Website is */ | |
| /* http://hci.iwr.uni-heidelberg.de/vigra/ */ | | /* http://hci.iwr.uni-heidelberg.de/vigra/ */ | |
| /* Please direct questions, bug reports, and contributions to */ | | /* Please direct questions, bug reports, and contributions to */ | |
| /* ullrich.koethe@iwr.uni-heidelberg.de or */ | | /* ullrich.koethe@iwr.uni-heidelberg.de or */ | |
| /* vigra@informatik.uni-hamburg.de */ | | /* vigra@informatik.uni-hamburg.de */ | |
| /* */ | | /* */ | |
| /* Permission is hereby granted, free of charge, to any person */ | | /* Permission is hereby granted, free of charge, to any person */ | |
| /* obtaining a copy of this software and associated documentation */ | | /* obtaining a copy of this software and associated documentation */ | |
| | | | |
| skipping to change at line 44 | | skipping to change at line 44 | |
| /************************************************************************/ | | /************************************************************************/ | |
| | | | |
| #ifndef VIGRA_REGRESSION_HXX | | #ifndef VIGRA_REGRESSION_HXX | |
| #define VIGRA_REGRESSION_HXX | | #define VIGRA_REGRESSION_HXX | |
| | | | |
| #include "matrix.hxx" | | #include "matrix.hxx" | |
| #include "linear_solve.hxx" | | #include "linear_solve.hxx" | |
| #include "singular_value_decomposition.hxx" | | #include "singular_value_decomposition.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "functorexpression.hxx" | | #include "functorexpression.hxx" | |
|
| | | #include "autodiff.hxx" | |
| | | | |
| namespace vigra | | namespace vigra | |
| { | | { | |
| | | | |
| namespace linalg | | namespace linalg | |
| { | | { | |
| | | | |
| /** \addtogroup Optimization Optimization and Regression | | /** \addtogroup Optimization Optimization and Regression | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| skipping to change at line 73 | | skipping to change at line 74 | |
| | | | |
| When \a b is a matrix with <tt>k</tt> columns, \a x must also have | | When \a b is a matrix with <tt>k</tt> columns, \a x must also have | |
| <tt>k</tt> columns, which will contain the solutions for the corresp
onding columns of | | <tt>k</tt> columns, which will contain the solutions for the corresp
onding columns of | |
| \a b. Note that all matrices must already have the correct shape. | | \a b. Note that all matrices must already have the correct shape. | |
| | | | |
| This function is just another name for \ref linearSolve(), perhaps | | This function is just another name for \ref linearSolve(), perhaps | |
| leading to more readable code when \a A is a rectangular matrix. It
returns | | leading to more readable code when \a A is a rectangular matrix. It
returns | |
| <tt>false</tt> when the rank of \a A is less than <tt>n</tt>. | | <tt>false</tt> when the rank of \a A is less than <tt>n</tt>. | |
| See \ref linearSolve() for more documentation. | | See \ref linearSolve() for more documentation. | |
| | | | |
|
| <b>\#include</b> \<vigra/regression.hxx\> | | <b>\#include</b> \<vigra/regression.hxx\><br/> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| inline bool | | inline bool | |
| leastSquares(MultiArrayView<2, T, C1> const & A, | | leastSquares(MultiArrayView<2, T, C1> const & A, | |
| MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x
, | | MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x
, | |
| std::string method = "QR") | | std::string method = "QR") | |
| { | | { | |
| return linearSolve(A, b, x, method); | | return linearSolve(A, b, x, method); | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 115 | | skipping to change at line 116 | |
| | | | |
| where the square root of \a weights is just taken element-wise. | | where the square root of \a weights is just taken element-wise. | |
| | | | |
| When \a b is a matrix with <tt>k</tt> columns, \a x must also have | | When \a b is a matrix with <tt>k</tt> columns, \a x must also have | |
| <tt>k</tt> columns, which will contain the solutions for the corresp
onding columns of | | <tt>k</tt> columns, which will contain the solutions for the corresp
onding columns of | |
| \a b. Note that all matrices must already have the correct shape. | | \a b. Note that all matrices must already have the correct shape. | |
| | | | |
| The function returns | | The function returns | |
| <tt>false</tt> when the rank of the weighted matrix \a A is less tha
n <tt>n</tt>. | | <tt>false</tt> when the rank of the weighted matrix \a A is less tha
n <tt>n</tt>. | |
| | | | |
|
| <b>\#include</b> \<vigra/regression.hxx\> | | <b>\#include</b> \<vigra/regression.hxx\><br/> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3, class C4> | | template <class T, class C1, class C2, class C3, class C4> | |
| bool | | bool | |
| weightedLeastSquares(MultiArrayView<2, T, C1> const & A, | | weightedLeastSquares(MultiArrayView<2, T, C1> const & A, | |
| MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> co
nst &weights, | | MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> co
nst &weights, | |
| MultiArrayView<2, T, C4> &x, std::string method = "QR") | | MultiArrayView<2, T, C4> &x, std::string method = "QR") | |
| { | | { | |
|
| typedef T Real; | | | |
| | | | |
| const unsigned int rows = rowCount(A); | | const unsigned int rows = rowCount(A); | |
| const unsigned int cols = columnCount(A); | | const unsigned int cols = columnCount(A); | |
| const unsigned int rhsCount = columnCount(b); | | const unsigned int rhsCount = columnCount(b); | |
| vigra_precondition(rows >= cols, | | vigra_precondition(rows >= cols, | |
| "weightedLeastSquares(): Input matrix A must be rectangular with row
Count >= columnCount."); | | "weightedLeastSquares(): Input matrix A must be rectangular with row
Count >= columnCount."); | |
| vigra_precondition(rowCount(b) == rows, | | vigra_precondition(rowCount(b) == rows, | |
| "weightedLeastSquares(): Shape mismatch between matrices A and b."); | | "weightedLeastSquares(): Shape mismatch between matrices A and b."); | |
| vigra_precondition(rowCount(b) == rowCount(weights) && columnCount(weig
hts) == 1, | | vigra_precondition(rowCount(b) == rowCount(weights) && columnCount(weig
hts) == 1, | |
| "weightedLeastSquares(): Weight matrix has wrong shape."); | | "weightedLeastSquares(): Weight matrix has wrong shape."); | |
| vigra_precondition(rowCount(x) == cols && columnCount(x) == rhsCount, | | vigra_precondition(rowCount(x) == cols && columnCount(x) == rhsCount, | |
| | | | |
| skipping to change at line 175 | | skipping to change at line 174 | |
| | | | |
| This is implemented by means of \ref singularValueDecomposition(). | | This is implemented by means of \ref singularValueDecomposition(). | |
| | | | |
| When \a b is a matrix with <tt>k</tt> columns, \a x must also have | | When \a b is a matrix with <tt>k</tt> columns, \a x must also have | |
| <tt>k</tt> columns, which will contain the solutions for the corresp
onding columns of | | <tt>k</tt> columns, which will contain the solutions for the corresp
onding columns of | |
| \a b. Note that all matrices must already have the correct shape. | | \a b. Note that all matrices must already have the correct shape. | |
| | | | |
| The function returns <tt>false</tt> if the rank of \a A is less than
<tt>n</tt> | | The function returns <tt>false</tt> if the rank of \a A is less than
<tt>n</tt> | |
| and <tt>lambda == 0.0</tt>. | | and <tt>lambda == 0.0</tt>. | |
| | | | |
|
| <b>\#include</b> \<vigra/regression.hxx\> | | <b>\#include</b> \<vigra/regression.hxx\><br/> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| bool | | bool | |
| ridgeRegression(MultiArrayView<2, T, C1> const & A, | | ridgeRegression(MultiArrayView<2, T, C1> const & A, | |
| MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3>
&x, double lambda) | | MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3>
&x, double lambda) | |
| { | | { | |
|
| typedef T Real; | | | |
| | | | |
| const unsigned int rows = rowCount(A); | | const unsigned int rows = rowCount(A); | |
| const unsigned int cols = columnCount(A); | | const unsigned int cols = columnCount(A); | |
| const unsigned int rhsCount = columnCount(b); | | const unsigned int rhsCount = columnCount(b); | |
| vigra_precondition(rows >= cols, | | vigra_precondition(rows >= cols, | |
| "ridgeRegression(): Input matrix A must be rectangular with rowCount
>= columnCount."); | | "ridgeRegression(): Input matrix A must be rectangular with rowCount
>= columnCount."); | |
| vigra_precondition(rowCount(b) == rows, | | vigra_precondition(rowCount(b) == rows, | |
| "ridgeRegression(): Shape mismatch between matrices A and b."); | | "ridgeRegression(): Shape mismatch between matrices A and b."); | |
| vigra_precondition(rowCount(x) == cols && columnCount(x) == rhsCount, | | vigra_precondition(rowCount(x) == cols && columnCount(x) == rhsCount, | |
| "ridgeRegression(): Result matrix x has wrong shape."); | | "ridgeRegression(): Result matrix x has wrong shape."); | |
| vigra_precondition(lambda >= 0.0, | | vigra_precondition(lambda >= 0.0, | |
| | | | |
| skipping to change at line 248 | | skipping to change at line 245 | |
| where the square root of \a weights is just taken element-wise. Thi
s solution is | | where the square root of \a weights is just taken element-wise. Thi
s solution is | |
| computed by means of \ref singularValueDecomposition(). | | computed by means of \ref singularValueDecomposition(). | |
| | | | |
| When \a b is a matrix with <tt>k</tt> columns, \a x must also have | | When \a b is a matrix with <tt>k</tt> columns, \a x must also have | |
| <tt>k</tt> columns, which will contain the solutions for the corresp
onding columns of | | <tt>k</tt> columns, which will contain the solutions for the corresp
onding columns of | |
| \a b. Note that all matrices must already have the correct shape. | | \a b. Note that all matrices must already have the correct shape. | |
| | | | |
| The function returns <tt>false</tt> if the rank of \a A is less than
<tt>n</tt> | | The function returns <tt>false</tt> if the rank of \a A is less than
<tt>n</tt> | |
| and <tt>lambda == 0.0</tt>. | | and <tt>lambda == 0.0</tt>. | |
| | | | |
|
| <b>\#include</b> \<vigra/regression.hxx\> | | <b>\#include</b> \<vigra/regression.hxx\><br/> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3, class C4> | | template <class T, class C1, class C2, class C3, class C4> | |
| bool | | bool | |
| weightedRidgeRegression(MultiArrayView<2, T, C1> const & A, | | weightedRidgeRegression(MultiArrayView<2, T, C1> const & A, | |
| MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> co
nst &weights, | | MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> co
nst &weights, | |
| MultiArrayView<2, T, C4> &x, double lambda) | | MultiArrayView<2, T, C4> &x, double lambda) | |
| { | | { | |
|
| typedef T Real; | | | |
| | | | |
| const unsigned int rows = rowCount(A); | | const unsigned int rows = rowCount(A); | |
| const unsigned int cols = columnCount(A); | | const unsigned int cols = columnCount(A); | |
| const unsigned int rhsCount = columnCount(b); | | const unsigned int rhsCount = columnCount(b); | |
| vigra_precondition(rows >= cols, | | vigra_precondition(rows >= cols, | |
| "weightedRidgeRegression(): Input matrix A must be rectangular with
rowCount >= columnCount."); | | "weightedRidgeRegression(): Input matrix A must be rectangular with
rowCount >= columnCount."); | |
| vigra_precondition(rowCount(b) == rows, | | vigra_precondition(rowCount(b) == rows, | |
| "weightedRidgeRegression(): Shape mismatch between matrices A and b.
"); | | "weightedRidgeRegression(): Shape mismatch between matrices A and b.
"); | |
| vigra_precondition(rowCount(b) == rowCount(weights) && columnCount(weig
hts) == 1, | | vigra_precondition(rowCount(b) == rowCount(weights) && columnCount(weig
hts) == 1, | |
| "weightedRidgeRegression(): Weight matrix has wrong shape."); | | "weightedRidgeRegression(): Weight matrix has wrong shape."); | |
| vigra_precondition(rowCount(x) == cols && columnCount(x) == rhsCount, | | vigra_precondition(rowCount(x) == cols && columnCount(x) == rhsCount, | |
| | | | |
| skipping to change at line 302 | | skipping to change at line 297 | |
| is implemented so that the \ref singularValueDecomposition() has to
be executed only once. | | is implemented so that the \ref singularValueDecomposition() has to
be executed only once. | |
| \a lambda must be an array conforming to the <tt>std::vector</tt> in
terface, i.e. must | | \a lambda must be an array conforming to the <tt>std::vector</tt> in
terface, i.e. must | |
| support <tt>lambda.size()</tt> and <tt>lambda[k]</tt>. The columns o
f the matrix \a x | | support <tt>lambda.size()</tt> and <tt>lambda[k]</tt>. The columns o
f the matrix \a x | |
| will contain the solutions for the corresponding lambda, so the num
ber of columns of | | will contain the solutions for the corresponding lambda, so the num
ber of columns of | |
| the matrix \a x must be equal to <tt>lambda.size()</tt>, and \a b mu
st be a columns vector, | | the matrix \a x must be equal to <tt>lambda.size()</tt>, and \a b mu
st be a columns vector, | |
| i.e. cannot contain several right hand sides at once. | | i.e. cannot contain several right hand sides at once. | |
| | | | |
| The function returns <tt>false</tt> when the matrix \a A is rank def
icient. If this | | The function returns <tt>false</tt> when the matrix \a A is rank def
icient. If this | |
| happens, and one of the lambdas is zero, the corresponding column of
\a x will be skipped. | | happens, and one of the lambdas is zero, the corresponding column of
\a x will be skipped. | |
| | | | |
|
| <b>\#include</b> \<vigra/regression.hxx\> | | <b>\#include</b> \<vigra/regression.hxx\><br/> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| template <class T, class C1, class C2, class C3, class Array> | | template <class T, class C1, class C2, class C3, class Array> | |
| bool | | bool | |
| ridgeRegressionSeries(MultiArrayView<2, T, C1> const & A, | | ridgeRegressionSeries(MultiArrayView<2, T, C1> const & A, | |
| MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x, A
rray const & lambda) | | MultiArrayView<2, T, C2> const &b, MultiArrayView<2, T, C3> &x, A
rray const & lambda) | |
| { | | { | |
|
| typedef T Real; | | | |
| | | | |
| const unsigned int rows = rowCount(A); | | const unsigned int rows = rowCount(A); | |
| const unsigned int cols = columnCount(A); | | const unsigned int cols = columnCount(A); | |
| const unsigned int lambdaCount = lambda.size(); | | const unsigned int lambdaCount = lambda.size(); | |
| vigra_precondition(rows >= cols, | | vigra_precondition(rows >= cols, | |
| "ridgeRegressionSeries(): Input matrix A must be rectangular with ro
wCount >= columnCount."); | | "ridgeRegressionSeries(): Input matrix A must be rectangular with ro
wCount >= columnCount."); | |
| vigra_precondition(rowCount(b) == rows && columnCount(b) == 1, | | vigra_precondition(rowCount(b) == rows && columnCount(b) == 1, | |
| "ridgeRegressionSeries(): Shape mismatch between matrices A and b.")
; | | "ridgeRegressionSeries(): Shape mismatch between matrices A and b.")
; | |
| vigra_precondition(rowCount(x) == cols && columnCount(x) == lambdaCount
, | | vigra_precondition(rowCount(x) == cols && columnCount(x) == lambdaCount
, | |
| "ridgeRegressionSeries(): Result matrix x has wrong shape."); | | "ridgeRegressionSeries(): Result matrix x has wrong shape."); | |
| | | | |
| | | | |
| skipping to change at line 346 | | skipping to change at line 339 | |
| continue; | | continue; | |
| for(unsigned int k=0; k<cols; ++k) | | for(unsigned int k=0; k<cols; ++k) | |
| xt(k,0) = xl(k,0) * s(k,0) / (sq(s(k,0)) + lambda[i]); | | xt(k,0) = xl(k,0) * s(k,0) / (sq(s(k,0)) + lambda[i]); | |
| columnVector(x, i) = v*xt; | | columnVector(x, i) = v*xt; | |
| } | | } | |
| return (rank == n); | | return (rank == n); | |
| } | | } | |
| | | | |
| /** \brief Pass options to leastAngleRegression(). | | /** \brief Pass options to leastAngleRegression(). | |
| | | | |
|
| <b>\#include</b> \<vigra/regression.hxx\> | | <b>\#include</b> \<vigra/regression.hxx\><br/> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| */ | | */ | |
| class LeastAngleRegressionOptions | | class LeastAngleRegressionOptions | |
| { | | { | |
| public: | | public: | |
| enum Mode { LARS, LASSO, NNLASSO }; | | enum Mode { LARS, LASSO, NNLASSO }; | |
| | | | |
| /** Initialize all options with default values. | | /** Initialize all options with default values. | |
| */ | | */ | |
| LeastAngleRegressionOptions() | | LeastAngleRegressionOptions() | |
| : max_solution_count(0), | | : max_solution_count(0), | |
| | | | |
| skipping to change at line 372 | | skipping to change at line 365 | |
| | | | |
| /** Maximum number of solutions to be computed. | | /** Maximum number of solutions to be computed. | |
| | | | |
| If \a n is 0 (the default), the number of solutions is determin
ed by the length | | If \a n is 0 (the default), the number of solutions is determin
ed by the length | |
| of the solution array. Otherwise, the minimum of maxSolutionCou
nt() and that | | of the solution array. Otherwise, the minimum of maxSolutionCou
nt() and that | |
| length is taken.<br> | | length is taken.<br> | |
| Default: 0 (use length of solution array) | | Default: 0 (use length of solution array) | |
| */ | | */ | |
| LeastAngleRegressionOptions & maxSolutionCount(unsigned int n) | | LeastAngleRegressionOptions & maxSolutionCount(unsigned int n) | |
| { | | { | |
|
| max_solution_count = (int)n; | | max_solution_count = static_cast<int>(n); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** Set the mode of the algorithm. | | /** Set the mode of the algorithm. | |
| | | | |
| Mode must be one of "lars", "lasso", "nnlasso". The function ju
st calls | | Mode must be one of "lars", "lasso", "nnlasso". The function ju
st calls | |
| the member function of the corresponding name to set the mode. | | the member function of the corresponding name to set the mode. | |
| | | | |
| Default: "lasso" | | Default: "lasso" | |
| */ | | */ | |
| | | | |
| skipping to change at line 521 | | skipping to change at line 514 | |
| if(maxSolutionCount == 0) | | if(maxSolutionCount == 0) | |
| maxSolutionCount = lasso_modification | | maxSolutionCount = lasso_modification | |
| ? 10*maxRank | | ? 10*maxRank | |
| : maxRank; | | : maxRank; | |
| | | | |
| bool needToRemoveColumn = false; | | bool needToRemoveColumn = false; | |
| MultiArrayIndex columnToBeAdded = 0, columnToBeRemoved = 0; | | MultiArrayIndex columnToBeAdded = 0, columnToBeRemoved = 0; | |
| MultiArrayIndex currentSolutionCount = 0; | | MultiArrayIndex currentSolutionCount = 0; | |
| while(currentSolutionCount < maxSolutionCount) | | while(currentSolutionCount < maxSolutionCount) | |
| { | | { | |
|
| //ColumnSet activeSet = d.columnPermutation.subarray(0, (unsigned i | | //ColumnSet activeSet = d.columnPermutation.subarray(0, static_cast | |
| nt)d.activeSetSize); | | <unsigned int>(d.activeSetSize)); | |
| ColumnSet inactiveSet = d.columnPermutation.subarray((unsigned int) | | ColumnSet inactiveSet = d.columnPermutation.subarray(static_cast<un | |
| d.activeSetSize, (unsigned int)cols); | | signed int>(d.activeSetSize), static_cast<unsigned int>(cols)); | |
| | | | |
| // find next dimension to be activated | | // find next dimension to be activated | |
| Matrix<T> cLARS = transpose(d.A) * (d.b - d.lars_prediction),
// correlation with LARS residual | | Matrix<T> cLARS = transpose(d.A) * (d.b - d.lars_prediction),
// correlation with LARS residual | |
| cLSQ = transpose(d.A) * (d.b - d.next_lsq_prediction);
// correlation with LSQ residual | | cLSQ = transpose(d.A) * (d.b - d.next_lsq_prediction);
// correlation with LSQ residual | |
| | | | |
| // In theory, all vectors in the active set should have the same co
rrelation C, and | | // In theory, all vectors in the active set should have the same co
rrelation C, and | |
| // the correlation of all others should not exceed this. In practic
e, we may find the | | // the correlation of all others should not exceed this. In practic
e, we may find the | |
| // maximum correlation in any variable due to tiny numerical inaccu
racies. Therefore, we | | // maximum correlation in any variable due to tiny numerical inaccu
racies. Therefore, we | |
| // determine C from the entire set of variables. | | // determine C from the entire set of variables. | |
| MultiArrayIndex cmaxIndex = enforce_positive | | MultiArrayIndex cmaxIndex = enforce_positive | |
| | | | |
| skipping to change at line 611 | | skipping to change at line 604 | |
| activeSets.push_back(typename Array1::value_type(d.columnPermutatio
n.begin(), d.columnPermutation.begin()+d.activeSetSize)); | | activeSets.push_back(typename Array1::value_type(d.columnPermutatio
n.begin(), d.columnPermutation.begin()+d.activeSetSize)); | |
| | | | |
| if(lsq_solutions != 0) | | if(lsq_solutions != 0) | |
| { | | { | |
| if(enforce_positive) | | if(enforce_positive) | |
| { | | { | |
| ArrayVector<Matrix<T> > nnresults; | | ArrayVector<Matrix<T> > nnresults; | |
| ArrayVector<ArrayVector<MultiArrayIndex> > nnactiveSets; | | ArrayVector<ArrayVector<MultiArrayIndex> > nnactiveSets; | |
| LarsData<T, C1, C2> nnd(d, d.activeSetSize); | | LarsData<T, C1, C2> nnd(d, d.activeSetSize); | |
| | | | |
|
| leastAngleRegressionMainLoop(nnd, nnactiveSets, &nnresults,
(Array3*)0, | | leastAngleRegressionMainLoop(nnd, nnactiveSets, &nnresults,
static_cast<Array3*>(0), | |
| LeastAngleRegressionOptions().
leastSquaresSolutions(false).nnlasso()); | | LeastAngleRegressionOptions().
leastSquaresSolutions(false).nnlasso()); | |
| //Matrix<T> nnlsq_solution(d.activeSetSize, 1); | | //Matrix<T> nnlsq_solution(d.activeSetSize, 1); | |
| typename Array2::value_type nnlsq_solution(Shape(d.activeSe
tSize, 1)); | | typename Array2::value_type nnlsq_solution(Shape(d.activeSe
tSize, 1)); | |
| for(unsigned int k=0; k<nnactiveSets.back().size(); ++k) | | for(unsigned int k=0; k<nnactiveSets.back().size(); ++k) | |
| { | | { | |
| nnlsq_solution(nnactiveSets.back()[k],0) = nnresults.ba
ck()[k]; | | nnlsq_solution(nnactiveSets.back()[k],0) = nnresults.ba
ck()[k]; | |
| } | | } | |
| //lsq_solutions->push_back(nnlsq_solution); | | //lsq_solutions->push_back(nnlsq_solution); | |
| lsq_solutions->push_back(typename Array3::value_type()); | | lsq_solutions->push_back(typename Array3::value_type()); | |
| lsq_solutions->back() = nnlsq_solution; | | lsq_solutions->back() = nnlsq_solution; | |
| | | | |
| skipping to change at line 691 | | skipping to change at line 684 | |
| Subarray qtbactive = d.qtb.subarray(Shape(0,0), Shape(d.activeSetSi
ze, 1)); | | Subarray qtbactive = d.qtb.subarray(Shape(0,0), Shape(d.activeSetSi
ze, 1)); | |
| Subarray next_lsq_solution_view = d.next_lsq_solution.subarray(Shap
e(0,0), Shape(d.activeSetSize, 1)); | | Subarray next_lsq_solution_view = d.next_lsq_solution.subarray(Shap
e(0,0), Shape(d.activeSetSize, 1)); | |
| linearSolveUpperTriangular(Ractive, qtbactive, next_lsq_solution_vi
ew); | | linearSolveUpperTriangular(Ractive, qtbactive, next_lsq_solution_vi
ew); | |
| | | | |
| // compute the LSQ prediction of the new active set | | // compute the LSQ prediction of the new active set | |
| d.next_lsq_prediction.init(0.0); | | d.next_lsq_prediction.init(0.0); | |
| for(MultiArrayIndex k=0; k<d.activeSetSize; ++k) | | for(MultiArrayIndex k=0; k<d.activeSetSize; ++k) | |
| d.next_lsq_prediction += next_lsq_solution_view(k,0)*columnVect
or(d.A, d.columnPermutation[k]); | | d.next_lsq_prediction += next_lsq_solution_view(k,0)*columnVect
or(d.A, d.columnPermutation[k]); | |
| } | | } | |
| | | | |
|
| return (unsigned int)currentSolutionCount; | | return static_cast<unsigned int>(currentSolutionCount); | |
| } | | } | |
| | | | |
| template <class T, class C1, class C2, class Array1, class Array2> | | template <class T, class C1, class C2, class Array1, class Array2> | |
| unsigned int | | unsigned int | |
| leastAngleRegressionImpl(MultiArrayView<2, T, C1> const & A, MultiArrayView
<2, T, C2> const &b, | | leastAngleRegressionImpl(MultiArrayView<2, T, C1> const & A, MultiArrayView
<2, T, C2> const &b, | |
| Array1 & activeSets, Array2 * lasso_solutions, Arr
ay2 * lsq_solutions, | | Array1 & activeSets, Array2 * lasso_solutions, Arr
ay2 * lsq_solutions, | |
| LeastAngleRegressionOptions const & options) | | LeastAngleRegressionOptions const & options) | |
| { | | { | |
| using namespace vigra::functor; | | using namespace vigra::functor; | |
| | | | |
| | | | |
| skipping to change at line 732 | | skipping to change at line 725 | |
| detail::qrColumnHouseholderStep(0, d.R, d.qtb); | | detail::qrColumnHouseholderStep(0, d.R, d.qtb); | |
| d.next_lsq_solution(0,0) = d.qtb(0,0) / d.R(0,0); | | d.next_lsq_solution(0,0) = d.qtb(0,0) / d.R(0,0); | |
| d.next_lsq_prediction = d.next_lsq_solution(0,0) * columnVector(A, d.co
lumnPermutation[0]); | | d.next_lsq_prediction = d.next_lsq_solution(0,0) * columnVector(A, d.co
lumnPermutation[0]); | |
| d.searchVector = d.next_lsq_solution(0,0) * columnVector(A, d.columnPer
mutation[0]); | | d.searchVector = d.next_lsq_solution(0,0) * columnVector(A, d.columnPer
mutation[0]); | |
| | | | |
| return leastAngleRegressionMainLoop(d, activeSets, lasso_solutions, lsq
_solutions, options); | | return leastAngleRegressionMainLoop(d, activeSets, lasso_solutions, lsq
_solutions, options); | |
| } | | } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
|
| /** Least Angle Regression. | | /** Least Angle Regression. | |
| | | | |
|
| <b>\#include</b> \<vigra/regression.hxx\> | | <b>\#include</b> \<vigra/regression.hxx\><br/> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
| | | | |
|
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| namespace linalg { | | namespace linalg { | |
| // compute either LASSO or least squares solutions | | // compute either LASSO or least squares solutions | |
| template <class T, class C1, class C2, class Array1, class Array2> | | template <class T, class C1, class C2, class Array1, class Arra | |
| unsigned int | | y2> | |
| leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArray | | unsigned int | |
| View<2, T, C2> const &b, | | leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiA | |
| Array1 & activeSets, Array2 & solutions, | | rrayView<2, T, C2> const &b, | |
| LeastAngleRegressionOptions const & options = | | Array1 & activeSets, Array2 & solutions, | |
| LeastAngleRegressionOptions()); | | LeastAngleRegressionOptions const & options = LeastAng | |
| | | leRegressionOptions()); | |
| // compute LASSO and least squares solutions | | | |
| template <class T, class C1, class C2, class Array1, class Array2> | | // compute LASSO and least squares solutions | |
| unsigned int | | template <class T, class C1, class C2, class Array1, class Arra | |
| leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArray | | y2> | |
| View<2, T, C2> const &b, | | unsigned int | |
| Array1 & activeSets, Array2 & lasso_solutions, | | leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiA | |
| Array2 & lsq_solutions, | | rrayView<2, T, C2> const &b, | |
| LeastAngleRegressionOptions const & options = | | Array1 & activeSets, Array2 & lasso_solutions, Array2 | |
| LeastAngleRegressionOptions()); | | & lsq_solutions, | |
| } | | LeastAngleRegressionOptions const & options = LeastAng | |
| using linalg::leastAngleRegression; | | leRegressionOptions()); | |
| } | | } | |
| \endcode | | using linalg::leastAngleRegression; | |
| | | } | |
| | | \endcode | |
| | | | |
| This function implements Least Angle Regression (LARS) as described
in | | This function implements Least Angle Regression (LARS) as described
in | |
| | | | |
| | | | |
| B.Efron, T.Hastie, I.Johnstone, and R.Tibshirani: <i>"Least Angle Re
gression"</i>, | | B.Efron, T.Hastie, I.Johnstone, and R.Tibshirani: <i>"Least Angle Re
gression"</i>, | |
| Annals of Statistics 32(2):407-499, 2004. | | Annals of Statistics 32(2):407-499, 2004. | |
| | | | |
| It is an efficient algorithm to solve the L1-regularized least squar
es (LASSO) problem | | It is an efficient algorithm to solve the L1-regularized least squar
es (LASSO) problem | |
| | | | |
| \f[ \tilde \textrm{\bf x} = \textrm{argmin} | | \f[ \tilde \textrm{\bf x} = \textrm{argmin} | |
| | | | |
| skipping to change at line 781 | | skipping to change at line 774 | |
| \f] | | \f] | |
| | | | |
| and the L1-regularized non-negative least squares (NN-LASSO) problem | | and the L1-regularized non-negative least squares (NN-LASSO) problem | |
| | | | |
| \f[ \tilde \textrm{\bf x} = \textrm{argmin} \left|\left|\textrm{\bf
A} \textrm{\bf x} - \textrm{\bf b}\right|\right|_2^2 | | \f[ \tilde \textrm{\bf x} = \textrm{argmin} \left|\left|\textrm{\bf
A} \textrm{\bf x} - \textrm{\bf b}\right|\right|_2^2 | |
| \textrm{ subject to } \left|\left|\textrm{\bf x}\right|\right|_1
\le s \textrm{ and } \textrm{\bf x}\ge \textrm{\bf 0} | | \textrm{ subject to } \left|\left|\textrm{\bf x}\right|\right|_1
\le s \textrm{ and } \textrm{\bf x}\ge \textrm{\bf 0} | |
| \f] | | \f] | |
| | | | |
| where \a A is a matrix with <tt>m</tt> rows and <tt>n</tt> columns (
often with <tt>m \< n</tt>), | | where \a A is a matrix with <tt>m</tt> rows and <tt>n</tt> columns (
often with <tt>m \< n</tt>), | |
| \a b a vector of length <tt>m</tt>, and a regularization parameter s
\>= 0.0. | | \a b a vector of length <tt>m</tt>, and a regularization parameter s
\>= 0.0. | |
|
| L1-regularization has the desirable effect that it causes the soluti | | L1-regularization has the desirable effect that it causes the soluti | |
| on \a x to be sparse, i.e. only | | on <b>x</b> to be sparse, i.e. only | |
| the most important variables (called the <em>active set</em>) have n | | the most important elements in <b>x</b> (called the <em>active set</ | |
| on-zero values. The | | em>) have non-zero values. The | |
| key insight of the LARS algorithm is the following: When the solutio | | key insight of the LARS algorithm is the following: When the solutio | |
| n vector is considered | | n vector <b>x</b> is considered | |
| as a function of the regularization parameter s, then <b>x</b>(s) is
a piecewise | | as a function of the regularization parameter s, then <b>x</b>(s) is
a piecewise | |
|
| linear function, i.e. a polyline in n-dimensional space. The knots o | | linear function, i.e. a polyline in n-dimensional space. The knots o | |
| f the polyline | | f the polyline <b>x</b>(s) | |
| occur precisely at those values of s where one variable enters or le | | are located precisely at those values of s where one variable enters | |
| aves the active set, | | or leaves the active set | |
| and can be efficiently computed. | | and can be efficiently computed. | |
| | | | |
| Therefore, leastAngleRegression() returns the entire solution path a
s a sequence of knot points, starting | | Therefore, leastAngleRegression() returns the entire solution path a
s a sequence of knot points, starting | |
| at \f$\textrm{\bf x}(s=0)\f$ (where the only feasible solution is ob
viously <b>x</b> = 0) and ending at | | at \f$\textrm{\bf x}(s=0)\f$ (where the only feasible solution is ob
viously <b>x</b> = 0) and ending at | |
| \f$\textrm{\bf x}(s=\infty)\f$ (where the solution becomes the ordin
ary least squares solution). Actually, | | \f$\textrm{\bf x}(s=\infty)\f$ (where the solution becomes the ordin
ary least squares solution). Actually, | |
| the initial null solution is not explicitly returned, i.e. the seque
nce starts at the first non-zero | | the initial null solution is not explicitly returned, i.e. the seque
nce starts at the first non-zero | |
| solution with one variable in the active set. The function leastAngl
eRegression() returns the number | | solution with one variable in the active set. The function leastAngl
eRegression() returns the number | |
|
| of solutions( i.e. knot points) computed. | | of solutions (i.e. knot points) computed. | |
| | | | |
| The sequences of active sets and corresponding variable weights are
returned in \a activeSets and | | The sequences of active sets and corresponding variable weights are
returned in \a activeSets and | |
| \a solutions respectively. That is, <tt>activeSets[i]</tt> is an \re
f vigra::ArrayVector "ArrayVector\<int\>" | | \a solutions respectively. That is, <tt>activeSets[i]</tt> is an \re
f vigra::ArrayVector "ArrayVector\<int\>" | |
| containing the indices of the variables that are active at the i-th
knot, and <tt>solutions</tt> is a | | containing the indices of the variables that are active at the i-th
knot, and <tt>solutions</tt> is a | |
| \ref vigra::linalg::Matrix "Matrix\<T\>" containing the weights of t
hose variables, in the same order (see | | \ref vigra::linalg::Matrix "Matrix\<T\>" containing the weights of t
hose variables, in the same order (see | |
| example below). Variables not contained in <tt>activeSets[i]</tt> ar
e zero at this solution. | | example below). Variables not contained in <tt>activeSets[i]</tt> ar
e zero at this solution. | |
| | | | |
| The behavior of the algorithm can be adapted by \ref vigra::linalg::
LeastAngleRegressionOptions | | The behavior of the algorithm can be adapted by \ref vigra::linalg::
LeastAngleRegressionOptions | |
| "LeastAngleRegressionOptions": | | "LeastAngleRegressionOptions": | |
| <DL> | | <DL> | |
| | | | |
| skipping to change at line 884 | | skipping to change at line 877 | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> unsigned int leastAngleRegressio
n) | | doxygen_overloaded_function(template <...> unsigned int leastAngleRegressio
n) | |
| | | | |
| template <class T, class C1, class C2, class Array1, class Array2> | | template <class T, class C1, class C2, class Array1, class Array2> | |
| inline unsigned int | | inline unsigned int | |
| leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArrayView<2,
T, C2> const &b, | | leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArrayView<2,
T, C2> const &b, | |
| Array1 & activeSets, Array2 & solutions, | | Array1 & activeSets, Array2 & solutions, | |
| LeastAngleRegressionOptions const & options = LeastAng
leRegressionOptions()) | | LeastAngleRegressionOptions const & options = LeastAng
leRegressionOptions()) | |
| { | | { | |
| if(options.least_squares_solutions) | | if(options.least_squares_solutions) | |
|
| return detail::leastAngleRegressionImpl(A, b, activeSets, (Array2*)
0, &solutions, options); | | return detail::leastAngleRegressionImpl(A, b, activeSets, static_ca
st<Array2*>(0), &solutions, options); | |
| else | | else | |
|
| return detail::leastAngleRegressionImpl(A, b, activeSets, &solution
s, (Array2*)0, options); | | return detail::leastAngleRegressionImpl(A, b, activeSets, &solution
s, static_cast<Array2*>(0), options); | |
| } | | } | |
| | | | |
| template <class T, class C1, class C2, class Array1, class Array2> | | template <class T, class C1, class C2, class Array1, class Array2> | |
| inline unsigned int | | inline unsigned int | |
| leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArrayView<2,
T, C2> const &b, | | leastAngleRegression(MultiArrayView<2, T, C1> const & A, MultiArrayView<2,
T, C2> const &b, | |
| Array1 & activeSets, Array2 & lasso_solutions, Array2
& lsq_solutions, | | Array1 & activeSets, Array2 & lasso_solutions, Array2
& lsq_solutions, | |
| LeastAngleRegressionOptions const & options = LeastAng
leRegressionOptions()) | | LeastAngleRegressionOptions const & options = LeastAng
leRegressionOptions()) | |
| { | | { | |
| return detail::leastAngleRegressionImpl(A, b, activeSets, &lasso_soluti
ons, &lsq_solutions, options); | | return detail::leastAngleRegressionImpl(A, b, activeSets, &lasso_soluti
ons, &lsq_solutions, options); | |
| } | | } | |
| | | | |
|
| /** Non-negative Least Squares Regression. | | /** Non-negative Least Squares Regression. | |
| | | | |
|
| Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wit | | Given a matrix \a A with <tt>m</tt> rows and <tt>n</tt> columns (wi | |
| h <tt>m \>= n</tt>), | | th <tt>m \>= n</tt>), | |
| and a column vector \a b of length <tt>m</tt> rows, this function co | | and a column vector \a b of length <tt>m</tt> rows, this function c | |
| mputes | | omputes | |
| a column vector \a x of length <tt>n</tt> with <b>non-negative entri | | a column vector \a x of length <tt>n</tt> with <b>non-negative entr | |
| es</b> that solves the optimization problem | | ies</b> that solves the optimization problem | |
| | | | |
|
| \f[ \tilde \textrm{\bf x} = \textrm{argmin} | | \f[ \tilde \textrm{\bf x} = \textrm{argmin} | |
| \left|\left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\righ | | \left|\left|\textrm{\bf A} \textrm{\bf x} - \textrm{\bf b}\rig | |
| t|\right|_2^2 | | ht|\right|_2^2 | |
| \textrm{ subject to } \textrm{\bf x} \ge \textrm{\bf 0} | | \textrm{ subject to } \textrm{\bf x} \ge \textrm{\bf 0} | |
| \f] | | \f] | |
| | | | |
|
| Both \a b and \a x must be column vectors (i.e. matrices with <tt>1< | | Both \a b and \a x must be column vectors (i.e. matrices with <tt>1 | |
| /tt> column). | | </tt> column). | |
| Note that all matrices must already have the correct shape. The solu | | Note that all matrices must already have the correct shape. The sol | |
| tion is computed by means | | ution is computed by means | |
| of \ref leastAngleRegression() with non-negativity constraint. | | of \ref leastAngleRegression() with non-negativity constraint. | |
| | | | |
|
| <b>\#include</b> \<vigra/regression.hxx\> | | <b>\#include</b> \<vigra/regression.hxx\><br/> | |
| Namespaces: vigra and vigra::linalg | | Namespaces: vigra and vigra::linalg | |
|
| */ | | | |
| | | <b> Declarations:</b> | |
| | | | |
| | | \code | |
| | | namespace vigra { | |
| | | namespace linalg { | |
| | | template <class T, class C1, class C2, class C3> | |
| | | void | |
| | | nonnegativeLeastSquares(MultiArrayView<2, T, C1> const & A, | |
| | | MultiArrayView<2, T, C2> const &b, | |
| | | MultiArrayView<2, T, C3> &x); | |
| | | } | |
| | | using linalg::nonnegativeLeastSquares; | |
| | | } | |
| | | \endcode | |
| | | */ | |
| | | doxygen_overloaded_function(template <...> unsigned int nonnegativeLeastSqu | |
| | | ares) | |
| | | | |
| template <class T, class C1, class C2, class C3> | | template <class T, class C1, class C2, class C3> | |
| inline void | | inline void | |
| nonnegativeLeastSquares(MultiArrayView<2, T, C1> const & A, | | nonnegativeLeastSquares(MultiArrayView<2, T, C1> const & A, | |
| MultiArrayView<2, T, C2> const &b, MultiArrayView<2
, T, C3> &x) | | MultiArrayView<2, T, C2> const &b, MultiArrayView<2
, T, C3> &x) | |
| { | | { | |
| vigra_precondition(columnCount(A) == rowCount(x) && rowCount(A) == rowC
ount(b), | | vigra_precondition(columnCount(A) == rowCount(x) && rowCount(A) == rowC
ount(b), | |
| "nonnegativeLeastSquares(): Matrix shape mismatch."); | | "nonnegativeLeastSquares(): Matrix shape mismatch."); | |
| vigra_precondition(columnCount(b) == 1 && columnCount(x) == 1, | | vigra_precondition(columnCount(b) == 1 && columnCount(x) == 1, | |
| "nonnegativeLeastSquares(): RHS and solution must be vectors (i.e.
columnCount == 1)."); | | "nonnegativeLeastSquares(): RHS and solution must be vectors (i.e.
columnCount == 1)."); | |
| | | | |
| | | | |
| skipping to change at line 950 | | skipping to change at line 960 | |
| | | | |
| using linalg::leastSquares; | | using linalg::leastSquares; | |
| using linalg::weightedLeastSquares; | | using linalg::weightedLeastSquares; | |
| using linalg::ridgeRegression; | | using linalg::ridgeRegression; | |
| using linalg::weightedRidgeRegression; | | using linalg::weightedRidgeRegression; | |
| using linalg::ridgeRegressionSeries; | | using linalg::ridgeRegressionSeries; | |
| using linalg::nonnegativeLeastSquares; | | using linalg::nonnegativeLeastSquares; | |
| using linalg::leastAngleRegression; | | using linalg::leastAngleRegression; | |
| using linalg::LeastAngleRegressionOptions; | | using linalg::LeastAngleRegressionOptions; | |
| | | | |
|
| | | namespace detail { | |
| | | | |
| | | template <class T, class S> | |
| | | inline T | |
| | | getRow(MultiArrayView<1, T, S> const & a, MultiArrayIndex i) | |
| | | { | |
| | | return a(i); | |
| | | } | |
| | | | |
| | | template <class T, class S> | |
| | | inline MultiArrayView<1, T> | |
| | | getRow(MultiArrayView<2, T, S> const & a, MultiArrayIndex i) | |
| | | { | |
| | | return a.bindInner(i); | |
| | | } | |
| | | | |
| | | } // namespace detail | |
| | | | |
| | | /** \addtogroup Optimization | |
| | | */ | |
| | | //@{ | |
| | | | |
| | | /** \brief Pass options to nonlinearLeastSquares(). | |
| | | | |
| | | <b>\#include</b> \<vigra/regression.hxx\> | |
| | | Namespace: vigra | |
| | | */ | |
| | | class NonlinearLSQOptions | |
| | | { | |
| | | public: | |
| | | | |
| | | double epsilon, lambda, tau; | |
| | | int max_iter; | |
| | | | |
| | | /** \brief Initialize options with default values. | |
| | | */ | |
| | | NonlinearLSQOptions() | |
| | | : epsilon(0.0), | |
| | | lambda(0.1), | |
| | | tau(1.4), | |
| | | max_iter(50) | |
| | | {} | |
| | | | |
| | | /** \brief Set minimum relative improvement in residual. | |
| | | | |
| | | The algorithm stops when the relative improvement in residuals | |
| | | between consecutive iterations is less than this value. | |
| | | | |
| | | Default: 0 (i.e. choose tolerance automatically, will be 10*eps | |
| | | ilon of the numeric type) | |
| | | */ | |
| | | NonlinearLSQOptions & tolerance(double eps) | |
| | | { | |
| | | epsilon = eps; | |
| | | return *this; | |
| | | } | |
| | | | |
| | | /** \brief Set maximum number of iterations. | |
| | | | |
| | | Default: 50 | |
| | | */ | |
| | | NonlinearLSQOptions & maxIterations(int iter) | |
| | | { | |
| | | max_iter = iter; | |
| | | return *this; | |
| | | } | |
| | | | |
| | | /** \brief Set damping parameters for Levenberg-Marquardt algorithm | |
| | | . | |
| | | | |
| | | \a lambda determines by how much the diagonal is emphasized, an | |
| | | d \a v is | |
| | | the factor by which lambda will be increased if more damping is | |
| | | needed | |
| | | for convergence | |
| | | (see <a href="http://en.wikipedia.org/wiki/Levenberg%E2%80%93Ma | |
| | | rquardt_algorithm">Wikipedia</a> | |
| | | for more explanations). | |
| | | | |
| | | Default: lambda = 0.1, v = 1.4 | |
| | | */ | |
| | | NonlinearLSQOptions & dampingParamters(double lambda, double v) | |
| | | { | |
| | | vigra_precondition(lambda > 0.0 && v > 0.0, | |
| | | "NonlinearLSQOptions::dampingParamters(): parameters must be po | |
| | | sitive."); | |
| | | this->lambda = lambda; | |
| | | tau = v; | |
| | | return *this; | |
| | | } | |
| | | }; | |
| | | | |
| | | template <unsigned int D, class T, class S1, class S2, | |
| | | class U, int N, | |
| | | class Functor> | |
| | | T | |
| | | nonlinearLeastSquaresImpl(MultiArrayView<D, T, S1> const & features, | |
| | | MultiArrayView<1, T, S2> const & response, | |
| | | TinyVector<U, N> & p, | |
| | | Functor model, | |
| | | NonlinearLSQOptions const & options) | |
| | | { | |
| | | vigra_precondition(features.shape(0) == response.shape(0), | |
| | | "nonlinearLeastSquares(): shape mismatch between fea | |
| | | tures and response."); | |
| | | | |
| | | double t = options.tau, l = options.lambda; // initial damping paramet | |
| | | ers | |
| | | | |
| | | double epsilonT = NumericTraits<T>::epsilon()*10.0, | |
| | | epsilonU = NumericTraits<U>::epsilon()*10.0, | |
| | | epsilon = options.epsilon <= 0.0 | |
| | | ? std::max(epsilonT, epsilonU) | |
| | | : options.epsilon; | |
| | | | |
| | | linalg::Matrix<T> jj(N,N); // outer product of the Jacobian | |
| | | TinyVector<U, N> jr, dp; | |
| | | | |
| | | T residual = 0.0; | |
| | | bool didStep = true; | |
| | | | |
| | | for(int iter=0; iter<options.max_iter; ++iter) | |
| | | { | |
| | | if(didStep) | |
| | | { | |
| | | // update the residual and Jacobian | |
| | | residual = 0.0; | |
| | | jr = 0.0; | |
| | | jj = 0.0; | |
| | | | |
| | | for(int i=0; i<features.shape(0); ++i) | |
| | | { | |
| | | autodiff::DualVector<U, N> res = model(detail::getRow(featu | |
| | | res, i), autodiff::dualMatrix(p)); | |
| | | | |
| | | T r = response(i) - res.v; | |
| | | jr += r * res.d; | |
| | | jj += outer(res.d); | |
| | | residual += sq(r); | |
| | | } | |
| | | } | |
| | | | |
| | | // perform a damped gradient step | |
| | | linalg::Matrix<T> djj(jj); | |
| | | djj.diagonal() *= 1.0 + l; | |
| | | linearSolve(djj, jr, dp); | |
| | | | |
| | | TinyVector<U, N> p_new = p + dp; | |
| | | | |
| | | // compute the new residual | |
| | | T residual_new = 0.0; | |
| | | for(int i=0; i<features.shape(0); ++i) | |
| | | { | |
| | | residual_new += sq(response(i) - model(detail::getRow(features, | |
| | | i), p_new)); | |
| | | } | |
| | | | |
| | | if(residual_new < residual) | |
| | | { | |
| | | // accept the step | |
| | | p = p_new; | |
| | | if(std::abs((residual - residual_new) / residual) < epsilon) | |
| | | return residual_new; | |
| | | // try less damping in the next iteration | |
| | | l /= t; | |
| | | didStep = true; | |
| | | } | |
| | | else | |
| | | { | |
| | | // reject the step und use more damping in the next iteration | |
| | | l *= t; | |
| | | didStep = false; | |
| | | } | |
| | | } | |
| | | | |
| | | return residual; | |
| | | } | |
| | | | |
| | | /********************************************************/ | |
| | | /* */ | |
| | | /* nonlinearLeastSquares */ | |
| | | /* */ | |
| | | /********************************************************/ | |
| | | | |
| | | /** \brief Fit a non-linear model to given data by minimizing least squares | |
| | | loss. | |
| | | | |
| | | <b> Declarations:</b> | |
| | | | |
| | | \code | |
| | | namespace vigra { | |
| | | // variant 1: optimize a univariate model ('x' is a 1D array of sca | |
| | | lar data points) | |
| | | template <class T, class S1, class S2, | |
| | | class U, int N, | |
| | | class Functor> | |
| | | T | |
| | | nonlinearLeastSquares(MultiArrayView<1, T, S1> const & x, | |
| | | MultiArrayView<1, T, S2> const & y, | |
| | | TinyVector<U, N> & model_parameters, | |
| | | Functor model, | |
| | | NonlinearLSQOptions const & options = Nonline | |
| | | arLSQOptions()); | |
| | | | |
| | | // variant 2: optimize a multivariate model ('x' is a 2D array of v | |
| | | ector-valued data points) | |
| | | template <class T, class S1, class S2, | |
| | | class U, int N, | |
| | | class Functor> | |
| | | T | |
| | | nonlinearLeastSquares(MultiArrayView<2, T, S1> const & x, | |
| | | MultiArrayView<1, T, S2> const & y, | |
| | | TinyVector<U, N> & model_parameters, | |
| | | Functor model, | |
| | | NonlinearLSQOptions const & options = Nonline | |
| | | arLSQOptions()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | This function implements the | |
| | | <a href="http://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algor | |
| | | ithm">Levenberg-Marquardt algorithm</a> | |
| | | to fit a non-linear model to given data. The model depends on a vector | |
| | | of | |
| | | parameters <b>p</b> which are to be choosen such that the least-squares | |
| | | residual | |
| | | between the data and the model's predictions is minimized according to | |
| | | the objective function: | |
| | | | |
| | | \f[ \tilde \textrm{\bf p} = \textrm{argmin}_{\textrm{\bf p}} \sum_i \le | |
| | | ft( y_i - f(\textrm{\bf x}_i; \textrm{\bf p}) \right)^2 | |
| | | \f] | |
| | | | |
| | | where \f$f(\textrm{\bf x}; \textrm{\bf p})\f$ is the model to be optimi | |
| | | zed | |
| | | (with arguments \f$\textrm{\bf x}\f$ and parameters \f$\textrm{\bf p}\f | |
| | | $), and | |
| | | \f$(\textrm{\bf x}_i; y_i)\f$ are the feature/response pairs of the giv | |
| | | en data. | |
| | | Since the model is non-linear (otherwise, you should use ordinary \ref | |
| | | leastSquares()), | |
| | | it must be linearized in terms of a first-order Taylor expansion, and t | |
| | | he optimal | |
| | | parameters <b>p</b> have to be determined iteratively. In order for the | |
| | | iterations to | |
| | | converge to the desired solution, a good initial guess on <b>p</b> is r | |
| | | equired. | |
| | | | |
| | | The model must be specified by a functor which takes one of the followi | |
| | | ng forms: | |
| | | \code | |
| | | typedef double DataType; // type of your data samples, may be any num | |
| | | eric type | |
| | | static const int N = ...; // number of model parameters | |
| | | | |
| | | // variant 1: the features x are scalars | |
| | | struct UnivariateModel | |
| | | { | |
| | | template <class T> | |
| | | T operator()(DataType x, TinyVector<T, N> const & p) const { ... } | |
| | | }; | |
| | | | |
| | | // variant 2: the features x are vectors | |
| | | struct MultivariateModel | |
| | | { | |
| | | template <class T> | |
| | | T operator()(MultiArrayView<1, DataType> const & x, TinyVector<T, N | |
| | | > const & p) const { ... } | |
| | | }; | |
| | | \endcode | |
| | | Each call to the functor's <tt>operator()</tt> computes the model's pre | |
| | | diction for a single data | |
| | | point. The current model parameters are specified in a TinyVector of ap | |
| | | propriate length. | |
| | | The type <tt>T</tt> must be templated: normally, it is the same as <tt> | |
| | | DataType</tt>, but | |
| | | the nonlinearLeastSquares() function will temporarily replace it with a | |
| | | special number type | |
| | | that supports <a href="http://en.wikipedia.org/wiki/Automatic_different | |
| | | iation">automatic differentiation</a> | |
| | | (see \ref vigra::autodiff::DualVector). In this way, the derivatives ne | |
| | | eded in the model's Taylor | |
| | | expansion can be computed automatically. | |
| | | | |
| | | When the model is univariate (has a single scalar argument), the sample | |
| | | s must be passed to | |
| | | nonlinearLeastSquares() in a pair 'x', 'y' of 1D <tt>MultiArrayView</tt | |
| | | >s (variant 1). | |
| | | When the model is multivariate (has a vector-valued argument), the 'x' | |
| | | input must | |
| | | be a 2D <tt>MultiArrayView</tt> (variant 2) whose rows represent a sing | |
| | | le data sample | |
| | | (i.e. the number of columns corresponds to the length of the model's ar | |
| | | gument vector). | |
| | | The number of rows in 'x' defines the number of data samples and must m | |
| | | atch the length | |
| | | of array 'y'. | |
| | | | |
| | | The <tt>TinyVector</tt> 'model_parameters' holds the initial guess for | |
| | | the model parameters and | |
| | | will be overwritten by the optimal values found by the algorithm. The a | |
| | | lgorithm's internal behavior | |
| | | can be controlled by customizing the option object \ref vigra::Nonlinea | |
| | | rLSQOptions. | |
| | | | |
| | | The function returns the residual sum of squared errors of the final so | |
| | | lution. | |
| | | | |
| | | <b> Usage:</b> | |
| | | | |
| | | <b>\#include</b> \<vigra/regression.hxx\><br> | |
| | | Namespace: vigra | |
| | | | |
| | | Suppose that we want to fit a centered Gaussian function of the form | |
| | | \f[ f(x ; a, s, b) = a \exp\left(-\frac{x^2}{2 s^2}\right) + b \f] | |
| | | to noisy data \f$(x_i, y_i)\f$, i.e. we want to find parameters a, s, b | |
| | | such that | |
| | | the residual \f$\sum_i \left(y_i - f(x_i; a,s,b)\right)^2\f$ is minimiz | |
| | | ed. | |
| | | The model parameters are placed in a <tt>TinyVector<T, 3></tt> <b>p</b> | |
| | | according to the rules<br/> | |
| | | <tt>p[0] <=> a</tt>, <tt>p[1] <=> s</tt> and <tt>p[2] <=> b</tt>.<br/> | |
| | | The following | |
| | | functor computes the model's prediction for a single data point <tt>x</ | |
| | | tt>: | |
| | | \code | |
| | | struct GaussianModel | |
| | | { | |
| | | template <class T> | |
| | | T operator()(double x, TinyVector<T, 3> const & p) const | |
| | | { | |
| | | return p[0] * exp(-0.5 * sq(x / p[1])) + p[2]; | |
| | | } | |
| | | }; | |
| | | \endcode | |
| | | Now we can find optimal values for the parameters like this: | |
| | | \code | |
| | | int size = ...; // number of data points | |
| | | MultiArray<1, double> x(size), y(size); | |
| | | ... // fill the data arrays | |
| | | | |
| | | TinyVector<double, 3> p(2.0, 1.0, 0.5); // your initial guess of the p | |
| | | arameters | |
| | | // (will be overwritten with t | |
| | | he optimal values) | |
| | | double residual = nonlinearLeastSquares(x, y, p, GaussianModel()); | |
| | | | |
| | | std::cout << "Model parameters: a=" << p[0] << ", s=" << p[1] << ", b=" | |
| | | << p[2] << " (residual: " << residual << ")\n"; | |
| | | \endcode | |
| | | */ | |
| | | doxygen_overloaded_function(template <...> void nonlinearLeastSquares) | |
| | | | |
| | | template <class T, class S1, class S2, | |
| | | class U, int N, | |
| | | class Functor> | |
| | | inline T | |
| | | nonlinearLeastSquares(MultiArrayView<1, T, S1> const & features, | |
| | | MultiArrayView<1, T, S2> const & response, | |
| | | TinyVector<U, N> & p, | |
| | | Functor model, | |
| | | NonlinearLSQOptions const & options = NonlinearLSQOpt | |
| | | ions()) | |
| | | { | |
| | | return nonlinearLeastSquaresImpl(features, response, p, model, options) | |
| | | ; | |
| | | } | |
| | | | |
| | | template <class T, class S1, class S2, | |
| | | class U, int N, | |
| | | class Functor> | |
| | | inline T | |
| | | nonlinearLeastSquares(MultiArrayView<2, T, S1> const & features, | |
| | | MultiArrayView<1, T, S2> const & response, | |
| | | TinyVector<U, N> & p, | |
| | | Functor model, | |
| | | NonlinearLSQOptions const & options = NonlinearLSQOpt | |
| | | ions()) | |
| | | { | |
| | | return nonlinearLeastSquaresImpl(features, response, p, model, options) | |
| | | ; | |
| | | } | |
| | | | |
| | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_REGRESSION_HXX | | #endif // VIGRA_REGRESSION_HXX | |
| | | | |
End of changes. 32 change blocks. |
| 89 lines changed or deleted | | 487 lines changed or added | |
|
| resampling_convolution.hxx | | resampling_convolution.hxx | |
| | | | |
| skipping to change at line 47 | | skipping to change at line 47 | |
| #define VIGRA_RESAMPLING_CONVOLUTION_HXX | | #define VIGRA_RESAMPLING_CONVOLUTION_HXX | |
| | | | |
| #include <cmath> | | #include <cmath> | |
| #include "stdimage.hxx" | | #include "stdimage.hxx" | |
| #include "array_vector.hxx" | | #include "array_vector.hxx" | |
| #include "rational.hxx" | | #include "rational.hxx" | |
| #include "functortraits.hxx" | | #include "functortraits.hxx" | |
| #include "functorexpression.hxx" | | #include "functorexpression.hxx" | |
| #include "transformimage.hxx" | | #include "transformimage.hxx" | |
| #include "imagecontainer.hxx" | | #include "imagecontainer.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| namespace resampling_detail | | namespace resampling_detail | |
| { | | { | |
| | | | |
| struct MapTargetToSourceCoordinate | | struct MapTargetToSourceCoordinate | |
| { | | { | |
| MapTargetToSourceCoordinate(Rational<int> const & samplingRatio, | | MapTargetToSourceCoordinate(Rational<int> const & samplingRatio, | |
| Rational<int> const & offset) | | Rational<int> const & offset) | |
| | | | |
| skipping to change at line 250 | | skipping to change at line 251 | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Performs a 1-dimensional resampling convolution of the source si
gnal using the given | | /** \brief Performs a 1-dimensional resampling convolution of the source si
gnal using the given | |
| set of kernels. | | set of kernels. | |
| | | | |
| This function is mainly used internally: It is called for each dimensio
n of a | | This function is mainly used internally: It is called for each dimensio
n of a | |
| higher dimensional array in order to perform a separable resize operati
on. | | higher dimensional array in order to perform a separable resize operati
on. | |
| | | | |
| <b> Declaration:</b> | | <b> Declaration:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/resampling_convolution.hxx\> | | <b>\#include</b> \<vigra/resampling_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIter, class SrcAcc, | | template <class SrcIter, class SrcAcc, | |
| class DestIter, class DestAcc, | | class DestIter, class DestAcc, | |
| class KernelArray, | | class KernelArray, | |
| class Functor> | | class Functor> | |
| void | | void | |
| resamplingConvolveLine(SrcIter s, SrcIter send, SrcAcc src, | | resamplingConvolveLine(SrcIter s, SrcIter send, SrcAcc src, | |
| DestIter d, DestIter dend, DestAcc dest, | | DestIter d, DestIter dend, DestAcc dest, | |
| | | | |
| skipping to change at line 357 | | skipping to change at line 359 | |
| void | | void | |
| createResamplingKernels(Kernel const & kernel, | | createResamplingKernels(Kernel const & kernel, | |
| MapCoordinate const & mapCoordinate, KernelArray & kernels) | | MapCoordinate const & mapCoordinate, KernelArray & kernels) | |
| { | | { | |
| for(unsigned int idest = 0; idest < kernels.size(); ++idest) | | for(unsigned int idest = 0; idest < kernels.size(); ++idest) | |
| { | | { | |
| int isrc = mapCoordinate(idest); | | int isrc = mapCoordinate(idest); | |
| double idsrc = mapCoordinate.toDouble(idest); | | double idsrc = mapCoordinate.toDouble(idest); | |
| double offset = idsrc - isrc; | | double offset = idsrc - isrc; | |
| double radius = kernel.radius(); | | double radius = kernel.radius(); | |
|
| int left = int(ceil(-radius - offset)); | | int left = std::min(0, int(ceil(-radius - offset))); | |
| int right = int(floor(radius - offset)); | | int right = std::max(0, int(floor(radius - offset))); | |
| kernels[idest].initExplicitly(left, right); | | kernels[idest].initExplicitly(left, right); | |
| | | | |
| double x = left + offset; | | double x = left + offset; | |
| for(int i = left; i <= right; ++i, ++x) | | for(int i = left; i <= right; ++i, ++x) | |
| kernels[idest][i] = kernel(x); | | kernels[idest][i] = kernel(x); | |
| kernels[idest].normalize(1.0, kernel.derivativeOrder(), offset); | | kernels[idest].normalize(1.0, kernel.derivativeOrder(), offset); | |
| } | | } | |
| } | | } | |
| | | | |
| /** \brief Apply a resampling filter in the x-direction. | | /** \brief Apply a resampling filter in the x-direction. | |
| | | | |
| skipping to change at line 389 | | skipping to change at line 391 | |
| | | | |
| The <tt>samplingRatio</tt> and <tt>offset</tt> must be given as \ref vi
gra::Rational | | The <tt>samplingRatio</tt> and <tt>offset</tt> must be given as \ref vi
gra::Rational | |
| in order to avoid rounding errors in this transformation. It is require
d that for all | | in order to avoid rounding errors in this transformation. It is require
d that for all | |
| pixels of the target image, <tt>xsource</tt> remains within the range o
f the source | | pixels of the target image, <tt>xsource</tt> remains within the range o
f the source | |
| image (i.e. <tt>0 <= xsource <= sourceWidth-1</tt>. Since <tt>xsource</
tt> is | | image (i.e. <tt>0 <= xsource <= sourceWidth-1</tt>. Since <tt>xsource</
tt> is | |
| in general not an integer, the <tt>kernel</tt> must be a functor that c
an be accessed at | | in general not an integer, the <tt>kernel</tt> must be a functor that c
an be accessed at | |
| arbitrary (<tt>double</tt>) coordinates. It must also provide a member
function <tt>radius()</tt> | | arbitrary (<tt>double</tt>) coordinates. It must also provide a member
function <tt>radius()</tt> | |
| which specifies the support (non-zero interval) of the kernel. VIGRA al
ready | | which specifies the support (non-zero interval) of the kernel. VIGRA al
ready | |
| provides a number of suitable functors, e.g. \ref vigra::Gaussian, \ref
vigra::BSpline | | provides a number of suitable functors, e.g. \ref vigra::Gaussian, \ref
vigra::BSpline | |
| \ref vigra::CatmullRomSpline, and \ref vigra::CoscotFunction. The funct
ion | | \ref vigra::CatmullRomSpline, and \ref vigra::CoscotFunction. The funct
ion | |
|
| \ref resizeImageSplineInterpolation() is implemented by means resamplin
gConvolveX() and | | \ref resizeImageSplineInterpolation() is implemented by means of resamp
lingConvolveX() and | |
| resamplingConvolveY(). | | resamplingConvolveY(). | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Kernel> | |
| | | void | |
| | | resamplingConvolveX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel const & kernel, | |
| | | Rational<int> const & samplingRatio, Rational<i | |
| | | nt> const & offset); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{resamplingConvolveX} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIter, class SrcAcc, | | template <class SrcIter, class SrcAcc, | |
| class DestIter, class DestAcc, | | class DestIter, class DestAcc, | |
| class Kernel> | | class Kernel> | |
| void | | void | |
| resamplingConvolveX(SrcIter sul, SrcIter slr, SrcAcc src, | | resamplingConvolveX(SrcIter sul, SrcIter slr, SrcAcc src, | |
| DestIter dul, DestIter dlr, DestAcc dest, | | DestIter dul, DestIter dlr, DestAcc dest, | |
| Kernel const & kernel, | | Kernel const & kernel, | |
| Rational<int> const & samplingRatio, Rational<i
nt> const & offset); | | Rational<int> const & samplingRatio, Rational<i
nt> const & offset); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIter, class SrcAcc, | | template <class SrcIter, class SrcAcc, | |
| class DestIter, class DestAcc, | | class DestIter, class DestAcc, | |
| class Kernel> | | class Kernel> | |
| void | | void | |
| resamplingConvolveX(triple<SrcIter, SrcIter, SrcAcc> src, | | resamplingConvolveX(triple<SrcIter, SrcIter, SrcAcc> src, | |
| triple<DestIter, DestIter, DestAcc> dest, | | triple<DestIter, DestIter, DestAcc> dest, | |
| Kernel const & kernel, | | Kernel const & kernel, | |
| Rational<int> const & samplingRatio, Rational<i
nt> const & offset); | | Rational<int> const & samplingRatio, Rational<i
nt> const & offset); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/resampling_convolution.hxx\> | | <b>\#include</b> \<vigra/resampling_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| Rational<int> ratio(2), offset(0); | | Rational<int> ratio(2), offset(0); | |
| | | | |
|
| | | MultiArray<2, float> src(w,h), | |
| | | dest(rational_cast<int>(ratio*w), h); | |
| | | | |
| | | float sigma = 2.0; | |
| | | Gaussian<float> smooth(sigma); | |
| | | ... | |
| | | | |
| | | // simultaneously enlarge and smooth source image | |
| | | resamplingConvolveX(src, dest, | |
| | | smooth, ratio, offset); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{resamplingConvolveX} | |
| | | \code | |
| | | Rational<int> ratio(2), offset(0); | |
| | | | |
| FImage src(w,h), | | FImage src(w,h), | |
| dest(rational_cast<int>(ratio*w), h); | | dest(rational_cast<int>(ratio*w), h); | |
| | | | |
| float sigma = 2.0; | | float sigma = 2.0; | |
| Gaussian<float> smooth(sigma); | | Gaussian<float> smooth(sigma); | |
| ... | | ... | |
| | | | |
| // simultaneously enlarge and smooth source image | | // simultaneously enlarge and smooth source image | |
| resamplingConvolveX(srcImageRange(src), destImageRange(dest), | | resamplingConvolveX(srcImageRange(src), destImageRange(dest), | |
| smooth, ratio, offset); | | smooth, ratio, offset); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| Kernel kernel; | | Kernel kernel; | |
| int kernelRadius = kernel.radius(); | | int kernelRadius = kernel.radius(); | |
| double x = ...; // must be <= radius() | | double x = ...; // must be <= radius() | |
| double value = kernel(x); | | double value = kernel(x); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void resamplingConvolveX) | | doxygen_overloaded_function(template <...> void resamplingConvolveX) | |
| | | | |
| template <class SrcIter, class SrcAcc, | | template <class SrcIter, class SrcAcc, | |
| class DestIter, class DestAcc, | | class DestIter, class DestAcc, | |
| class Kernel> | | class Kernel> | |
| void | | void | |
| resamplingConvolveX(SrcIter sul, SrcIter slr, SrcAcc src, | | resamplingConvolveX(SrcIter sul, SrcIter slr, SrcAcc src, | |
| DestIter dul, DestIter dlr, DestAcc dest, | | DestIter dul, DestIter dlr, DestAcc dest, | |
| Kernel const & kernel, | | Kernel const & kernel, | |
| | | | |
| skipping to change at line 499 | | skipping to change at line 532 | |
| resamplingConvolveX(triple<SrcIter, SrcIter, SrcAcc> src, | | resamplingConvolveX(triple<SrcIter, SrcIter, SrcAcc> src, | |
| triple<DestIter, DestIter, DestAcc> dest, | | triple<DestIter, DestIter, DestAcc> dest, | |
| Kernel const & kernel, | | Kernel const & kernel, | |
| Rational<int> const & samplingRatio, Rational<int> cons
t & offset) | | Rational<int> const & samplingRatio, Rational<int> cons
t & offset) | |
| { | | { | |
| resamplingConvolveX(src.first, src.second, src.third, | | resamplingConvolveX(src.first, src.second, src.third, | |
| dest.first, dest.second, dest.third, | | dest.first, dest.second, dest.third, | |
| kernel, samplingRatio, offset); | | kernel, samplingRatio, offset); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Kernel> | |
| | | inline void | |
| | | resamplingConvolveX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel const & kernel, | |
| | | Rational<int> const & samplingRatio, Rational<int> cons | |
| | | t & offset) | |
| | | { | |
| | | resamplingConvolveX(srcImageRange(src), | |
| | | destImageRange(dest), | |
| | | kernel, samplingRatio, offset); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* resamplingConvolveY */ | | /* resamplingConvolveY */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply a resampling filter in the y-direction. | | /** \brief Apply a resampling filter in the y-direction. | |
| | | | |
| This function implements a convolution operation in y-direction | | This function implements a convolution operation in y-direction | |
| (i.e. applies a 1D filter to every column) where the height of the sour
ce | | (i.e. applies a 1D filter to every column) where the height of the sour
ce | |
| | | | |
| skipping to change at line 526 | | skipping to change at line 573 | |
| | | | |
| The <tt>samplingRatio</tt> and <tt>offset</tt> must be given as \ref vi
gra::Rational | | The <tt>samplingRatio</tt> and <tt>offset</tt> must be given as \ref vi
gra::Rational | |
| in order to avoid rounding errors in this transformation. It is require
d that for all | | in order to avoid rounding errors in this transformation. It is require
d that for all | |
| pixels of the target image, <tt>ysource</tt> remains within the range o
f the source | | pixels of the target image, <tt>ysource</tt> remains within the range o
f the source | |
| image (i.e. <tt>0 <= ysource <= sourceHeight-1</tt>. Since <tt>ysource<
/tt> is | | image (i.e. <tt>0 <= ysource <= sourceHeight-1</tt>. Since <tt>ysource<
/tt> is | |
| in general not an integer, the <tt>kernel</tt> must be a functor that c
an be accessed at | | in general not an integer, the <tt>kernel</tt> must be a functor that c
an be accessed at | |
| arbitrary (<tt>double</tt>) coordinates. It must also provide a member
function <tt>radius()</tt> | | arbitrary (<tt>double</tt>) coordinates. It must also provide a member
function <tt>radius()</tt> | |
| which specifies the support (non-zero interval) of the kernel. VIGRA al
ready | | which specifies the support (non-zero interval) of the kernel. VIGRA al
ready | |
| provides a number of suitable functors, e.g. \ref vigra::Gaussian, \ref
vigra::BSpline | | provides a number of suitable functors, e.g. \ref vigra::Gaussian, \ref
vigra::BSpline | |
| \ref vigra::CatmullRomSpline, and \ref vigra::CoscotFunction. The funct
ion | | \ref vigra::CatmullRomSpline, and \ref vigra::CoscotFunction. The funct
ion | |
|
| \ref resizeImageSplineInterpolation() is implemented by means resamplin
gConvolveX() and | | \ref resizeImageSplineInterpolation() is implemented by means of resamp
lingConvolveX() and | |
| resamplingConvolveY(). | | resamplingConvolveY(). | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Kernel> | |
| | | void | |
| | | resamplingConvolveY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel const & kernel, | |
| | | Rational<int> const & samplingRatio, Rational<i | |
| | | nt> const & offset); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{resamplingConvolveY} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIter, class SrcAcc, | | template <class SrcIter, class SrcAcc, | |
| class DestIter, class DestAcc, | | class DestIter, class DestAcc, | |
| class Kernel> | | class Kernel> | |
| void | | void | |
| resamplingConvolveY(SrcIter sul, SrcIter slr, SrcAcc src, | | resamplingConvolveY(SrcIter sul, SrcIter slr, SrcAcc src, | |
| DestIter dul, DestIter dlr, DestAcc dest, | | DestIter dul, DestIter dlr, DestAcc dest, | |
| Kernel const & kernel, | | Kernel const & kernel, | |
| Rational<int> const & samplingRatio, Rational<i
nt> const & offset); | | Rational<int> const & samplingRatio, Rational<i
nt> const & offset); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIter, class SrcAcc, | | template <class SrcIter, class SrcAcc, | |
| class DestIter, class DestAcc, | | class DestIter, class DestAcc, | |
| class Kernel> | | class Kernel> | |
| void | | void | |
| resamplingConvolveY(triple<SrcIter, SrcIter, SrcAcc> src, | | resamplingConvolveY(triple<SrcIter, SrcIter, SrcAcc> src, | |
| triple<DestIter, DestIter, DestAcc> dest, | | triple<DestIter, DestIter, DestAcc> dest, | |
| Kernel const & kernel, | | Kernel const & kernel, | |
| Rational<int> const & samplingRatio, Rational<i
nt> const & offset); | | Rational<int> const & samplingRatio, Rational<i
nt> const & offset); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/resampling_convolution.hxx\> | | <b>\#include</b> \<vigra/resampling_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | Rational<int> ratio(2), offset(0); | |
| | | | |
| | | MultiArray<2, float> src(w,h), | |
| | | dest(w, rational_cast<int>(ratio*h)); | |
| | | | |
| | | float sigma = 2.0; | |
| | | Gaussian<float> smooth(sigma); | |
| | | ... | |
| | | | |
|
| | | // simultaneously enlarge and smooth source image | |
| | | resamplingConvolveY(src, dest, | |
| | | smooth, ratio, offset); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{resamplingConvolveY} | |
| \code | | \code | |
| Rational<int> ratio(2), offset(0); | | Rational<int> ratio(2), offset(0); | |
| | | | |
| FImage src(w,h), | | FImage src(w,h), | |
| dest(w, rational_cast<int>(ratio*h)); | | dest(w, rational_cast<int>(ratio*h)); | |
| | | | |
| float sigma = 2.0; | | float sigma = 2.0; | |
| Gaussian<float> smooth(sigma); | | Gaussian<float> smooth(sigma); | |
| ... | | ... | |
| | | | |
| // simultaneously enlarge and smooth source image | | // simultaneously enlarge and smooth source image | |
| resamplingConvolveY(srcImageRange(src), destImageRange(dest), | | resamplingConvolveY(srcImageRange(src), destImageRange(dest), | |
| smooth, ratio, offset); | | smooth, ratio, offset); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| Kernel kernel; | | Kernel kernel; | |
| int kernelRadius = kernel.radius(); | | int kernelRadius = kernel.radius(); | |
| double y = ...; // must be <= radius() | | double y = ...; // must be <= radius() | |
| double value = kernel(y); | | double value = kernel(y); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void resamplingConvolveY) | | doxygen_overloaded_function(template <...> void resamplingConvolveY) | |
| | | | |
| template <class SrcIter, class SrcAcc, | | template <class SrcIter, class SrcAcc, | |
| class DestIter, class DestAcc, | | class DestIter, class DestAcc, | |
| class Kernel> | | class Kernel> | |
| void | | void | |
| resamplingConvolveY(SrcIter sul, SrcIter slr, SrcAcc src, | | resamplingConvolveY(SrcIter sul, SrcIter slr, SrcAcc src, | |
| DestIter dul, DestIter dlr, DestAcc dest, | | DestIter dul, DestIter dlr, DestAcc dest, | |
| Kernel const & kernel, | | Kernel const & kernel, | |
| | | | |
| skipping to change at line 623 | | skipping to change at line 701 | |
| | | | |
| for(; sul.x < slr.x; ++sul.x, ++dul.x) | | for(; sul.x < slr.x; ++sul.x, ++dul.x) | |
| { | | { | |
| typename SrcIter::column_iterator sc = sul.columnIterator(); | | typename SrcIter::column_iterator sc = sul.columnIterator(); | |
| typename DestIter::column_iterator dc = dul.columnIterator(); | | typename DestIter::column_iterator dc = dul.columnIterator(); | |
| resamplingConvolveLine(sc, sc+hold, src, dc, dc+hnew, dest, | | resamplingConvolveLine(sc, sc+hold, src, dc, dc+hnew, dest, | |
| kernels, mapCoordinate); | | kernels, mapCoordinate); | |
| } | | } | |
| } | | } | |
| | | | |
|
| template <class SrcIter, class SrcAcc, | | template <class SrcIter, class SrcAccessor, | |
| class DestIter, class DestAcc, | | class DestIter, class DestAccessor, | |
| class Kernel> | | class Kernel> | |
| inline void | | inline void | |
|
| resamplingConvolveY(triple<SrcIter, SrcIter, SrcAcc> src, | | resamplingConvolveY(triple<SrcIter, SrcIter, SrcAccessor> src, | |
| triple<DestIter, DestIter, DestAcc> dest, | | triple<DestIter, DestIter, DestAccessor> dest, | |
| Kernel const & kernel, | | Kernel const & kernel, | |
| Rational<int> const & samplingRatio, Rational<int> cons
t & offset) | | Rational<int> const & samplingRatio, Rational<int> cons
t & offset) | |
| { | | { | |
| resamplingConvolveY(src.first, src.second, src.third, | | resamplingConvolveY(src.first, src.second, src.third, | |
| dest.first, dest.second, dest.third, | | dest.first, dest.second, dest.third, | |
| kernel, samplingRatio, offset); | | kernel, samplingRatio, offset); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Kernel> | |
| | | inline void | |
| | | resamplingConvolveY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel const & kernel, | |
| | | Rational<int> const & samplingRatio, Rational<int> cons | |
| | | t & offset) | |
| | | { | |
| | | resamplingConvolveY(srcImageRange(src), | |
| | | destImageRange(dest), | |
| | | kernel, samplingRatio, offset); | |
| | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* resamplingConvolveImage */ | | /* resamplingConvolveImage */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Apply two separable resampling filters successively, the first i
n x-direction, | | /** \brief Apply two separable resampling filters successively, the first i
n x-direction, | |
| the second in y-direction. | | the second in y-direction. | |
| | | | |
| This function is a shorthand for the concatenation of a call to | | This function is a shorthand for the concatenation of a call to | |
| \ref resamplingConvolveX() and \ref resamplingConvolveY() | | \ref resamplingConvolveX() and \ref resamplingConvolveY() | |
| with the given kernels. See there for detailed documentation. | | with the given kernels. See there for detailed documentation. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class KernelX, class KernelY> | |
| | | void | |
| | | resamplingConvolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | KernelX const & kx, | |
| | | Rational<int> const & samplingRatioX, Ratio | |
| | | nal<int> const & offsetX, | |
| | | KernelY const & ky, | |
| | | Rational<int> const & samplingRatioY, Ratio | |
| | | nal<int> const & offsetY); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{resamplingConvolveImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelX, class KernelY> | | class KernelX, class KernelY> | |
| void resamplingConvolveImage(SrcIterator sul,SrcIterator slr, SrcAc
cessor src, | | void resamplingConvolveImage(SrcIterator sul,SrcIterator slr, SrcAc
cessor src, | |
| DestIterator dul, DestIterator dlr, DestAccessor
dest, | | DestIterator dul, DestIterator dlr, DestAccessor
dest, | |
| KernelX const & kx, | | KernelX const & kx, | |
| Rational<int> const & samplingRatioX, Rational<i
nt> const & offsetX, | | Rational<int> const & samplingRatioX, Rational<i
nt> const & offsetX, | |
| KernelY const & ky, | | KernelY const & ky, | |
| Rational<int> const & samplingRatioY, Rational<i
nt> const & offsetY); | | Rational<int> const & samplingRatioY, Rational<i
nt> const & offsetY); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelX, class KernelY> | | class KernelX, class KernelY> | |
| void | | void | |
| resamplingConvolveImage(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | | resamplingConvolveImage(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | |
| triple<DestIterator, DestIterator, DestAccessor>
dest, | | triple<DestIterator, DestIterator, DestAccessor>
dest, | |
| KernelX const & kx, | | KernelX const & kx, | |
| Rational<int> const & samplingRatioX, Rational<i
nt> const & offsetX, | | Rational<int> const & samplingRatioX, Rational<i
nt> const & offsetX, | |
| KernelY const & ky, | | KernelY const & ky, | |
| Rational<int> const & samplingRatioY, Rational<i
nt> const & offsetY); | | Rational<int> const & samplingRatioY, Rational<i
nt> const & offsetY); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/resampling_convolution.hxx\> | | <b>\#include</b> \<vigra/resampling_convolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| Rational<int> xratio(2), yratio(3), offset(0); | | Rational<int> xratio(2), yratio(3), offset(0); | |
| | | | |
|
| FImage src(w,h), | | MultiArray<2, float> src(w,h), | |
| dest(rational_cast<int>(xratio*w), rational_cast<int>(yratio*h)) | | dest(rational_cast<int>(xratio*w), rational_cast<i | |
| ; | | nt>(yratio*h)); | |
| | | | |
| float sigma = 2.0; | | float sigma = 2.0; | |
| Gaussian<float> smooth(sigma); | | Gaussian<float> smooth(sigma); | |
| ... | | ... | |
| | | | |
| // simultaneously enlarge and smooth source image | | // simultaneously enlarge and smooth source image | |
|
| resamplingConvolveImage(srcImageRange(src), destImageRange(dest), | | resamplingConvolveImage(src, dest, | |
| smooth, xratio, offset, | | smooth, xratio, offset, | |
| smooth, yratio, offset); | | smooth, yratio, offset); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void resamplingConvolveImage) | | doxygen_overloaded_function(template <...> void resamplingConvolveImage) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelX, class KernelY> | | class KernelX, class KernelY> | |
| void resamplingConvolveImage(SrcIterator sul,SrcIterator slr, SrcAccessor s
rc, | | void resamplingConvolveImage(SrcIterator sul,SrcIterator slr, SrcAccessor s
rc, | |
| DestIterator dul, DestIterator dlr, DestAccessor dest, | | DestIterator dul, DestIterator dlr, DestAccessor dest, | |
| KernelX const & kx, | | KernelX const & kx, | |
| Rational<int> const & samplingRatioX, Rational<int> cons
t & offsetX, | | Rational<int> const & samplingRatioX, Rational<int> cons
t & offsetX, | |
| | | | |
| skipping to change at line 736 | | skipping to change at line 844 | |
| resamplingConvolveY(srcImageRange(tmp), | | resamplingConvolveY(srcImageRange(tmp), | |
| destIterRange(dul, dlr, dest), | | destIterRange(dul, dlr, dest), | |
| ky, samplingRatioY, offsetY); | | ky, samplingRatioY, offsetY); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelX, class KernelY> | | class KernelX, class KernelY> | |
| inline void | | inline void | |
| resamplingConvolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | resamplingConvolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| triple<DestIterator, DestIterator, DestAccessor> dest, | | triple<DestIterator, DestIterator, DestAccessor> de | |
| KernelX const & kx, | | st, | |
| Rational<int> const & samplingRatioX, Rational<int> cons | | KernelX const & kx, | |
| t & offsetX, | | Rational<int> const & samplingRatioX, Rational<int> | |
| KernelY const & ky, | | const & offsetX, | |
| Rational<int> const & samplingRatioY, Rational<int> cons | | KernelY const & ky, | |
| t & offsetY) | | Rational<int> const & samplingRatioY, Rational<int> | |
| | | const & offsetY) | |
| { | | { | |
| resamplingConvolveImage(src.first, src.second, src.third, | | resamplingConvolveImage(src.first, src.second, src.third, | |
| dest.first, dest.second, dest.third, | | dest.first, dest.second, dest.third, | |
| kx, samplingRatioX, offsetX, | | kx, samplingRatioX, offsetX, | |
| ky, samplingRatioY, offsetY); | | ky, samplingRatioY, offsetY); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class KernelX, class KernelY> | |
| | | inline void | |
| | | resamplingConvolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | KernelX const & kx, | |
| | | Rational<int> const & samplingRatioX, Rational<int> | |
| | | const & offsetX, | |
| | | KernelY const & ky, | |
| | | Rational<int> const & samplingRatioY, Rational<int> | |
| | | const & offsetY) | |
| | | { | |
| | | resamplingConvolveImage(srcImageRange(src), | |
| | | destImageRange(dest), | |
| | | kx, samplingRatioX, offsetX, | |
| | | ky, samplingRatioY, offsetY); | |
| | | } | |
| | | | |
| /** \brief Two-fold down-sampling for image pyramid construction. | | /** \brief Two-fold down-sampling for image pyramid construction. | |
| | | | |
| Sorry, no \ref detailedDocumentation() available yet. | | Sorry, no \ref detailedDocumentation() available yet. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
| <b>\#include</b> \<vigra/resampling_convolution.hxx\><br> | | <b>\#include</b> \<vigra/resampling_convolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void pyramidReduceBurtFilter(SrcIterator sul, SrcIterator slr, SrcA
ccessor src, | | void pyramidReduceBurtFilter(SrcIterator sul, SrcIterator slr, SrcA
ccessor src, | |
| DestIterator dul, DestIterator dlr, De
stAccessor dest, | | DestIterator dul, DestIterator dlr, De
stAccessor dest, | |
| double centerValue = 0.4); | | double centerValue = 0.4); | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedAPI{pyramidReduceBurtFilter} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor> | |
| | | void pyramidReduceBurtFilter(SrcIterator sul, SrcIterator slr, SrcA | |
| | | ccessor src, | |
| | | DestIterator dul, DestIterator dlr, De | |
| | | stAccessor dest, | |
| | | double centerValue = 0.4); | |
| | | } | |
| | | \endcode | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void pyramidReduceBurtFilter(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | | void pyramidReduceBurtFilter(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | |
| triple<DestIterator, DestIterator, Des
tAccessor> dest, | | triple<DestIterator, DestIterator, Des
tAccessor> dest, | |
| double centerValue = 0.4); | | double centerValue = 0.4); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| use a \ref vigra::ImagePyramid : | | use a \ref vigra::ImagePyramid : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Image, class Alloc> | | template <class Image, class Alloc> | |
| void pyramidReduceBurtFilter(ImagePyramid<Image, Alloc> & pyramid,
int fromLevel, int toLevel, | | void pyramidReduceBurtFilter(ImagePyramid<Image, Alloc> & pyramid,
int fromLevel, int toLevel, | |
| double centerValue = 0.4); | | double centerValue = 0.4); | |
| } | | } | |
| \endcode | | \endcode | |
| */ | | */ | |
| | | | |
| skipping to change at line 880 | | skipping to change at line 1017 | |
| | | | |
| /** \brief Two-fold up-sampling for image pyramid reconstruction. | | /** \brief Two-fold up-sampling for image pyramid reconstruction. | |
| | | | |
| Sorry, no \ref detailedDocumentation() available yet. | | Sorry, no \ref detailedDocumentation() available yet. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
| <b>\#include</b> \<vigra/resampling_convolution.hxx\><br> | | <b>\#include</b> \<vigra/resampling_convolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void pyramidExpandBurtFilter(SrcIterator sul, SrcIterator slr, SrcA
ccessor src, | | void pyramidExpandBurtFilter(SrcIterator sul, SrcIterator slr, SrcA
ccessor src, | |
| DestIterator dul, DestIterator dlr, De
stAccessor dest, | | DestIterator dul, DestIterator dlr, De
stAccessor dest, | |
| double centerValue = 0.4); | | double centerValue = 0.4); | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedAPI{pyramidExpandBurtFilter} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class DestIterator, class DestAccessor> | |
| | | void pyramidExpandBurtFilter(SrcIterator sul, SrcIterator slr, SrcA | |
| | | ccessor src, | |
| | | DestIterator dul, DestIterator dlr, De | |
| | | stAccessor dest, | |
| | | double centerValue = 0.4); | |
| | | } | |
| | | \endcode | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void pyramidExpandBurtFilter(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | | void pyramidExpandBurtFilter(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | |
| triple<DestIterator, DestIterator, Des
tAccessor> dest, | | triple<DestIterator, DestIterator, Des
tAccessor> dest, | |
| double centerValue = 0.4); | | double centerValue = 0.4); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| use a \ref vigra::ImagePyramid : | | use a \ref vigra::ImagePyramid : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class Image, class Alloc> | | template <class Image, class Alloc> | |
| void pyramidExpandBurtFilter(ImagePyramid<Image, Alloc> & pyramid,
int fromLevel, int toLevel, | | void pyramidExpandBurtFilter(ImagePyramid<Image, Alloc> & pyramid,
int fromLevel, int toLevel, | |
| double centerValue = 0.4); | | double centerValue = 0.4); | |
| } | | } | |
| \endcode | | \endcode | |
| */ | | */ | |
| | | | |
| skipping to change at line 1003 | | skipping to change at line 1152 | |
| } | | } | |
| | | | |
| /** \brief Create a Laplacian pyramid. | | /** \brief Create a Laplacian pyramid. | |
| | | | |
| Sorry, no \ref detailedDocumentation() available yet. | | Sorry, no \ref detailedDocumentation() available yet. | |
| | | | |
| <b>\#include</b> \<vigra/resampling_convolution.hxx\><br> | | <b>\#include</b> \<vigra/resampling_convolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class Image, class Alloc> | | template <class Image, class Alloc> | |
|
| inline | | inline void | |
| void pyramidReduceBurtLaplacian(ImagePyramid<Image, Alloc> & pyramid, int f | | pyramidReduceBurtLaplacian(ImagePyramid<Image, Alloc> & pyramid, int fromLe | |
| romLevel, int toLevel, | | vel, int toLevel, | |
| double centerValue = 0.4) | | double centerValue = 0.4) | |
| { | | { | |
| using namespace functor; | | using namespace functor; | |
| | | | |
| pyramidReduceBurtFilter(pyramid, fromLevel, toLevel, centerValue); | | pyramidReduceBurtFilter(pyramid, fromLevel, toLevel, centerValue); | |
| for(int i=fromLevel; i < toLevel; ++i) | | for(int i=fromLevel; i < toLevel; ++i) | |
| { | | { | |
| typename ImagePyramid<Image, Alloc>::value_type tmpImage(pyramid[i]
.size()); | | typename ImagePyramid<Image, Alloc>::value_type tmpImage(pyramid[i]
.size()); | |
| pyramidExpandBurtFilter(srcImageRange(pyramid[i+1]), destImageRange
(tmpImage), centerValue); | | pyramidExpandBurtFilter(srcImageRange(pyramid[i+1]), destImageRange
(tmpImage), centerValue); | |
| combineTwoImages(srcImageRange(tmpImage), srcImage(pyramid[i]), des
tImage(pyramid[i]), | | combineTwoImages(srcImageRange(tmpImage), srcImage(pyramid[i]), des
tImage(pyramid[i]), | |
| Arg1() - Arg2()); | | Arg1() - Arg2()); | |
| | | | |
| skipping to change at line 1027 | | skipping to change at line 1176 | |
| } | | } | |
| | | | |
| /** \brief Reconstruct a Laplacian pyramid. | | /** \brief Reconstruct a Laplacian pyramid. | |
| | | | |
| Sorry, no \ref detailedDocumentation() available yet. | | Sorry, no \ref detailedDocumentation() available yet. | |
| | | | |
| <b>\#include</b> \<vigra/resampling_convolution.hxx\><br> | | <b>\#include</b> \<vigra/resampling_convolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| */ | | */ | |
| template <class Image, class Alloc> | | template <class Image, class Alloc> | |
|
| inline | | inline void | |
| void pyramidExpandBurtLaplacian(ImagePyramid<Image, Alloc> & pyramid, int f | | pyramidExpandBurtLaplacian(ImagePyramid<Image, Alloc> & pyramid, int fromLe | |
| romLevel, int toLevel, | | vel, int toLevel, | |
| double centerValue = 0.4) | | double centerValue = 0.4) | |
| { | | { | |
| using namespace functor; | | using namespace functor; | |
| | | | |
| vigra_precondition(fromLevel > toLevel, | | vigra_precondition(fromLevel > toLevel, | |
| "pyramidExpandBurtLaplacian(): fromLevel must be larger than toLevel
."); | | "pyramidExpandBurtLaplacian(): fromLevel must be larger than toLevel
."); | |
| vigra_precondition(pyramid.lowestLevel() <= toLevel && fromLevel <= pyr
amid.highestLevel(), | | vigra_precondition(pyramid.lowestLevel() <= toLevel && fromLevel <= pyr
amid.highestLevel(), | |
| "pyramidExpandBurtLaplacian(): fromLevel and toLevel must be between
the lowest and highest pyramid levels (inclusive)."); | | "pyramidExpandBurtLaplacian(): fromLevel and toLevel must be between
the lowest and highest pyramid levels (inclusive)."); | |
| | | | |
| for(int i=fromLevel-1; i >= toLevel; --i) | | for(int i=fromLevel-1; i >= toLevel; --i) | |
| { | | { | |
| | | | |
End of changes. 43 change blocks. |
| 45 lines changed or deleted | | 207 lines changed or added | |
|
| resizeimage.hxx | | resizeimage.hxx | |
| | | | |
| skipping to change at line 47 | | skipping to change at line 47 | |
| #define VIGRA_RESIZEIMAGE_HXX | | #define VIGRA_RESIZEIMAGE_HXX | |
| | | | |
| #include <vector> | | #include <vector> | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "stdimage.hxx" | | #include "stdimage.hxx" | |
| #include "recursiveconvolution.hxx" | | #include "recursiveconvolution.hxx" | |
| #include "separableconvolution.hxx" | | #include "separableconvolution.hxx" | |
| #include "resampling_convolution.hxx" | | #include "resampling_convolution.hxx" | |
| #include "splines.hxx" | | #include "splines.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| /*****************************************************************/ | | /*****************************************************************/ | |
| /* */ | | /* */ | |
| /* CoscotFunction */ | | /* CoscotFunction */ | |
| /* */ | | /* */ | |
| /*****************************************************************/ | | /*****************************************************************/ | |
| | | | |
|
| /*! The Coscot interpolation function. | | /** The Coscot interpolation function. | |
| | | | |
| Implements the Coscot interpolation function proposed by Maria Magnusso
n Seger | | Implements the Coscot interpolation function proposed by Maria Magnusso
n Seger | |
| (maria@isy.liu.se) in the context of tomographic reconstruction. It pro
vides a fast | | (maria@isy.liu.se) in the context of tomographic reconstruction. It pro
vides a fast | |
| transition between the pass- and stop-bands and minimal ripple outside
the transition | | transition between the pass- and stop-bands and minimal ripple outside
the transition | |
| region. Both properties are important for this application and can be t
uned by the parameters | | region. Both properties are important for this application and can be t
uned by the parameters | |
| <i>m</i> and <i>h</i> (with defaults 3 and 0.5). The function is define
d by | | <i>m</i> and <i>h</i> (with defaults 3 and 0.5). The function is define
d by | |
| | | | |
| \f[ f_{m,h}(x) = \left\{ \begin{array}{ll} | | \f[ f_{m,h}(x) = \left\{ \begin{array}{ll} | |
| \frac{1}{2m}\sin(\pi x)\cot(\pi x / (2 m
))(h + (1-h)\cos(\pi x/m)) & |x| \leq m \\ | | \frac{1}{2m}\sin(\pi x)\cot(\pi x / (2 m
))(h + (1-h)\cos(\pi x/m)) & |x| \leq m \\ | |
| 0 & \mbox{otherwise} | | 0 & \mbox{otherwise} | |
| | | | |
| skipping to change at line 132 | | skipping to change at line 133 | |
| /** Derivative order of the function: always 0. | | /** Derivative order of the function: always 0. | |
| */ | | */ | |
| unsigned int derivativeOrder() const | | unsigned int derivativeOrder() const | |
| { return 0; } | | { return 0; } | |
| | | | |
| /** Prefilter coefficients for compatibility with \ref vigra::BSpli
ne. | | /** Prefilter coefficients for compatibility with \ref vigra::BSpli
ne. | |
| (array has zero length, since prefiltering is not necessary). | | (array has zero length, since prefiltering is not necessary). | |
| */ | | */ | |
| ArrayVector<double> const & prefilterCoefficients() const | | ArrayVector<double> const & prefilterCoefficients() const | |
| { | | { | |
|
| static ArrayVector<double> b; | | return prefilterCoefficients_; | |
| return b; | | | |
| } | | } | |
| | | | |
| protected: | | protected: | |
|
| | | static ArrayVector<double> prefilterCoefficients_; | |
| unsigned int m_; | | unsigned int m_; | |
| double h_; | | double h_; | |
| }; | | }; | |
| | | | |
|
| | | template <class T> | |
| | | ArrayVector<double> CoscotFunction<T>::prefilterCoefficients_; | |
| | | | |
| /** \addtogroup GeometricTransformations Geometric Transformations | | /** \addtogroup GeometricTransformations Geometric Transformations | |
| Zoom up and down by repeating pixels, or using various interpolation sc
hemes. | | Zoom up and down by repeating pixels, or using various interpolation sc
hemes. | |
| | | | |
| See also: \ref resamplingConvolveImage(), \ref resampleImage(), \ref re
sizeMultiArraySplineInterpolation() | | See also: \ref resamplingConvolveImage(), \ref resampleImage(), \ref re
sizeMultiArraySplineInterpolation() | |
| | | | |
| <b>\#include</b> \<vigra/stdimagefunctions.hxx\><br> | | <b>\#include</b> \<vigra/stdimagefunctions.hxx\><br> | |
| <b>or</b><br> | | <b>or</b><br> | |
| <b>\#include</b> \<vigra/resizeimage.hxx\><br> | | <b>\#include</b> \<vigra/resizeimage.hxx\><br> | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
| skipping to change at line 199 | | skipping to change at line 202 | |
| /** \brief Resize image by repeating the nearest pixel values. | | /** \brief Resize image by repeating the nearest pixel values. | |
| | | | |
| This algorithm is very fast and does not require any arithmetic on | | This algorithm is very fast and does not require any arithmetic on | |
| the pixel types. | | the pixel types. | |
| | | | |
| The range of both the input and output images (resp. regions) must | | The range of both the input and output images (resp. regions) must | |
| be given. Both images must have a size of at least 2x2 pixels. The | | be given. Both images must have a size of at least 2x2 pixels. The | |
| scaling factors are then calculated accordingly. Destination | | scaling factors are then calculated accordingly. Destination | |
| pixels are directly copied from the appropriate source pixels. | | pixels are directly copied from the appropriate source pixels. | |
| | | | |
|
| The function uses accessors. | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | resizeImageNoInterpolation(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{resizeImageNoInterpolation} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| resizeImageNoInterpolation( | | resizeImageNoInterpolation( | |
| SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa, | | SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa, | |
| DestImageIterator id, DestImageIterator idend, DestAccessor d
a) | | DestImageIterator id, DestImageIterator idend, DestAccessor d
a) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| resizeImageNoInterpolation( | | resizeImageNoInterpolation( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | |
| triple<DestImageIterator, DestImageIterator, DestAccessor> de
st) | | triple<DestImageIterator, DestImageIterator, DestAccessor> de
st) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/resizeimage.hxx\><br> | | <b>\#include</b> \<vigra/resizeimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, unsigned char> src(w, h); | |
| | | MultiArray<2, float> dest(w_new, h_new); | |
| | | | |
| | | resizeImageNoInterpolation(src, dest); | |
| | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{resizeImageNoInterpolation} | |
| \code | | \code | |
| vigra::resizeImageNoInterpolation( | | vigra::resizeImageNoInterpolation( | |
| src.upperLeft(), src.lowerRight(), src.accessor(), | | src.upperLeft(), src.lowerRight(), src.accessor(), | |
| dest.upperLeft(), dest.lowerRight(), dest.accessor()); | | dest.upperLeft(), dest.lowerRight(), dest.accessor()); | |
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft, src_lowerright; | | DestImageIterator dest_upperleft, src_lowerright; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| dest_accessor.set(src_accessor(src_upperleft), dest_upperleft); | | dest_accessor.set(src_accessor(src_upperleft), dest_upperleft); | |
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
|
| \code | | Source and destination must have at least 2 pixels along each axis. | |
| src_lowerright.x - src_upperleft.x > 1 | | | |
| src_lowerright.y - src_upperleft.y > 1 | | | |
| dest_lowerright.x - dest_upperleft.x > 1 | | | |
| dest_lowerright.y - dest_upperleft.y > 1 | | | |
| \endcode | | | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void resizeImageNoInterpolation) | | doxygen_overloaded_function(template <...> void resizeImageNoInterpolation) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| resizeImageNoInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa
, | | resizeImageNoInterpolation(SrcIterator is, SrcIterator iend, SrcAccessor sa
, | |
| DestIterator id, DestIterator idend, DestAccessor da) | | DestIterator id, DestIterator idend, DestAccessor da) | |
| { | | { | |
| int w = iend.x - is.x; | | int w = iend.x - is.x; | |
| | | | |
| skipping to change at line 311 | | skipping to change at line 325 | |
| { | | { | |
| typename DestIterator::row_iterator rd = id.rowIterator(); | | typename DestIterator::row_iterator rd = id.rowIterator(); | |
| typename TmpImageIterator::row_iterator rt = yt.rowIterator(); | | typename TmpImageIterator::row_iterator rt = yt.rowIterator(); | |
| | | | |
| resizeLineNoInterpolation(rt, rt + w, tmp.accessor(), rd, rd + wnew
, da); | | resizeLineNoInterpolation(rt, rt + w, tmp.accessor(), rd, rd + wnew
, da); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline void | |
| void | | | |
| resizeImageNoInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> sr
c, | | resizeImageNoInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> sr
c, | |
| triple<DestIterator, DestIterator, DestAccessor>
dest) | | triple<DestIterator, DestIterator, DestAccessor>
dest) | |
| { | | { | |
| resizeImageNoInterpolation(src.first, src.second, src.third, | | resizeImageNoInterpolation(src.first, src.second, src.third, | |
|
| dest.first, dest.second, dest.third); | | dest.first, dest.second, dest.third); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | resizeImageNoInterpolation(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest) | |
| | | { | |
| | | resizeImageNoInterpolation(srcImageRange(src), | |
| | | destImageRange(dest)); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* resizeLineLinearInterpolation */ | | /* resizeLineLinearInterpolation */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| | | | |
| skipping to change at line 383 | | skipping to change at line 406 | |
| obtain a good compromise between quality and speed. | | obtain a good compromise between quality and speed. | |
| | | | |
| The range must of both the input and output images (resp. regions) | | The range must of both the input and output images (resp. regions) | |
| must be given. Both images must have a size of at | | must be given. Both images must have a size of at | |
| least 2x2. The scaling factors are then calculated | | least 2x2. The scaling factors are then calculated | |
| accordingly. If the source image is larger than the destination, it | | accordingly. If the source image is larger than the destination, it | |
| is smoothed (band limited) using a recursive | | is smoothed (band limited) using a recursive | |
| exponential filter. The source value_type (SrcAccessor::value_type) mus
t | | exponential filter. The source value_type (SrcAccessor::value_type) mus
t | |
| be a linear space, i.e. it must support addition, multiplication | | be a linear space, i.e. it must support addition, multiplication | |
| with a scalar real number and \ref NumericTraits "NumericTraits". | | with a scalar real number and \ref NumericTraits "NumericTraits". | |
|
| The function uses accessors. | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | resizeImageLinearInterpolation(MultiArrayView<2, T1, S1> const & sr | |
| | | c, | |
| | | MultiArrayView<2, T2, S2> dest); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{resizeImageLinearInterpolation} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| resizeImageLinearInterpolation( | | resizeImageLinearInterpolation( | |
| SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa, | | SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa, | |
| DestImageIterator id, DestImageIterator idend, DestAccessor d
a) | | DestImageIterator id, DestImageIterator idend, DestAccessor d
a) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor> | | class DestImageIterator, class DestAccessor> | |
| void | | void | |
| resizeImageLinearInterpolation( | | resizeImageLinearInterpolation( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | |
| triple<DestImageIterator, DestImageIterator, DestAccessor> de
st) | | triple<DestImageIterator, DestImageIterator, DestAccessor> de
st) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/resizeimage.hxx\><br> | | <b>\#include</b> \<vigra/resizeimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, unsigned char> src(w, h); | |
| | | MultiArray<2, float> dest(w_new, h_new); | |
| | | | |
| | | resizeImageLinearInterpolation(src, dest); | |
| | | \endcode | |
| | | | |
|
| | | \deprecatedUsage{resizeImageLinearInterpolation} | |
| \code | | \code | |
| vigra::resizeImageLinearInterpolation( | | vigra::resizeImageLinearInterpolation( | |
| src.upperLeft(), src.lowerRight(), src.accessor(), | | src.upperLeft(), src.lowerRight(), src.accessor(), | |
| dest.upperLeft(), dest.lowerRight(), dest.accessor()); | | dest.upperLeft(), dest.lowerRight(), dest.accessor()); | |
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft, src_lowerright; | | DestImageIterator dest_upperleft, src_lowerright; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| NumericTraits<SrcAccessor::value_type>::RealPromote | | NumericTraits<SrcAccessor::value_type>::RealPromote | |
| u = src_accessor(src_upperleft), | | u = src_accessor(src_upperleft), | |
| v = src_accessor(src_upperleft, 1); | | v = src_accessor(src_upperleft, 1); | |
| double d; | | double d; | |
| | | | |
| u = d * v; | | u = d * v; | |
| u = u + v; | | u = u + v; | |
| | | | |
| dest_accessor.set( | | dest_accessor.set( | |
| NumericTraits<DestAccessor::value_type>::fromRealPromote(u), | | NumericTraits<DestAccessor::value_type>::fromRealPromote(u), | |
| dest_upperleft); | | dest_upperleft); | |
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
|
| \code | | Source and destination must have at least 2 pixels along each axis. | |
| src_lowerright.x - src_upperleft.x > 1 | | | |
| src_lowerright.y - src_upperleft.y > 1 | | | |
| dest_lowerright.x - dest_upperleft.x > 1 | | | |
| dest_lowerright.y - dest_upperleft.y > 1 | | | |
| \endcode | | | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void resizeImageLinearInterpolat
ion) | | doxygen_overloaded_function(template <...> void resizeImageLinearInterpolat
ion) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| resizeImageLinearInterpolation(SrcIterator is, SrcIterator iend, SrcAccesso
r sa, | | resizeImageLinearInterpolation(SrcIterator is, SrcIterator iend, SrcAccesso
r sa, | |
| DestIterator id, DestIterator idend, DestAccessor da) | | DestIterator id, DestIterator idend, DestAccessor da) | |
| { | | { | |
| int w = iend.x - is.x; | | int w = iend.x - is.x; | |
| | | | |
| skipping to change at line 537 | | skipping to change at line 572 | |
| else | | else | |
| { | | { | |
| resizeLineLinearInterpolation(rt, rt + w, tmp.accessor(), | | resizeLineLinearInterpolation(rt, rt + w, tmp.accessor(), | |
| rd, rd + wnew, da); | | rd, rd + wnew, da); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline void | |
| void | | | |
| resizeImageLinearInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | | resizeImageLinearInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | |
| triple<DestIterator, DestIterator, DestAcces
sor> dest) | | triple<DestIterator, DestIterator, DestAcces
sor> dest) | |
| { | | { | |
| resizeImageLinearInterpolation(src.first, src.second, src.third, | | resizeImageLinearInterpolation(src.first, src.second, src.third, | |
| dest.first, dest.second, dest.third); | | dest.first, dest.second, dest.third); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | resizeImageLinearInterpolation(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest) | |
| | | { | |
| | | resizeImageLinearInterpolation(srcImageRange(src), | |
| | | destImageRange(dest)); | |
| | | } | |
| | | | |
| /***************************************************************/ | | /***************************************************************/ | |
| /* */ | | /* */ | |
| /* resizeImageSplineInterpolation */ | | /* resizeImageSplineInterpolation */ | |
| /* */ | | /* */ | |
| /***************************************************************/ | | /***************************************************************/ | |
| | | | |
| /** \brief Resize image using B-spline interpolation. | | /** \brief Resize image using B-spline interpolation. | |
| | | | |
| The function implements separable spline interpolation algorithm descri
bed in | | The function implements separable spline interpolation algorithm descri
bed in | |
| | | | |
| | | | |
| skipping to change at line 582 | | skipping to change at line 626 | |
| accordingly. If the source image is larger than the destination, it | | accordingly. If the source image is larger than the destination, it | |
| is smoothed (band limited) using a recursive | | is smoothed (band limited) using a recursive | |
| exponential filter. The source value_type (SrcAccessor::value_type) mus
t | | exponential filter. The source value_type (SrcAccessor::value_type) mus
t | |
| be a linear algebra, i.e. it must support addition, subtraction, | | be a linear algebra, i.e. it must support addition, subtraction, | |
| and multiplication (+, -, *), multiplication with a scalar | | and multiplication (+, -, *), multiplication with a scalar | |
| real number and \ref NumericTraits "NumericTraits". | | real number and \ref NumericTraits "NumericTraits". | |
| The function uses accessors. | | The function uses accessors. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class SPLINE> | |
| | | void | |
| | | resizeImageSplineInterpolation(MultiArrayView<2, T1, S1> const & sr | |
| | | c, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | SPLINE const & spline = BSpline<3, d | |
| | | ouble>()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{resizeImageSplineInterpolation} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor, | | class DestImageIterator, class DestAccessor, | |
| class SPLINE> | | class SPLINE> | |
| void | | void | |
| resizeImageSplineInterpolation( | | resizeImageSplineInterpolation( | |
| SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa, | | SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa, | |
| DestImageIterator id, DestImageIterator idend, DestAccessor d
a, | | DestImageIterator id, DestImageIterator idend, DestAccessor d
a, | |
| SPLINE spline = BSpline<3, double>()) | | SPLINE spline = BSpline<3, double>()) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor, | | class DestImageIterator, class DestAccessor, | |
| class SPLINE> | | class SPLINE> | |
| void | | void | |
| resizeImageSplineInterpolation( | | resizeImageSplineInterpolation( | |
| triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | | triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src, | |
| triple<DestImageIterator, DestImageIterator, DestAccessor> de
st, | | triple<DestImageIterator, DestImageIterator, DestAccessor> de
st, | |
| SPLINE spline = BSpline<3, double>()) | | SPLINE spline = BSpline<3, double>()) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/resizeimage.hxx\><br> | | <b>\#include</b> \<vigra/resizeimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, unsigned char> src(w, h); | |
| | | MultiArray<2, float> dest(w_new, h_new); | |
| | | | |
| | | // use default cubic spline interpolator | |
| | | resizeImageSplineInterpolation(src, dest); | |
| | | | |
| | | // use 5th-order spline interpolator | |
| | | resizeImageSplineInterpolation(src, dest, BSpline<5, double>()); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{resizeImageSplineInterpolation} | |
| | | \code | |
| vigra::resizeImageSplineInterpolation( | | vigra::resizeImageSplineInterpolation( | |
| src.upperLeft(), src.lowerRight(), src.accessor(), | | src.upperLeft(), src.lowerRight(), src.accessor(), | |
| dest.upperLeft(), dest.lowerRight(), dest.accessor()); | | dest.upperLeft(), dest.lowerRight(), dest.accessor()); | |
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcImageIterator src_upperleft, src_lowerright; | | SrcImageIterator src_upperleft, src_lowerright; | |
| DestImageIterator dest_upperleft, src_lowerright; | | DestImageIterator dest_upperleft, src_lowerright; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| NumericTraits<SrcAccessor::value_type>::RealPromote | | NumericTraits<SrcAccessor::value_type>::RealPromote | |
| u = src_accessor(src_upperleft), | | u = src_accessor(src_upperleft), | |
| v = src_accessor(src_upperleft, 1); | | v = src_accessor(src_upperleft, 1); | |
| | | | |
| skipping to change at line 648 | | skipping to change at line 716 | |
| u = u - v; | | u = u - v; | |
| u = u * v; | | u = u * v; | |
| u += v; | | u += v; | |
| u -= v; | | u -= v; | |
| | | | |
| dest_accessor.set( | | dest_accessor.set( | |
| NumericTraits<DestAccessor::value_type>::fromRealPromote(u), | | NumericTraits<DestAccessor::value_type>::fromRealPromote(u), | |
| dest_upperleft); | | dest_upperleft); | |
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
|
| \code | | Source and destination must have at least 2 pixels along each axis. | |
| src_lowerright.x - src_upperleft.x > 3 | | | |
| src_lowerright.y - src_upperleft.y > 3 | | | |
| dest_lowerright.x - dest_upperleft.x > 1 | | | |
| dest_lowerright.y - dest_upperleft.y > 1 | | | |
| \endcode | | | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void resizeImageSplineInterpolat
ion) | | doxygen_overloaded_function(template <...> void resizeImageSplineInterpolat
ion) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class SPLINE> | | class SPLINE> | |
| void | | void | |
| resizeImageSplineInterpolation( | | resizeImageSplineInterpolation( | |
| SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc, | | SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc, | |
| DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_a
cc, | | DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_a
cc, | |
| | | | |
| skipping to change at line 810 | | skipping to change at line 873 | |
| line_tmp, line.accessor(), (double)widt
h_old/width_new/scale); | | line_tmp, line.accessor(), (double)widt
h_old/width_new/scale); | |
| } | | } | |
| resamplingConvolveLine(line_tmp, line_tmp + width_old, line.acc
essor(), | | resamplingConvolveLine(line_tmp, line_tmp + width_old, line.acc
essor(), | |
| r_dest, r_dest + width_new, dest_acc, | | r_dest, r_dest + width_new, dest_acc, | |
| kernels, xmapCoordinate); | | kernels, xmapCoordinate); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
|
| class DestIterator, class DestAccessor, | | | |
| class SPLINE> | | | |
| inline | | | |
| void | | | |
| resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor | | | |
| > src, | | | |
| triple<DestIterator, DestIterator, DestAccessor> dest | | | |
| , | | | |
| SPLINE const & spline) | | | |
| { | | | |
| resizeImageSplineInterpolation(src.first, src.second, src.third, | | | |
| dest.first, dest.second, dest.third, spl | | | |
| ine); | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccesso
r sa, | | resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccesso
r sa, | |
| DestIterator id, DestIterator idend, DestAccessor da) | | DestIterator id, DestIterator idend, DestAccessor da) | |
| { | | { | |
| resizeImageSplineInterpolation(is, iend, sa, id, idend, da, BSpline<3,
double>()); | | resizeImageSplineInterpolation(is, iend, sa, id, idend, da, BSpline<3,
double>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
|
| | | class DestIterator, class DestAccessor, | |
| | | class SPLINE> | |
| | | inline void | |
| | | resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor | |
| | | > src, | |
| | | triple<DestIterator, DestIterator, DestAcces | |
| | | sor> dest, | |
| | | SPLINE const & spline) | |
| | | { | |
| | | resizeImageSplineInterpolation(src.first, src.second, src.third, | |
| | | dest.first, dest.second, dest.third, spl | |
| | | ine); | |
| | | } | |
| | | | |
| | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline void | |
| void | | | |
| resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | | resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | |
|
| triple<DestIterator, DestIterator, DestAccessor> dest
) | | triple<DestIterator, DestIterator, DestAcces
sor> dest) | |
| { | | { | |
| resizeImageSplineInterpolation(src.first, src.second, src.third, | | resizeImageSplineInterpolation(src.first, src.second, src.third, | |
| dest.first, dest.second, dest.third); | | dest.first, dest.second, dest.third); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class SPLINE> | |
| | | inline void | |
| | | resizeImageSplineInterpolation(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | SPLINE const & spline) | |
| | | { | |
| | | resizeImageSplineInterpolation(srcImageRange(src), | |
| | | destImageRange(dest), spline); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline void | |
| | | resizeImageSplineInterpolation(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest) | |
| | | { | |
| | | resizeImageSplineInterpolation(srcImageRange(src), | |
| | | destImageRange(dest)); | |
| | | } | |
| | | | |
| /*****************************************************************/ | | /*****************************************************************/ | |
| /* */ | | /* */ | |
| /* resizeImageCatmullRomInterpolation */ | | /* resizeImageCatmullRomInterpolation */ | |
| /* */ | | /* */ | |
| /*****************************************************************/ | | /*****************************************************************/ | |
| | | | |
| /** \brief Resize image using the Catmull/Rom interpolation function. | | /** \brief Resize image using the Catmull/Rom interpolation function. | |
| | | | |
| The function calls like \ref resizeImageSplineInterpolation() with | | The function calls like \ref resizeImageSplineInterpolation() with | |
| \ref vigra::CatmullRomSpline as an interpolation kernel. | | \ref vigra::CatmullRomSpline as an interpolation kernel. | |
| The interpolated function has one continuous derivative. | | The interpolated function has one continuous derivative. | |
| (See \ref resizeImageSplineInterpolation() for more documentation) | | (See \ref resizeImageSplineInterpolation() for more documentation) | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | resizeImageCatmullRomInterpolation(MultiArrayView<2, T1, S1> const | |
| | | & src, | |
| | | MultiArrayView<2, T2, S2> dest); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{resizeImageCatmullRomInterpolation} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterato
r src_iter_end, SrcAccessor src_acc, | | resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterato
r src_iter_end, SrcAccessor src_acc, | |
| DestIterator dest_iter, DestIterator dest_ite
r_end, DestAccessor dest_acc); | | DestIterator dest_iter, DestIterator dest_ite
r_end, DestAccessor dest_acc); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator,
SrcAccessor> src, | | resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator,
SrcAccessor> src, | |
| triple<DestIterator, DestIterator, DestAccess
or> dest); | | triple<DestIterator, DestIterator, DestAccess
or> dest); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b>\#include</b> \<vigra/resizeimage.hxx\><br> | | <b>\#include</b> \<vigra/resizeimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
|
| | | \code | |
| | | MultiArray<2, unsigned char> src(w, h); | |
| | | MultiArray<2, float> dest(w_new, h_new); | |
| | | | |
| | | resizeImageCatmullRomInterpolation(src, dest); | |
| | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void resizeImageCatmullRomInterp
olation) | | doxygen_overloaded_function(template <...> void resizeImageCatmullRomInterp
olation) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline void | | inline void | |
| resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_it
er_end, SrcAccessor src_acc, | | resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_it
er_end, SrcAccessor src_acc, | |
| DestIterator dest_iter, DestIterator dest_iter_end, D
estAccessor dest_acc) | | DestIterator dest_iter, DestIterator dest_iter_end, D
estAccessor dest_acc) | |
| { | | { | |
| resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_it
er, dest_iter_end, dest_acc, | | resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_it
er, dest_iter_end, dest_acc, | |
| CatmullRomSpline<double>()); | | CatmullRomSpline<double>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline void | |
| void | | | |
| resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAcce
ssor> src, | | resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAcce
ssor> src, | |
|
| triple<DestIterator, DestIterator, DestAccessor> dest
) | | triple<DestIterator, DestIterator, DestA
ccessor> dest) | |
| { | | { | |
| resizeImageCatmullRomInterpolation(src.first, src.second, src.third, | | resizeImageCatmullRomInterpolation(src.first, src.second, src.third, | |
|
| dest.first, dest.second, dest.third); | | dest.first, dest.second, dest.third) | |
| } | | ; | |
| | | | |
| #if 0 | | | |
| /*****************************************************************/ | | | |
| /* */ | | | |
| /* resizeImageCubicInterpolation */ | | | |
| /* */ | | | |
| /*****************************************************************/ | | | |
| | | | |
| /** \brief Resize image using the cardinal B-spline interpolation function. | | | |
| | | | |
| The function calls like \ref resizeImageSplineInterpolation() with | | | |
| \ref vigra::BSpline<3, double> and prefiltering as an interpolation ker | | | |
| nel. | | | |
| The interpolated function has two continuous derivatives. | | | |
| (See \ref resizeImageSplineInterpolation() for more documentation) | | | |
| | | | |
| <b>\#include</b> \<vigra/resizeimage.hxx\><br> | | | |
| Namespace: vigra | | | |
| | | | |
| */ | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | | |
| void | | | |
| resizeImageCubicInterpolation(SrcIterator src_iter, SrcIterator src_iter_en | | | |
| d, SrcAccessor src_acc, | | | |
| DestIterator dest_iter, DestIterator dest_iter_end, D | | | |
| estAccessor dest_acc) | | | |
| { | | | |
| resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_it | | | |
| er, dest_iter_end, dest_acc, | | | |
| BSpline<3, double>()); | | | |
| } | | } | |
| | | | |
|
| template <class SrcIterator, class SrcAccessor, | | template <class T1, class S1, | |
| class DestIterator, class DestAccessor> | | class T2, class S2> | |
| inline | | inline void | |
| void | | resizeImageCatmullRomInterpolation(MultiArrayView<2, T1, S1> const & src, | |
| resizeImageCubicInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> | | MultiArrayView<2, T2, S2> dest) | |
| src, | | | |
| triple<DestIterator, DestIterator, DestAccessor> dest | | | |
| ) | | | |
| { | | { | |
|
| resizeImageCubicInterpolation(src.first, src.second, src.third, | | resizeImageCatmullRomInterpolation(srcImageRange(src), | |
| dest.first, dest.second, dest.third); | | destImageRange(dest)); | |
| } | | } | |
|
| #endif | | | |
| | | | |
| /*****************************************************************/ | | /*****************************************************************/ | |
| /* */ | | /* */ | |
| /* resizeImageCoscotInterpolation */ | | /* resizeImageCoscotInterpolation */ | |
| /* */ | | /* */ | |
| /*****************************************************************/ | | /*****************************************************************/ | |
| | | | |
| /** \brief Resize image using the Coscot interpolation function. | | /** \brief Resize image using the Coscot interpolation function. | |
| | | | |
| The function calls \ref resizeImageSplineInterpolation() with | | The function calls \ref resizeImageSplineInterpolation() with | |
| \ref vigra::CoscotFunction as an interpolation kernel. | | \ref vigra::CoscotFunction as an interpolation kernel. | |
| The interpolated function has one continuous derivative. | | The interpolated function has one continuous derivative. | |
| (See \ref resizeImageSplineInterpolation() for more documentation) | | (See \ref resizeImageSplineInterpolation() for more documentation) | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | void | |
| | | resizeImageCoscotInterpolation(MultiArrayView<2, T1, S1> const & sr | |
| | | c, | |
| | | MultiArrayView<2, T2, S2> dest); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{resizeImageCoscotInterpolation} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator sr
c_iter_end, SrcAccessor src_acc, | | resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator sr
c_iter_end, SrcAccessor src_acc, | |
| DestIterator dest_iter, DestIterator dest_ite
r_end, DestAccessor dest_acc); | | DestIterator dest_iter, DestIterator dest_ite
r_end, DestAccessor dest_acc); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, Src
Accessor> src, | | resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, Src
Accessor> src, | |
| triple<DestIterator, DestIterator, DestAccess
or> dest); | | triple<DestIterator, DestIterator, DestAccess
or> dest); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b>\#include</b> \<vigra/resizeimage.hxx\><br> | | <b>\#include</b> \<vigra/resizeimage.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
|
| | | \code | |
| | | MultiArray<2, unsigned char> src(w, h); | |
| | | MultiArray<2, float> dest(w_new, h_new); | |
| | | | |
| | | resizeImageCoscotInterpolation(src, dest); | |
| | | \endcode | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void resizeImageCoscotInterpolat
ion) | | doxygen_overloaded_function(template <...> void resizeImageCoscotInterpolat
ion) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| void | | void | |
| resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_e
nd, SrcAccessor src_acc, | | resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_e
nd, SrcAccessor src_acc, | |
| DestIterator dest_iter, DestIterator dest_iter_end, D
estAccessor dest_acc) | | DestIterator dest_iter, DestIterator dest_iter_end, D
estAccessor dest_acc) | |
| { | | { | |
| resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_it
er, dest_iter_end, dest_acc, | | resizeImageSplineInterpolation(src_iter, src_iter_end, src_acc, dest_it
er, dest_iter_end, dest_acc, | |
| CoscotFunction<double>()); | | CoscotFunction<double>()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
|
| inline | | inline void | |
| void | | | |
| resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | | resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | |
|
| triple<DestIterator, DestIterator, DestAccessor> dest
) | | triple<DestIterator, DestIterator, DestAcces
sor> dest) | |
| { | | { | |
| resizeImageCoscotInterpolation(src.first, src.second, src.third, | | resizeImageCoscotInterpolation(src.first, src.second, src.third, | |
| dest.first, dest.second, dest.third); | | dest.first, dest.second, dest.third); | |
| } | | } | |
| | | | |
|
| #if 0 // old version of the spline interpolation algorithm | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| /********************************************************/ | | inline void | |
| /* */ | | resizeImageCoscotInterpolation(MultiArrayView<2, T1, S1> const & src, | |
| /* resizeCalculateSplineCoefficients */ | | MultiArrayView<2, T2, S2> dest) | |
| /* (internally used by resize functions) */ | | | |
| /* */ | | | |
| /********************************************************/ | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, class VALUETYPE> | | | |
| void | | | |
| resizeCalculateSplineCoefficients(SrcIterator i1, SrcIterator iend, | | | |
| SrcAccessor a, VALUETYPE * i2) | | | |
| { | | | |
| int n = iend - i1; | | | |
| | | | |
| if(n <= 0) return; | | | |
| | | | |
| VALUETYPE zero = NumericTraits<VALUETYPE>::zero(); | | | |
| VALUETYPE two = 2.0 * NumericTraits<VALUETYPE>::one(); | | | |
| VALUETYPE half = 0.5 * NumericTraits<VALUETYPE>::one(); | | | |
| | | | |
| *i2 = zero; | | | |
| if(n == 1) return; | | | |
| | | | |
| std::vector<VALUETYPE> vec(n); | | | |
| typename std::vector<VALUETYPE>::iterator u = vec.begin(); | | | |
| | | | |
| *u = zero; | | | |
| | | | |
| for(++i1, ++i2, ++u, --iend; i1 != iend; ++i1, ++i2, ++u) | | | |
| { | | | |
| VALUETYPE p = 0.5 * i2[-1] + two; | | | |
| *i2 = half / p; | | | |
| *u = 3.0 *(a(i1,1) - 2.0 * a(i1) + a(i1, -1)) - 0.5 * u[-1] / p; | | | |
| } | | | |
| | | | |
| *i2 = zero; | | | |
| | | | |
| for(--i2, --u; u != vec; --u, --i2) | | | |
| { | | | |
| *i2 = *i2 * i2[1] + *u; | | | |
| } | | | |
| } | | | |
| | | | |
| /********************************************************/ | | | |
| /* */ | | | |
| /* resizeImageInternalSplineGradient */ | | | |
| /* */ | | | |
| /********************************************************/ | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DoubleIterator, class TempIterator, class DestIterator> | | | |
| void | | | |
| resizeImageInternalSplineGradient(SrcIterator in, SrcIterator inend, SrcAcc | | | |
| essor sa, | | | |
| DoubleIterator tmp, TempIterator r, DestIterator i | | | |
| d) | | | |
| { | | | |
| int w = inend - in; | | | |
| | | | |
| int x; | | | |
| | | | |
| typedef typename SrcAccessor::value_type SRCVT; | | | |
| typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE; | | | |
| | | | |
| // calculate border derivatives | | | |
| SrcIterator xs = in; | | | |
| TMPTYPE p0 = -11.0/6.0 * sa(xs); ++xs; | | | |
| p0 += 3.0 * sa(xs); ++xs; | | | |
| p0 += -1.5 * sa(xs); ++xs; | | | |
| p0 += 1.0/3.0 * sa(xs); | | | |
| | | | |
| xs = in + w-1; | | | |
| TMPTYPE pw = 11.0/6.0 * sa(xs); --xs; | | | |
| pw += -3.0 * sa(xs); --xs; | | | |
| pw += 1.5 * sa(xs); --xs; | | | |
| pw += -1.0/3.0 * sa(xs); | | | |
| | | | |
| xs = in + 2; | | | |
| SrcIterator xs1 = in; | | | |
| | | | |
| for(x=1; x<w-1; ++x, ++xs, ++xs1) | | | |
| { | | | |
| r[x] = 3.0 * (sa(xs) - sa(xs1)); | | | |
| } | | | |
| | | | |
| r[1] -= p0; | | | |
| r[w-2] -= pw; | | | |
| | | | |
| double q = 0.25; | | | |
| | | | |
| id[0] = p0; | | | |
| id[w-1] = pw; | | | |
| id[1] = 0.25 * r[1]; | | | |
| | | | |
| for(x=2; x<w-1; ++x) | | | |
| { | | | |
| tmp[x] = q; | | | |
| q = 1.0 / (4.0 - q); | | | |
| id[x] = q * (r[x] - id[x-1]); | | | |
| } | | | |
| | | | |
| for(x=w-3; x>=1; --x) | | | |
| { | | | |
| id[x] -= tmp[x+1]*id[x+1]; | | | |
| } | | | |
| } | | | |
| | | | |
| /********************************************************/ | | | |
| /* */ | | | |
| /* resizeImageInternalSplineInterpolation */ | | | |
| /* */ | | | |
| /********************************************************/ | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | | |
| void | | | |
| resizeImageInternalSplineInterpolation(SrcIterator is, SrcIterator iend, Sr | | | |
| cAccessor sa, | | | |
| DestIterator id, DestIterator idend, DestAccessor da) | | | |
| { | | | |
| int w = iend.x - is.x; | | | |
| int h = iend.y - is.y; | | | |
| | | | |
| int wnew = idend.x - id.x; | | | |
| int hnew = idend.y - id.y; | | | |
| | | | |
| typedef typename SrcAccessor::value_type SRCVT; | | | |
| typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE; | | | |
| typedef typename BasicImage<TMPTYPE>::Iterator TMPITER; | | | |
| typedef | | | |
| NumericTraits<typename DestAccessor::value_type> DestTraits; | | | |
| | | | |
| BasicImage<TMPTYPE> dx(w,h); | | | |
| BasicImage<TMPTYPE> dy(w,h); | | | |
| BasicImage<TMPTYPE> dxy(w,h); | | | |
| BasicImage<TMPTYPE> W(4,4), W1(4,4); | | | |
| std::vector<TMPTYPE> R(w > h ? w : h); | | | |
| std::vector<double> tmp(w > h ? w : h); | | | |
| | | | |
| typename BasicImage<TMPTYPE>::Accessor ta; | | | |
| | | | |
| SrcIterator in = is; | | | |
| | | | |
| TMPITER idx = dx.upperLeft(); | | | |
| TMPITER idy = dy.upperLeft(); | | | |
| TMPITER idxy = dxy.upperLeft(); | | | |
| typename std::vector<TMPTYPE>::iterator r = R.begin(); | | | |
| typename std::vector<double>::iterator it = tmp.begin(); | | | |
| | | | |
| double ig[] = { 1.0, 0.0, -3.0, 2.0, | | | |
| 0.0, 1.0, -2.0, 1.0, | | | |
| 0.0, 0.0, 3.0, -2.0, | | | |
| 0.0, 0.0, -1.0, 1.0 }; | | | |
| | | | |
| int x, y, i, j, k; | | | |
| | | | |
| // calculate x derivatives | | | |
| for(y=0; y<h; ++y, ++in.y, ++idx.y) | | | |
| { | | | |
| typename SrcIterator::row_iterator sr = in.rowIterator(); | | | |
| typename TMPITER::row_iterator dr = idx.rowIterator(); | | | |
| resizeImageInternalSplineGradient(sr, sr+w, sa, | | | |
| it, r, dr); | | | |
| } | | | |
| | | | |
| in = is; | | | |
| | | | |
| // calculate y derivatives | | | |
| for(x=0; x<w; ++x, ++in.x, ++idy.x) | | | |
| { | | | |
| typename SrcIterator::column_iterator sc = in.columnIterator(); | | | |
| typename TMPITER::column_iterator dc = idy.columnIterator(); | | | |
| resizeImageInternalSplineGradient(sc, sc+h, sa, | | | |
| it, r, dc); | | | |
| } | | | |
| | | | |
| in = is; | | | |
| idy = dy.upperLeft(); | | | |
| | | | |
| // calculate mixed derivatives | | | |
| for(y=0; y<h; ++y, ++idy.y, ++idxy.y) | | | |
| { | | | |
| typename TMPITER::row_iterator sr = idy.rowIterator(); | | | |
| typename TMPITER::row_iterator dr = idxy.rowIterator(); | | | |
| resizeImageInternalSplineGradient(sr, sr+w, ta, | | | |
| it, r, dr); | | | |
| } | | | |
| | | | |
| double du = (double)(w-1) / (wnew-1); | | | |
| double dv = (double)(h-1) / (hnew-1); | | | |
| double ov = 0.0; | | | |
| int oy = 0; | | | |
| int yy = oy; | | | |
| | | | |
| DestIterator xxd = id, yyd = id; | | | |
| | | | |
| static Diff2D down(0,1), right(1,0), downright(1,1); | | | |
| | | | |
| for(y=0; y<h-1; ++y, ++in.y, ov -= 1.0) | | | |
| { | | | |
| if(y < h-2 && ov >= 1.0) continue; | | | |
| int y1 = y+1; | | | |
| double v = ov; | | | |
| double ou = 0.0; | | | |
| int ox = 0; | | | |
| int xx = ox; | | | |
| | | | |
| SrcIterator xs = in; | | | |
| for(x=0; x<w-1; ++x, ++xs.x, ou -= 1.0) | | | |
| { | | | |
| if(x < w-2 && ou >= 1.0) continue; | | | |
| int x1 = x+1; | | | |
| double u = ou; | | | |
| | | | |
| DestIterator xd = id + Diff2D(ox,oy); | | | |
| W[0][0] = sa(xs); | | | |
| W[0][1] = dy(x, y); | | | |
| W[0][2] = sa(xs, down); | | | |
| W[0][3] = dy(x, y1); | | | |
| W[1][0] = dx(x, y); | | | |
| W[1][1] = dxy(x, y); | | | |
| W[1][2] = dx(x, y1); | | | |
| W[1][3] = dxy(x, y1); | | | |
| W[2][0] = sa(xs, right); | | | |
| W[2][1] = dy(x1,y); | | | |
| W[2][2] = sa(xs, downright); | | | |
| W[2][3] = dy(x1, y1); | | | |
| W[3][0] = dx(x1, y); | | | |
| W[3][1] = dxy(x1, y); | | | |
| W[3][2] = dx(x1, y1); | | | |
| W[3][3] = dxy(x1, y1); | | | |
| | | | |
| for(i=0; i<4; ++i) | | | |
| { | | | |
| for(j=0; j<4; ++j) | | | |
| { | | | |
| W1[j][i] = ig[j] * W[0][i]; | | | |
| for(k=1; k<4; ++k) | | | |
| { | | | |
| W1[j][i] += ig[j+4*k] * W[k][i]; | | | |
| } | | | |
| } | | | |
| } | | | |
| for(i=0; i<4; ++i) | | | |
| { | | | |
| for(j=0; j<4; ++j) | | | |
| { | | | |
| W[j][i] = ig[i] * W1[j][0]; | | | |
| for(k=1; k<4; ++k) | | | |
| { | | | |
| W[j][i] += ig[4*k+i] * W1[j][k]; | | | |
| } | | | |
| } | | | |
| } | | | |
| | | | |
| TMPTYPE a1,a2,a3,a4; | | | |
| | | | |
| yyd = xd; | | | |
| for(v=ov, yy=oy; v<1.0; v+=dv, ++yyd.y, ++yy) | | | |
| { | | | |
| a1 = W[0][0] + v * (W[0][1] + | | | |
| v * (W[0][2] + v * W[0][3])); | | | |
| a2 = W[1][0] + v * (W[1][1] + | | | |
| v * (W[1][2] + v * W[1][3])); | | | |
| a3 = W[2][0] + v * (W[2][1] + | | | |
| v * (W[2][2] + v * W[2][3])); | | | |
| a4 = W[3][0] + v * (W[3][1] + | | | |
| v * (W[3][2] + v * W[3][3])); | | | |
| | | | |
| xxd = yyd; | | | |
| for(u=ou, xx=ox; u<1.0; u+=du, ++xxd.x, ++xx) | | | |
| { | | | |
| da.set(DestTraits::fromRealPromote(a1 + u * (a2 + u * ( | | | |
| a3 + u * a4))), xxd); | | | |
| } | | | |
| | | | |
| if(xx == wnew-1) | | | |
| { | | | |
| da.set(DestTraits::fromRealPromote(a1 + a2 + a3 + a4), | | | |
| xxd); | | | |
| } | | | |
| } | | | |
| | | | |
| if(yy == hnew-1) | | | |
| { | | | |
| a1 = W[0][0] + W[0][1] + W[0][2] + W[0][3]; | | | |
| a2 = W[1][0] + W[1][1] + W[1][2] + W[1][3]; | | | |
| a3 = W[2][0] + W[2][1] + W[2][2] + W[2][3]; | | | |
| a4 = W[3][0] + W[3][1] + W[3][2] + W[3][3]; | | | |
| | | | |
| DestIterator xxd = yyd; | | | |
| for(u=ou, xx=ox; u<1.0; u+=du, ++xxd.x, ++xx) | | | |
| { | | | |
| da.set(DestTraits::fromRealPromote(a1 + u * (a2 + u * ( | | | |
| a3 + u * a4))), xxd); | | | |
| } | | | |
| | | | |
| if(xx == wnew-1) | | | |
| { | | | |
| da.set(DestTraits::fromRealPromote(a1 + a2 + a3 + a4), | | | |
| xxd); | | | |
| } | | | |
| } | | | |
| | | | |
| ou = u; | | | |
| ox = xx; | | | |
| } | | | |
| ov = v; | | | |
| oy = yy; | | | |
| } | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | | |
| void | | | |
| resizeImageSplineInterpolation(SrcIterator is, SrcIterator iend, SrcAccesso | | | |
| r sa, | | | |
| DestIterator id, DestIterator idend, DestAccessor da) | | | |
| { | | | |
| int w = iend.x - is.x; | | | |
| int h = iend.y - is.y; | | | |
| | | | |
| int wnew = idend.x - id.x; | | | |
| int hnew = idend.y - id.y; | | | |
| | | | |
| vigra_precondition((w > 3) && (h > 3), | | | |
| "resizeImageSplineInterpolation(): " | | | |
| "Source image too small.\n"); | | | |
| vigra_precondition((wnew > 1) && (hnew > 1), | | | |
| "resizeImageSplineInterpolation(): " | | | |
| "Destination image too small.\n"); | | | |
| | | | |
| double scale = 2.0; | | | |
| | | | |
| if(wnew < w || hnew < h) | | | |
| { | | | |
| typedef typename SrcAccessor::value_type SRCVT; | | | |
| typedef typename NumericTraits<SRCVT>::RealPromote TMPTYPE; | | | |
| typedef typename BasicImage<TMPTYPE>::Iterator TMPITER; | | | |
| | | | |
| BasicImage<TMPTYPE> t(w,h); | | | |
| TMPITER it = t.upperLeft(); | | | |
| | | | |
| if(wnew < w) | | | |
| { | | | |
| recursiveSmoothX(is, iend, sa, | | | |
| it, t.accessor(), (double)w/wnew/scale); | | | |
| | | | |
| if(hnew < h) | | | |
| { | | | |
| recursiveSmoothY(it, t.lowerRight(), t.accessor(), | | | |
| it, t.accessor(), (double)h/hnew/scale); | | | |
| } | | | |
| } | | | |
| else | | | |
| { | | | |
| recursiveSmoothY(is, iend, sa, | | | |
| it, t.accessor(), (double)h/hnew/scale); | | | |
| } | | | |
| | | | |
| resizeImageInternalSplineInterpolation(it, t.lowerRight(), t.access | | | |
| or(), | | | |
| id, idend, da); | | | |
| } | | | |
| else | | | |
| { | | | |
| resizeImageInternalSplineInterpolation(is, iend, sa, id, idend, da) | | | |
| ; | | | |
| } | | | |
| } | | | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor> | | | |
| inline | | | |
| void | | | |
| resizeImageSplineInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor | | | |
| > src, | | | |
| triple<DestIterator, DestIterator, DestAccessor> dest | | | |
| ) | | | |
| { | | { | |
|
| resizeImageSplineInterpolation(src.first, src.second, src.third, | | resizeImageCoscotInterpolation(srcImageRange(src), | |
| dest.first, dest.second, dest.third); | | destImageRange(dest)); | |
| } | | } | |
|
| #endif // old algorithm version | | | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_RESIZEIMAGE_HXX | | #endif // VIGRA_RESIZEIMAGE_HXX | |
| | | | |
End of changes. 62 change blocks. |
| 508 lines changed or deleted | | 218 lines changed or added | |
|
| separableconvolution.hxx | | separableconvolution.hxx | |
| | | | |
| skipping to change at line 46 | | skipping to change at line 46 | |
| #ifndef VIGRA_SEPARABLECONVOLUTION_HXX | | #ifndef VIGRA_SEPARABLECONVOLUTION_HXX | |
| #define VIGRA_SEPARABLECONVOLUTION_HXX | | #define VIGRA_SEPARABLECONVOLUTION_HXX | |
| | | | |
| #include <cmath> | | #include <cmath> | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "imageiteratoradapter.hxx" | | #include "imageiteratoradapter.hxx" | |
| #include "bordertreatment.hxx" | | #include "bordertreatment.hxx" | |
| #include "gaussians.hxx" | | #include "gaussians.hxx" | |
| #include "array_vector.hxx" | | #include "array_vector.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
|
| | | template <class ARITHTYPE> | |
| | | class Kernel1D; | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* internalConvolveLineOptimistic */ | | /* internalConvolveLineOptimistic */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| // This function assumes that the input array is actually larger than | | // This function assumes that the input array is actually larger than | |
| // the range [is, iend), so that it can safely access values outside | | // the range [is, iend), so that it can safely access values outside | |
| // this range. This is useful if (1) we work on a small ROI, or | | // this range. This is useful if (1) we work on a small ROI, or | |
| // (2) we enlarge the input by copying with border treatment. | | // (2) we enlarge the input by copying with border treatment. | |
| | | | |
| skipping to change at line 794 | | skipping to change at line 798 | |
| If <tt>start</tt> and <tt>stop</tt> are non-zero, the relation | | If <tt>start</tt> and <tt>stop</tt> are non-zero, the relation | |
| <tt>0 <= start < stop <= width</tt> must hold (where <tt>width</tt> | | <tt>0 <= start < stop <= width</tt> must hold (where <tt>width</tt> | |
| is the length of the input array). The convolution is then restricted t
o that | | is the length of the input array). The convolution is then restricted t
o that | |
| subrange, and it is assumed that the output array only refers to that | | subrange, and it is assumed that the output array only refers to that | |
| subrange (i.e. <tt>id</tt> points to the element corresponding to | | subrange (i.e. <tt>id</tt> points to the element corresponding to | |
| <tt>start</tt>). If <tt>start</tt> and <tt>stop</tt> are both zero | | <tt>start</tt>). If <tt>start</tt> and <tt>stop</tt> are both zero | |
| (the default), the entire array is convolved. | | (the default), the entire array is convolved. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void convolveLine(SrcIterator is, SrcIterator isend, SrcAccessor sa
, | | void convolveLine(SrcIterator is, SrcIterator isend, SrcAccessor sa
, | |
| DestIterator id, DestAccessor da, | | DestIterator id, DestAccessor da, | |
| KernelIterator ik, KernelAccessor ka, | | KernelIterator ik, KernelAccessor ka, | |
| int kleft, int kright, BorderTreatmentMode border
, | | int kleft, int kright, BorderTreatmentMode border
, | |
| int start = 0, int stop = 0 ) | | int start = 0, int stop = 0 ) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void convolveLine(triple<SrcIterator, SrcIterator, SrcAccessor> src
, | | void convolveLine(triple<SrcIterator, SrcIterator, SrcAccessor> src
, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| tuple5<KernelIterator, KernelAccessor, | | tuple5<KernelIterator, KernelAccessor, | |
| int, int, BorderTreatmentMode> kernel, | | int, int, BorderTreatmentMode> kernel, | |
| int start = 0, int stop = 0) | | int start = 0, int stop = 0) | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/separableconvolution.hxx\> | | <b>\#include</b> \<vigra/separableconvolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
| std::vector<float> src, dest; | | std::vector<float> src, dest; | |
| ... | | ... | |
| | | | |
| // define binomial filter of size 5 | | // define binomial filter of size 5 | |
| static float kernel[] = | | static float kernel[] = | |
| { 1.0/16.0, 4.0/16.0, 6.0/16.0, 4.0/16.0, 1.0/16.0}; | | { 1.0/16.0, 4.0/16.0, 6.0/16.0, 4.0/16.0, 1.0/16.0}; | |
| | | | |
| typedef vigra::StandardAccessor<float> FAccessor; | | typedef vigra::StandardAccessor<float> FAccessor; | |
| | | | |
| skipping to change at line 886 | | skipping to change at line 890 | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| kleft <= 0 | | kleft <= 0 | |
| kright >= 0 | | kright >= 0 | |
| iend - is >= kright + kleft + 1 | | iend - is >= kright + kleft + 1 | |
| \endcode | | \endcode | |
| | | | |
| If border == BORDER_TREATMENT_CLIP: Sum of kernel elements must be | | If border == BORDER_TREATMENT_CLIP: Sum of kernel elements must be | |
| != 0. | | != 0. | |
|
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void convolveLine) | | doxygen_overloaded_function(template <...> void convolveLine) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void convolveLine(SrcIterator is, SrcIterator iend, SrcAccessor sa, | | void convolveLine(SrcIterator is, SrcIterator iend, SrcAccessor sa, | |
| DestIterator id, DestAccessor da, | | DestIterator id, DestAccessor da, | |
| KernelIterator ik, KernelAccessor ka, | | KernelIterator ik, KernelAccessor ka, | |
| int kleft, int kright, BorderTreatmentMode border, | | int kleft, int kright, BorderTreatmentMode border, | |
| int start = 0, int stop = 0) | | int start = 0, int stop = 0) | |
| { | | { | |
|
| typedef typename KernelAccessor::value_type KernelValue; | | | |
| | | | |
| vigra_precondition(kleft <= 0, | | vigra_precondition(kleft <= 0, | |
| "convolveLine(): kleft must be <= 0.\n"); | | "convolveLine(): kleft must be <= 0.\n"); | |
| vigra_precondition(kright >= 0, | | vigra_precondition(kright >= 0, | |
| "convolveLine(): kright must be >= 0.\n"); | | "convolveLine(): kright must be >= 0.\n"); | |
| | | | |
| // int w = iend - is; | | // int w = iend - is; | |
| int w = std::distance( is, iend ); | | int w = std::distance( is, iend ); | |
| | | | |
| vigra_precondition(w >= std::max(kright, -kleft) + 1, | | vigra_precondition(w >= std::max(kright, -kleft) + 1, | |
| "convolveLine(): kernel longer than line.\n"); | | "convolveLine(): kernel longer than line.\n"); | |
| | | | |
| skipping to change at line 1000 | | skipping to change at line 1001 | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Performs a 1 dimensional convolution in x direction. | | /** \brief Performs a 1 dimensional convolution in x direction. | |
| | | | |
| It calls \ref convolveLine() for every row of the image. See \ref convo
lveLine() | | It calls \ref convolveLine() for every row of the image. See \ref convo
lveLine() | |
| for more information about required interfaces and vigra_preconditions. | | for more information about required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3> | |
| | | void | |
| | | separableConvolveX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel1D<T3> const & kernel); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{separableConvolveX} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor, | | class DestImageIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void separableConvolveX(SrcImageIterator supperleft, | | void separableConvolveX(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor s
a, | | SrcImageIterator slowerright, SrcAccessor s
a, | |
| DestImageIterator dupperleft, DestAccessor
da, | | DestImageIterator dupperleft, DestAccessor
da, | |
| KernelIterator ik, KernelAccessor ka, | | KernelIterator ik, KernelAccessor ka, | |
| int kleft, int kright, BorderTreatmentMode
border) | | int kleft, int kright, BorderTreatmentMode
border) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor, | | class DestImageIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void separableConvolveX(triple<SrcImageIterator, SrcImageIterator,
SrcAccessor> src, | | void separableConvolveX(triple<SrcImageIterator, SrcImageIterator,
SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| tuple5<KernelIterator, KernelAccessor, | | tuple5<KernelIterator, KernelAccessor, | |
| int, int, BorderTreatmentMode>
kernel) | | int, int, BorderTreatmentMode>
kernel) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/separableconvolution.hxx\> | | <b>\#include</b> \<vigra/separableconvolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | // define Gaussian kernel with std. deviation 3.0 | |
| | | Kernel1D<double> kernel; | |
| | | kernel.initGaussian(3.0); | |
| | | | |
|
| | | // apply 1D filter along the x-axis | |
| | | separableConvolveX(src, dest, kernel); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{separableConvolveX} | |
| \code | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| // define Gaussian kernel with std. deviation 3.0 | | // define Gaussian kernel with std. deviation 3.0 | |
| vigra::Kernel1D<double> kernel; | | vigra::Kernel1D<double> kernel; | |
| kernel.initGaussian(3.0); | | kernel.initGaussian(3.0); | |
| | | | |
|
| | | // apply 1D filter along the x-axis | |
| vigra::separableConvolveX(srcImageRange(src), destImage(dest), kernel1d
(kernel)); | | vigra::separableConvolveX(srcImageRange(src), destImage(dest), kernel1d
(kernel)); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
|
| | | <b>Preconditions:</b> | |
| | | | |
| | | <ul> | |
| | | <li> The x-axis must be longer than the kernel radius: <tt>w > std::max | |
| | | (kernel.right(), -kernel.left())</tt>. | |
| | | <li> If <tt>border == BORDER_TREATMENT_CLIP</tt>: The sum of kernel ele | |
| | | ments must be != 0. | |
| | | </ul> | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void separableConvolveX) | | doxygen_overloaded_function(template <...> void separableConvolveX) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void separableConvolveX(SrcIterator supperleft, | | void separableConvolveX(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIterator dupperleft, DestAccessor da, | | DestIterator dupperleft, DestAccessor da, | |
| KernelIterator ik, KernelAccessor ka, | | KernelIterator ik, KernelAccessor ka, | |
| int kleft, int kright, BorderTreatmentMode border) | | int kleft, int kright, BorderTreatmentMode border) | |
| { | | { | |
|
| typedef typename KernelAccessor::value_type KernelValue; | | | |
| | | | |
| vigra_precondition(kleft <= 0, | | vigra_precondition(kleft <= 0, | |
| "separableConvolveX(): kleft must be <= 0.\n"); | | "separableConvolveX(): kleft must be <= 0.\n"); | |
| vigra_precondition(kright >= 0, | | vigra_precondition(kright >= 0, | |
| "separableConvolveX(): kright must be >= 0.\n"); | | "separableConvolveX(): kright must be >= 0.\n"); | |
| | | | |
| int w = slowerright.x - supperleft.x; | | int w = slowerright.x - supperleft.x; | |
| int h = slowerright.y - supperleft.y; | | int h = slowerright.y - supperleft.y; | |
| | | | |
| vigra_precondition(w >= std::max(kright, -kleft) + 1, | | vigra_precondition(w >= std::max(kright, -kleft) + 1, | |
| "separableConvolveX(): kernel longer than line\n"); | | "separableConvolveX(): kernel longer than line\n"); | |
| | | | |
| skipping to change at line 1085 | | skipping to change at line 1119 | |
| convolveLine(rs, rs+w, sa, rd, da, | | convolveLine(rs, rs+w, sa, rd, da, | |
| ik, ka, kleft, kright, border); | | ik, ka, kleft, kright, border); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| inline void | | inline void | |
| separableConvolveX(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | separableConvolveX(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| tuple5<KernelIterator, KernelAccessor, | | tuple5<KernelIterator, KernelAccessor, | |
| int, int, BorderTreatmentMode> kernel) | | int, int, BorderTreatmentMode> kernel) | |
| { | | { | |
| separableConvolveX(src.first, src.second, src.third, | | separableConvolveX(src.first, src.second, src.third, | |
|
| dest.first, dest.second, | | dest.first, dest.second, | |
| kernel.first, kernel.second, | | kernel.first, kernel.second, | |
| kernel.third, kernel.fourth, kernel.fifth); | | kernel.third, kernel.fourth, kernel.fifth); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3> | |
| | | inline void | |
| | | separableConvolveX(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel1D<T3> const & kernel) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "separableConvolveX(): shape mismatch between input and output."); | |
| | | separableConvolveX(srcImageRange(src), | |
| | | destImage(dest), kernel1d(kernel)); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* separableConvolveY */ | | /* separableConvolveY */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Performs a 1 dimensional convolution in y direction. | | /** \brief Performs a 1 dimensional convolution in y direction. | |
| | | | |
| It calls \ref convolveLine() for every column of the image. See \ref co
nvolveLine() | | It calls \ref convolveLine() for every column of the image. See \ref co
nvolveLine() | |
| for more information about required interfaces and vigra_preconditions. | | for more information about required interfaces and vigra_preconditions. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3> | |
| | | void | |
| | | separableConvolveY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel1D<T3> const & kernel); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{separableConvolveY} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor, | | class DestImageIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void separableConvolveY(SrcImageIterator supperleft, | | void separableConvolveY(SrcImageIterator supperleft, | |
| SrcImageIterator slowerright, SrcAccessor s
a, | | SrcImageIterator slowerright, SrcAccessor s
a, | |
| DestImageIterator dupperleft, DestAccessor
da, | | DestImageIterator dupperleft, DestAccessor
da, | |
| KernelIterator ik, KernelAccessor ka, | | KernelIterator ik, KernelAccessor ka, | |
| int kleft, int kright, BorderTreatmentMode
border) | | int kleft, int kright, BorderTreatmentMode
border) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcImageIterator, class SrcAccessor, | | template <class SrcImageIterator, class SrcAccessor, | |
| class DestImageIterator, class DestAccessor, | | class DestImageIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void separableConvolveY(triple<SrcImageIterator, SrcImageIterator,
SrcAccessor> src, | | void separableConvolveY(triple<SrcImageIterator, SrcImageIterator,
SrcAccessor> src, | |
| pair<DestImageIterator, DestAccessor> dest, | | pair<DestImageIterator, DestAccessor> dest, | |
| tuple5<KernelIterator, KernelAccessor, | | tuple5<KernelIterator, KernelAccessor, | |
| int, int, BorderTreatmentMode>
kernel) | | int, int, BorderTreatmentMode>
kernel) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/separableconvolution.hxx\> | | <b>\#include</b> \<vigra/separableconvolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | // define Gaussian kernel with std. deviation 3.0 | |
| | | Kernel1D kernel; | |
| | | kernel.initGaussian(3.0); | |
| | | | |
| | | // apply 1D filter along the y-axis | |
| | | separableConvolveY(src, dest, kernel); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{separableConvolveY} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| // define Gaussian kernel with std. deviation 3.0 | | // define Gaussian kernel with std. deviation 3.0 | |
| vigra::Kernel1D kernel; | | vigra::Kernel1D kernel; | |
| kernel.initGaussian(3.0); | | kernel.initGaussian(3.0); | |
| | | | |
| vigra::separableConvolveY(srcImageRange(src), destImage(dest), kernel1d
(kernel)); | | vigra::separableConvolveY(srcImageRange(src), destImage(dest), kernel1d
(kernel)); | |
|
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| | | <b>Preconditions:</b> | |
| | | | |
|
| | | <ul> | |
| | | <li> The y-axis must be longer than the kernel radius: <tt>h > std::max | |
| | | (kernel.right(), -kernel.left())</tt>. | |
| | | <li> If <tt>border == BORDER_TREATMENT_CLIP</tt>: The sum of kernel ele | |
| | | ments must be != 0. | |
| | | </ul> | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void separableConvolveY) | | doxygen_overloaded_function(template <...> void separableConvolveY) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void separableConvolveY(SrcIterator supperleft, | | void separableConvolveY(SrcIterator supperleft, | |
| SrcIterator slowerright, SrcAccessor sa, | | SrcIterator slowerright, SrcAccessor sa, | |
| DestIterator dupperleft, DestAccessor da, | | DestIterator dupperleft, DestAccessor da, | |
| KernelIterator ik, KernelAccessor ka, | | KernelIterator ik, KernelAccessor ka, | |
| int kleft, int kright, BorderTreatmentMode border) | | int kleft, int kright, BorderTreatmentMode border) | |
| { | | { | |
|
| typedef typename KernelAccessor::value_type KernelValue; | | | |
| | | | |
| vigra_precondition(kleft <= 0, | | vigra_precondition(kleft <= 0, | |
| "separableConvolveY(): kleft must be <= 0.\n"); | | "separableConvolveY(): kleft must be <= 0.\n"); | |
| vigra_precondition(kright >= 0, | | vigra_precondition(kright >= 0, | |
| "separableConvolveY(): kright must be >= 0.\n"); | | "separableConvolveY(): kright must be >= 0.\n"); | |
| | | | |
| int w = slowerright.x - supperleft.x; | | int w = slowerright.x - supperleft.x; | |
| int h = slowerright.y - supperleft.y; | | int h = slowerright.y - supperleft.y; | |
| | | | |
| vigra_precondition(h >= std::max(kright, -kleft) + 1, | | vigra_precondition(h >= std::max(kright, -kleft) + 1, | |
| "separableConvolveY(): kernel longer than line\n"); | | "separableConvolveY(): kernel longer than line\n"); | |
| | | | |
| skipping to change at line 1193 | | skipping to change at line 1273 | |
| convolveLine(cs, cs+h, sa, cd, da, | | convolveLine(cs, cs+h, sa, cd, da, | |
| ik, ka, kleft, kright, border); | | ik, ka, kleft, kright, border); | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| inline void | | inline void | |
| separableConvolveY(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | separableConvolveY(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| tuple5<KernelIterator, KernelAccessor, | | tuple5<KernelIterator, KernelAccessor, | |
| int, int, BorderTreatmentMode> kernel) | | int, int, BorderTreatmentMode> kernel) | |
| { | | { | |
| separableConvolveY(src.first, src.second, src.third, | | separableConvolveY(src.first, src.second, src.third, | |
|
| dest.first, dest.second, | | dest.first, dest.second, | |
| kernel.first, kernel.second, | | kernel.first, kernel.second, | |
| kernel.third, kernel.fourth, kernel.fifth); | | kernel.third, kernel.fourth, kernel.fifth); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3> | |
| | | inline void | |
| | | separableConvolveY(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel1D<T3> const & kernel) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "separableConvolveY(): shape mismatch between input and output."); | |
| | | separableConvolveY(srcImageRange(src), | |
| | | destImage(dest), kernel1d(kernel)); | |
| } | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* Kernel1D */ | | /* Kernel1D */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| | | | |
| skipping to change at line 1226 | | skipping to change at line 1320 | |
| Convolution functions access the kernel via a 1 dimensional random acce
ss | | Convolution functions access the kernel via a 1 dimensional random acce
ss | |
| iterator which they get by calling \ref center(). This iterator | | iterator which they get by calling \ref center(). This iterator | |
| points to the center of the kernel. The kernel's size is given by its l
eft() (<=0) | | points to the center of the kernel. The kernel's size is given by its l
eft() (<=0) | |
| and right() (>= 0) methods. The desired border treatment mode is | | and right() (>= 0) methods. The desired border treatment mode is | |
| returned by borderTreatment(). | | returned by borderTreatment(). | |
| | | | |
| The different init functions create a kernel with the specified | | The different init functions create a kernel with the specified | |
| properties. The kernel's value_type must be a linear space, i.e. it | | properties. The kernel's value_type must be a linear space, i.e. it | |
| must define multiplication with doubles and NumericTraits. | | must define multiplication with doubles and NumericTraits. | |
| | | | |
|
| The kernel defines a factory function kernel1d() to create an argument | | | |
| object | | | |
| (see \ref KernelArgumentObjectFactories). | | | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/stdconvolution.hxx\> | | <b>\#include</b> \<vigra/separableconvolution.hxx\><br/> | |
| | | Namespace: vigra | |
| | | | |
| | | \code | |
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | ... | |
| | | | |
| | | // define Gaussian kernel with std. deviation 3.0 | |
| | | Kernel1D kernel; | |
| | | kernel.initGaussian(3.0); | |
| | | | |
|
| | | // apply 1D kernel along the x-axis | |
| | | separableConvolveX(src, dest, kernel); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{Kernel1D} | |
| | | The kernel defines a factory function kernel1d() to create an argument | |
| | | object | |
| | | (see \ref KernelArgumentObjectFactories). | |
| \code | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| // define Gaussian kernel with std. deviation 3.0 | | // define Gaussian kernel with std. deviation 3.0 | |
| vigra::Kernel1D kernel; | | vigra::Kernel1D kernel; | |
| kernel.initGaussian(3.0); | | kernel.initGaussian(3.0); | |
| | | | |
| vigra::separableConvolveX(srcImageRange(src), destImage(dest), kernel1d
(kernel)); | | vigra::separableConvolveX(srcImageRange(src), destImage(dest), kernel1d
(kernel)); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| value_type v = vigra::NumericTraits<value_type>::one(); // if norm is n
ot | | value_type v = vigra::NumericTraits<value_type>::one(); // if norm is n
ot | |
| // given explic
itly | | // given explic
itly | |
| double d; | | double d; | |
| | | | |
| v = d * v; | | v = d * v; | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| | | | |
|
| template <class ARITHTYPE> | | template <class ARITHTYPE = double> | |
| class Kernel1D | | class Kernel1D | |
| { | | { | |
| public: | | public: | |
| typedef ArrayVector<ARITHTYPE> InternalVector; | | typedef ArrayVector<ARITHTYPE> InternalVector; | |
| | | | |
| /** the kernel's value type | | /** the kernel's value type | |
| */ | | */ | |
| typedef typename InternalVector::value_type value_type; | | typedef typename InternalVector::value_type value_type; | |
| | | | |
| /** the kernel's reference type | | /** the kernel's reference type | |
| | | | |
| skipping to change at line 1772 | | skipping to change at line 1878 | |
| void initAveraging(int radius, value_type norm); | | void initAveraging(int radius, value_type norm); | |
| | | | |
| /** Init as an Averaging filter with norm 1. | | /** Init as an Averaging filter with norm 1. | |
| */ | | */ | |
| void initAveraging(int radius) | | void initAveraging(int radius) | |
| { | | { | |
| initAveraging(radius, one()); | | initAveraging(radius, one()); | |
| } | | } | |
| | | | |
| /** | | /** | |
|
| Init as a symmetric gradient filter of the form | | Init as a symmetric gradient filter of the form | |
| <TT>[ 0.5 * norm, 0.0 * norm, -0.5 * norm]</TT> | | <TT>[ 0.5 * norm, 0.0 * norm, -0.5 * norm]</TT> | |
| | | | |
|
| <b>Deprecated</b>. Use initSymmetricDifference() instead. | | <b>Deprecated</b>. Use initSymmetricDifference() instead. | |
| | | | |
| Postconditions: | | Postconditions: | |
| \code | | \code | |
| 1. left() == -1 | | 1. left() == -1 | |
| 2. right() == 1 | | 2. right() == 1 | |
| 3. borderTreatment() == BORDER_TREATMENT_REPEAT | | 3. borderTreatment() == BORDER_TREATMENT_REPEAT | |
| 4. norm() == norm | | 4. norm() == norm | |
| \endcode | | \endcode | |
| */ | | */ | |
|
| void | | void initSymmetricGradient(value_type norm ) | |
| initSymmetricGradient(value_type norm ) | | | |
| { | | { | |
| initSymmetricDifference(norm); | | initSymmetricDifference(norm); | |
| setBorderTreatment(BORDER_TREATMENT_REPEAT); | | setBorderTreatment(BORDER_TREATMENT_REPEAT); | |
| } | | } | |
| | | | |
| /** Init as a symmetric gradient filter with norm 1. | | /** Init as a symmetric gradient filter with norm 1. | |
| | | | |
| <b>Deprecated</b>. Use initSymmetricDifference() instead. | | <b>Deprecated</b>. Use initSymmetricDifference() instead. | |
| */ | | */ | |
| void initSymmetricGradient() | | void initSymmetricGradient() | |
| | | | |
| skipping to change at line 1849 | | skipping to change at line 1954 | |
| 3. borderTreatment() == BORDER_TREATMENT_REFLECT | | 3. borderTreatment() == BORDER_TREATMENT_REFLECT | |
| 4. norm() == 1.0 | | 4. norm() == 1.0 | |
| \endcode | | \endcode | |
| */ | | */ | |
| void initBackwardDifference() | | void initBackwardDifference() | |
| { | | { | |
| this->initExplicitly(0, 1) = 1.0, -1.0; | | this->initExplicitly(0, 1) = 1.0, -1.0; | |
| this->setBorderTreatment(BORDER_TREATMENT_REFLECT); | | this->setBorderTreatment(BORDER_TREATMENT_REFLECT); | |
| } | | } | |
| | | | |
|
| void | | void initSymmetricDifference(value_type norm ); | |
| initSymmetricDifference(value_type norm ); | | | |
| | | | |
| /** Init as the 3-tap symmetric difference filter | | /** Init as the 3-tap symmetric difference filter | |
| The filter values are | | The filter values are | |
| | | | |
| \code | | \code | |
| [0.5, 0, -0.5] | | [0.5, 0, -0.5] | |
| \endcode | | \endcode | |
| | | | |
| Postconditions: | | Postconditions: | |
| \code | | \code | |
| | | | |
| skipping to change at line 1888 | | skipping to change at line 1992 | |
| \endcode | | \endcode | |
| | | | |
| Postconditions: | | Postconditions: | |
| \code | | \code | |
| 1. left() == -1 | | 1. left() == -1 | |
| 2. right() == 1 | | 2. right() == 1 | |
| 3. borderTreatment() == BORDER_TREATMENT_REFLECT | | 3. borderTreatment() == BORDER_TREATMENT_REFLECT | |
| 4. norm() == 1 | | 4. norm() == 1 | |
| \endcode | | \endcode | |
| */ | | */ | |
|
| void | | void initSecondDifference3() | |
| initSecondDifference3() | | | |
| { | | { | |
| this->initExplicitly(-1, 1) = 1.0, -2.0, 1.0; | | this->initExplicitly(-1, 1) = 1.0, -2.0, 1.0; | |
| this->setBorderTreatment(BORDER_TREATMENT_REFLECT); | | this->setBorderTreatment(BORDER_TREATMENT_REFLECT); | |
| } | | } | |
| | | | |
| /** | | /** | |
| Init an optimal 5-tap first derivative filter. | | Init an optimal 5-tap first derivative filter. | |
|
| This filter must be used in conjunction with the corresponding 5 | | This filter must be used in conjunction with the corresponding | |
| -tap smoothing filter | | 5-tap smoothing filter | |
| (see initOptimalFirstDerivativeSmoothing5()), such that the deri | | (see initOptimalFirstDerivativeSmoothing5()), such that the der | |
| vative filter is applied along one dimension, | | ivative filter is applied along one dimension, | |
| and the smoothing filter along the other. | | and the smoothing filter along the other. | |
| The filter values are | | The filter values are | |
| | | | |
| \code | | \code | |
| [0.1, 0.3, 0.0, -0.3, -0.1] | | [0.1, 0.3, 0.0, -0.3, -0.1] | |
| \endcode | | \endcode | |
| | | | |
| These values are optimal in the sense that the 5x5 filter obtai
ned by combining | | These values are optimal in the sense that the 5x5 filter obtai
ned by combining | |
| this filter with the corresponding 5-tap smoothing filter is th
e best possible 5x5 approximation to a | | this filter with the corresponding 5-tap smoothing filter is th
e best possible 5x5 approximation to a | |
| Gaussian first derivative filter. The equivalent Gaussian has s
igma = 0.906. | | Gaussian first derivative filter. The equivalent Gaussian has s
igma = 0.906. | |
| | | | |
| skipping to change at line 1929 | | skipping to change at line 2032 | |
| \endcode | | \endcode | |
| */ | | */ | |
| void initOptimalFirstDerivative5() | | void initOptimalFirstDerivative5() | |
| { | | { | |
| this->initExplicitly(-2, 2) = 0.1, 0.3, 0.0, -0.3, -0.1; | | this->initExplicitly(-2, 2) = 0.1, 0.3, 0.0, -0.3, -0.1; | |
| this->setBorderTreatment(BORDER_TREATMENT_REFLECT); | | this->setBorderTreatment(BORDER_TREATMENT_REFLECT); | |
| } | | } | |
| | | | |
| /** | | /** | |
| Init an optimal 5-tap second derivative filter. | | Init an optimal 5-tap second derivative filter. | |
|
| This filter must be used in conjunction with the corresponding 5 | | This filter must be used in conjunction with the corresponding | |
| -tap smoothing filter | | 5-tap smoothing filter | |
| (see initOptimalSecondDerivativeSmoothing5()), such that the der | | (see initOptimalSecondDerivativeSmoothing5()), such that the de | |
| ivative filter is applied along one dimension, | | rivative filter is applied along one dimension, | |
| and the smoothing filter along the other. | | and the smoothing filter along the other. | |
| The filter values are | | The filter values are | |
| | | | |
| \code | | \code | |
| [0.22075, 0.117, -0.6755, 0.117, 0.22075] | | [0.22075, 0.117, -0.6755, 0.117, 0.22075] | |
| \endcode | | \endcode | |
| | | | |
| These values are optimal in the sense that the 5x5 filter obtai
ned by combining | | These values are optimal in the sense that the 5x5 filter obtai
ned by combining | |
| this filter with the corresponding 5-tap smoothing filter is th
e best possible 5x5 approximation to a | | this filter with the corresponding 5-tap smoothing filter is th
e best possible 5x5 approximation to a | |
| Gaussian second derivative filter. The equivalent Gaussian has
sigma = 0.817. | | Gaussian second derivative filter. The equivalent Gaussian has
sigma = 0.817. | |
| | | | |
| skipping to change at line 2142 | | skipping to change at line 2245 | |
| { | | { | |
| *k = *k * sum; | | *k = *k * sum; | |
| } | | } | |
| | | | |
| norm_ = norm; | | norm_ = norm; | |
| } | | } | |
| | | | |
| /***********************************************************************/ | | /***********************************************************************/ | |
| | | | |
| template <class ARITHTYPE> | | template <class ARITHTYPE> | |
|
| void Kernel1D<ARITHTYPE>::initGaussian(double std_dev, | | void | |
| value_type norm, | | Kernel1D<ARITHTYPE>::initGaussian(double std_dev, | |
| double windowRatio) | | value_type norm, | |
| | | double windowRatio) | |
| { | | { | |
| vigra_precondition(std_dev >= 0.0, | | vigra_precondition(std_dev >= 0.0, | |
| "Kernel1D::initGaussian(): Standard deviation must be >= 0.")
; | | "Kernel1D::initGaussian(): Standard deviation must be >= 0.")
; | |
| vigra_precondition(windowRatio >= 0.0, | | vigra_precondition(windowRatio >= 0.0, | |
| "Kernel1D::initGaussian(): windowRatio must be >= 0."); | | "Kernel1D::initGaussian(): windowRatio must be >= 0."); | |
| | | | |
| if(std_dev > 0.0) | | if(std_dev > 0.0) | |
| { | | { | |
| Gaussian<ARITHTYPE> gauss((ARITHTYPE)std_dev); | | Gaussian<ARITHTYPE> gauss((ARITHTYPE)std_dev); | |
| | | | |
| | | | |
| skipping to change at line 2195 | | skipping to change at line 2299 | |
| else | | else | |
| norm_ = 1.0; | | norm_ = 1.0; | |
| | | | |
| // best border treatment for Gaussians is BORDER_TREATMENT_REFLECT | | // best border treatment for Gaussians is BORDER_TREATMENT_REFLECT | |
| border_treatment_ = BORDER_TREATMENT_REFLECT; | | border_treatment_ = BORDER_TREATMENT_REFLECT; | |
| } | | } | |
| | | | |
| /***********************************************************************/ | | /***********************************************************************/ | |
| | | | |
| template <class ARITHTYPE> | | template <class ARITHTYPE> | |
|
| void Kernel1D<ARITHTYPE>::initDiscreteGaussian(double std_dev, | | void | |
| value_type norm) | | Kernel1D<ARITHTYPE>::initDiscreteGaussian(double std_dev, | |
| | | value_type norm) | |
| { | | { | |
| vigra_precondition(std_dev >= 0.0, | | vigra_precondition(std_dev >= 0.0, | |
| "Kernel1D::initDiscreteGaussian(): Standard deviation must be
>= 0."); | | "Kernel1D::initDiscreteGaussian(): Standard deviation must be
>= 0."); | |
| | | | |
| if(std_dev > 0.0) | | if(std_dev > 0.0) | |
| { | | { | |
| // first calculate required kernel sizes | | // first calculate required kernel sizes | |
| int radius = (int)(3.0*std_dev + 0.5); | | int radius = (int)(3.0*std_dev + 0.5); | |
| if(radius == 0) | | if(radius == 0) | |
| radius = 1; | | radius = 1; | |
| | | | |
| skipping to change at line 2371 | | skipping to change at line 2476 | |
| right_ = radius; | | right_ = radius; | |
| norm_ = norm; | | norm_ = norm; | |
| | | | |
| // best border treatment for Binomial is BORDER_TREATMENT_REFLECT | | // best border treatment for Binomial is BORDER_TREATMENT_REFLECT | |
| border_treatment_ = BORDER_TREATMENT_REFLECT; | | border_treatment_ = BORDER_TREATMENT_REFLECT; | |
| } | | } | |
| | | | |
| /***********************************************************************/ | | /***********************************************************************/ | |
| | | | |
| template <class ARITHTYPE> | | template <class ARITHTYPE> | |
|
| void Kernel1D<ARITHTYPE>::initAveraging(int radius, | | void | |
| value_type norm) | | Kernel1D<ARITHTYPE>::initAveraging(int radius, | |
| | | value_type norm) | |
| { | | { | |
| vigra_precondition(radius > 0, | | vigra_precondition(radius > 0, | |
| "Kernel1D::initAveraging(): Radius must be > 0."); | | "Kernel1D::initAveraging(): Radius must be > 0."); | |
| | | | |
| // calculate scaling | | // calculate scaling | |
| double scale = 1.0 / (radius * 2 + 1); | | double scale = 1.0 / (radius * 2 + 1); | |
| | | | |
| // normalize | | // normalize | |
| kernel_.erase(kernel_.begin(), kernel_.end()); | | kernel_.erase(kernel_.begin(), kernel_.end()); | |
| kernel_.reserve(radius*2+1); | | kernel_.reserve(radius*2+1); | |
| | | | |
End of changes. 47 change blocks. |
| 61 lines changed or deleted | | 171 lines changed or added | |
|
| stdconvolution.hxx | | stdconvolution.hxx | |
| | | | |
| skipping to change at line 45 | | skipping to change at line 45 | |
| | | | |
| #ifndef VIGRA_STDCONVOLUTION_HXX | | #ifndef VIGRA_STDCONVOLUTION_HXX | |
| #define VIGRA_STDCONVOLUTION_HXX | | #define VIGRA_STDCONVOLUTION_HXX | |
| | | | |
| #include <cmath> | | #include <cmath> | |
| #include "stdimage.hxx" | | #include "stdimage.hxx" | |
| #include "bordertreatment.hxx" | | #include "bordertreatment.hxx" | |
| #include "separableconvolution.hxx" | | #include "separableconvolution.hxx" | |
| #include "utilities.hxx" | | #include "utilities.hxx" | |
| #include "sized_int.hxx" | | #include "sized_int.hxx" | |
|
| | | #include "multi_iterator.hxx" | |
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
|
| /** \addtogroup StandardConvolution Two-dimensional convolution functions | | template <class ARITHTYPE> | |
| | | class Kernel2D; | |
| Perform 2D non-separable convolution, with and without ROI mask. | | | |
| | | | |
|
| These generic convolution functions implement | | /** \addtogroup CommonConvolutionFilters | |
| the standard 2D convolution operation for images that fit | | | |
| into the required interface. Arbitrary ROI's are supported | | | |
| by the mask version of the algorithm. | | | |
| The functions need a suitable 2D kernel to operate. | | | |
| */ | | */ | |
| //@{ | | //@{ | |
| | | | |
|
| /** \brief Performs a 2 dimensional convolution of the source image using t | | // documentation is in convolution.hxx | |
| he given | | | |
| kernel. | | | |
| | | | |
| The KernelIterator must point to the center of the kernel, and | | | |
| the kernel's size is given by its upper left (x and y of distance <= 0) | | | |
| and | | | |
| lower right (distance >= 0) corners. The image must always be larger th | | | |
| an the | | | |
| kernel. At those positions where the kernel does not completely fit | | | |
| into the image, the specified \ref BorderTreatmentMode is | | | |
| applied. You can choice between following BorderTreatmentModes: | | | |
| <ul> | | | |
| <li>BORDER_TREATMENT_CLIP</li> | | | |
| <li>BORDER_TREATMENT_AVOID</li> | | | |
| <li>BORDER_TREATMENT_WRAP</li> | | | |
| <li>BORDER_TREATMENT_REFLECT</li> | | | |
| <li>BORDER_TREATMENT_REPEAT</li> | | | |
| </ul><br> | | | |
| The images's pixel type (SrcAccessor::value_type) must be a | | | |
| linear space over the kernel's value_type (KernelAccessor::value_type), | | | |
| i.e. addition of source values, multiplication with kernel values, | | | |
| and NumericTraits must be defined. | | | |
| The kernel's value_type must be an algebraic field, | | | |
| i.e. the arithmetic operations (+, -, *, /) and NumericTraits must | | | |
| be defined. | | | |
| | | | |
| <b> Declarations:</b> | | | |
| | | | |
| pass arguments explicitly: | | | |
| \code | | | |
| namespace vigra { | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor, | | | |
| class KernelIterator, class KernelAccessor> | | | |
| void convolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAcces | | | |
| sor src_acc, | | | |
| DestIterator dest_ul, DestAccessor dest_acc, | | | |
| KernelIterator ki, KernelAccessor ak, | | | |
| Diff2D kul, Diff2D klr, BorderTreatmentMode bord | | | |
| er); | | | |
| } | | | |
| \endcode | | | |
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | | |
| \code | | | |
| namespace vigra { | | | |
| template <class SrcIterator, class SrcAccessor, | | | |
| class DestIterator, class DestAccessor, | | | |
| class KernelIterator, class KernelAccessor> | | | |
| void convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> sr | | | |
| c, | | | |
| pair<DestIterator, DestAccessor> dest, | | | |
| tuple5<KernelIterator, KernelAccessor, Diff2D, D | | | |
| iff2D, | | | |
| BorderTreatmentMode> kernel); | | | |
| } | | | |
| \endcode | | | |
| | | | |
| <b> Usage:</b> | | | |
| | | | |
| <b>\#include</b> \<vigra/stdconvolution.hxx\><br> | | | |
| Namespace: vigra | | | |
| | | | |
| \code | | | |
| vigra::FImage src(w,h), dest(w,h); | | | |
| ... | | | |
| | | | |
| // define horizontal Sobel filter | | | |
| vigra::Kernel2D<float> sobel; | | | |
| | | | |
| sobel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = // upper left and l | | | |
| ower right | | | |
| 0.125, 0.0, -0.125, | | | |
| 0.25, 0.0, -0.25, | | | |
| 0.125, 0.0, -0.125; | | | |
| sobel.setBorderTreatment(vigra::BORDER_TREATMENT_REFLECT); | | | |
| | | | |
| vigra::convolveImage(srcImageRange(src), destImage(dest), kernel2d(sobe | | | |
| l)); | | | |
| \endcode | | | |
| | | | |
| <b> Required Interface:</b> | | | |
| | | | |
| \code | | | |
| ImageIterator src_ul, src_lr; | | | |
| ImageIterator dest_ul; | | | |
| ImageIterator ik; | | | |
| | | | |
| SrcAccessor src_accessor; | | | |
| DestAccessor dest_accessor; | | | |
| KernelAccessor kernel_accessor; | | | |
| | | | |
| NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(sr | | | |
| c_ul); | | | |
| | | | |
| s = s + s; | | | |
| s = kernel_accessor(ik) * s; | | | |
| s -= s; | | | |
| | | | |
| dest_accessor.set( | | | |
| NumericTraits<DestAccessor::value_type>::fromRealPromote(s), dest_ul); | | | |
| | | | |
| NumericTraits<KernelAccessor::value_type>::RealPromote k = kernel_acces | | | |
| sor(ik); | | | |
| | | | |
| k += k; | | | |
| k -= k; | | | |
| k = k / k; | | | |
| | | | |
| \endcode | | | |
| | | | |
| <b> Preconditions:</b> | | | |
| | | | |
| \code | | | |
| kul.x <= 0 | | | |
| kul.y <= 0 | | | |
| klr.x >= 0 | | | |
| klr.y >= 0 | | | |
| src_lr.x - src_ul.x >= klr.x + kul.x + 1 | | | |
| src_lr.y - src_ul.y >= klr.y + kul.y + 1 | | | |
| \endcode | | | |
| | | | |
| If border == BORDER_TREATMENT_CLIP: Sum of kernel elements must be | | | |
| != 0. | | | |
| | | | |
| */ | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void convolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_
acc, | | void convolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_
acc, | |
| DestIterator dest_ul, DestAccessor dest_acc, | | DestIterator dest_ul, DestAccessor dest_acc, | |
| KernelIterator ki, KernelAccessor ak, | | KernelIterator ki, KernelAccessor ak, | |
| Diff2D kul, Diff2D klr, BorderTreatmentMode border) | | Diff2D kul, Diff2D klr, BorderTreatmentMode border) | |
| { | | { | |
| vigra_precondition((border == BORDER_TREATMENT_CLIP || | | vigra_precondition((border == BORDER_TREATMENT_CLIP || | |
| border == BORDER_TREATMENT_AVOID || | | border == BORDER_TREATMENT_AVOID || | |
| | | | |
| skipping to change at line 383 | | skipping to change at line 265 | |
| | | | |
| // store convolution result in destination pixel | | // store convolution result in destination pixel | |
| dest_acc.set(detail::RequiresExplicitCast<DestType>::cast(sum),
xd); | | dest_acc.set(detail::RequiresExplicitCast<DestType>::cast(sum),
xd); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
|
| inline | | inline void | |
| void convolveImage( | | convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| triple<SrcIterator, SrcIterator, SrcAccessor> src, | | pair<DestIterator, DestAccessor> dest, | |
| pair<DestIterator, DestAccessor> dest, | | tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D, | |
| tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D, | | BorderTreatmentMode> kernel) | |
| BorderTreatmentMode> kernel) | | | |
| { | | { | |
| convolveImage(src.first, src.second, src.third, | | convolveImage(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| kernel.first, kernel.second, kernel.third, | | kernel.first, kernel.second, kernel.third, | |
| kernel.fourth, kernel.fifth); | | kernel.fourth, kernel.fifth); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class T3> | |
| | | inline void | |
| | | convolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel2D<T3> const & kernel) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "convolveImage(): shape mismatch between input and output."); | |
| | | convolveImage(srcImageRange(src), | |
| | | destImage(dest), | |
| | | kernel2d(kernel)); | |
| | | } | |
| | | | |
| /** \brief Performs a 2-dimensional normalized convolution, i.e. convolutio
n with a mask image. | | /** \brief Performs a 2-dimensional normalized convolution, i.e. convolutio
n with a mask image. | |
| | | | |
| This functions computes | | This functions computes | |
| <a href ="http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/PIROD
DI1/NormConv/NormConv.html">normalized | | <a href ="http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/PIROD
DI1/NormConv/NormConv.html">normalized | |
| convolution</a> as defined in | | convolution</a> as defined in | |
| Knutsson, H. and Westin, C-F.: <i>Normalized and differential convoluti
on: | | Knutsson, H. and Westin, C-F.: <i>Normalized and differential convoluti
on: | |
| Methods for Interpolation and Filtering of incomplete and uncertain dat
a</i>. | | Methods for Interpolation and Filtering of incomplete and uncertain dat
a</i>. | |
| Proc. of the IEEE Conf. on Computer Vision and Pattern Recognition, 199
3, 515-523. | | Proc. of the IEEE Conf. on Computer Vision and Pattern Recognition, 199
3, 515-523. | |
| | | | |
| The mask image must be binary and encodes which pixels of the original
image | | The mask image must be binary and encodes which pixels of the original
image | |
| | | | |
| skipping to change at line 434 | | skipping to change at line 330 | |
| The images's pixel type (SrcAccessor::value_type) must be a | | The images's pixel type (SrcAccessor::value_type) must be a | |
| linear space over the kernel's value_type (KernelAccessor::value_type), | | linear space over the kernel's value_type (KernelAccessor::value_type), | |
| i.e. addition of source values, multiplication with kernel values, | | i.e. addition of source values, multiplication with kernel values, | |
| and NumericTraits must be defined. | | and NumericTraits must be defined. | |
| The kernel's value_type must be an algebraic field, | | The kernel's value_type must be an algebraic field, | |
| i.e. the arithmetic operations (+, -, *, /) and NumericTraits must | | i.e. the arithmetic operations (+, -, *, /) and NumericTraits must | |
| be defined. | | be defined. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class TM, class SM, | |
| | | class T3> | |
| | | void | |
| | | normalizedConvolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel2D<T3> const & kernel); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{normalizedConvolveImage} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void | | void | |
| normalizedConvolveImage(SrcIterator src_ul, SrcIterator src_lr, Src
Accessor src_acc, | | normalizedConvolveImage(SrcIterator src_ul, SrcIterator src_lr, Src
Accessor src_acc, | |
| MaskIterator mul, MaskAccessor am, | | MaskIterator mul, MaskAccessor am, | |
| DestIterator dest_ul, DestAccessor dest_acc
, | | DestIterator dest_ul, DestAccessor dest_acc
, | |
| KernelIterator ki, KernelAccessor ak, | | KernelIterator ki, KernelAccessor ak, | |
| Diff2D kul, Diff2D klr, BorderTreatmentMode
border); | | Diff2D kul, Diff2D klr, BorderTreatmentMode
border); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void normalizedConvolveImage(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | | void normalizedConvolveImage(triple<SrcIterator, SrcIterator, SrcAc
cessor> src, | |
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| tuple5<KernelIterator, KernelAccessor,
Diff2D, Diff2D, | | tuple5<KernelIterator, KernelAccessor,
Diff2D, Diff2D, | |
| BorderTreatmentMode> kernel); | | BorderTreatmentMode> kernel); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/stdconvolution.hxx\><br> | | <b>\#include</b> \<vigra/stdconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w,h), dest(w,h); | |
| | | MultiArray<2, unsigned char> mask(w,h); | |
| | | ... | |
| | | // define 3x3 binomial filter | |
| | | vigra::Kernel2D<float> binom; | |
| | | binom.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = // upper left and | |
| | | lower right | |
| | | 0.0625, 0.125, 0.0625, | |
| | | 0.125, 0.25, 0.125, | |
| | | 0.0625, 0.125, 0.0625; | |
| | | | |
| | | normalizedConvolveImage(src, mask, dest, binom); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{normalizedConvolveImage} | |
| | | \code | |
| vigra::FImage src(w,h), dest(w,h); | | vigra::FImage src(w,h), dest(w,h); | |
| vigra::CImage mask(w,h); | | vigra::CImage mask(w,h); | |
| ... | | ... | |
| | | | |
| // define 3x3 binomial filter | | // define 3x3 binomial filter | |
| vigra::Kernel2D<float> binom; | | vigra::Kernel2D<float> binom; | |
| | | | |
| binom.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = // upper left and
lower right | | binom.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = // upper left and
lower right | |
| 0.0625, 0.125, 0.0625, | | 0.0625, 0.125, 0.0625, | |
| 0.125, 0.25, 0.125, | | 0.125, 0.25, 0.125, | |
| 0.0625, 0.125, 0.0625; | | 0.0625, 0.125, 0.0625; | |
| | | | |
| vigra::normalizedConvolveImage(srcImageRange(src), maskImage(mask), des
tImage(dest), kernel2d(binom)); | | vigra::normalizedConvolveImage(srcImageRange(src), maskImage(mask), des
tImage(dest), kernel2d(binom)); | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| ImageIterator src_ul, src_lr; | | ImageIterator src_ul, src_lr; | |
| ImageIterator mul; | | ImageIterator mul; | |
| ImageIterator dest_ul; | | ImageIterator dest_ul; | |
| ImageIterator ik; | | ImageIterator ik; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| MaskAccessor mask_accessor; | | MaskAccessor mask_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| KernelAccessor kernel_accessor; | | KernelAccessor kernel_accessor; | |
| | | | |
| skipping to change at line 517 | | skipping to change at line 442 | |
| dest_accessor.set( | | dest_accessor.set( | |
| NumericTraits<DestAccessor::value_type>::fromRealPromote(s), dest_ul); | | NumericTraits<DestAccessor::value_type>::fromRealPromote(s), dest_ul); | |
| | | | |
| NumericTraits<KernelAccessor::value_type>::RealPromote k = kernel_acces
sor(ik); | | NumericTraits<KernelAccessor::value_type>::RealPromote k = kernel_acces
sor(ik); | |
| | | | |
| k += k; | | k += k; | |
| k -= k; | | k -= k; | |
| k = k / k; | | k = k / k; | |
| | | | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
|
| \code | | <ul> | |
| kul.x <= 0 | | <li> The image must be longer than the kernel radius: <tt>w > std::max( | |
| kul.y <= 0 | | kernel.lowerRight().x, -kernel.upperLeft().x)</tt> and | |
| klr.x >= 0 | | <tt>h > std::max(kernel.lowerRight().y, -kernel.upperLeft().y)</tt | |
| klr.y >= 0 | | >. | |
| src_lr.x - src_ul.x >= klr.x + kul.x + 1 | | <li> The sum of kernel elements must be != 0. | |
| src_lr.y - src_ul.y >= klr.y + kul.y + 1 | | <li> <tt>border == BORDER_TREATMENT_CLIP || border == BORDER_TREATMENT_ | |
| border == BORDER_TREATMENT_CLIP || border == BORDER_TREATMENT_AVOID | | AVOID</tt> | |
| \endcode | | </ul> | |
| | | | |
| Sum of kernel elements must be != 0. | | | |
| | | | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void normalizedConvolveImage) | | doxygen_overloaded_function(template <...> void normalizedConvolveImage) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void | | void | |
| normalizedConvolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor
src_acc, | | normalizedConvolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor
src_acc, | |
| MaskIterator mul, MaskAccessor am, | | MaskIterator mul, MaskAccessor am, | |
| | | | |
| skipping to change at line 662 | | skipping to change at line 582 | |
| detail::RequiresExplicitCast<SumType>::cast((n
orm / ksum) * sum)), xd); | | detail::RequiresExplicitCast<SumType>::cast((n
orm / ksum) * sum)), xd); | |
| } | | } | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
|
| inline | | inline void | |
| void normalizedConvolveImage( | | normalizedConvolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| triple<SrcIterator, SrcIterator, SrcAccessor> sr | | pair<MaskIterator, MaskAccessor> mask, | |
| c, | | pair<DestIterator, DestAccessor> dest, | |
| pair<MaskIterator, MaskAccessor> mask, | | tuple5<KernelIterator, KernelAccessor, Diff2D, Diff | |
| pair<DestIterator, DestAccessor> dest, | | 2D, | |
| tuple5<KernelIterator, KernelAccessor, Diff2D, D | | BorderTreatmentMode> kernel) | |
| iff2D, | | | |
| BorderTreatmentMode> kernel) | | | |
| { | | { | |
| normalizedConvolveImage(src.first, src.second, src.third, | | normalizedConvolveImage(src.first, src.second, src.third, | |
| mask.first, mask.second, | | mask.first, mask.second, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| kernel.first, kernel.second, kernel.third, | | kernel.first, kernel.second, kernel.third, | |
| kernel.fourth, kernel.fifth); | | kernel.fourth, kernel.fifth); | |
| } | | } | |
| | | | |
|
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class TM, class SM, | |
| | | class T3> | |
| | | inline void | |
| | | normalizedConvolveImage(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, TM, SM> const & mask, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Kernel2D<T3> const & kernel) | |
| | | { | |
| | | vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.s | |
| | | hape(), | |
| | | "normalizedConvolveImage(): shape mismatch between input and output | |
| | | ."); | |
| | | normalizedConvolveImage(srcImageRange(src), | |
| | | maskImage(mask), | |
| | | destImage(dest), | |
| | | kernel2d(kernel)); | |
| | | } | |
| | | | |
| /** \brief Deprecated name of 2-dimensional normalized convolution, i.e. co
nvolution with a mask image. | | /** \brief Deprecated name of 2-dimensional normalized convolution, i.e. co
nvolution with a mask image. | |
| | | | |
| See \ref normalizedConvolveImage() for documentation. | | See \ref normalizedConvolveImage() for documentation. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void | | void | |
| convolveImageWithMask(SrcIterator src_ul, SrcIterator src_lr, SrcAc
cessor src_acc, | | convolveImageWithMask(SrcIterator src_ul, SrcIterator src_lr, SrcAc
cessor src_acc, | |
| MaskIterator mul, MaskAccessor am, | | MaskIterator mul, MaskAccessor am, | |
| DestIterator dest_ul, DestAccessor dest_acc, | | DestIterator dest_ul, DestAccessor dest_acc, | |
| KernelIterator ki, KernelAccessor ak, | | KernelIterator ki, KernelAccessor ak, | |
| Diff2D kul, Diff2D klr, BorderTreatmentMode b
order); | | Diff2D kul, Diff2D klr, BorderTreatmentMode b
order); | |
| } | | } | |
| \endcode | | \endcode | |
| | | | |
|
| | | \deprecatedAPI{convolveImageWithMask} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class SrcIterator, class SrcAccessor, | |
| | | class MaskIterator, class MaskAccessor, | |
| | | class DestIterator, class DestAccessor, | |
| | | class KernelIterator, class KernelAccessor> | |
| | | void | |
| | | convolveImageWithMask(SrcIterator src_ul, SrcIterator src_lr, SrcAc | |
| | | cessor src_acc, | |
| | | MaskIterator mul, MaskAccessor am, | |
| | | DestIterator dest_ul, DestAccessor dest_acc, | |
| | | KernelIterator ki, KernelAccessor ak, | |
| | | Diff2D kul, Diff2D klr, BorderTreatmentMode b | |
| | | order); | |
| | | } | |
| | | \endcode | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| void convolveImageWithMask(triple<SrcIterator, SrcIterator, SrcAcce
ssor> src, | | void convolveImageWithMask(triple<SrcIterator, SrcIterator, SrcAcce
ssor> src, | |
| pair<MaskIterator, MaskAccessor> mask, | | pair<MaskIterator, MaskAccessor> mask, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| tuple5<KernelIterator, KernelAccessor, D
iff2D, Diff2D, | | tuple5<KernelIterator, KernelAccessor, D
iff2D, Diff2D, | |
| BorderTreatmentMode> kernel); | | BorderTreatmentMode> kernel); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> void convolveImageWithMask) | | doxygen_overloaded_function(template <...> void convolveImageWithMask) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class MaskIterator, class MaskAccessor, | | class MaskIterator, class MaskAccessor, | |
| class KernelIterator, class KernelAccessor> | | class KernelIterator, class KernelAccessor> | |
| inline void | | inline void | |
| convolveImageWithMask(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor s
rc_acc, | | convolveImageWithMask(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor s
rc_acc, | |
| MaskIterator mul, MaskAccessor am, | | MaskIterator mul, MaskAccessor am, | |
| | | | |
| skipping to change at line 770 | | skipping to change at line 724 | |
| /** \brief Generic 2 dimensional convolution kernel. | | /** \brief Generic 2 dimensional convolution kernel. | |
| | | | |
| This kernel may be used for convolution of 2 dimensional signals. | | This kernel may be used for convolution of 2 dimensional signals. | |
| | | | |
| Convolution functions access the kernel via an ImageIterator | | Convolution functions access the kernel via an ImageIterator | |
| which they get by calling \ref center(). This iterator | | which they get by calling \ref center(). This iterator | |
| points to the center of the kernel. The kernel's size is given by its u
pperLeft() | | points to the center of the kernel. The kernel's size is given by its u
pperLeft() | |
| (upperLeft().x <= 0, upperLeft().y <= 0) | | (upperLeft().x <= 0, upperLeft().y <= 0) | |
| and lowerRight() (lowerRight().x >= 0, lowerRight().y >= 0) methods. | | and lowerRight() (lowerRight().x >= 0, lowerRight().y >= 0) methods. | |
| The desired border treatment mode is returned by borderTreatment(). | | The desired border treatment mode is returned by borderTreatment(). | |
|
| (Note that the \ref StandardConvolution "2D convolution functions" don' | | | |
| t currently | | | |
| support all modes.) | | | |
| | | | |
| The different init functions create a kernel with the specified | | The different init functions create a kernel with the specified | |
| properties. The requirements for the kernel's value_type depend | | properties. The requirements for the kernel's value_type depend | |
| on the init function used. At least NumericTraits must be defined. | | on the init function used. At least NumericTraits must be defined. | |
| | | | |
|
| The kernel defines a factory function kernel2d() to create an argument | | | |
| object | | | |
| (see \ref KernelArgumentObjectFactories). | | | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/stdconvolution.hxx\><br> | | <b>\#include</b> \<vigra/stdconvolution.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| vigra::FImage src(w,h), dest(w,h); | | MultiArray<2, float> src(w,h), dest(w,h); | |
| ... | | ... | |
| | | | |
| // define horizontal Sobel filter | | // define horizontal Sobel filter | |
| vigra::Kernel2D<float> sobel; | | vigra::Kernel2D<float> sobel; | |
|
| | | | |
| sobel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = // upper left and l
ower right | | sobel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = // upper left and l
ower right | |
| 0.125, 0.0, -0.125, | | 0.125, 0.0, -0.125, | |
| 0.25, 0.0, -0.25, | | 0.25, 0.0, -0.25, | |
| 0.125, 0.0, -0.125; | | 0.125, 0.0, -0.125; | |
| | | | |
|
| vigra::convolveImage(srcImageRange(src), destImage(dest), kernel2d(sobe
l)); | | convolveImage(src, dest, sobel); | |
| \endcode | | \endcode | |
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
| | | | |
| \code | | \code | |
| value_type v = NumericTraits<value_type>::one(); | | value_type v = NumericTraits<value_type>::one(); | |
| \endcode | | \endcode | |
| | | | |
| See also the init functions. | | See also the init functions. | |
| */ | | */ | |
|
| template <class ARITHTYPE> | | template <class ARITHTYPE = double> | |
| class Kernel2D | | class Kernel2D | |
| { | | { | |
| public: | | public: | |
| /** the kernel's value type | | /** the kernel's value type | |
| */ | | */ | |
| typedef ARITHTYPE value_type; | | typedef ARITHTYPE value_type; | |
| | | | |
| /** 2D random access iterator over the kernel's values | | /** 2D random access iterator over the kernel's values | |
| */ | | */ | |
| typedef typename BasicImage<value_type>::traverser Iterator; | | typedef typename BasicImage<value_type>::traverser Iterator; | |
| | | | |
| skipping to change at line 959 | | skipping to change at line 907 | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
| | | | |
| The kernel's value_type must be a linear algebra. | | The kernel's value_type must be a linear algebra. | |
| | | | |
| \code | | \code | |
| vigra::Kernel2D<...>::value_type v; | | vigra::Kernel2D<...>::value_type v; | |
| v = v * v; | | v = v * v; | |
| \endcode | | \endcode | |
| */ | | */ | |
| void initSeparable(Kernel1D<value_type> const & kx, | | void initSeparable(Kernel1D<value_type> const & kx, | |
|
| Kernel1D<value_type> const & ky) | | Kernel1D<value_type> const & ky) | |
| { | | { | |
| left_ = Diff2D(kx.left(), ky.left()); | | left_ = Diff2D(kx.left(), ky.left()); | |
| right_ = Diff2D(kx.right(), ky.right()); | | right_ = Diff2D(kx.right(), ky.right()); | |
| int w = right_.x - left_.x + 1; | | int w = right_.x - left_.x + 1; | |
| int h = right_.y - left_.y + 1; | | int h = right_.y - left_.y + 1; | |
| kernel_.resize(w, h); | | kernel_.resize(w, h); | |
| | | | |
| norm_ = kx.norm() * ky.norm(); | | norm_ = kx.norm() * ky.norm(); | |
| | | | |
| typedef typename Kernel1D<value_type>::const_iterator KIter; | | typedef typename Kernel1D<value_type>::const_iterator KIter; | |
| | | | |
| skipping to change at line 1011 | | skipping to change at line 959 | |
| | | | |
| \code | | \code | |
| xleft <= 0; | | xleft <= 0; | |
| xright >= 0; | | xright >= 0; | |
| yleft <= 0; | | yleft <= 0; | |
| yright >= 0; | | yright >= 0; | |
| \endcode | | \endcode | |
| */ | | */ | |
| template <class KernelIterator> | | template <class KernelIterator> | |
| void initSeparable(KernelIterator kxcenter, int xleft, int xright, | | void initSeparable(KernelIterator kxcenter, int xleft, int xright, | |
|
| KernelIterator kycenter, int yleft, int yright) | | KernelIterator kycenter, int yleft, int yright
) | |
| { | | { | |
| vigra_precondition(xleft <= 0 && yleft <= 0, | | vigra_precondition(xleft <= 0 && yleft <= 0, | |
| "Kernel2D::initSeparable(): left borders must be
<= 0."); | | "Kernel2D::initSeparable(): left borders must be
<= 0."); | |
| vigra_precondition(xright >= 0 && yright >= 0, | | vigra_precondition(xright >= 0 && yright >= 0, | |
| "Kernel2D::initSeparable(): right borders must b
e >= 0."); | | "Kernel2D::initSeparable(): right borders must b
e >= 0."); | |
| | | | |
| left_ = Point2D(xleft, yleft); | | left_ = Point2D(xleft, yleft); | |
| right_ = Point2D(xright, yright); | | right_ = Point2D(xright, yright); | |
| | | | |
| int w = right_.x - left_.x + 1; | | int w = right_.x - left_.x + 1; | |
| | | | |
| skipping to change at line 1049 | | skipping to change at line 997 | |
| typename BasicImage<value_type>::iterator iend = kernel_.end(); | | typename BasicImage<value_type>::iterator iend = kernel_.end(); | |
| norm_ = *i; | | norm_ = *i; | |
| ++i; | | ++i; | |
| | | | |
| for(; i!= iend; ++i) | | for(; i!= iend; ++i) | |
| { | | { | |
| norm_ += *i; | | norm_ += *i; | |
| } | | } | |
| } | | } | |
| | | | |
|
| /** Init as a 2D Gaussian function with given standard deviation an | | /** \brief Init as a 2D box filter with given radius. | |
| d norm. | | | |
| | | The function returns a reference to the kernel. | |
| | | */ | |
| | | void initAveraging(int radius) | |
| | | { | |
| | | Kernel1D<value_type> avg; | |
| | | avg.initAveraging(radius); | |
| | | return initSeparable(avg, avg); | |
| | | } | |
| | | | |
| | | /** \brief Init as a 2D Gaussian function with given standard devia | |
| | | tion and norm. | |
| | | | |
| | | The function returns a reference to the kernel. | |
| */ | | */ | |
| void initGaussian(double std_dev, value_type norm) | | void initGaussian(double std_dev, value_type norm) | |
| { | | { | |
| Kernel1D<value_type> gauss; | | Kernel1D<value_type> gauss; | |
| gauss.initGaussian(std_dev, norm); | | gauss.initGaussian(std_dev, norm); | |
|
| initSeparable(gauss, gauss); | | return initSeparable(gauss, gauss); | |
| } | | } | |
| | | | |
|
| /** Init as a 2D Gaussian function with given standard deviation an | | /** \brief Init as a 2D Gaussian function with given standard devia | |
| d unit norm. | | tion and unit norm. | |
| | | | |
| | | The function returns a reference to the kernel. | |
| */ | | */ | |
| void initGaussian(double std_dev) | | void initGaussian(double std_dev) | |
| { | | { | |
|
| initGaussian(std_dev, NumericTraits<value_type>::one()); | | return initGaussian(std_dev, NumericTraits<value_type>::one()); | |
| } | | } | |
| | | | |
| /** Init the 2D kernel as a circular averaging filter. The norm wil
l be | | /** Init the 2D kernel as a circular averaging filter. The norm wil
l be | |
| calculated as | | calculated as | |
| <TT>NumericTraits<value_type>::one() / (number of non-zero kern
el values)</TT>. | | <TT>NumericTraits<value_type>::one() / (number of non-zero kern
el values)</TT>. | |
| The kernel's value_type must be a linear space. | | The kernel's value_type must be a linear space. | |
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
| | | | |
| \code | | \code | |
| | | | |
| skipping to change at line 1128 | | skipping to change at line 1091 | |
| for(int y=-radius; y<=radius; ++y) | | for(int y=-radius; y<=radius; ++y) | |
| { | | { | |
| for(int x=-radius; x<=radius; ++x) | | for(int x=-radius; x<=radius; ++x) | |
| { | | { | |
| k(x,y) = count * k(x,y); | | k(x,y) = count * k(x,y); | |
| } | | } | |
| } | | } | |
| } | | } | |
| | | | |
| /** Init the kernel by an explicit initializer list. | | /** Init the kernel by an explicit initializer list. | |
|
| The upper left and lower right corners of the kernel must be pa | | The upper left and lower right corners (inclusive) of the kerne | |
| ssed. | | l must be passed | |
| A comma-separated initializer list is given after the assignmen | | either as <tt>Shape2</tt> or <tt>Diff2D</tt> objects. A comma-s | |
| t operator. | | eparated initializer | |
| This function is used like this: | | list for the kernel's weights is given after the assignment ope | |
| | | rator like this: | |
| | | | |
| \code | | \code | |
| // define horizontal Sobel filter | | // define horizontal Sobel filter | |
| vigra::Kernel2D<float> sobel; | | vigra::Kernel2D<float> sobel; | |
| | | | |
| sobel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = | | sobel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = | |
| 0.125, 0.0, -0.125, | | 0.125, 0.0, -0.125, | |
| 0.25, 0.0, -0.25, | | 0.25, 0.0, -0.25, | |
| 0.125, 0.0, -0.125; | | 0.125, 0.0, -0.125; | |
| \endcode | | \endcode | |
| | | | |
| The norm is set to the sum of the initializer values. If the wr
ong number of | | The norm is set to the sum of the initializer values. If the wr
ong number of | |
| values is given, a run-time error results. It is, however, poss
ible to give | | values is given, a run-time error results. It is, however, poss
ible to give | |
| just one initializer. This creates an averaging filter with the
given constant: | | just one initializer. This creates an averaging filter with the
given constant: | |
| | | | |
| \code | | \code | |
| vigra::Kernel2D<float> average3x3; | | vigra::Kernel2D<float> average3x3; | |
| | | | |
|
| average3x3.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = 1.0/9.0
; | | average3x3.initExplicitly(Shape2(-1,-1), Shape2(1,1)) = 1.0/9.0
; | |
| \endcode | | \endcode | |
| | | | |
| Here, the norm is set to value*width()*height(). | | Here, the norm is set to value*width()*height(). | |
| | | | |
| <b> Preconditions:</b> | | <b> Preconditions:</b> | |
| | | | |
| \code | | \code | |
| 1. upperleft.x <= 0; | | 1. upperleft.x <= 0; | |
| 2. upperleft.y <= 0; | | 2. upperleft.y <= 0; | |
| 3. lowerright.x >= 0; | | 3. lowerright.x >= 0; | |
| 4. lowerright.y >= 0; | | 4. lowerright.y >= 0; | |
| 5. the number of values in the initializer list | | 5. the number of values in the initializer list | |
| is 1 or equals the size of the kernel. | | is 1 or equals the size of the kernel. | |
| \endcode | | \endcode | |
| */ | | */ | |
|
| Kernel2D & initExplicitly(Diff2D upperleft, Diff2D lowerright) | | Kernel2D & initExplicitly(Shape2 const & upperleft, Shape2 const & lowe
rright) | |
| { | | { | |
|
| vigra_precondition(upperleft.x <= 0 && upperleft.y <= 0, | | vigra_precondition(upperleft[0] <= 0 && upperleft[1] <= 0, | |
| "Kernel2D::initExplicitly(): left borders must b
e <= 0."); | | "Kernel2D::initExplicitly(): left borders must b
e <= 0."); | |
|
| vigra_precondition(lowerright.x >= 0 && lowerright.y >= 0, | | vigra_precondition(lowerright[0] >= 0 && lowerright[1] >= 0, | |
| "Kernel2D::initExplicitly(): right borders must
be >= 0."); | | "Kernel2D::initExplicitly(): right borders must
be >= 0."); | |
| | | | |
|
| left_ = Point2D(upperleft); | | left_ = Point2D(upperleft[0], upperleft[1]); | |
| right_ = Point2D(lowerright); | | right_ = Point2D(lowerright[0], lowerright[1]); | |
| | | | |
| int w = right_.x - left_.x + 1; | | int w = right_.x - left_.x + 1; | |
| int h = right_.y - left_.y + 1; | | int h = right_.y - left_.y + 1; | |
| kernel_.resize(w, h); | | kernel_.resize(w, h); | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| | | Kernel2D & initExplicitly(Diff2D const & upperleft, Diff2D const & lowe | |
| | | rright) | |
| | | { | |
| | | return initExplicitly(Shape2(upperleft), Shape2(lowerright)); | |
| | | } | |
| | | | |
| /** Coordinates of the upper left corner of the kernel. | | /** Coordinates of the upper left corner of the kernel. | |
| */ | | */ | |
| Point2D upperLeft() const { return left_; } | | Point2D upperLeft() const { return left_; } | |
| | | | |
| /** Coordinates of the lower right corner of the kernel. | | /** Coordinates of the lower right corner of the kernel. | |
| */ | | */ | |
| Point2D lowerRight() const { return right_; } | | Point2D lowerRight() const { return right_; } | |
| | | | |
| /** Width of the kernel. | | /** Width of the kernel. | |
| */ | | */ | |
| | | | |
End of changes. 38 change blocks. |
| 197 lines changed or deleted | | 161 lines changed or added | |
|
| tinyvector.hxx | | tinyvector.hxx | |
| | | | |
| skipping to change at line 39 | | skipping to change at line 39 | |
| /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ | | /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ | |
| /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | | /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ | |
| /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | | /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ | |
| /* OTHER DEALINGS IN THE SOFTWARE. */ | | /* OTHER DEALINGS IN THE SOFTWARE. */ | |
| /* */ | | /* */ | |
| /************************************************************************/ | | /************************************************************************/ | |
| | | | |
| #ifndef VIGRA_TINYVECTOR_HXX | | #ifndef VIGRA_TINYVECTOR_HXX | |
| #define VIGRA_TINYVECTOR_HXX | | #define VIGRA_TINYVECTOR_HXX | |
| | | | |
|
| | | namespace lemon { | |
| | | | |
| | | struct Invalid; | |
| | | | |
| | | } // namespace lemon | |
| | | | |
| #include <cmath> // abs(double) | | #include <cmath> // abs(double) | |
| #include <cstdlib> // abs(int) | | #include <cstdlib> // abs(int) | |
| #include <iosfwd> // ostream | | #include <iosfwd> // ostream | |
| #include <algorithm> | | #include <algorithm> | |
| #include "config.hxx" | | #include "config.hxx" | |
| #include "error.hxx" | | #include "error.hxx" | |
| #include "metaprogramming.hxx" | | #include "metaprogramming.hxx" | |
| #include "numerictraits.hxx" | | #include "numerictraits.hxx" | |
| #include "memory.hxx" | | #include "memory.hxx" | |
| #include "mathutil.hxx" | | #include "mathutil.hxx" | |
| #include "diff2d.hxx" | | #include "diff2d.hxx" | |
|
| | | #include "static_assert.hxx" | |
| | | | |
| #ifdef VIGRA_CHECK_BOUNDS | | #ifdef VIGRA_CHECK_BOUNDS | |
| #define VIGRA_ASSERT_INSIDE(diff) \ | | #define VIGRA_ASSERT_INSIDE(diff) \ | |
| vigra_precondition(diff >= 0, "Index out of bounds");\ | | vigra_precondition(diff >= 0, "Index out of bounds");\ | |
| vigra_precondition(diff < SIZE, "Index out of bounds"); | | vigra_precondition(diff < SIZE, "Index out of bounds"); | |
| #else | | #else | |
| #define VIGRA_ASSERT_INSIDE(diff) | | #define VIGRA_ASSERT_INSIDE(diff) | |
| #endif | | #endif | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| skipping to change at line 143 | | skipping to change at line 150 | |
| { | | { | |
| for(int i=0; i<LEVEL; ++i) | | for(int i=0; i<LEVEL; ++i) | |
| left[i] = detail::RequiresExplicitCast<T1>::cast(pow(left, righ
t)); | | left[i] = detail::RequiresExplicitCast<T1>::cast(pow(left, righ
t)); | |
| } | | } | |
| | | | |
| VIGRA_EXEC_LOOP(assign, =) | | VIGRA_EXEC_LOOP(assign, =) | |
| VIGRA_EXEC_LOOP(add, +=) | | VIGRA_EXEC_LOOP(add, +=) | |
| VIGRA_EXEC_LOOP(sub, -=) | | VIGRA_EXEC_LOOP(sub, -=) | |
| VIGRA_EXEC_LOOP(mul, *=) | | VIGRA_EXEC_LOOP(mul, *=) | |
| VIGRA_EXEC_LOOP(div, /=) | | VIGRA_EXEC_LOOP(div, /=) | |
|
| | | VIGRA_EXEC_LOOP(mod, %=) | |
| VIGRA_EXEC_LOOP(neg, = -) | | VIGRA_EXEC_LOOP(neg, = -) | |
| VIGRA_EXEC_LOOP(abs, = vigra::abs) | | VIGRA_EXEC_LOOP(abs, = vigra::abs) | |
| VIGRA_EXEC_LOOP(floor, = vigra::floor) | | VIGRA_EXEC_LOOP(floor, = vigra::floor) | |
| VIGRA_EXEC_LOOP(ceil, = vigra::ceil) | | VIGRA_EXEC_LOOP(ceil, = vigra::ceil) | |
|
| | | VIGRA_EXEC_LOOP(round, = vigra::round) | |
| VIGRA_EXEC_LOOP(sqrt, = vigra::sqrt) | | VIGRA_EXEC_LOOP(sqrt, = vigra::sqrt) | |
| VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) | | VIGRA_EXEC_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) | |
| VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) | | VIGRA_EXEC_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote) | |
|
| | | VIGRA_EXEC_LOOP_SCALAR(addScalar, +) | |
| | | VIGRA_EXEC_LOOP_SCALAR(subScalar, -) | |
| VIGRA_EXEC_LOOP_SCALAR(mulScalar, *) | | VIGRA_EXEC_LOOP_SCALAR(mulScalar, *) | |
| VIGRA_EXEC_LOOP_SCALAR(divScalar, /) | | VIGRA_EXEC_LOOP_SCALAR(divScalar, /) | |
| | | | |
| VIGRA_EXEC_LOOP_MINMAX(min, >) | | VIGRA_EXEC_LOOP_MINMAX(min, >) | |
| VIGRA_EXEC_LOOP_MINMAX(max, <) | | VIGRA_EXEC_LOOP_MINMAX(max, <) | |
| | | | |
| template <class T> | | template <class T> | |
| static T const & minimum(T const * p) | | static T const & minimum(T const * p) | |
| { | | { | |
| return *std::min_element(p, p+LEVEL); | | return *std::min_element(p, p+LEVEL); | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static T const & maximum(T const * p) | | static T const & maximum(T const * p) | |
| { | | { | |
| return *std::max_element(p, p+LEVEL); | | return *std::max_element(p, p+LEVEL); | |
| } | | } | |
| | | | |
|
| | | template <class T> | |
| | | static bool all(T const * p, T const & zero) | |
| | | { | |
| | | for(int i=0; i<LEVEL; ++i) | |
| | | if(p[i] == zero) | |
| | | return false; | |
| | | return true; | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static bool any(T const * p, T const & zero) | |
| | | { | |
| | | for(int i=0; i<LEVEL; ++i) | |
| | | if(p[i] != zero) | |
| | | return true; | |
| | | return false; | |
| | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static bool notEqual(T1 const * left, T2 const * right) | | static bool notEqual(T1 const * left, T2 const * right) | |
| { | | { | |
| for(int i=0; i<LEVEL; ++i) | | for(int i=0; i<LEVEL; ++i) | |
| if(left[i] != right[i]) | | if(left[i] != right[i]) | |
| return true; | | return true; | |
| return false; | | return false; | |
| } | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
|
| static bool less(T1 const * left, T2 const * right) | | static bool lexicographicLessThan(T1 const * left, T2 const * right) | |
| { | | { | |
| for(int i=0; i<LEVEL; ++i) | | for(int i=0; i<LEVEL; ++i) | |
| { | | { | |
| if(left[i] < right[i]) | | if(left[i] < right[i]) | |
| return true; | | return true; | |
| if(right[i] < left[i]) | | if(right[i] < left[i]) | |
| return false; | | return false; | |
| } | | } | |
| return false; | | return false; | |
| } | | } | |
|
| | | | |
| | | template <class T> | |
| | | static bool closeAtTolerance(T const * left, T const * right, T epsilon | |
| | | ) | |
| | | { | |
| | | bool res = true; | |
| | | for(int i=0; i<LEVEL; ++i) | |
| | | { | |
| | | res = res && vigra::closeAtTolerance(left[i], right[i], epsilon | |
| | | ); | |
| | | } | |
| | | return res; | |
| | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static typename NumericTraits<T>::Promote | | static typename NumericTraits<T>::Promote | |
| dot(T const * d) | | dot(T const * d) | |
| { | | { | |
| typename NumericTraits<T>::Promote res(*d * *d); | | typename NumericTraits<T>::Promote res(*d * *d); | |
| for(int i=1; i<LEVEL; ++i) | | for(int i=1; i<LEVEL; ++i) | |
| res += d[i] * d[i]; | | res += d[i] * d[i]; | |
| return res; | | return res; | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 267 | | skipping to change at line 308 | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static T const & maximum(T const * p) | | static T const & maximum(T const * p) | |
| { | | { | |
| T const & m = UnrollScalarResult<LEVEL - 1>::maximum(p+1); | | T const & m = UnrollScalarResult<LEVEL - 1>::maximum(p+1); | |
| return *p > m | | return *p > m | |
| ? *p | | ? *p | |
| : m; | | : m; | |
| } | | } | |
|
| | | | |
| | | template <class T> | |
| | | static bool all(T const * p, T const & zero) | |
| | | { | |
| | | return *p != zero && UnrollScalarResult<LEVEL - 1>::all(p+1, zero); | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static bool any(T const * p, T const & zero) | |
| | | { | |
| | | return *p != zero || UnrollScalarResult<LEVEL - 1>::any(p+1, zero); | |
| | | } | |
| }; | | }; | |
| | | | |
| template <> | | template <> | |
| struct UnrollScalarResult<1> | | struct UnrollScalarResult<1> | |
| { | | { | |
| template <class T> | | template <class T> | |
| static typename NumericTraits<T>::Promote | | static typename NumericTraits<T>::Promote | |
| dot(T const * d) | | dot(T const * d) | |
| { | | { | |
| return *d * *d ; | | return *d * *d ; | |
| | | | |
| skipping to change at line 310 | | skipping to change at line 363 | |
| static T const & minimum(T const * p) | | static T const & minimum(T const * p) | |
| { | | { | |
| return *p; | | return *p; | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static T const & maximum(T const * p) | | static T const & maximum(T const * p) | |
| { | | { | |
| return *p; | | return *p; | |
| } | | } | |
|
| | | | |
| | | template <class T> | |
| | | static bool all(T const * p, T const & zero) | |
| | | { | |
| | | return *p != zero; | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static bool any(T const * p, T const & zero) | |
| | | { | |
| | | return *p != zero; | |
| | | } | |
| }; | | }; | |
| | | | |
| #undef VIGRA_EXEC_LOOP | | #undef VIGRA_EXEC_LOOP | |
| #undef VIGRA_EXEC_LOOP_MINMAX | | #undef VIGRA_EXEC_LOOP_MINMAX | |
| #undef VIGRA_EXEC_LOOP_SCALAR | | #undef VIGRA_EXEC_LOOP_SCALAR | |
| | | | |
| #define VIGRA_UNROLL_LOOP(NAME, OPER) \ | | #define VIGRA_UNROLL_LOOP(NAME, OPER) \ | |
| template <class T1, class T2> \ | | template <class T1, class T2> \ | |
| static void NAME(T1 * left, T2 const * right) \ | | static void NAME(T1 * left, T2 const * right) \ | |
| { \ | | { \ | |
| | | | |
| skipping to change at line 377 | | skipping to change at line 442 | |
| { | | { | |
| *left = detail::RequiresExplicitCast<T1>::cast(pow(*left, right)); | | *left = detail::RequiresExplicitCast<T1>::cast(pow(*left, right)); | |
| UnrollLoop<LEVEL-1>::power(left+1, right); | | UnrollLoop<LEVEL-1>::power(left+1, right); | |
| } | | } | |
| | | | |
| VIGRA_UNROLL_LOOP(assign, =) | | VIGRA_UNROLL_LOOP(assign, =) | |
| VIGRA_UNROLL_LOOP(add, +=) | | VIGRA_UNROLL_LOOP(add, +=) | |
| VIGRA_UNROLL_LOOP(sub, -=) | | VIGRA_UNROLL_LOOP(sub, -=) | |
| VIGRA_UNROLL_LOOP(mul, *=) | | VIGRA_UNROLL_LOOP(mul, *=) | |
| VIGRA_UNROLL_LOOP(div, /=) | | VIGRA_UNROLL_LOOP(div, /=) | |
|
| | | VIGRA_UNROLL_LOOP(mod, %=) | |
| VIGRA_UNROLL_LOOP(neg, = -) | | VIGRA_UNROLL_LOOP(neg, = -) | |
| VIGRA_UNROLL_LOOP(abs, = vigra::abs) | | VIGRA_UNROLL_LOOP(abs, = vigra::abs) | |
| VIGRA_UNROLL_LOOP(floor, = vigra::floor) | | VIGRA_UNROLL_LOOP(floor, = vigra::floor) | |
| VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) | | VIGRA_UNROLL_LOOP(ceil, = vigra::ceil) | |
|
| | | VIGRA_UNROLL_LOOP(round, = vigra::round) | |
| VIGRA_UNROLL_LOOP(sqrt, = vigra::sqrt) | | VIGRA_UNROLL_LOOP(sqrt, = vigra::sqrt) | |
| VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) | | VIGRA_UNROLL_LOOP(fromPromote, = NumericTraits<T1>::fromPromote) | |
| VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote
) | | VIGRA_UNROLL_LOOP(fromRealPromote, = NumericTraits<T1>::fromRealPromote
) | |
|
| | | VIGRA_UNROLL_LOOP_SCALAR(addScalar, +) | |
| | | VIGRA_UNROLL_LOOP_SCALAR(subScalar, -) | |
| VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *) | | VIGRA_UNROLL_LOOP_SCALAR(mulScalar, *) | |
| VIGRA_UNROLL_LOOP_SCALAR(divScalar, /) | | VIGRA_UNROLL_LOOP_SCALAR(divScalar, /) | |
| | | | |
| VIGRA_UNROLL_LOOP_MINMAX(min, >) | | VIGRA_UNROLL_LOOP_MINMAX(min, >) | |
| VIGRA_UNROLL_LOOP_MINMAX(max, <) | | VIGRA_UNROLL_LOOP_MINMAX(max, <) | |
| | | | |
| template <class T> | | template <class T> | |
| static T const & minimum(T const * p) | | static T const & minimum(T const * p) | |
| { | | { | |
| return UnrollScalarResult<LEVEL>::minimum(p); | | return UnrollScalarResult<LEVEL>::minimum(p); | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static T const & maximum(T const * p) | | static T const & maximum(T const * p) | |
| { | | { | |
| return UnrollScalarResult<LEVEL>::maximum(p); | | return UnrollScalarResult<LEVEL>::maximum(p); | |
| } | | } | |
| | | | |
|
| | | template <class T> | |
| | | static bool all(T const * p, T const & zero) | |
| | | { | |
| | | return UnrollScalarResult<LEVEL>::all(p, zero); | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static bool any(T const * p, T const & zero) | |
| | | { | |
| | | return UnrollScalarResult<LEVEL>::any(p, zero); | |
| | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static bool notEqual(T1 const * left, T2 const * right) | | static bool notEqual(T1 const * left, T2 const * right) | |
| { | | { | |
| return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1,
right+1); | | return (*left != *right) || UnrollLoop<LEVEL - 1>::notEqual(left+1,
right+1); | |
| } | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
|
| static bool less(T1 const * left, T2 const * right) | | static bool lexicographicLessThan(T1 const * left, T2 const * right) | |
| { | | { | |
| if(*left < *right) | | if(*left < *right) | |
| return true; | | return true; | |
| if(*right < *left) | | if(*right < *left) | |
| return false; | | return false; | |
|
| return UnrollLoop<LEVEL - 1>::less(left+1, right+1); | | return UnrollLoop<LEVEL - 1>::lexicographicLessThan(left+1, right+1 | |
| | | ); | |
| | | } | |
| | | | |
| | | template <class T> | |
| | | static bool closeAtTolerance(T const * left, T const * right, T epsilon | |
| | | ) | |
| | | { | |
| | | return vigra::closeAtTolerance(*left, *right, epsilon) && | |
| | | UnrollLoop<LEVEL - 1>::closeAtTolerance(left+1, right+1, | |
| | | epsilon); | |
| } | | } | |
| | | | |
| template <class T> | | template <class T> | |
| static typename NumericTraits<T>::Promote | | static typename NumericTraits<T>::Promote | |
| dot(T const * d) | | dot(T const * d) | |
| { | | { | |
| return UnrollScalarResult<LEVEL>::dot(d); | | return UnrollScalarResult<LEVEL>::dot(d); | |
| } | | } | |
| | | | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| | | | |
| skipping to change at line 460 | | skipping to change at line 548 | |
| static void assignCast(T1, T2) {} | | static void assignCast(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void assign(T1, T2) {} | | static void assign(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void assignScalar(T1, T2) {} | | static void assignScalar(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void power(T1, T2) {} | | static void power(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void add(T1, T2) {} | | static void add(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
|
| | | static void addScalar(T1, T2) {} | |
| | | template <class T1, class T2> | |
| static void sub(T1, T2) {} | | static void sub(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
|
| | | static void subScalar(T1, T2) {} | |
| | | template <class T1, class T2> | |
| static void mul(T1, T2) {} | | static void mul(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void mulScalar(T1, T2) {} | | static void mulScalar(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void div(T1, T2) {} | | static void div(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
|
| | | static void mod(T1, T2) {} | |
| | | template <class T1, class T2> | |
| static void divScalar(T1, T2) {} | | static void divScalar(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void fromPromote(T1, T2) {} | | static void fromPromote(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void fromRealPromote(T1, T2) {} | | static void fromRealPromote(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void neg(T1, T2) {} | | static void neg(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void abs(T1, T2) {} | | static void abs(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void floor(T1, T2) {} | | static void floor(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void ceil(T1, T2) {} | | static void ceil(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
|
| | | static void round(T1, T2) {} | |
| | | template <class T1, class T2> | |
| static void sqrt(T1, T2) {} | | static void sqrt(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static bool notEqual(T1, T2) { return false; } | | static bool notEqual(T1, T2) { return false; } | |
| template <class T1, class T2> | | template <class T1, class T2> | |
|
| static bool less(T1, T2) { return false; } | | static bool lexicographicLessThan(T1, T2) { return false; } | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void min(T1, T2) {} | | static void min(T1, T2) {} | |
| template <class T1, class T2> | | template <class T1, class T2> | |
| static void max(T1, T2) {} | | static void max(T1, T2) {} | |
| template <class T> | | template <class T> | |
|
| static T minimum(T const * p) | | static T minimum(T const *) { return NumericTraits<T>::max(); } | |
| { | | | |
| return NumericTraits<T>::max(); | | | |
| } | | | |
| template <class T> | | template <class T> | |
|
| static T maximum(T const * p) | | static T maximum(T const *) { return NumericTraits<T>::min(); } | |
| { | | template <class T> | |
| return NumericTraits<T>::min(); | | static bool all(T const *, T const &) { return true; } | |
| } | | template <class T> | |
| | | static bool any(T const *, T const &) { return false; } | |
| | | template <class T> | |
| | | static bool closeAtTolerance(T const *, T const *, T) { return true; } | |
| }; | | }; | |
| | | | |
| template <int SIZE> | | template <int SIZE> | |
| struct LoopType | | struct LoopType | |
| { | | { | |
|
| typedef typename IfBool<(SIZE <= 5), UnrollLoop<SIZE>, ExecLoop<SIZE> > | | static const int MaxUnrollSize = 5; | |
| ::type type; | | typedef typename IfBool<(SIZE <= MaxUnrollSize), UnrollLoop<SIZE>, Exec | |
| | | Loop<SIZE> >::type type; | |
| | | | |
| }; | | }; | |
| | | | |
| struct DontInit {}; | | struct DontInit {}; | |
| | | | |
| inline DontInit dontInit() {return DontInit(); } | | inline DontInit dontInit() {return DontInit(); } | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| template <class T, int SIZE> | | template <class T, int SIZE> | |
| | | | |
| skipping to change at line 657 | | skipping to change at line 754 | |
| | | | |
| /** Component-wise divide-assignment | | /** Component-wise divide-assignment | |
| */ | | */ | |
| template <class T1, class D1, class D2> | | template <class T1, class D1, class D2> | |
| DERIVED & operator/=(TinyVectorBase<T1, SIZE, D1, D2> const & r) | | DERIVED & operator/=(TinyVectorBase<T1, SIZE, D1, D2> const & r) | |
| { | | { | |
| Loop::div(data_, r.begin()); | | Loop::div(data_, r.begin()); | |
| return static_cast<DERIVED &>(*this); | | return static_cast<DERIVED &>(*this); | |
| } | | } | |
| | | | |
|
| | | /** Component-wise modulo-assignment | |
| | | */ | |
| | | template <class T1, class D1, class D2> | |
| | | DERIVED & operator%=(TinyVectorBase<T1, SIZE, D1, D2> const & r) | |
| | | { | |
| | | Loop::mod(data_, r.begin()); | |
| | | return static_cast<DERIVED &>(*this); | |
| | | } | |
| | | | |
| | | /** Component-wise scalar multiply-assignment | |
| | | */ | |
| | | DERIVED & operator+=(double r) | |
| | | { | |
| | | Loop::addScalar(data_, r); | |
| | | return static_cast<DERIVED &>(*this); | |
| | | } | |
| | | | |
| | | /** Component-wise scalar divide-assignment | |
| | | */ | |
| | | DERIVED & operator-=(double r) | |
| | | { | |
| | | Loop::subScalar(data_, r); | |
| | | return static_cast<DERIVED &>(*this); | |
| | | } | |
| | | | |
| /** Component-wise scalar multiply-assignment | | /** Component-wise scalar multiply-assignment | |
| */ | | */ | |
| DERIVED & operator*=(double r) | | DERIVED & operator*=(double r) | |
| { | | { | |
| Loop::mulScalar(data_, r); | | Loop::mulScalar(data_, r); | |
| return static_cast<DERIVED &>(*this); | | return static_cast<DERIVED &>(*this); | |
| } | | } | |
| | | | |
| /** Component-wise scalar divide-assignment | | /** Component-wise scalar divide-assignment | |
| */ | | */ | |
| DERIVED & operator/=(double r) | | DERIVED & operator/=(double r) | |
| { | | { | |
| Loop::divScalar(data_, r); | | Loop::divScalar(data_, r); | |
| return static_cast<DERIVED &>(*this); | | return static_cast<DERIVED &>(*this); | |
| } | | } | |
| | | | |
|
| /** Calculate magnitude. | | /** Calculate magnitude (i.e. 2-norm / Euclidean norm / length). | |
| */ | | * \see squaredMagnitude() | |
| | | */ | |
| NormType magnitude() const | | NormType magnitude() const | |
| { | | { | |
| return sqrt(static_cast<typename | | return sqrt(static_cast<typename | |
| SquareRootTraits<SquaredNormType>::SquareRootArgument>(square
dMagnitude())); | | SquareRootTraits<SquaredNormType>::SquareRootArgument>(square
dMagnitude())); | |
| } | | } | |
| | | | |
|
| /** Calculate squared magnitude. | | /** Calculate squared magnitude (i.e. sum of squared elements). | |
| */ | | */ | |
| SquaredNormType squaredMagnitude() const | | SquaredNormType squaredMagnitude() const | |
| { | | { | |
| return Loop::squaredNorm(data_); | | return Loop::squaredNorm(data_); | |
| } | | } | |
| | | | |
| /** Return the minimal element. | | /** Return the minimal element. | |
| */ | | */ | |
| VALUETYPE const & minimum() const | | VALUETYPE const & minimum() const | |
| { | | { | |
| return Loop::minimum(data_); | | return Loop::minimum(data_); | |
| } | | } | |
| | | | |
| /** Return the maximal element. | | /** Return the maximal element. | |
| */ | | */ | |
| VALUETYPE const & maximum() const | | VALUETYPE const & maximum() const | |
| { | | { | |
| return Loop::maximum(data_); | | return Loop::maximum(data_); | |
| } | | } | |
| | | | |
|
| | | /** Check that all elements of this vector are non-zero (or 'true' | |
| | | if T is bool). | |
| | | */ | |
| | | bool all() const | |
| | | { | |
| | | return Loop::all(data_, VALUETYPE()); | |
| | | } | |
| | | | |
| | | /** Check that at least one element of this vector is non-zero (or | |
| | | 'true' if T is bool). | |
| | | */ | |
| | | bool any() const | |
| | | { | |
| | | return Loop::any(data_, VALUETYPE()); | |
| | | } | |
| | | | |
| /** Access component by index. | | /** Access component by index. | |
| */ | | */ | |
| reference operator[](difference_type i) | | reference operator[](difference_type i) | |
| { | | { | |
| VIGRA_ASSERT_INSIDE(i); | | VIGRA_ASSERT_INSIDE(i); | |
| return data_[i]; | | return data_[i]; | |
| } | | } | |
| | | | |
| /** Get component by index. | | /** Get component by index. | |
| */ | | */ | |
| | | | |
| skipping to change at line 733 | | skipping to change at line 870 | |
| iterator end() { return data_ + SIZE; } | | iterator end() { return data_ + SIZE; } | |
| | | | |
| /** Get const random access iterator to begin of vector. | | /** Get const random access iterator to begin of vector. | |
| */ | | */ | |
| const_iterator begin() const { return data_; } | | const_iterator begin() const { return data_; } | |
| | | | |
| /** Get const random access iterator past-the-end of vector. | | /** Get const random access iterator past-the-end of vector. | |
| */ | | */ | |
| const_iterator end() const { return data_ + SIZE; } | | const_iterator end() const { return data_ + SIZE; } | |
| | | | |
|
| | | /** Get const random access iterator to begin of vector. | |
| | | */ | |
| | | const_iterator cbegin() const { return data_; } | |
| | | | |
| | | /** Get const random access iterator past-the-end of vector. | |
| | | */ | |
| | | const_iterator cend() const { return data_ + SIZE; } | |
| | | | |
| | | /** Get a view to the subarray with length <tt>(TO-FROM)</tt> start | |
| | | ing at <tt>FROM</tt>. | |
| | | The bounds must fullfill <tt>0 <= FROM < TO <= SIZE</tt>, but t | |
| | | his is only | |
| | | checked when <tt>VIGRA_CHECK_BOUNDS</tt> is \#define'd. | |
| | | */ | |
| | | template <int FROM, int TO> | |
| | | TinyVectorView<VALUETYPE, TO-FROM> subarray() const | |
| | | { | |
| | | #ifdef VIGRA_CHECK_BOUNDS | |
| | | vigra_precondition(FROM >= 0, "Index out of bounds"); | |
| | | vigra_precondition(FROM < TO, "Index out of bounds"); | |
| | | vigra_precondition(TO <=SIZE, "Index out of bounds"); | |
| | | #endif | |
| | | return TinyVectorView<VALUETYPE, TO-FROM>(data_+FROM); | |
| | | } | |
| | | | |
| | | TinyVector<VALUETYPE, SIZE-1> | |
| | | dropIndex(int m) const | |
| | | { | |
| | | #ifdef VIGRA_CHECK_BOUNDS | |
| | | vigra_precondition(0 <= m && m < SIZE, "Dimension out of bounds"); | |
| | | #endif | |
| | | TinyVector<VALUETYPE, SIZE-1> res(SkipInitialization); | |
| | | for(int k=0; k<m; ++k) | |
| | | res[k] = data_[k]; | |
| | | for(int k=m; k<SIZE-1; ++k) | |
| | | res[k] = data_[k+1]; | |
| | | return res; | |
| | | } | |
| | | | |
| /** Size of TinyVector vector always equals the template parameter
SIZE. | | /** Size of TinyVector vector always equals the template parameter
SIZE. | |
| */ | | */ | |
| size_type size() const { return SIZE; } | | size_type size() const { return SIZE; } | |
| | | | |
| pointer data() { return data_; } | | pointer data() { return data_; } | |
| | | | |
| const_pointer data() const { return data_; } | | const_pointer data() const { return data_; } | |
| | | | |
|
| | | reference front() | |
| | | { | |
| | | return data_[0]; | |
| | | } | |
| | | | |
| | | const_reference front() const | |
| | | { | |
| | | return data_[0]; | |
| | | } | |
| | | | |
| | | reference back() | |
| | | { | |
| | | return data_[SIZE-1]; | |
| | | } | |
| | | | |
| | | const_reference back() const | |
| | | { | |
| | | return data_[SIZE-1]; | |
| | | } | |
| | | | |
| | | /** \brief Factory function for a unit vector for dimension \a k. | |
| | | */ | |
| | | static TinyVector<VALUETYPE, SIZE> unitVector(int k) | |
| | | { | |
| | | VIGRA_ASSERT_INSIDE(k); | |
| | | TinyVector<VALUETYPE, SIZE> ret; | |
| | | ret[k] = 1; | |
| | | return ret; | |
| | | } | |
| | | | |
| | | /** \brief Factory function for a linear sequence. | |
| | | | |
| | | The result will be initialized as <tt>res[k] = start + k*step</ | |
| | | tt>. | |
| | | */ | |
| | | static TinyVector<VALUETYPE, SIZE> linearSequence(VALUETYPE start=VALUE | |
| | | TYPE(), VALUETYPE step=VALUETYPE(1)) | |
| | | { | |
| | | TinyVector<VALUETYPE, SIZE> ret(SkipInitialization); | |
| | | for(int k=0; k<SIZE; ++k, start+=step) | |
| | | ret[k] = start; | |
| | | return ret; | |
| | | } | |
| | | | |
| protected: | | protected: | |
| | | | |
| DATA data_; | | DATA data_; | |
| }; | | }; | |
| | | | |
|
| | | #ifndef DOXYGEN | |
| | | | |
| | | template <int SIZE, int DESIRED_SIZE> | |
| | | struct TinyVector_constructor_has_wrong_number_of_arguments | |
| | | : staticAssert::AssertBool<SIZE == DESIRED_SIZE> | |
| | | {}; | |
| | | | |
| | | #endif /* DOXYGEN */ | |
| | | | |
| /** \brief Class for fixed size vectors. | | /** \brief Class for fixed size vectors. | |
| \ingroup RangesAndPoints | | \ingroup RangesAndPoints | |
| | | | |
| This class contains an array of size SIZE of the specified VALUETYPE. | | This class contains an array of size SIZE of the specified VALUETYPE. | |
| The interface conforms to STL vector, except that there are no function
s | | The interface conforms to STL vector, except that there are no function
s | |
| that change the size of a TinyVector. | | that change the size of a TinyVector. | |
| | | | |
| \ref TinyVectorOperators "Arithmetic operations" | | \ref TinyVectorOperators "Arithmetic operations" | |
| on TinyVectors are defined as component-wise applications of these | | on TinyVectors are defined as component-wise applications of these | |
| operations. Addition and subtraction of two TinyVectors | | operations. Addition and subtraction of two TinyVectors | |
| | | | |
| skipping to change at line 808 | | skipping to change at line 1033 | |
| /** Construction with constant value. | | /** Construction with constant value. | |
| | | | |
| Initializes all vector elements with the given value. | | Initializes all vector elements with the given value. | |
| */ | | */ | |
| explicit TinyVector(value_type const & initial) | | explicit TinyVector(value_type const & initial) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| Loop::assignScalar(BaseType::begin(), initial); | | Loop::assignScalar(BaseType::begin(), initial); | |
| } | | } | |
| | | | |
|
| | | /** Construction from lemon::Invalid. | |
| | | | |
| | | Initializes all vector elements with -1. | |
| | | */ | |
| | | TinyVector(lemon::Invalid const &) | |
| | | : BaseType() | |
| | | { | |
| | | Loop::assignScalar(BaseType::begin(), -1); | |
| | | } | |
| | | | |
| /** Construction with Diff2D. | | /** Construction with Diff2D. | |
| | | | |
| Use only when <tt>SIZE == 2</tt>. | | Use only when <tt>SIZE == 2</tt>. | |
| */ | | */ | |
| explicit TinyVector(Diff2D const & initial) | | explicit TinyVector(Diff2D const & initial) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.
x); | | BaseType::data_[0] = detail::RequiresExplicitCast<T>::cast(initial.
x); | |
| BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.
y); | | BaseType::data_[1] = detail::RequiresExplicitCast<T>::cast(initial.
y); | |
| } | | } | |
| | | | |
| /** Construction with explicit values. | | /** Construction with explicit values. | |
| Call only if SIZE == 2 | | Call only if SIZE == 2 | |
| */ | | */ | |
| TinyVector(value_type const & i1, value_type const & i2) | | TinyVector(value_type const & i1, value_type const & i2) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
|
| | | VIGRA_STATIC_ASSERT((TinyVector_constructor_has_wrong_number_of_arg
uments<SIZE, 2>)); | |
| BaseType::data_[0] = i1; | | BaseType::data_[0] = i1; | |
| BaseType::data_[1] = i2; | | BaseType::data_[1] = i2; | |
| } | | } | |
| | | | |
| /** Construction with explicit values. | | /** Construction with explicit values. | |
| Call only if SIZE == 3 | | Call only if SIZE == 3 | |
| */ | | */ | |
| TinyVector(value_type const & i1, value_type const & i2, value_type con
st & i3) | | TinyVector(value_type const & i1, value_type const & i2, value_type con
st & i3) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
|
| | | VIGRA_STATIC_ASSERT((TinyVector_constructor_has_wrong_number_of_arg
uments<SIZE, 3>)); | |
| BaseType::data_[0] = i1; | | BaseType::data_[0] = i1; | |
| BaseType::data_[1] = i2; | | BaseType::data_[1] = i2; | |
| BaseType::data_[2] = i3; | | BaseType::data_[2] = i3; | |
| } | | } | |
| | | | |
| /** Construction with explicit values. | | /** Construction with explicit values. | |
| Call only if SIZE == 4 | | Call only if SIZE == 4 | |
| */ | | */ | |
| TinyVector(value_type const & i1, value_type const & i2, | | TinyVector(value_type const & i1, value_type const & i2, | |
| value_type const & i3, value_type const & i4) | | value_type const & i3, value_type const & i4) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
|
| | | VIGRA_STATIC_ASSERT((TinyVector_constructor_has_wrong_number_of_arg
uments<SIZE, 4>)); | |
| BaseType::data_[0] = i1; | | BaseType::data_[0] = i1; | |
| BaseType::data_[1] = i2; | | BaseType::data_[1] = i2; | |
| BaseType::data_[2] = i3; | | BaseType::data_[2] = i3; | |
| BaseType::data_[3] = i4; | | BaseType::data_[3] = i4; | |
| } | | } | |
| | | | |
| /** Construction with explicit values. | | /** Construction with explicit values. | |
| Call only if SIZE == 5 | | Call only if SIZE == 5 | |
| */ | | */ | |
| TinyVector(value_type const & i1, value_type const & i2, | | TinyVector(value_type const & i1, value_type const & i2, | |
| value_type const & i3, value_type const & i4, | | value_type const & i3, value_type const & i4, | |
| value_type const & i5) | | value_type const & i5) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
|
| | | VIGRA_STATIC_ASSERT((TinyVector_constructor_has_wrong_number_of_arg
uments<SIZE, 5>)); | |
| BaseType::data_[0] = i1; | | BaseType::data_[0] = i1; | |
| BaseType::data_[1] = i2; | | BaseType::data_[1] = i2; | |
| BaseType::data_[2] = i3; | | BaseType::data_[2] = i3; | |
| BaseType::data_[3] = i4; | | BaseType::data_[3] = i4; | |
| BaseType::data_[4] = i5; | | BaseType::data_[4] = i5; | |
| } | | } | |
| | | | |
| /** Default constructor (initializes all elements with zero). | | /** Default constructor (initializes all elements with zero). | |
| */ | | */ | |
| TinyVector() | | TinyVector() | |
| : BaseType() | | : BaseType() | |
| { | | { | |
|
| Loop::assignScalar(BaseType::data_, NumericTraits<value_type>::zero
()); | | Loop::assignScalar(BaseType::data_, value_type()); | |
| } | | } | |
| | | | |
| /** Construct without initializing the vector elements. | | /** Construct without initializing the vector elements. | |
| */ | | */ | |
| explicit TinyVector(SkipInitializationTag) | | explicit TinyVector(SkipInitializationTag) | |
| : BaseType() | | : BaseType() | |
| {} | | {} | |
| | | | |
| explicit TinyVector(detail::DontInit) | | explicit TinyVector(detail::DontInit) | |
| : BaseType() | | : BaseType() | |
| | | | |
| skipping to change at line 896 | | skipping to change at line 1135 | |
| /** Copy constructor. | | /** Copy constructor. | |
| */ | | */ | |
| TinyVector(TinyVector const & r) | | TinyVector(TinyVector const & r) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| Loop::assign(BaseType::data_, r.data_); | | Loop::assign(BaseType::data_, r.data_); | |
| } | | } | |
| | | | |
| /** Constructor from C array. | | /** Constructor from C array. | |
| */ | | */ | |
|
| explicit TinyVector(const_pointer data) | | template <class U> | |
| | | explicit TinyVector(U const * data) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| Loop::assign(BaseType::data_, data); | | Loop::assign(BaseType::data_, data); | |
| } | | } | |
| | | | |
| /** Constructor by reverse copy from C array. | | /** Constructor by reverse copy from C array. | |
| | | | |
| Usage: | | Usage: | |
| \code | | \code | |
| TinyVector<int, 3> v(1,2,3); | | TinyVector<int, 3> v(1,2,3); | |
|
| TinyVector<int, 3> reverse(v.begin(), TinyVector<int, 3>::Rever
seCopy); | | TinyVector<int, 3> reversed(v.begin(), TinyVector<int, 3>::Reve
rseCopy); | |
| \endcode | | \endcode | |
| */ | | */ | |
| explicit TinyVector(const_pointer data, ReverseCopyTag) | | explicit TinyVector(const_pointer data, ReverseCopyTag) | |
| : BaseType() | | : BaseType() | |
| { | | { | |
| Loop::reverseAssign(BaseType::data_, data+SIZE-1); | | Loop::reverseAssign(BaseType::data_, data+SIZE-1); | |
| } | | } | |
| | | | |
| /** Copy with type conversion. | | /** Copy with type conversion. | |
| */ | | */ | |
| | | | |
| skipping to change at line 1117 | | skipping to change at line 1357 | |
| /// component-wise not equal | | /// component-wise not equal | |
| template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | |
| inline bool | | inline bool | |
| operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l, | | operator!=(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| TinyVectorBase<V2, SIZE, D3, D4> const & r) | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| { | | { | |
| typedef typename detail::LoopType<SIZE>::type ltype; | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| return ltype::notEqual(l.begin(), r.begin()); | | return ltype::notEqual(l.begin(), r.begin()); | |
| } | | } | |
| | | | |
|
| /// component-wise lexicographical comparison | | /// lexicographical comparison | |
| template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | |
| inline bool | | inline bool | |
| operator<(TinyVectorBase<V1, SIZE, D1, D2> const & l, | | operator<(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
|
| TinyVectorBase<V2, SIZE, D3, D4> const & r) | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| { | | { | |
| typedef typename detail::LoopType<SIZE>::type ltype; | | typedef typename detail::LoopType<SIZE>::type ltype; | |
|
| return ltype::less(l.begin(), r.begin()); | | return ltype::lexicographicLessThan(l.begin(), r.begin()); | |
| | | } | |
| | | | |
| | | /// pointwise less-than | |
| | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class | |
| | | D4> | |
| | | inline bool | |
| | | allLess(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| | | { | |
| | | for(int k=0; k < SIZE; ++k) | |
| | | if (l[k] >= r[k]) | |
| | | return false; | |
| | | return true; | |
| | | } | |
| | | | |
| | | /// pointwise greater-than | |
| | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class | |
| | | D4> | |
| | | inline bool | |
| | | allGreater(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| | | { | |
| | | for(int k=0; k < SIZE; ++k) | |
| | | if(l[k] <= r[k]) | |
| | | return false; | |
| | | return true; | |
| | | } | |
| | | | |
| | | /// pointwise less-equal | |
| | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class | |
| | | D4> | |
| | | inline bool | |
| | | allLessEqual(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| | | { | |
| | | for(int k=0; k < SIZE; ++k) | |
| | | if (l[k] > r[k]) | |
| | | return false; | |
| | | return true; | |
| | | } | |
| | | | |
| | | /// pointwise greater-equal | |
| | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class | |
| | | D4> | |
| | | inline bool | |
| | | allGreaterEqual(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| | | { | |
| | | for(int k=0; k < SIZE; ++k) | |
| | | if (l[k] < r[k]) | |
| | | return false; | |
| | | return true; | |
| | | } | |
| | | | |
| | | template <class V, int SIZE, class D1, class D2, class D3, class D4> | |
| | | bool | |
| | | closeAtTolerance(TinyVectorBase<V, SIZE, D1, D2> const & l, | |
| | | TinyVectorBase<V, SIZE, D3, D4> const & r, | |
| | | V epsilon = NumericTraits<V>::epsilon()) | |
| | | { | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | return ltype::closeAtTolerance(l.begin(), r.begin(), epsilon); | |
| | | } | |
| | | | |
| | | template <class V, int SIZE> | |
| | | bool | |
| | | closeAtTolerance(TinyVector<V, SIZE> const & l, | |
| | | TinyVector<V, SIZE> const & r, | |
| | | V epsilon = NumericTraits<V>::epsilon()) | |
| | | { | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | return ltype::closeAtTolerance(l.begin(), r.begin(), epsilon); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* TinyVector Output */ | | /* TinyVector Output */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /// stream output | | /// stream output | |
| template <class V1, int SIZE, class DATA, class DERIVED> | | template <class V1, int SIZE, class DATA, class DERIVED> | |
| | | | |
| skipping to change at line 1527 | | skipping to change at line 1835 | |
| /// component-wise division | | /// component-wise division | |
| template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class
D4> | |
| inline | | inline | |
| typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promot
e | | typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promot
e | |
| operator/(TinyVectorBase<V1, SIZE, D1, D2> const & l, | | operator/(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| TinyVectorBase<V2, SIZE, D3, D4> const & r) | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| { | | { | |
| return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZ
E> >::Promote(l) /= r; | | return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZ
E> >::Promote(l) /= r; | |
| } | | } | |
| | | | |
|
| | | /// component-wise modulo | |
| | | template <class V1, int SIZE, class D1, class D2, class V2, class D3, class | |
| | | D4> | |
| | | inline | |
| | | typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2, SIZE> >::Promot | |
| | | e | |
| | | operator%(TinyVectorBase<V1, SIZE, D1, D2> const & l, | |
| | | TinyVectorBase<V2, SIZE, D3, D4> const & r) | |
| | | { | |
| | | return typename PromoteTraits<TinyVector<V1, SIZE>, TinyVector<V2 , SIZ | |
| | | E> >::Promote(l) %= r; | |
| | | } | |
| | | | |
| | | /// component-wise left scalar addition | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | |
| | | operator+(double v, TinyVectorBase<V, SIZE, D1, D2> const & r) | |
| | | { | |
| | | return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) += | |
| | | v; | |
| | | } | |
| | | | |
| | | /// component-wise right scalar addition | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | |
| | | operator+(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) | |
| | | { | |
| | | return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) += | |
| | | v; | |
| | | } | |
| | | | |
| | | /// component-wise left scalar subtraction | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | |
| | | operator-(double v, TinyVectorBase<V, SIZE, D1, D2> const & r) | |
| | | { | |
| | | return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(v) -= | |
| | | r; | |
| | | } | |
| | | | |
| | | /// component-wise right scalar subtraction | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | |
| | | operator-(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) | |
| | | { | |
| | | return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) -= | |
| | | v; | |
| | | } | |
| | | | |
| /// component-wise left scalar multiplication | | /// component-wise left scalar multiplication | |
| template <class V, int SIZE, class D1, class D2> | | template <class V, int SIZE, class D1, class D2> | |
| inline | | inline | |
| typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | | typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | |
| operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r) | | operator*(double v, TinyVectorBase<V, SIZE, D1, D2> const & r) | |
| { | | { | |
| return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *=
v; | | return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(r) *=
v; | |
| } | | } | |
| | | | |
| /// component-wise right scalar multiplication | | /// component-wise right scalar multiplication | |
| template <class V, int SIZE, class D1, class D2> | | template <class V, int SIZE, class D1, class D2> | |
| inline | | inline | |
| typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | | typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | |
| operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) | | operator*(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) | |
| { | | { | |
| return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *=
v; | | return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) *=
v; | |
| } | | } | |
| | | | |
|
| /// component-wise scalar division | | /// component-wise left scalar division | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | |
| | | operator/(double v, TinyVectorBase<V, SIZE, D1, D2> const & r) | |
| | | { | |
| | | return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(v) /= | |
| | | r; | |
| | | } | |
| | | | |
| | | /// component-wise right scalar division | |
| template <class V, int SIZE, class D1, class D2> | | template <class V, int SIZE, class D1, class D2> | |
| inline | | inline | |
| typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | | typename NumericTraits<TinyVector<V, SIZE> >::RealPromote | |
| operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) | | operator/(TinyVectorBase<V, SIZE, D1, D2> const & l, double v) | |
| { | | { | |
| return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /=
v; | | return typename NumericTraits<TinyVector<V, SIZE> >::RealPromote(l) /=
v; | |
| } | | } | |
| | | | |
| /// component-wise scalar division without type promotion | | /// component-wise scalar division without type promotion | |
| template <class V, int SIZE, class D1, class D2> | | template <class V, int SIZE, class D1, class D2> | |
| | | | |
| skipping to change at line 1617 | | skipping to change at line 1980 | |
| inline | | inline | |
| TinyVector<V, SIZE> | | TinyVector<V, SIZE> | |
| floor(TinyVectorBase<V, SIZE, D1, D2> const & v) | | floor(TinyVectorBase<V, SIZE, D1, D2> const & v) | |
| { | | { | |
| TinyVector<V, SIZE> res(detail::dontInit()); | | TinyVector<V, SIZE> res(detail::dontInit()); | |
| typedef typename detail::LoopType<SIZE>::type ltype; | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| ltype::floor(res.begin(), v.begin()); | | ltype::floor(res.begin(), v.begin()); | |
| return res; | | return res; | |
| } | | } | |
| | | | |
|
| | | /** Apply round() function to each vector component. | |
| | | */ | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | TinyVector<V, SIZE> | |
| | | round(TinyVectorBase<V, SIZE, D1, D2> const & v) | |
| | | { | |
| | | TinyVector<V, SIZE> res(detail::dontInit()); | |
| | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| | | ltype::round(res.begin(), v.begin()); | |
| | | return res; | |
| | | } | |
| | | | |
| | | /** Apply roundi() function to each vector component, i.e. return an in | |
| | | teger vector. | |
| | | */ | |
| | | template <class V, int SIZE, class D1, class D2> | |
| | | inline | |
| | | TinyVector<std::ptrdiff_t, SIZE> | |
| | | roundi(TinyVectorBase<V, SIZE, D1, D2> const & v) | |
| | | { | |
| | | TinyVector<V, SIZE> res(detail::dontInit()); | |
| | | for(int k=0; k<SIZE; ++k) | |
| | | res[k] = roundi(v[k]); | |
| | | return res; | |
| | | } | |
| | | | |
| /** Apply sqrt() function to each vector component. | | /** Apply sqrt() function to each vector component. | |
| */ | | */ | |
| template <class V, int SIZE, class D1, class D2> | | template <class V, int SIZE, class D1, class D2> | |
| inline | | inline | |
| TinyVector<V, SIZE> | | TinyVector<V, SIZE> | |
| sqrt(TinyVectorBase<V, SIZE, D1, D2> const & v) | | sqrt(TinyVectorBase<V, SIZE, D1, D2> const & v) | |
| { | | { | |
| TinyVector<V, SIZE> res(detail::dontInit()); | | TinyVector<V, SIZE> res(detail::dontInit()); | |
| typedef typename detail::LoopType<SIZE>::type ltype; | | typedef typename detail::LoopType<SIZE>::type ltype; | |
| ltype::sqrt(res.begin(), v.begin()); | | ltype::sqrt(res.begin(), v.begin()); | |
| | | | |
| skipping to change at line 1833 | | skipping to change at line 2222 | |
| } | | } | |
| | | | |
| /// squared norm | | /// squared norm | |
| template <class V, int SIZE> | | template <class V, int SIZE> | |
| inline | | inline | |
| typename TinyVector<V, SIZE>::SquaredNormType | | typename TinyVector<V, SIZE>::SquaredNormType | |
| squaredNorm(TinyVector<V, SIZE> const & t) | | squaredNorm(TinyVector<V, SIZE> const & t) | |
| { | | { | |
| return t.squaredMagnitude(); | | return t.squaredMagnitude(); | |
| } | | } | |
|
| | | | |
| | | using std::reverse; | |
| | | | |
| | | /// reversed copy | |
| | | template <class V, int SIZE> | |
| | | inline | |
| | | TinyVector<V, SIZE> | |
| | | reverse(TinyVector<V, SIZE> const & t) | |
| | | { | |
| | | return TinyVector<V, SIZE>(t.begin(), TinyVector<V, SIZE>::ReverseCopy) | |
| | | ; | |
| | | } | |
| | | | |
| | | /** \brief transposed copy | |
| | | | |
| | | Elements are arranged such that <tt>res[k] = t[permutation[k]]</tt> | |
| | | . | |
| | | */ | |
| | | template <class V, int SIZE, class T> | |
| | | inline | |
| | | TinyVector<V, SIZE> | |
| | | transpose(TinyVector<V, SIZE> const & t, TinyVector<T, SIZE> const & permut | |
| | | ation) | |
| | | { | |
| | | TinyVector<V, SIZE> res(SkipInitialization); | |
| | | for(int k=0; k<SIZE; ++k) | |
| | | { | |
| | | VIGRA_ASSERT_INSIDE(permutation[k]); | |
| | | res[k] = t[permutation[k]]; | |
| | | } | |
| | | return res; | |
| | | } | |
| | | | |
| | | /** \brief Clip negative values. | |
| | | | |
| | | All elements smaller than 0 are set to zero. | |
| | | */ | |
| | | template<class V,int SIZE> | |
| | | inline | |
| | | TinyVector<V, SIZE> clipLower(TinyVector<V, SIZE> const & t){ | |
| | | return clipLower(t, V(0)); | |
| | | } | |
| | | | |
| | | /** \brief Clip values below a threshold. | |
| | | | |
| | | All elements smaller than \a val are set to \a val. | |
| | | */ | |
| | | template<class V,int SIZE> | |
| | | inline | |
| | | TinyVector<V, SIZE> clipLower(TinyVector<V, SIZE> const & t,const V val){ | |
| | | TinyVector<V, SIZE> res(SkipInitialization); | |
| | | for(int k=0; k<SIZE; ++k){ | |
| | | res[k]=t[k]< val ? val : t[k]; | |
| | | } | |
| | | return res; | |
| | | } | |
| | | | |
| | | /** \brief Clip values above a threshold. | |
| | | | |
| | | All elements bigger than \a val are set to \a val. | |
| | | */ | |
| | | template<class V,int SIZE> | |
| | | inline | |
| | | TinyVector<V, SIZE> clipUpper(TinyVector<V, SIZE> const & t,const V val){ | |
| | | TinyVector<V, SIZE> res(SkipInitialization); | |
| | | for(int k=0; k<SIZE; ++k){ | |
| | | res[k]=t[k]> val ? val : t[k]; | |
| | | } | |
| | | return res; | |
| | | } | |
| | | | |
| | | /** \brief Clip values to an interval. | |
| | | | |
| | | All elements less than \a valLower are set to \a valLower, all elem | |
| | | ents | |
| | | bigger than \a valUpper are set to \a valUpper. | |
| | | */ | |
| | | template<class V,int SIZE> | |
| | | inline | |
| | | TinyVector<V, SIZE> clip(TinyVector<V, SIZE> const & t,const V valLower, co | |
| | | nst V valUpper){ | |
| | | TinyVector<V, SIZE> res(SkipInitialization); | |
| | | for(int k=0; k<SIZE; ++k){ | |
| | | res[k] = (t[k] < valLower) | |
| | | ? valLower | |
| | | : (t[k] > valUpper) | |
| | | ? valUpper | |
| | | : t[k]; | |
| | | } | |
| | | return res; | |
| | | } | |
| | | | |
| | | /** \brief Clip values to a vector of intervals. | |
| | | | |
| | | All elements less than \a valLower are set to \a valLower, all elem | |
| | | ents | |
| | | bigger than \a valUpper are set to \a valUpper. | |
| | | */ | |
| | | template<class V,int SIZE> | |
| | | inline | |
| | | TinyVector<V, SIZE> clip(TinyVector<V, SIZE> const & t, | |
| | | TinyVector<V, SIZE> const & valLower, | |
| | | TinyVector<V, SIZE> const & valUpper) | |
| | | { | |
| | | TinyVector<V, SIZE> res(SkipInitialization); | |
| | | for(int k=0; k<SIZE; ++k){ | |
| | | res[k] = (t[k] < valLower[k]) | |
| | | ? valLower[k] | |
| | | : (t[k] > valUpper[k]) | |
| | | ? valUpper[k] | |
| | | : t[k]; | |
| | | } | |
| | | return res; | |
| | | } | |
| | | | |
| | | template<class V,int SIZE> | |
| | | inline | |
| | | bool isZero(TinyVector<V, SIZE> const & t){ | |
| | | for(int k=0; k<SIZE; ++k){ | |
| | | if(t[k]!=static_cast<V>(0)) | |
| | | return false; | |
| | | } | |
| | | return true; | |
| | | } | |
| | | | |
| | | template<class V,int SIZE> | |
| | | inline typename NumericTraits<V>::RealPromote | |
| | | mean(TinyVector<V, SIZE> const & t){ | |
| | | const V sumVal = sum(t); | |
| | | return static_cast< typename NumericTraits<V>::RealPromote>(sumVal)/SIZ | |
| | | E; | |
| | | } | |
| | | | |
| | | template<class V,int SIZE> | |
| | | inline typename NumericTraits<V>::RealPromote | |
| | | sizeDividedSquaredNorm(TinyVector<V, SIZE> const & t){ | |
| | | return squaredNorm(t)/SIZE; | |
| | | } | |
| | | | |
| | | template<class V,int SIZE> | |
| | | inline typename NumericTraits<V>::RealPromote | |
| | | sizeDividedNorm(TinyVector<V, SIZE> const & t){ | |
| | | return norm(t)/SIZE; | |
| | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| // mask cl.exe shortcomings [end] | | // mask cl.exe shortcomings [end] | |
| #if defined(_MSC_VER) | | #if defined(_MSC_VER) | |
| #pragma warning( pop ) | | #pragma warning( pop ) | |
| #endif | | #endif | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| #undef VIGRA_ASSERT_INSIDE | | #undef VIGRA_ASSERT_INSIDE | |
| #endif // VIGRA_TINYVECTOR_HXX | | #endif // VIGRA_TINYVECTOR_HXX | |
| | | | |
End of changes. 46 change blocks. |
| 24 lines changed or deleted | | 582 lines changed or added | |
|
| voxelneighborhood.hxx | | voxelneighborhood.hxx | |
| | | | |
| skipping to change at line 190 | | skipping to change at line 190 | |
| CausalFirst = InFront, | | CausalFirst = InFront, | |
| CausalLast = West, | | CausalLast = West, | |
| AntiCausalFirst = Behind, | | AntiCausalFirst = Behind, | |
| AntiCausalLast = East, | | AntiCausalLast = East, | |
| | | | |
| InitialDirection = InFront, | | InitialDirection = InFront, | |
| OppositeDirPrefix = 1, | | OppositeDirPrefix = 1, | |
| OppositeOffset = 3 | | OppositeOffset = 3 | |
| }; | | }; | |
| | | | |
|
| | | template <int DUMMY> | |
| | | struct StaticData | |
| | | { | |
| | | static unsigned int b[]; | |
| | | static unsigned int c[]; | |
| | | static Direction bd[43][6]; | |
| | | static Direction bc[43][3]; | |
| | | static Diff3D d[]; | |
| | | static Diff3D rd[][6]; | |
| | | }; | |
| | | | |
| static unsigned int directionBit(Direction d) | | static unsigned int directionBit(Direction d) | |
| { | | { | |
|
| static unsigned int b[] = { 1 << InFront, | | return StaticData<0>::b[d]; | |
| 1 << North, | | | |
| 1 << West, | | | |
| 1 << Behind, | | | |
| 1 << South, | | | |
| 1 << East | | | |
| }; | | | |
| return b[d]; | | | |
| }; | | }; | |
| | | | |
| /** The number of valid neighbors if the current center is at the volum
e border. | | /** The number of valid neighbors if the current center is at the volum
e border. | |
| */ | | */ | |
| static unsigned int nearBorderDirectionCount(AtVolumeBorder b) | | static unsigned int nearBorderDirectionCount(AtVolumeBorder b) | |
| { | | { | |
|
| static unsigned int c[] = { 6, 5, 5, 0, 5, 4, 4, 0, 5, 4, | | return StaticData<0>::c[b]; | |
| 4, 0, 0, 0, 0, 0, 5, 4, 4, 0, | | | |
| 4, 3, 3, 0, 4, 3, 3, 0, 0, 0, | | | |
| 0, 0, 5, 4, 4, 0, 4, 3, 3, 0, | | | |
| 4, 3, 3}; | | | |
| return c[b]; | | | |
| } | | } | |
| | | | |
| /** The valid direction codes when the center is at the volume border. | | /** The valid direction codes when the center is at the volume border. | |
| \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1
</tt>. | | \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1
</tt>. | |
| */ | | */ | |
| static Direction nearBorderDirections(AtVolumeBorder b, int index) | | static Direction nearBorderDirections(AtVolumeBorder b, int index) | |
| { | | { | |
|
| static Direction c[43][6] = { | | return StaticData<0>::bd[b][index]; | |
| { InFront, North, West, Behind, South, East}, // 0 - NotA | | | |
| tBorder | | | |
| { InFront, North, West, Behind, South, Error}, // 1 - AtRi | | | |
| ghtBorder | | | |
| { InFront, North, Behind, South, East, Error}, // 2 - AtLe | | | |
| ftBorder | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { InFront, West, Behind, South, East, Error}, // 4 - AtTo | | | |
| pBorder | | | |
| { InFront, West, Behind, South, Error, Error}, // 5 - AtTo | | | |
| pRightBorder | | | |
| { InFront, Behind, South, East, Error, Error}, // 6 - AtTo | | | |
| pLeftBorder | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { InFront, North, West, Behind, East, Error}, // 8 - AtBo | | | |
| ttomBorder | | | |
| { InFront, North, West, Behind, Error, Error}, // 9 - AtBo | | | |
| ttomRightBorder | | | |
| { InFront, North, Behind, East, Error, Error}, //10- AtBot | | | |
| tomLeftBorder | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { North, West, Behind, South, East, Error}, //16 - AtFr | | | |
| ontBorder | | | |
| { North, West, Behind, South, Error, Error}, //17 - AtFr | | | |
| ontRightBorder | | | |
| { North, Behind, South, East, Error, Error}, //18 - AtFr | | | |
| ontLeftBorder | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { West, Behind, South, East, Error, Error}, //20 - AtTo | | | |
| pFrontBorder | | | |
| { West, Behind, South, Error, Error, Error}, //21 - AtTo | | | |
| pRightFrontBorder | | | |
| { Behind, South, East, Error, Error, Error}, //22 - AtTo | | | |
| pLeftFrontBorder | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { North, West, Behind, East, Error, Error}, //24 - AtBo | | | |
| ttomFrontBorder | | | |
| { North, West, Behind, Error, Error, Error}, //25 - AtBo | | | |
| ttomRightFrontBorder | | | |
| { North, Behind, East, Error, Error, Error}, //26 - AtBo | | | |
| ttomLeftFrontBorder | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { InFront, North, West, South, East,Error}, //32 - AtRe | | | |
| arBorder | | | |
| { InFront, North, West, South, Error, Error}, //33 - AtRe | | | |
| arRightBorder | | | |
| { InFront, North, South, East, Error, Error}, //34 - AtRe | | | |
| arLeftBorder | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { InFront, West, South, East, Error, Error}, //36 - AtTo | | | |
| pRearBorder | | | |
| { InFront, West, South, Error, Error, Error}, //37 - AtTo | | | |
| pRightRearBorder | | | |
| { InFront, South, East, Error, Error, Error}, //38 - AtTo | | | |
| pLeftRearBorder | | | |
| { Error, Error, Error, Error, Error, Error}, | | | |
| { InFront, North, West, East, Error, Error}, //40 - AtBo | | | |
| ttomRearBorder | | | |
| { InFront, North, West, Error, Error, Error}, //41 - AtBo | | | |
| ttomRightRearBorder | | | |
| { InFront, North, East, Error, Error, Error} //42 - AtBo | | | |
| ttomLeftRearBorder | | | |
| }; | | | |
| return c[b][index]; | | | |
| } | | } | |
| | | | |
| /** The valid direction three codes in anti causal direction (means: lo
ok back in scanline | | /** The valid direction three codes in anti causal direction (means: lo
ok back in scanline | |
| direction)when the center is at the volume border. | | direction)when the center is at the volume border. | |
| Should be used with isAtVolumeBorderCausal to determine the Directi
ons, as this | | Should be used with isAtVolumeBorderCausal to determine the Directi
ons, as this | |
| avoids using of the nonesense border ids (e.g. 0,1,8,9...) of this
table. | | avoids using of the nonesense border ids (e.g. 0,1,8,9...) of this
table. | |
| \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1
</tt>. | | \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1
</tt>. | |
| */ | | */ | |
| static Direction nearBorderDirectionsCausal(AtVolumeBorder b, int index
) | | static Direction nearBorderDirectionsCausal(AtVolumeBorder b, int index
) | |
| { | | { | |
|
| static Direction c[43][3] = { | | return StaticData<0>::bc[b][index]; | |
| { InFront, North, West}, // 0 - NotAtBorder | | | |
| { InFront, North, West}, // 1 - AtRightBorde | | | |
| r | | | |
| { InFront, North, Error}, // 2 - AtLeftBorder | | | |
| { Error, Error, Error}, | | | |
| { InFront, West, Error}, // 4 - AtTopBorder | | | |
| { InFront, West, Error}, // 5 - AtTopRightBo | | | |
| rder | | | |
| { InFront, Error,Error}, // 6 - AtTopLeftBor | | | |
| der | | | |
| { Error, Error, Error}, | | | |
| { InFront, North, West}, // 8 - AtBottomBord | | | |
| er | | | |
| { InFront, North, West}, // 9 - AtBottomRigh | | | |
| tBorder | | | |
| { InFront, North, Error}, //10- AtBottomLeftB | | | |
| order | | | |
| { Error, Error, Error}, | | | |
| { Error, Error, Error}, | | | |
| { Error, Error, Error}, | | | |
| { Error, Error, Error}, | | | |
| { Error, Error, Error}, | | | |
| { North, West, Error}, //16 - AtFrontBorde | | | |
| r | | | |
| { North, West, Error}, //17 - AtFrontRight | | | |
| Border | | | |
| { North, Error, Error}, //18 - AtFrontLeftB | | | |
| order | | | |
| { Error, Error, Error}, | | | |
| { West, Error, Error}, //20 - AtTopFrontBo | | | |
| rder | | | |
| { West, Error, Error}, //21 - AtTopRightFr | | | |
| ontBorder | | | |
| { Error, Error, Error}, //22 - AtTopLeftFro | | | |
| ntBorder | | | |
| { Error, Error, Error}, | | | |
| { North, West, Error}, //24 - AtBottomFron | | | |
| tBorder | | | |
| { North, West, Error}, //25 - AtBottomRigh | | | |
| tFrontBorder | | | |
| { North, Error, Error}, //26 - AtBottomLeft | | | |
| FrontBorder | | | |
| { Error, Error, Error}, | | | |
| { Error, Error, Error}, | | | |
| { Error, Error, Error}, | | | |
| { Error, Error, Error}, | | | |
| { Error, Error, Error}, | | | |
| { InFront, North, West}, //32 - AtRearBorder | | | |
| { InFront, North, West}, //33 - AtRearRightB | | | |
| order | | | |
| { InFront, North, Error}, //34 - AtRearLeftBo | | | |
| rder | | | |
| { Error, Error, Error}, | | | |
| { InFront, West, Error}, //36 - AtTopRearBor | | | |
| der | | | |
| { InFront, West, Error}, //37 - AtTopRightRe | | | |
| arBorder | | | |
| { InFront, Error, Error}, //38 - AtTopLeftRea | | | |
| rBorder | | | |
| { Error, Error, Error}, | | | |
| { InFront, North, West}, //40 - AtBottomRear | | | |
| Border | | | |
| { InFront, North, West}, //41 - AtBottomRigh | | | |
| tRearBorder | | | |
| { InFront, North, Error} //42 - AtBottomLeft | | | |
| RearBorder | | | |
| }; | | | |
| return c[b][index]; | | | |
| } | | } | |
| | | | |
| /** transform direction code into corresponding Diff3D offset. | | /** transform direction code into corresponding Diff3D offset. | |
| (note: there is no bounds checking on the code you pass.) | | (note: there is no bounds checking on the code you pass.) | |
| */ | | */ | |
| static Diff3D const & diff(Direction code) | | static Diff3D const & diff(Direction code) | |
| { | | { | |
|
| static Diff3D d[] = { | | return StaticData<0>::d[code]; | |
| Diff3D( 0, 0, -1), //InFront | | | |
| Diff3D( 0, -1, 0), //North | | | |
| Diff3D( -1, 0, 0), //West | | | |
| Diff3D( 0, 0, 1), //Behind | | | |
| Diff3D( 0, 1, 0), //South | | | |
| Diff3D( 1, 0, 0) //East | | | |
| }; | | | |
| return d[code]; | | | |
| } | | } | |
| | | | |
| /** Equivalent to <tt>diff(static_cast<Direction>(code))</tt>. | | /** Equivalent to <tt>diff(static_cast<Direction>(code))</tt>. | |
| (note: there is no bounds checking on the code you pass.) | | (note: there is no bounds checking on the code you pass.) | |
| */ | | */ | |
| static Diff3D const & diff(int code) { return diff(static_cast<Directio
n>(code)); } | | static Diff3D const & diff(int code) { return diff(static_cast<Directio
n>(code)); } | |
| | | | |
| /** Equivalent to <tt>diff(code)[dim]</tt> */ | | /** Equivalent to <tt>diff(code)[dim]</tt> */ | |
| static int diff(Direction code, int dim) { return diff(code)[dim]; } | | static int diff(Direction code, int dim) { return diff(code)[dim]; } | |
| | | | |
| /** Get the relative offset from one neighbor to the other. | | /** Get the relative offset from one neighbor to the other. | |
| For example, <tt>relativeDiff(East, West) == multi_differencetype(-
2,0,0)</tt>. | | For example, <tt>relativeDiff(East, West) == multi_differencetype(-
2,0,0)</tt>. | |
| (note: there is no bounds checking on the code you pass.) | | (note: there is no bounds checking on the code you pass.) | |
| */ | | */ | |
| static Diff3D const & relativeDiff(Direction fromCode, Direction toCode
) | | static Diff3D const & relativeDiff(Direction fromCode, Direction toCode
) | |
| { | | { | |
|
| static Diff3D d[6][6] = | | return StaticData<0>::rd[fromCode][toCode]; | |
| { | | | |
| // InFront - North - West | | | |
| - Behind - South - East | | | |
| { Diff3D( 0, 0, 0), Diff3D(0, -1, 1), Diff3D(-1, 0, 1), Dif | | | |
| f3D( 0, 0, 2), Diff3D( 0, 1, 1), Diff3D( 1, 0, 1)}, //InFront | | | |
| { Diff3D( 0, 1,-1), Diff3D( 0, 0, 0), Diff3D(-1, 1, 0), Dif | | | |
| f3D( 0, 1, 1), Diff3D( 0, 2, 0), Diff3D( 1, 1, 0)}, //North | | | |
| { Diff3D( 1, 0,-1), Diff3D( 1,-1, 0), Diff3D( 0, 0, 0), Dif | | | |
| f3D( 1, 0, 1), Diff3D( 1, 1, 0), Diff3D( 2, 0, 0)}, //West | | | |
| { Diff3D( 0, 0,-2), Diff3D( 0,-1,-1), Diff3D(-1, 0,-1), Dif | | | |
| f3D( 0, 0, 0), Diff3D( 0, 1,-1), Diff3D( 1, 0,-1)}, //Behind | | | |
| { Diff3D( 0,-1,-1), Diff3D( 0,-2, 0), Diff3D(-1,-1, 0), Dif | | | |
| f3D( 0,-1, 1), Diff3D( 0, 0, 0), Diff3D( 1,-1, 0)}, //South | | | |
| { Diff3D(-1, 0,-1), Diff3D(-1,-1, 0), Diff3D(-2, 0, 0), Dif | | | |
| f3D(-1, 0, 1), Diff3D(-1, 1, 0), Diff3D( 0, 0, 0) } //East | | | |
| }; | | | |
| | | | |
| return d[fromCode][toCode]; | | | |
| } | | } | |
| | | | |
| /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static
_cast<Direction>(toCode)). | | /** Equivalent to relativeDiff(static_cast<Direction>(fromCode), static
_cast<Direction>(toCode)). | |
| (note: there is no bounds checking on the code you pass.) | | (note: there is no bounds checking on the code you pass.) | |
| */ | | */ | |
| static Diff3D const & relativeDiff(int fromCode, int toCode) | | static Diff3D const & relativeDiff(int fromCode, int toCode) | |
| { | | { | |
| return relativeDiff(static_cast<Direction>(fromCode), static_cast<D
irection>(toCode)); | | return relativeDiff(static_cast<Direction>(fromCode), static_cast<D
irection>(toCode)); | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 459 | | skipping to change at line 349 | |
| typedef NeighborCode3D::Direction Direction; | | typedef NeighborCode3D::Direction Direction; | |
| | | | |
| static const Direction East = NeighborCode3D::East;
/**< Export NeighborCode3D::East to namespace Neighborhood3DSix */ | | static const Direction East = NeighborCode3D::East;
/**< Export NeighborCode3D::East to namespace Neighborhood3DSix */ | |
| static const Direction North = NeighborCode3D::North;
/**< Export NeighborCode3D::North to namespace Neighborhood3DSix */ | | static const Direction North = NeighborCode3D::North;
/**< Export NeighborCode3D::North to namespace Neighborhood3DSix */ | |
| static const Direction West = NeighborCode3D::West;
/**< Export NeighborCode3D::West to namespace Neighborhood3DSix */ | | static const Direction West = NeighborCode3D::West;
/**< Export NeighborCode3D::West to namespace Neighborhood3DSix */ | |
| static const Direction South = NeighborCode3D::South;
/**< Export NeighborCode3D::South to namespace Neighborhood3DSix */ | | static const Direction South = NeighborCode3D::South;
/**< Export NeighborCode3D::South to namespace Neighborhood3DSix */ | |
| static const Direction Behind = NeighborCode3D::Behind;
/**< Export NeighborCode3D::Behind to namespace Neighborhood3DSix */ | | static const Direction Behind = NeighborCode3D::Behind;
/**< Export NeighborCode3D::Behind to namespace Neighborhood3DSix */ | |
| static const Direction InFront = NeighborCode3D::InFront;
/**< Export NeighborCode3D::InFront to namespace Neighborhood3DSix */ | | static const Direction InFront = NeighborCode3D::InFront;
/**< Export NeighborCode3D::InFront to namespace Neighborhood3DSix */ | |
| static const Direction DirectionCount = NeighborCode3D::DirectionCount;
/**< Export NeighborCode3D::DirectionCount to namespace Neighborhood3DSix
*/ | | static const Direction DirectionCount = NeighborCode3D::DirectionCount;
/**< Export NeighborCode3D::DirectionCount to namespace Neighborhood3DSix
*/ | |
| | | | |
|
| | | template <int DUMMY> | |
| | | unsigned int NeighborCode3D::StaticData<DUMMY>::b[] = { | |
| | | 1 << InFront, | |
| | | 1 << North, | |
| | | 1 << West, | |
| | | 1 << Behind, | |
| | | 1 << South, | |
| | | 1 << East | |
| | | }; | |
| | | | |
| | | template <int DUMMY> | |
| | | unsigned int NeighborCode3D::StaticData<DUMMY>::c[] = { | |
| | | 6, 5, 5, 0, 5, 4, 4, 0, 5, 4, | |
| | | 4, 0, 0, 0, 0, 0, 5, 4, 4, 0, | |
| | | 4, 3, 3, 0, 4, 3, 3, 0, 0, 0, | |
| | | 0, 0, 5, 4, 4, 0, 4, 3, 3, 0, | |
| | | 4, 3, 3}; | |
| | | | |
| | | template <int DUMMY> | |
| | | Direction NeighborCode3D::StaticData<DUMMY>::bd[43][6] = { | |
| | | { InFront, North, West, Behind, South, East}, // 0 - NotA | |
| | | tBorder | |
| | | { InFront, North, West, Behind, South, Error}, // 1 - AtRi | |
| | | ghtBorder | |
| | | { InFront, North, Behind, South, East, Error}, // 2 - AtLe | |
| | | ftBorder | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { InFront, West, Behind, South, East, Error}, // 4 - AtTo | |
| | | pBorder | |
| | | { InFront, West, Behind, South, Error, Error}, // 5 - AtTo | |
| | | pRightBorder | |
| | | { InFront, Behind, South, East, Error, Error}, // 6 - AtTo | |
| | | pLeftBorder | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { InFront, North, West, Behind, East, Error}, // 8 - AtBo | |
| | | ttomBorder | |
| | | { InFront, North, West, Behind, Error, Error}, // 9 - AtBo | |
| | | ttomRightBorder | |
| | | { InFront, North, Behind, East, Error, Error}, //10- AtBot | |
| | | tomLeftBorder | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { North, West, Behind, South, East, Error}, //16 - AtFr | |
| | | ontBorder | |
| | | { North, West, Behind, South, Error, Error}, //17 - AtFr | |
| | | ontRightBorder | |
| | | { North, Behind, South, East, Error, Error}, //18 - AtFr | |
| | | ontLeftBorder | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { West, Behind, South, East, Error, Error}, //20 - AtTo | |
| | | pFrontBorder | |
| | | { West, Behind, South, Error, Error, Error}, //21 - AtTo | |
| | | pRightFrontBorder | |
| | | { Behind, South, East, Error, Error, Error}, //22 - AtTo | |
| | | pLeftFrontBorder | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { North, West, Behind, East, Error, Error}, //24 - AtBo | |
| | | ttomFrontBorder | |
| | | { North, West, Behind, Error, Error, Error}, //25 - AtBo | |
| | | ttomRightFrontBorder | |
| | | { North, Behind, East, Error, Error, Error}, //26 - AtBo | |
| | | ttomLeftFrontBorder | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { InFront, North, West, South, East,Error}, //32 - AtRe | |
| | | arBorder | |
| | | { InFront, North, West, South, Error, Error}, //33 - AtRe | |
| | | arRightBorder | |
| | | { InFront, North, South, East, Error, Error}, //34 - AtRe | |
| | | arLeftBorder | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { InFront, West, South, East, Error, Error}, //36 - AtTo | |
| | | pRearBorder | |
| | | { InFront, West, South, Error, Error, Error}, //37 - AtTo | |
| | | pRightRearBorder | |
| | | { InFront, South, East, Error, Error, Error}, //38 - AtTo | |
| | | pLeftRearBorder | |
| | | { Error, Error, Error, Error, Error, Error}, | |
| | | { InFront, North, West, East, Error, Error}, //40 - AtBo | |
| | | ttomRearBorder | |
| | | { InFront, North, West, Error, Error, Error}, //41 - AtBo | |
| | | ttomRightRearBorder | |
| | | { InFront, North, East, Error, Error, Error} //42 - AtBo | |
| | | ttomLeftRearBorder | |
| | | }; | |
| | | | |
| | | template <int DUMMY> | |
| | | Direction NeighborCode3D::StaticData<DUMMY>::bc[43][3] = { | |
| | | { InFront, North, West}, // 0 - NotAtBorder | |
| | | { InFront, North, West}, // 1 - AtRightBorde | |
| | | r | |
| | | { InFront, North, Error}, // 2 - AtLeftBorder | |
| | | { Error, Error, Error}, | |
| | | { InFront, West, Error}, // 4 - AtTopBorder | |
| | | { InFront, West, Error}, // 5 - AtTopRightBo | |
| | | rder | |
| | | { InFront, Error,Error}, // 6 - AtTopLeftBor | |
| | | der | |
| | | { Error, Error, Error}, | |
| | | { InFront, North, West}, // 8 - AtBottomBord | |
| | | er | |
| | | { InFront, North, West}, // 9 - AtBottomRigh | |
| | | tBorder | |
| | | { InFront, North, Error}, //10- AtBottomLeftB | |
| | | order | |
| | | { Error, Error, Error}, | |
| | | { Error, Error, Error}, | |
| | | { Error, Error, Error}, | |
| | | { Error, Error, Error}, | |
| | | { Error, Error, Error}, | |
| | | { North, West, Error}, //16 - AtFrontBorde | |
| | | r | |
| | | { North, West, Error}, //17 - AtFrontRight | |
| | | Border | |
| | | { North, Error, Error}, //18 - AtFrontLeftB | |
| | | order | |
| | | { Error, Error, Error}, | |
| | | { West, Error, Error}, //20 - AtTopFrontBo | |
| | | rder | |
| | | { West, Error, Error}, //21 - AtTopRightFr | |
| | | ontBorder | |
| | | { Error, Error, Error}, //22 - AtTopLeftFro | |
| | | ntBorder | |
| | | { Error, Error, Error}, | |
| | | { North, West, Error}, //24 - AtBottomFron | |
| | | tBorder | |
| | | { North, West, Error}, //25 - AtBottomRigh | |
| | | tFrontBorder | |
| | | { North, Error, Error}, //26 - AtBottomLeft | |
| | | FrontBorder | |
| | | { Error, Error, Error}, | |
| | | { Error, Error, Error}, | |
| | | { Error, Error, Error}, | |
| | | { Error, Error, Error}, | |
| | | { Error, Error, Error}, | |
| | | { InFront, North, West}, //32 - AtRearBorder | |
| | | { InFront, North, West}, //33 - AtRearRightB | |
| | | order | |
| | | { InFront, North, Error}, //34 - AtRearLeftBo | |
| | | rder | |
| | | { Error, Error, Error}, | |
| | | { InFront, West, Error}, //36 - AtTopRearBor | |
| | | der | |
| | | { InFront, West, Error}, //37 - AtTopRightRe | |
| | | arBorder | |
| | | { InFront, Error, Error}, //38 - AtTopLeftRea | |
| | | rBorder | |
| | | { Error, Error, Error}, | |
| | | { InFront, North, West}, //40 - AtBottomRear | |
| | | Border | |
| | | { InFront, North, West}, //41 - AtBottomRigh | |
| | | tRearBorder | |
| | | { InFront, North, Error} //42 - AtBottomLeft | |
| | | RearBorder | |
| | | }; | |
| | | | |
| | | template <int DUMMY> | |
| | | Diff3D NeighborCode3D::StaticData<DUMMY>::d[] = { | |
| | | Diff3D( 0, 0, -1), //InFront | |
| | | Diff3D( 0, -1, 0), //North | |
| | | Diff3D( -1, 0, 0), //West | |
| | | Diff3D( 0, 0, 1), //Behind | |
| | | Diff3D( 0, 1, 0), //South | |
| | | Diff3D( 1, 0, 0) //East | |
| | | }; | |
| | | | |
| | | template <int DUMMY> | |
| | | Diff3D NeighborCode3D::StaticData<DUMMY>::rd[][6] = { | |
| | | // InFront - North - West - Beh | |
| | | ind - South - East | |
| | | { Diff3D( 0, 0, 0), Diff3D(0, -1, 1), Diff3D(-1, 0, 1), Diff3D( 0, 0, 2), D | |
| | | iff3D( 0, 1, 1), Diff3D( 1, 0, 1)}, //InFront | |
| | | { Diff3D( 0, 1,-1), Diff3D( 0, 0, 0), Diff3D(-1, 1, 0), Diff3D( 0, 1, 1), D | |
| | | iff3D( 0, 2, 0), Diff3D( 1, 1, 0)}, //North | |
| | | { Diff3D( 1, 0,-1), Diff3D( 1,-1, 0), Diff3D( 0, 0, 0), Diff3D( 1, 0, 1), D | |
| | | iff3D( 1, 1, 0), Diff3D( 2, 0, 0)}, //West | |
| | | { Diff3D( 0, 0,-2), Diff3D( 0,-1,-1), Diff3D(-1, 0,-1), Diff3D( 0, 0, 0), D | |
| | | iff3D( 0, 1,-1), Diff3D( 1, 0,-1)}, //Behind | |
| | | { Diff3D( 0,-1,-1), Diff3D( 0,-2, 0), Diff3D(-1,-1, 0), Diff3D( 0,-1, 1), D | |
| | | iff3D( 0, 0, 0), Diff3D( 1,-1, 0)}, //South | |
| | | { Diff3D(-1, 0,-1), Diff3D(-1,-1, 0), Diff3D(-2, 0, 0), Diff3D(-1, 0, 1), D | |
| | | iff3D(-1, 1, 0), Diff3D( 0, 0, 0) } //East | |
| | | }; | |
| | | | |
| }//namespace Neighborhood3DSix | | }//namespace Neighborhood3DSix | |
| | | | |
| /** Export \ref vigra::Neighborhood3DSix::NeighborCode3D into the scope of
namespace vigra. | | /** Export \ref vigra::Neighborhood3DSix::NeighborCode3D into the scope of
namespace vigra. | |
| */ | | */ | |
| typedef Neighborhood3DSix::NeighborCode3D NeighborCode3DSix; | | typedef Neighborhood3DSix::NeighborCode3D NeighborCode3DSix; | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
| /* Neighborhood3DTwentySix */ | | /* Neighborhood3DTwentySix */ | |
| /* */ | | /* */ | |
| | | | |
| skipping to change at line 527 | | skipping to change at line 550 | |
| CausalFirst = InFrontNorthWest, | | CausalFirst = InFrontNorthWest, | |
| CausalLast = West, | | CausalLast = West, | |
| AntiCausalFirst = BehindSouthEast, | | AntiCausalFirst = BehindSouthEast, | |
| AntiCausalLast = East, | | AntiCausalLast = East, | |
| | | | |
| InitialDirection = InFrontNorthWest, | | InitialDirection = InFrontNorthWest, | |
| OppositeDirPrefix = -1, | | OppositeDirPrefix = -1, | |
| OppositeOffset = 25 | | OppositeOffset = 25 | |
| }; | | }; | |
| | | | |
|
| static unsigned int directionBit(Direction d) | | template <int DUMMY> | |
| | | struct StaticData | |
| { | | { | |
|
| static unsigned int b[] = { | | static unsigned int b[]; | |
| 1 << InFrontNorthWest, | | static unsigned int c[]; | |
| 1 << InFrontNorth, | | static Direction bd[43][26]; | |
| 1 << InFrontNorthEast, | | static Direction bc[43][13]; | |
| 1 << InFrontWest, | | static Diff3D d[]; | |
| 1 << InFront, | | }; | |
| 1 << InFrontEast, | | | |
| 1 << InFrontSouthWest, | | | |
| 1 << InFrontSouth, | | | |
| 1 << InFrontSouthEast, | | | |
| | | | |
| 1 << NorthWest, | | | |
| 1 << North, | | | |
| 1 << NorthEast, | | | |
| 1 << West, | | | |
| 1 << East, | | | |
| 1 << SouthWest, | | | |
| 1 << South, | | | |
| 1 << SouthEast, | | | |
| | | | |
|
| 1 << BehindNorthWest, | | static unsigned int directionBit(Direction d) | |
| 1 << BehindNorth, | | { | |
| 1 << BehindNorthEast, | | return StaticData<0>::b[d]; | |
| 1 << BehindWest, | | | |
| 1 << Behind, | | | |
| 1 << BehindEast, | | | |
| 1 << BehindSouthWest, | | | |
| 1 << BehindSouth, | | | |
| 1 << BehindSouthEast | | | |
| }; | | | |
| return b[d]; | | | |
| }; | | }; | |
| | | | |
| /** The number of valid neighbors if the current center is at the volum
e border. | | /** The number of valid neighbors if the current center is at the volum
e border. | |
| */ | | */ | |
| static unsigned int nearBorderDirectionCount(AtVolumeBorder b) | | static unsigned int nearBorderDirectionCount(AtVolumeBorder b) | |
| { | | { | |
|
| static unsigned int c[] = { 26, 17, 17, 0, 17, 11, 11, 0, 17, 11, | | return StaticData<0>::c[b]; | |
| 11, 0, 0, 0, 0, 0, 17, 11, 11, 0, | | | |
| 11, 7, 7, 0, 11, 7, 7, 0, 0, 0, | | | |
| 0, 0, 17, 11, 11, 0, 11, 7, 7, 0, | | | |
| 11, 7, 7}; | | | |
| return c[b]; | | | |
| } | | } | |
| | | | |
| /** The valid direction codes when the center is at the volume border. | | /** The valid direction codes when the center is at the volume border. | |
| \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1
</tt>. | | \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1
</tt>. | |
| */ | | */ | |
| static Direction nearBorderDirections(AtVolumeBorder b, int index) | | static Direction nearBorderDirections(AtVolumeBorder b, int index) | |
| { | | { | |
|
| static Direction c[43][26] = { | | return StaticData<0>::bd[b][index]; | |
| //0 - NotAtBorder | | | |
| { InFrontNorthWest, InFrontNorth, InFrontNorthEas | | | |
| t, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEas | | | |
| t, | | | |
| | | | |
| NorthWest, North, NorthEast, | | | |
| West, East, | | | |
| SouthWest, South, SouthEast, | | | |
| | | | |
| BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast}, | | | |
| //1 - AtRightBorder | | | |
| { InFrontNorthWest, InFrontNorth, /*InFrontNorthEast, | | | |
| */ | | | |
| InFrontWest, InFront, /*InFrontEast,*/ | | | |
| InFrontSouthWest, InFrontSouth, /*InFrontSouthEast, | | | |
| */ | | | |
| | | | |
| NorthWest, North, /*NorthEast,*/ | | | |
| West, /*East,*/ | | | |
| SouthWest, South, /*SouthEast,*/ | | | |
| | | | |
| BehindNorthWest, BehindNorth, /*BehindNorthEast,*/ | | | |
| BehindWest, Behind, /*BehindEast,*/ | | | |
| BehindSouthWest, BehindSouth, /*BehindSouthEast,*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //2 - AtLeftBorder | | | |
| { /*InFrontNorthWest,*/ InFrontNorth, InFrontNorthE | | | |
| ast, | | | |
| /*InFrontWest,*/ InFront, InFrontEast, | | | |
| /*InFrontSouthWest,*/ InFrontSouth, InFrontSouthE | | | |
| ast, | | | |
| | | | |
| /*NorthWest,*/ North, NorthEast, | | | |
| /*West,*/ East, | | | |
| /*SouthWest,*/ South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest,*/ BehindNorth, BehindNorthEast, | | | |
| /*BehindWest,*/ Behind, BehindEast, | | | |
| /*BehindSouthWest,*/ BehindSouth, BehindSouthEast, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //3 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //4 - AtTopBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | | | |
| */ | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEast, | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| West, East, | | | |
| SouthWest, South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast,*/ | | | |
| BehindWest, Behind, | | | |
| BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //5 - AtTopRightBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEas | | | |
| t,*/ | | | |
| InFrontWest, InFront, /*InFrontEast,* | | | |
| / | | | |
| InFrontSouthWest, InFrontSouth, /*InFrontSouthE | | | |
| ast,*/ | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| West, /*East,*/ | | | |
| SouthWest, South, /*SouthEast,*/ | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast,*/ | | | |
| BehindWest, Behind, /*BehindEast,*/ | | | |
| BehindSouthWest, BehindSouth, /*BehindSouthEast,* | | | |
| / | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //6 - AtTopLeftBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNort | | | |
| hEast,*/ | | | |
| /*InFrontWest,*/ InFront, InFrontEast | | | |
| , | | | |
| /*InFrontSouthWest,*/ InFrontSouth, InFrontSout | | | |
| hEast, | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| /*West,*/ East, | | | |
| /*SouthWest,*/ South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEas | | | |
| t,*/ | | | |
| /*BehindWest, */ Behind, BehindEast, | | | |
| /*BehindSouthWest,*/ BehindSouth, BehindSouthEas | | | |
| t, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //7 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //8 - AtBottomBorder | | | |
| { InFrontNorthWest, InFrontNorth, InFrontNorthEast | | | |
| , | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| /*InFrontSouthWest, InFrontSouth, InFrontSouthEast, | | | |
| */ | | | |
| | | | |
| NorthWest, North, NorthEast, | | | |
| West, East, | | | |
| /*SouthWest, South, SouthEast,*/ | | | |
| | | | |
| BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //9 - AtBottomRightBorder | | | |
| { InFrontNorthWest, InFrontNorth, /*InFrontNorthEa | | | |
| st,*/ | | | |
| InFrontWest, InFront, /*InFrontEast,*/ | | | |
| /*InFrontSouthWest, InFrontSouth, InFrontSouthEast | | | |
| ,*/ | | | |
| | | | |
| NorthWest, North, /*NorthEast,*/ | | | |
| West, /*East,*/ | | | |
| /*SouthWest, South, SouthEast,*/ | | | |
| | | | |
| BehindNorthWest, BehindNorth, /*BehindNorthEast,* | | | |
| / | | | |
| BehindWest, Behind, /*BehindEast,*/ | | | |
| /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //10 - AtBottomLeftBorder | | | |
| { /*InFrontNorthWest,*/ InFrontNorth, InFrontNort | | | |
| hEast, | | | |
| /*InFrontWest,*/ InFront, InFrontEast | | | |
| , | | | |
| /*InFrontSouthWest, InFrontSouth, InFrontSout | | | |
| hEast,*/ | | | |
| | | | |
| /*NorthWest,*/ North, NorthEast, | | | |
| /*West,*/ East, | | | |
| /*SouthWest, South, SouthEast,*/ | | | |
| | | | |
| /*BehindNorthWest,*/ BehindNorth, BehindNorthEast | | | |
| , | | | |
| /*BehindWest,*/ Behind, BehindEast, | | | |
| /*BehindSouthWest, BehindSouth, BehindSouthEast | | | |
| */ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //11 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //12 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //13 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //14 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //15 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //16 - AtFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEa | | | |
| st, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | | | |
| | | | |
| NorthWest, North, NorthEast, | | | |
| West, East, | | | |
| SouthWest, South, SouthEast, | | | |
| | | | |
| BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //17 - AtFrontRightBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEa | | | |
| st, | | | |
| InFrontWest, InFront, | | | |
| InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | | | |
| | | | |
| NorthWest, North, /*NorthEast,*/ | | | |
| West, /*East,*/ | | | |
| SouthWest, South, /*SouthEast,*/ | | | |
| | | | |
| BehindNorthWest, BehindNorth, /*BehindNorthEast,*/ | | | |
| BehindWest, Behind, /*BehindEast,*/ | | | |
| BehindSouthWest, BehindSouth, /*BehindSouthEast,*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //18 - AtFrontLeftBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEas | | | |
| t, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEas | | | |
| t,*/ | | | |
| | | | |
| /*NorthWest,*/ North, NorthEast, | | | |
| /*West,*/ East, | | | |
| /*SouthWest,*/ South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest,*/ BehindNorth, BehindNorthEast, | | | |
| /*BehindWest,*/ Behind, BehindEast, | | | |
| /*BehindSouthWest,*/ BehindSouth, BehindSouthEast, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //19 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //20 - AtTopFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEas | | | |
| t, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEas | | | |
| t,*/ | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| West, East, | | | |
| SouthWest, South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast | | | |
| ,*/ | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast | | | |
| , | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //21 - AtTopRightFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast | | | |
| , | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEast | | | |
| ,*/ | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| West, /*East,*/ | | | |
| SouthWest, South, /*SouthEast,*/ | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast,*/ | | | |
| BehindWest, Behind, /*BehindEast,*/ | | | |
| BehindSouthWest, BehindSouth, /*BehindSouthEast,* | | | |
| / | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error}, | | | |
| //22 - AtTopLeftFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEas | | | |
| t, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEas | | | |
| t,*/ | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| /*West,*/ East, | | | |
| /*SouthWest,*/ South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEas | | | |
| t,*/ | | | |
| /*BehindWest,*/ Behind, BehindEast, | | | |
| /*BehindSouthWest,*/ BehindSouth, BehindSouthEas | | | |
| t, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error}, | | | |
| //23 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //24 - AtBottomFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEast, | | | |
| */ | | | |
| | | | |
| NorthWest, North, NorthEast, | | | |
| West, East, | | | |
| /*SouthWest, South, SouthEast,*/ | | | |
| | | | |
| BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //25 - AtBottomRightFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEa | | | |
| st, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | | | |
| | | | |
| NorthWest, North, /*NorthEast,*/ | | | |
| West, /* East,*/ | | | |
| /*SouthWest, South, SouthEast,*/ | | | |
| | | | |
| BehindNorthWest, BehindNorth, /*BehindNorthEast, | | | |
| */ | | | |
| BehindWest, Behind, /*BehindEast,*/ | | | |
| /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error}, | | | |
| //26 - AtBottomLeftFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | | | |
| | | | |
| /*NorthWest,*/ North, NorthEast, | | | |
| /*West,*/ East, | | | |
| /*SouthWest, South, SouthEast,*/ | | | |
| | | | |
| /*BehindNorthWest,*/ BehindNorth, BehindNorthEast, | | | |
| /*BehindWest,*/ Behind, BehindEast, | | | |
| /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error}, | | | |
| //27 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //28 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //29 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //30 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //31 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //32 - AtRearBorder | | | |
| { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEast, | | | |
| | | | |
| NorthWest, North, NorthEast, | | | |
| West, East, | | | |
| SouthWest, South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast,*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //33 - AtRearRightBorder | | | |
| { InFrontNorthWest, InFrontNorth, /*InFrontNorthEast, | | | |
| */ | | | |
| InFrontWest, InFront, /*InFrontEast,*/ | | | |
| InFrontSouthWest, InFrontSouth, /*InFrontSouthEast, | | | |
| */ | | | |
| | | | |
| NorthWest, North, /*NorthEast,*/ | | | |
| West, /*East,*/ | | | |
| SouthWest, South, /*SouthEast,*/ | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast,*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //34 - AtRearLeftBorder | | | |
| { /*InFrontNorthWest,*/ InFrontNorth, InFrontNorthEas | | | |
| t, | | | |
| /*InFrontWest,*/ InFront, InFrontEast, | | | |
| /*InFrontSouthWest,*/ InFrontSouth, InFrontSouthEas | | | |
| t, | | | |
| | | | |
| /*NorthWest,*/ North, NorthEast, | | | |
| /*West,*/ East, | | | |
| /*SouthWest,*/ South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast,* | | | |
| / | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //35 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //36 - AtTopRearBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEas | | | |
| t,*/ | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| InFrontSouthWest, InFrontSouth, InFrontSouthEas | | | |
| t, | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| West, East, | | | |
| SouthWest, South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast,* | | | |
| / | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //37 - AtTopRightRearBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNorthEas | | | |
| t,*/ | | | |
| InFrontWest, InFront, /*InFrontEast,* | | | |
| / | | | |
| InFrontSouthWest, InFrontSouth, /*InFrontSouthE | | | |
| ast,*/ | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| West, /*East,*/ | | | |
| SouthWest, South, /*SouthEast,*/ | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast,*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error}, | | | |
| //38 - AtTopLeftRearBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFrontNor | | | |
| thEast,*/ | | | |
| /*InFrontWest,*/ InFront, InFrontEas | | | |
| t, | | | |
| /*InFrontSouthWest,*/ InFrontSouth, InFrontSout | | | |
| hEast, | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| /*West,*/ East, | | | |
| /*SouthWest,*/ South, SouthEast, | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast | | | |
| , | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast | | | |
| ,*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error}, | | | |
| //39 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error}, | | | |
| //40 - AtBottomRearBorder | | | |
| { InFrontNorthWest, InFrontNorth, InFrontNorthEas | | | |
| t, | | | |
| InFrontWest, InFront, InFrontEast, | | | |
| /*InFrontSouthWest, InFrontSouth, InFrontSouthEas | | | |
| t,*/ | | | |
| | | | |
| NorthWest, North, NorthEast, | | | |
| West, East, | | | |
| /*SouthWest, South, SouthEast,*/ | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast,*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //41 - AtBottomRightRearBorder | | | |
| { InFrontNorthWest, InFrontNorth, /*InFrontNorthEas | | | |
| t,*/ | | | |
| InFrontWest, InFront, /*InFrontEast,*/ | | | |
| /*InFrontSouthWest, InFrontSouth, InFrontSouthEast, | | | |
| */ | | | |
| | | | |
| NorthWest, North, /*NorthEast,*/ | | | |
| West, /*East,*/ | | | |
| /*SouthWest, South, SouthEast,*/ | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast,*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error}, | | | |
| //42 - AtBottomLeftRearBorder | | | |
| { /*InFrontNorthWest,*/ InFrontNorth, InFrontNort | | | |
| hEast, | | | |
| /*InFrontWest,*/ InFront, InFrontEast | | | |
| , | | | |
| /*InFrontSouthWest, InFrontSouth, InFrontSout | | | |
| hEast,*/ | | | |
| | | | |
| /*NorthWest,*/ North, NorthEast, | | | |
| /*West,*/ East, | | | |
| /*SouthWest, South, SouthEast,*/ | | | |
| | | | |
| /*BehindNorthWest, BehindNorth, BehindNorthEast, | | | |
| BehindWest, Behind, BehindEast, | | | |
| BehindSouthWest, BehindSouth, BehindSouthEast,*/ | | | |
| Error, Error, Error, Error, Error, Error, Error, Er | | | |
| ror, Error, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error} | | | |
| }; | | | |
| return c[b][index]; | | | |
| } | | } | |
| | | | |
| /** The valid direction three codes in anti causal direction (means: lo
ok back in scanline | | /** The valid direction three codes in anti causal direction (means: lo
ok back in scanline | |
| direction)when the center is at the volume border. | | direction)when the center is at the volume border. | |
| Should be used with isAtVolumeBorderCausal to determine the Dir
ections, as this | | Should be used with isAtVolumeBorderCausal to determine the Dir
ections, as this | |
| avoids using of the nonesense border ids (e.g. 0,1,8,9...) of t
his table. | | avoids using of the nonesense border ids (e.g. 0,1,8,9...) of t
his table. | |
| \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1
</tt>. | | \a index must be in the range <tt>0...nearBorderDirectionCount(b)-1
</tt>. | |
| */ | | */ | |
| static Direction nearBorderDirectionsCausal(AtVolumeBorder b, int index
) | | static Direction nearBorderDirectionsCausal(AtVolumeBorder b, int index
) | |
| { | | { | |
|
| static Direction c[43][13] = { | | return StaticData<0>::bc[b][index]; | |
| //0 - NotAtBorder -----> should never be used | | | |
| { InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| NorthWest, North, NorthE | | | |
| ast, | | | |
| West}, | | | |
| //1 - AtRightBorder | | | |
| { InFrontNorthWest, InFrontNorth, /* InF | | | |
| rontNorthEast, */ | | | |
| InFrontWest, InFront, /* InF | | | |
| rontEast, */ | | | |
| InFrontSouthWest, InFrontSouth, /* InF | | | |
| rontSouthEast, */ | | | |
| | | | |
| NorthWest, North, /* Nor | | | |
| thEast, */ | | | |
| West, | | | |
| Error, Error, Error, Error}, | | | |
| //2 - AtLeftBorder | | | |
| { /*InFrontNorthWest,*/ InFrontNorth,InFron | | | |
| tNorthEast, | | | |
| /*InFrontWest,*/ InFront, InFron | | | |
| tEast, | | | |
| /*InFrontSouthWest,*/InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| /*NorthWest,*/ North, NorthE | | | |
| ast, | | | |
| /*West*/ | | | |
| Error, Error, Error, Error, Error}, | | | |
| //3 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //4 - AtTopBorder | | | |
| { /*InFrontNorthWest,InFrontNorth, InFron | | | |
| tNorthEast,*/ | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| /*NorthWest, North, NorthE | | | |
| ast,*/ | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error} | | | |
| , | | | |
| //5 - AtTopRightBorder | | | |
| { /*InFrontNorthWest,InFrontNorth, InFron | | | |
| tNorthEast,*/ | | | |
| InFrontWest, InFront, /*InFr | | | |
| ontEast,*/ | | | |
| InFrontSouthWest, InFrontSouth, /*InFr | | | |
| ontSouthEast,*/ | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error}, | | | |
| //6 - AtTopLeftBorder | | | |
| { /*InFrontNorthWest,InFrontNorth, InFro | | | |
| ntNorthEast,*/ | | | |
| /*InFrontWest,*/ InFront, InFro | | | |
| ntEast, | | | |
| /*InFrontSouthWest,*/InFrontSouth, InFro | | | |
| ntSouthEast, | | | |
| | | | |
| /*NorthWest, North, North | | | |
| East,*/ | | | |
| /*West,*/ | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error}, | | | |
| //7 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //8 - AtBottomBorder | | | |
| { InFrontNorthWest, InFrontNorth, InFro | | | |
| ntNorthEast, | | | |
| InFrontWest, InFront, InFro | | | |
| ntEast, | | | |
| /* InFrontSouthWest, InFrontSouth, In | | | |
| FrontSouthEast, */ | | | |
| | | | |
| NorthWest, North, North | | | |
| East, | | | |
| West, | | | |
| Error, Error, Error}, | | | |
| //9 - AtBottomRightBorder | | | |
| { InFrontNorthWest, InFrontNorth, /* InF | | | |
| rontNorthEast, */ | | | |
| InFrontWest, InFront, /* InF | | | |
| rontEast, */ | | | |
| /* InFrontSouthWest, InFrontSouth, InF | | | |
| rontSouthEast, */ | | | |
| | | | |
| NorthWest, North, /* Nor | | | |
| thEast, */ | | | |
| West, | | | |
| Error, Error, Error,Error, Error, Error}, | | | |
| //10 - AtBottomLeftBorder | | | |
| { /*InFrontNorthWest,*/InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| /*InFrontWest,*/ InFront, InFron | | | |
| tEast, | | | |
| /*InFrontSouthWest, InFrontSouth, InFront | | | |
| SouthEast, */ | | | |
| | | | |
| /*NorthWest,*/ North, NorthE | | | |
| ast, | | | |
| /*West*/ | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error}, | | | |
| //11 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //12 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //13 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //14 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //15 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //16 - AtFrontBorder | | | |
| { /*InFrontNorthWest,InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast,*/ | | | |
| | | | |
| NorthWest, North, NorthE | | | |
| ast, | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error}, | | | |
| //17 - AtFrontRightBorder | | | |
| { /*InFrontNorthWest,InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast,*/ | | | |
| | | | |
| NorthWest, North, /*Nort | | | |
| hEast,*/ | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error}, | | | |
| //18 - AtFrontLeftBorder | | | |
| { /*InFrontNorthWest,InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast,*/ | | | |
| | | | |
| /*NorthWest,*/ North, NorthE | | | |
| ast, | | | |
| /*West,*/ | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error}, | | | |
| //19 - Nothin' | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //20 - AtTopFrontBorder | | | |
| { /*InFrontNorthWest,InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast,*/ | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //21 - AtTopRightFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast,*/ | | | |
| | | | |
| /*NorthWest, North, NorthE | | | |
| ast,*/ | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error}, | | | |
| //22 - AtTopLeftFrontBorder | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //23 - Nothin | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //24 - AtBottomFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast,*/ | | | |
| | | | |
| NorthWest, North, NorthE | | | |
| ast, | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error}, | | | |
| //25 - AtBottomRightFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast,*/ | | | |
| | | | |
| NorthWest, North, /*Nort | | | |
| hEast,*/ | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error}, | | | |
| //26 - AtBottomLeftFrontBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast,*/ | | | |
| | | | |
| /*NorthWest,*/ North, NorthE | | | |
| ast, | | | |
| /* West, */ | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error}, | | | |
| //27 - Nothin | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //28 - Nothin | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //29 - Nothin | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //30 - Nothin | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //31 - Nothin | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //32 - AtRearBorder | | | |
| { InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| NorthWest, North, NorthE | | | |
| ast, | | | |
| West}, | | | |
| //33 - AtRearRightBorder | | | |
| { InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| NorthWest, North, NorthE | | | |
| ast, | | | |
| West}, | | | |
| //34 - AtRearLeftBorder | | | |
| { /*InFrontNorthWest,*/InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| /*InFrontWest,*/ InFront, InFron | | | |
| tEast, | | | |
| /*InFrontSouthWest,*/InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| /*NorthWest,*/ North, NorthE | | | |
| ast, | | | |
| /*West*/ | | | |
| Error, Error, Error, Error, Error}, | | | |
| //35 - Nothin | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //36 - AtTopRearBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast,*/ | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| /*NorthWest, North, NorthE | | | |
| ast,*/ | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error} | | | |
| , | | | |
| //37 - AtTopRightRearBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast,*/ | | | |
| InFrontWest, InFront, /*InFr | | | |
| ontEast,*/ | | | |
| InFrontSouthWest, InFrontSouth, /*InFr | | | |
| ontSouthEast,*/ | | | |
| | | | |
| /*NorthWest, North, NorthE | | | |
| ast,*/ | | | |
| West, | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error}, | | | |
| //38 - AtTopLeftRearBorder | | | |
| { /*InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast,*/ | | | |
| /*InFrontWest,*/ InFront, InFron | | | |
| tEast, | | | |
| /*InFrontSouthWest,*/InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| /*NorthWest, North, NorthEast,*/ | | | |
| /*West,*/ | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error}, | | | |
| //39 - Nothin | | | |
| { Error, Error, Error, Error, Error, Error, | | | |
| Error, Error, Error, Error, Error, Error, Error}, | | | |
| //40 - AtBottomRearBorder | | | |
| { InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| NorthWest, North, NorthE | | | |
| ast, | | | |
| West}, | | | |
| //41 - AtBottomRightRearBorder | | | |
| { InFrontNorthWest, InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| InFrontWest, InFront, InFron | | | |
| tEast, | | | |
| InFrontSouthWest, InFrontSouth, InFron | | | |
| tSouthEast, | | | |
| | | | |
| NorthWest, North, NorthE | | | |
| ast, | | | |
| West}, | | | |
| //42 - AtBottomLeftRearBorder | | | |
| { /*InFrontNorthWest,*/InFrontNorth, InFron | | | |
| tNorthEast, | | | |
| /*InFrontWest,*/ InFront, InFron | | | |
| tEast, | | | |
| /*InFrontSouthWest,InFrontSouth, InFron | | | |
| tSouthEast,*/ | | | |
| | | | |
| /*NorthWest,*/ North, NorthE | | | |
| ast, | | | |
| /*West*/ | | | |
| Error, Error, Error, Error, Error, Error, | | | |
| Error} | | | |
| }; | | | |
| return c[b][index]; | | | |
| } | | } | |
| | | | |
| /** transform direction code into corresponding Diff3D offset. | | /** transform direction code into corresponding Diff3D offset. | |
| (note: there is no bounds checking on the code you pass.) | | (note: there is no bounds checking on the code you pass.) | |
| */ | | */ | |
| static Diff3D const & diff(Direction code) | | static Diff3D const & diff(Direction code) | |
| { | | { | |
|
| static Diff3D d[] = { Diff3D( -1, -1, -1), //InFrontNorthWest | | return StaticData<0>::d[code]; | |
| Diff3D( 0, -1, -1), //InFrontNorth | | | |
| Diff3D( 1, -1, -1), //InFrontNorthEast | | | |
| Diff3D( -1, 0, -1), //InFrontWest | | | |
| Diff3D( 0, 0, -1), //InFront | | | |
| Diff3D( 1, 0, -1), //InFrontEast | | | |
| Diff3D( -1, 1, -1), //InFrontSouthWest | | | |
| Diff3D( 0, 1, -1), //InFrontSouth | | | |
| Diff3D( 1, 1, -1), //InFrontSouthEast | | | |
| | | | |
| Diff3D( -1, -1, 0), //NorthWest | | | |
| Diff3D( 0, -1, 0), //North | | | |
| Diff3D( 1, -1, 0), //NorthEast | | | |
| Diff3D( -1, 0, 0), //West | | | |
| Diff3D( 1, 0, 0), //East | | | |
| Diff3D( -1, 1, 0), //SouthWest | | | |
| Diff3D( 0, 1, 0), //South | | | |
| Diff3D( 1, 1, 0), //SouthEast | | | |
| | | | |
| Diff3D( -1, -1, 1), //BehindNorthWest | | | |
| Diff3D( 0, -1, 1), //BehindNorth | | | |
| Diff3D( 1, -1, 1), //BehindNorthEast | | | |
| Diff3D( -1, 0, 1), //BehindWest | | | |
| Diff3D( 0, 0, 1), //Behind | | | |
| Diff3D( 1, 0, 1), //BehindEast | | | |
| Diff3D( -1, 1, 1), //BehindSouthWest | | | |
| Diff3D( 0, 1, 1), //BehindSouth | | | |
| Diff3D( 1, 1, 1), //BehindSouthEast | | | |
| }; | | | |
| return d[code]; | | | |
| } | | } | |
| | | | |
| /** Equivalent to <tt>diff(static_cast<Direction>(code))</tt>. | | /** Equivalent to <tt>diff(static_cast<Direction>(code))</tt>. | |
| (note: there is no bounds checking on the code you pass.) | | (note: there is no bounds checking on the code you pass.) | |
| */ | | */ | |
| static Diff3D const & diff(int code) { return diff(static_cast<Directio
n>(code)); } | | static Diff3D const & diff(int code) { return diff(static_cast<Directio
n>(code)); } | |
| | | | |
| /** Equivalent to <tt>diff(code)[dim]</tt> */ | | /** Equivalent to <tt>diff(code)[dim]</tt> */ | |
| static int diff(Direction code, int dim) { return diff(code)[dim]; } | | static int diff(Direction code, int dim) { return diff(code)[dim]; } | |
| | | | |
| | | | |
| skipping to change at line 1590 | | skipping to change at line 876 | |
| static const Direction BehindNorthEast = NeighborCode3D::BehindNorthEast
; /**< Export NeighborCode3D::BehindNorthEast to namespace Neighborho
od3DTwentySix */ | | static const Direction BehindNorthEast = NeighborCode3D::BehindNorthEast
; /**< Export NeighborCode3D::BehindNorthEast to namespace Neighborho
od3DTwentySix */ | |
| static const Direction BehindWest = NeighborCode3D::BehindWest;
/**< Export NeighborCode3D::BehindWest to namespace Neighborhood3DT
wentySix */ | | static const Direction BehindWest = NeighborCode3D::BehindWest;
/**< Export NeighborCode3D::BehindWest to namespace Neighborhood3DT
wentySix */ | |
| static const Direction Behind = NeighborCode3D::Behind;
/**< Export NeighborCode3D::Behind to namespace Neighborhood3DTwent
ySix */ | | static const Direction Behind = NeighborCode3D::Behind;
/**< Export NeighborCode3D::Behind to namespace Neighborhood3DTwent
ySix */ | |
| static const Direction BehindEast = NeighborCode3D::BehindEast;
/**< Export NeighborCode3D::BehindEast to namespace Neighborhood3DT
wentySix */ | | static const Direction BehindEast = NeighborCode3D::BehindEast;
/**< Export NeighborCode3D::BehindEast to namespace Neighborhood3DT
wentySix */ | |
| static const Direction BehindSouthWest = NeighborCode3D::BehindSouthWest
; /**< Export NeighborCode3D::BehindSouthWest to namespace Neighborho
od3DTwentySix */ | | static const Direction BehindSouthWest = NeighborCode3D::BehindSouthWest
; /**< Export NeighborCode3D::BehindSouthWest to namespace Neighborho
od3DTwentySix */ | |
| static const Direction BehindSouth = NeighborCode3D::BehindSouth;
/**< Export NeighborCode3D::BehindSouth to namespace Neighborhood3D
TwentySix */ | | static const Direction BehindSouth = NeighborCode3D::BehindSouth;
/**< Export NeighborCode3D::BehindSouth to namespace Neighborhood3D
TwentySix */ | |
| static const Direction BehindSouthEast = NeighborCode3D::BehindSouthEast
; /**< Export NeighborCode3D::BehindSouthEast to namespace Neighborho
od3DTwentySix */ | | static const Direction BehindSouthEast = NeighborCode3D::BehindSouthEast
; /**< Export NeighborCode3D::BehindSouthEast to namespace Neighborho
od3DTwentySix */ | |
| | | | |
| static const Direction DirectionCount = NeighborCode3D::DirectionCount;
/**< Export NeighborCode3D::DirectionCount to namespace Neighborhoo
d3DTwentySix */ | | static const Direction DirectionCount = NeighborCode3D::DirectionCount;
/**< Export NeighborCode3D::DirectionCount to namespace Neighborhoo
d3DTwentySix */ | |
| | | | |
|
| | | template <int DUMMY> | |
| | | unsigned int NeighborCode3D::StaticData<DUMMY>::b[] = { | |
| | | 1 << InFrontNorthWest, | |
| | | 1 << InFrontNorth, | |
| | | 1 << InFrontNorthEast, | |
| | | 1 << InFrontWest, | |
| | | 1 << InFront, | |
| | | 1 << InFrontEast, | |
| | | 1 << InFrontSouthWest, | |
| | | 1 << InFrontSouth, | |
| | | 1 << InFrontSouthEast, | |
| | | | |
| | | 1 << NorthWest, | |
| | | 1 << North, | |
| | | 1 << NorthEast, | |
| | | 1 << West, | |
| | | 1 << East, | |
| | | 1 << SouthWest, | |
| | | 1 << South, | |
| | | 1 << SouthEast, | |
| | | | |
| | | 1 << BehindNorthWest, | |
| | | 1 << BehindNorth, | |
| | | 1 << BehindNorthEast, | |
| | | 1 << BehindWest, | |
| | | 1 << Behind, | |
| | | 1 << BehindEast, | |
| | | 1 << BehindSouthWest, | |
| | | 1 << BehindSouth, | |
| | | 1 << BehindSouthEast | |
| | | }; | |
| | | | |
| | | template <int DUMMY> | |
| | | unsigned int NeighborCode3D::StaticData<DUMMY>::c[] = { | |
| | | 26, 17, 17, 0, 17, 11, 11, 0, 17, 11, | |
| | | 11, 0, 0, 0, 0, 0, 17, 11, 11, 0, | |
| | | 11, 7, 7, 0, 11, 7, 7, 0, 0, 0, | |
| | | 0, 0, 17, 11, 11, 0, 11, 7, 7, 0, | |
| | | 11, 7, 7}; | |
| | | | |
| | | template <int DUMMY> | |
| | | Direction NeighborCode3D::StaticData<DUMMY>::bd[43][26] = { | |
| | | //0 - NotAtBorder | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West, East, | |
| | | SouthWest, South, SouthEast, | |
| | | | |
| | | BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast}, | |
| | | //1 - AtRightBorder | |
| | | { InFrontNorthWest, InFrontNorth, /*InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, /*InFrontEast,*/ | |
| | | InFrontSouthWest, InFrontSouth, /*InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, /*NorthEast,*/ | |
| | | West, /*East,*/ | |
| | | SouthWest, South, /*SouthEast,*/ | |
| | | | |
| | | BehindNorthWest, BehindNorth, /*BehindNorthEast,*/ | |
| | | BehindWest, Behind, /*BehindEast,*/ | |
| | | BehindSouthWest, BehindSouth, /*BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //2 - AtLeftBorder | |
| | | { /*InFrontNorthWest,*/ InFrontNorth, InFrontNorthEast, | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest,*/ InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West,*/ East, | |
| | | /*SouthWest,*/ South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest,*/ BehindNorth, BehindNorthEast, | |
| | | /*BehindWest,*/ Behind, BehindEast, | |
| | | /*BehindSouthWest,*/ BehindSouth, BehindSouthEast, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //3 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //4 - AtTopBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, East, | |
| | | SouthWest, South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast,*/ | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //5 - AtTopRightBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, /*InFrontEast,*/ | |
| | | InFrontSouthWest, InFrontSouth, /*InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, /*East,*/ | |
| | | SouthWest, South, /*SouthEast,*/ | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast,*/ | |
| | | BehindWest, Behind, /*BehindEast,*/ | |
| | | BehindSouthWest, BehindSouth, /*BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //6 - AtTopLeftBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast,*/ | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest,*/ InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | /*West,*/ East, | |
| | | /*SouthWest,*/ South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast,*/ | |
| | | /*BehindWest, */ Behind, BehindEast, | |
| | | /*BehindSouthWest,*/ BehindSouth, BehindSouthEast, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //7 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //8 - AtBottomBorder | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | /*InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West, East, | |
| | | /*SouthWest, South, SouthEast,*/ | |
| | | | |
| | | BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //9 - AtBottomRightBorder | |
| | | { InFrontNorthWest, InFrontNorth, /*InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, /*InFrontEast,*/ | |
| | | /*InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, /*NorthEast,*/ | |
| | | West, /*East,*/ | |
| | | /*SouthWest, South, SouthEast,*/ | |
| | | | |
| | | BehindNorthWest, BehindNorth, /*BehindNorthEast,*/ | |
| | | BehindWest, Behind, /*BehindEast,*/ | |
| | | /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //10 - AtBottomLeftBorder | |
| | | { /*InFrontNorthWest,*/ InFrontNorth, InFrontNorthEast, | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West,*/ East, | |
| | | /*SouthWest, South, SouthEast,*/ | |
| | | | |
| | | /*BehindNorthWest,*/ BehindNorth, BehindNorthEast, | |
| | | /*BehindWest,*/ Behind, BehindEast, | |
| | | /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //11 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //12 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //13 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //14 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //15 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //16 - AtFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West, East, | |
| | | SouthWest, South, SouthEast, | |
| | | | |
| | | BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //17 - AtFrontRightBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, /*NorthEast,*/ | |
| | | West, /*East,*/ | |
| | | SouthWest, South, /*SouthEast,*/ | |
| | | | |
| | | BehindNorthWest, BehindNorth, /*BehindNorthEast,*/ | |
| | | BehindWest, Behind, /*BehindEast,*/ | |
| | | BehindSouthWest, BehindSouth, /*BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //18 - AtFrontLeftBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West,*/ East, | |
| | | /*SouthWest,*/ South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest,*/ BehindNorth, BehindNorthEast, | |
| | | /*BehindWest,*/ Behind, BehindEast, | |
| | | /*BehindSouthWest,*/ BehindSouth, BehindSouthEast, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //19 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //20 - AtTopFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, East, | |
| | | SouthWest, South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast,*/ | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //21 - AtTopRightFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, /*East,*/ | |
| | | SouthWest, South, /*SouthEast,*/ | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast,*/ | |
| | | BehindWest, Behind, /*BehindEast,*/ | |
| | | BehindSouthWest, BehindSouth, /*BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error}, | |
| | | //22 - AtTopLeftFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | /*West,*/ East, | |
| | | /*SouthWest,*/ South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast,*/ | |
| | | /*BehindWest,*/ Behind, BehindEast, | |
| | | /*BehindSouthWest,*/ BehindSouth, BehindSouthEast, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error}, | |
| | | //23 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //24 - AtBottomFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West, East, | |
| | | /*SouthWest, South, SouthEast,*/ | |
| | | | |
| | | BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //25 - AtBottomRightFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, /*NorthEast,*/ | |
| | | West, /* East,*/ | |
| | | /*SouthWest, South, SouthEast,*/ | |
| | | | |
| | | BehindNorthWest, BehindNorth, /*BehindNorthEast,*/ | |
| | | BehindWest, Behind, /*BehindEast,*/ | |
| | | /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error}, | |
| | | //26 - AtBottomLeftFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West,*/ East, | |
| | | /*SouthWest, South, SouthEast,*/ | |
| | | | |
| | | /*BehindNorthWest,*/ BehindNorth, BehindNorthEast, | |
| | | /*BehindWest,*/ Behind, BehindEast, | |
| | | /*BehindSouthWest, BehindSouth, BehindSouthEast*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error}, | |
| | | //27 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //28 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //29 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //30 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //31 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //32 - AtRearBorder | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West, East, | |
| | | SouthWest, South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //33 - AtRearRightBorder | |
| | | { InFrontNorthWest, InFrontNorth, /*InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, /*InFrontEast,*/ | |
| | | InFrontSouthWest, InFrontSouth, /*InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, /*NorthEast,*/ | |
| | | West, /*East,*/ | |
| | | SouthWest, South, /*SouthEast,*/ | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //34 - AtRearLeftBorder | |
| | | { /*InFrontNorthWest,*/ InFrontNorth, InFrontNorthEast, | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest,*/ InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West,*/ East, | |
| | | /*SouthWest,*/ South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //35 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //36 - AtTopRearBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, East, | |
| | | SouthWest, South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //37 - AtTopRightRearBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, /*InFrontEast,*/ | |
| | | InFrontSouthWest, InFrontSouth, /*InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, /*East,*/ | |
| | | SouthWest, South, /*SouthEast,*/ | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error}, | |
| | | //38 - AtTopLeftRearBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast,*/ | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest,*/ InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | /*West,*/ East, | |
| | | /*SouthWest,*/ South, SouthEast, | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error}, | |
| | | //39 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //40 - AtBottomRearBorder | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | /*InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West, East, | |
| | | /*SouthWest, South, SouthEast,*/ | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //41 - AtBottomRightRearBorder | |
| | | { InFrontNorthWest, InFrontNorth, /*InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, /*InFrontEast,*/ | |
| | | /*InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, /*NorthEast,*/ | |
| | | West, /*East,*/ | |
| | | /*SouthWest, South, SouthEast,*/ | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error}, | |
| | | //42 - AtBottomLeftRearBorder | |
| | | { /*InFrontNorthWest,*/ InFrontNorth, InFrontNorthEast, | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West,*/ East, | |
| | | /*SouthWest, South, SouthEast,*/ | |
| | | | |
| | | /*BehindNorthWest, BehindNorth, BehindNorthEast, | |
| | | BehindWest, Behind, BehindEast, | |
| | | BehindSouthWest, BehindSouth, BehindSouthEast,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error, Error} | |
| | | }; | |
| | | | |
| | | template <int DUMMY> | |
| | | Direction NeighborCode3D::StaticData<DUMMY>::bc[43][13] = { | |
| | | //0 - NotAtBorder -----> should never be used | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West}, | |
| | | //1 - AtRightBorder | |
| | | { InFrontNorthWest, InFrontNorth, /* InFrontNorthEast, */ | |
| | | InFrontWest, InFront, /* InFrontEast, */ | |
| | | InFrontSouthWest, InFrontSouth, /* InFrontSouthEast, */ | |
| | | | |
| | | NorthWest, North, /* NorthEast, */ | |
| | | West, | |
| | | Error, Error, Error, Error}, | |
| | | //2 - AtLeftBorder | |
| | | { /*InFrontNorthWest,*/ InFrontNorth,InFrontNorthEast, | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest,*/InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West*/ | |
| | | Error, Error, Error, Error, Error}, | |
| | | //3 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //4 - AtTopBorder | |
| | | { /*InFrontNorthWest,InFrontNorth, InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //5 - AtTopRightBorder | |
| | | { /*InFrontNorthWest,InFrontNorth, InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, /*InFrontEast,*/ | |
| | | InFrontSouthWest, InFrontSouth, /*InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //6 - AtTopLeftBorder | |
| | | { /*InFrontNorthWest,InFrontNorth, InFrontNorthEast,*/ | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest,*/InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | /*West,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //7 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //8 - AtBottomBorder | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | /* InFrontSouthWest, InFrontSouth, InFrontSouthEast, */ | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West, | |
| | | Error, Error, Error}, | |
| | | //9 - AtBottomRightBorder | |
| | | { InFrontNorthWest, InFrontNorth, /* InFrontNorthEast, */ | |
| | | InFrontWest, InFront, /* InFrontEast, */ | |
| | | /* InFrontSouthWest, InFrontSouth, InFrontSouthEast, */ | |
| | | | |
| | | NorthWest, North, /* NorthEast, */ | |
| | | West, | |
| | | Error, Error, Error,Error, Error, Error}, | |
| | | //10 - AtBottomLeftBorder | |
| | | { /*InFrontNorthWest,*/InFrontNorth, InFrontNorthEast, | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest, InFrontSouth, InFrontSouthEast, */ | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West*/ | |
| | | Error, Error, Error, Error, Error, Error, Error}, | |
| | | //11 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //12 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //13 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //14 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //15 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //16 - AtFrontBorder | |
| | | { /*InFrontNorthWest,InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //17 - AtFrontRightBorder | |
| | | { /*InFrontNorthWest,InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, /*NorthEast,*/ | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, Error} | |
| | | , | |
| | | //18 - AtFrontLeftBorder | |
| | | { /*InFrontNorthWest,InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error}, | |
| | | //19 - Nothin' | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //20 - AtTopFrontBorder | |
| | | { /*InFrontNorthWest,InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error}, | |
| | | //21 - AtTopRightFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error}, | |
| | | //22 - AtTopLeftFrontBorder | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //23 - Nothin | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //24 - AtBottomFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //25 - AtBottomRightFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | NorthWest, North, /*NorthEast,*/ | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, Error} | |
| | | , | |
| | | //26 - AtBottomLeftFrontBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /* West, */ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error}, | |
| | | //27 - Nothin | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //28 - Nothin | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //29 - Nothin | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //30 - Nothin | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //31 - Nothin | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //32 - AtRearBorder | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West}, | |
| | | //33 - AtRearRightBorder | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West}, | |
| | | //34 - AtRearLeftBorder | |
| | | { /*InFrontNorthWest,*/InFrontNorth, InFrontNorthEast, | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest,*/InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West*/ | |
| | | Error, Error, Error, Error, Error}, | |
| | | //35 - Nothin | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //36 - AtTopRearBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error}, | |
| | | //37 - AtTopRightRearBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast,*/ | |
| | | InFrontWest, InFront, /*InFrontEast,*/ | |
| | | InFrontSouthWest, InFrontSouth, /*InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | West, | |
| | | Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //38 - AtTopLeftRearBorder | |
| | | { /*InFrontNorthWest, InFrontNorth, InFrontNorthEast,*/ | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest,*/InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | /*NorthWest, North, NorthEast,*/ | |
| | | /*West,*/ | |
| | | Error, Error, Error, Error, Error, Error, Error, Error, Error}, | |
| | | //39 - Nothin | |
| | | { Error, Error, Error, Error, Error, Error, Error, Error, Error, Error, | |
| | | Error, Error, Error}, | |
| | | //40 - AtBottomRearBorder | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West}, | |
| | | //41 - AtBottomRightRearBorder | |
| | | { InFrontNorthWest, InFrontNorth, InFrontNorthEast, | |
| | | InFrontWest, InFront, InFrontEast, | |
| | | InFrontSouthWest, InFrontSouth, InFrontSouthEast, | |
| | | | |
| | | NorthWest, North, NorthEast, | |
| | | West}, | |
| | | //42 - AtBottomLeftRearBorder | |
| | | { /*InFrontNorthWest,*/InFrontNorth, InFrontNorthEast, | |
| | | /*InFrontWest,*/ InFront, InFrontEast, | |
| | | /*InFrontSouthWest,InFrontSouth, InFrontSouthEast,*/ | |
| | | | |
| | | /*NorthWest,*/ North, NorthEast, | |
| | | /*West*/ | |
| | | Error, Error, Error, Error, Error, Error, Error} | |
| | | }; | |
| | | | |
| | | template <int DUMMY> | |
| | | Diff3D NeighborCode3D::StaticData<DUMMY>::d[] = { | |
| | | Diff3D( -1, -1, -1), //InFrontNorthWest | |
| | | Diff3D( 0, -1, -1), //InFrontNorth | |
| | | Diff3D( 1, -1, -1), //InFrontNorthEast | |
| | | Diff3D( -1, 0, -1), //InFrontWest | |
| | | Diff3D( 0, 0, -1), //InFront | |
| | | Diff3D( 1, 0, -1), //InFrontEast | |
| | | Diff3D( -1, 1, -1), //InFrontSouthWest | |
| | | Diff3D( 0, 1, -1), //InFrontSouth | |
| | | Diff3D( 1, 1, -1), //InFrontSouthEast | |
| | | | |
| | | Diff3D( -1, -1, 0), //NorthWest | |
| | | Diff3D( 0, -1, 0), //North | |
| | | Diff3D( 1, -1, 0), //NorthEast | |
| | | Diff3D( -1, 0, 0), //West | |
| | | Diff3D( 1, 0, 0), //East | |
| | | Diff3D( -1, 1, 0), //SouthWest | |
| | | Diff3D( 0, 1, 0), //South | |
| | | Diff3D( 1, 1, 0), //SouthEast | |
| | | | |
| | | Diff3D( -1, -1, 1), //BehindNorthWest | |
| | | Diff3D( 0, -1, 1), //BehindNorth | |
| | | Diff3D( 1, -1, 1), //BehindNorthEast | |
| | | Diff3D( -1, 0, 1), //BehindWest | |
| | | Diff3D( 0, 0, 1), //Behind | |
| | | Diff3D( 1, 0, 1), //BehindEast | |
| | | Diff3D( -1, 1, 1), //BehindSouthWest | |
| | | Diff3D( 0, 1, 1), //BehindSouth | |
| | | Diff3D( 1, 1, 1), //BehindSouthEast | |
| | | }; | |
| | | | |
| }//namespace Neighborhood3DTwentySix | | }//namespace Neighborhood3DTwentySix | |
| | | | |
| /** Export \ref vigra::Neighborhood3DTwentySix::NeighborCode3D into the sco
pe of namespace vigra. | | /** Export \ref vigra::Neighborhood3DTwentySix::NeighborCode3D into the sco
pe of namespace vigra. | |
| */ | | */ | |
| typedef Neighborhood3DTwentySix::NeighborCode3D NeighborCode3DTwentySix; | | typedef Neighborhood3DTwentySix::NeighborCode3D NeighborCode3DTwentySix; | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| | | | |
End of changes. 16 change blocks. |
| 1213 lines changed or deleted | | 1004 lines changed or added | |
|
| watersheds.hxx | | watersheds.hxx | |
| | | | |
| skipping to change at line 48 | | skipping to change at line 48 | |
| | | | |
| #include <functional> | | #include <functional> | |
| #include "mathutil.hxx" | | #include "mathutil.hxx" | |
| #include "stdimage.hxx" | | #include "stdimage.hxx" | |
| #include "pixelneighborhood.hxx" | | #include "pixelneighborhood.hxx" | |
| #include "localminmax.hxx" | | #include "localminmax.hxx" | |
| #include "labelimage.hxx" | | #include "labelimage.hxx" | |
| #include "seededregiongrowing.hxx" | | #include "seededregiongrowing.hxx" | |
| #include "functorexpression.hxx" | | #include "functorexpression.hxx" | |
| #include "union_find.hxx" | | #include "union_find.hxx" | |
|
| | | #include "multi_shape.hxx" | |
| | | | |
| namespace vigra { | | namespace vigra { | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood> | | class Neighborhood> | |
| unsigned int watershedLabeling(SrcIterator upperlefts, | | unsigned int watershedLabeling(SrcIterator upperlefts, | |
| SrcIterator lowerrights, SrcAccessor sa, | | SrcIterator lowerrights, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| Neighborhood) | | Neighborhood) | |
| | | | |
| skipping to change at line 71 | | skipping to change at line 72 | |
| int w = lowerrights.x - upperlefts.x; | | int w = lowerrights.x - upperlefts.x; | |
| int h = lowerrights.y - upperlefts.y; | | int h = lowerrights.y - upperlefts.y; | |
| int x,y; | | int x,y; | |
| | | | |
| SrcIterator ys(upperlefts); | | SrcIterator ys(upperlefts); | |
| SrcIterator xs(ys); | | SrcIterator xs(ys); | |
| DestIterator yd(upperleftd); | | DestIterator yd(upperleftd); | |
| DestIterator xd(yd); | | DestIterator xd(yd); | |
| | | | |
| // temporary image to store region labels | | // temporary image to store region labels | |
|
| detail::UnionFindArray<LabelType> labels; | | UnionFindArray<LabelType> labels; | |
| | | | |
| // initialize the neighborhood circulators | | // initialize the neighborhood circulators | |
| NeighborOffsetCirculator<Neighborhood> ncstart(Neighborhood::CausalFirs
t); | | NeighborOffsetCirculator<Neighborhood> ncstart(Neighborhood::CausalFirs
t); | |
| NeighborOffsetCirculator<Neighborhood> ncstartBorder(Neighborhood::Nort
h); | | NeighborOffsetCirculator<Neighborhood> ncstartBorder(Neighborhood::Nort
h); | |
| NeighborOffsetCirculator<Neighborhood> ncend(Neighborhood::CausalLast); | | NeighborOffsetCirculator<Neighborhood> ncend(Neighborhood::CausalLast); | |
| ++ncend; | | ++ncend; | |
| NeighborOffsetCirculator<Neighborhood> ncendBorder(Neighborhood::North)
; | | NeighborOffsetCirculator<Neighborhood> ncendBorder(Neighborhood::North)
; | |
| ++ncendBorder; | | ++ncendBorder; | |
| | | | |
| // pass 1: scan image from upper left to lower right | | // pass 1: scan image from upper left to lower right | |
| | | | |
| skipping to change at line 94 | | skipping to change at line 95 | |
| // Each component will be represented by a tree of pixels. Each | | // Each component will be represented by a tree of pixels. Each | |
| // pixel contains the scan order address of its parent in the | | // pixel contains the scan order address of its parent in the | |
| // tree. In order for pass 2 to work correctly, the parent must | | // tree. In order for pass 2 to work correctly, the parent must | |
| // always have a smaller scan order address than the child. | | // always have a smaller scan order address than the child. | |
| // Therefore, we can merge trees only at their roots, because the | | // Therefore, we can merge trees only at their roots, because the | |
| // root of the combined tree must have the smallest scan order | | // root of the combined tree must have the smallest scan order | |
| // address among all the tree's pixels/ nodes. The root of each | | // address among all the tree's pixels/ nodes. The root of each | |
| // tree is distinguished by pointing to itself (it contains its | | // tree is distinguished by pointing to itself (it contains its | |
| // own scan order address). This condition is enforced whenever a | | // own scan order address). This condition is enforced whenever a | |
| // new region is found or two regions are merged | | // new region is found or two regions are merged | |
|
| da.set(labels.finalizeLabel(labels.nextFreeLabel()), xd); | | da.set(labels.finalizeIndex(labels.nextFreeIndex()), xd); | |
| | | | |
| ++xs.x; | | ++xs.x; | |
| ++xd.x; | | ++xd.x; | |
| for(x = 1; x != w; ++x, ++xs.x, ++xd.x) | | for(x = 1; x != w; ++x, ++xs.x, ++xd.x) | |
| { | | { | |
| if((sa(xs) & Neighborhood::directionBit(Neighborhood::West)) || | | if((sa(xs) & Neighborhood::directionBit(Neighborhood::West)) || | |
| (sa(xs, Neighborhood::west()) & Neighborhood::directionBit(Neigh
borhood::East))) | | (sa(xs, Neighborhood::west()) & Neighborhood::directionBit(Neigh
borhood::East))) | |
| { | | { | |
| da.set(da(xd, Neighborhood::west()), xd); | | da.set(da(xd, Neighborhood::west()), xd); | |
| } | | } | |
| else | | else | |
| { | | { | |
|
| da.set(labels.finalizeLabel(labels.nextFreeLabel()), xd); | | da.set(labels.finalizeIndex(labels.nextFreeIndex()), xd); | |
| } | | } | |
| } | | } | |
| | | | |
| ++ys.y; | | ++ys.y; | |
| ++yd.y; | | ++yd.y; | |
| for(y = 1; y != h; ++y, ++ys.y, ++yd.y) | | for(y = 1; y != h; ++y, ++ys.y, ++yd.y) | |
| { | | { | |
| xs = ys; | | xs = ys; | |
| xd = yd; | | xd = yd; | |
| | | | |
| for(x = 0; x != w; ++x, ++xs.x, ++xd.x) | | for(x = 0; x != w; ++x, ++xs.x, ++xd.x) | |
| { | | { | |
| NeighborOffsetCirculator<Neighborhood> nc(x == w-1 | | NeighborOffsetCirculator<Neighborhood> nc(x == w-1 | |
| ? ncstartBorder | | ? ncstartBorder | |
| : ncstart); | | : ncstart); | |
| NeighborOffsetCirculator<Neighborhood> nce(x == 0 | | NeighborOffsetCirculator<Neighborhood> nce(x == 0 | |
| ? ncendBorder | | ? ncendBorder | |
| : ncend); | | : ncend); | |
|
| LabelType currentLabel = labels.nextFreeLabel(); | | LabelType currentIndex = labels.nextFreeIndex(); | |
| for(; nc != nce; ++nc) | | for(; nc != nce; ++nc) | |
| { | | { | |
| if((sa(xs) & nc.directionBit()) || (sa(xs, *nc) & nc.opposi
teDirectionBit())) | | if((sa(xs) & nc.directionBit()) || (sa(xs, *nc) & nc.opposi
teDirectionBit())) | |
| { | | { | |
|
| currentLabel = labels.makeUnion(da(xd,*nc), currentLabe
l); | | currentIndex = labels.makeUnion(da(xd,*nc), currentInde
x); | |
| } | | } | |
| } | | } | |
|
| da.set(labels.finalizeLabel(currentLabel), xd); | | da.set(labels.finalizeIndex(currentIndex), xd); | |
| } | | } | |
| } | | } | |
| | | | |
| unsigned int count = labels.makeContiguous(); | | unsigned int count = labels.makeContiguous(); | |
| | | | |
| // pass 2: assign one label to each region (tree) | | // pass 2: assign one label to each region (tree) | |
| // so that labels form a consecutive sequence 1, 2, ... | | // so that labels form a consecutive sequence 1, 2, ... | |
| yd = upperleftd; | | yd = upperleftd; | |
| for(y=0; y != h; ++y, ++yd.y) | | for(y=0; y != h; ++y, ++yd.y) | |
| { | | { | |
| DestIterator xd(yd); | | DestIterator xd(yd); | |
| for(x = 0; x != w; ++x, ++xd.x) | | for(x = 0; x != w; ++x, ++xd.x) | |
| { | | { | |
|
| da.set(labels[da(xd)], xd); | | da.set(labels.findLabel(da(xd)), xd); | |
| } | | } | |
| } | | } | |
| return count; | | return count; | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood> | | class Neighborhood> | |
| unsigned int watershedLabeling(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | | unsigned int watershedLabeling(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| | | | |
| skipping to change at line 320 | | skipping to change at line 321 | |
| //@{ | | //@{ | |
| | | | |
| /**\brief Options object for generateWatershedSeeds(). | | /**\brief Options object for generateWatershedSeeds(). | |
| * | | * | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/watersheds.hxx\><br> | | <b>\#include</b> \<vigra/watersheds.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| \code | | \code | |
|
| IImage seeds(boundary_indicator.size()); | | MultiArray<2, float> boundary_indicator(w, h); | |
| | | MultiArray<2, int> seeds(boundary_indicator.shape()); | |
| | | | |
| // detect all minima in 'boundary_indicator' that are below gray le
vel 22 | | // detect all minima in 'boundary_indicator' that are below gray le
vel 22 | |
|
| generateWatershedSeeds(srcImageRange(boundary_indicator), | | generateWatershedSeeds(boundary_indicator, seeds, | |
| destImage(seeds), | | | |
| SeedOptions().minima().threshold(22.0)); | | SeedOptions().minima().threshold(22.0)); | |
| \endcode | | \endcode | |
| */ | | */ | |
| class SeedOptions | | class SeedOptions | |
| { | | { | |
| public: | | public: | |
| enum DetectMinima { LevelSets, Minima, ExtendedMinima, Unspecified }; | | enum DetectMinima { LevelSets, Minima, ExtendedMinima, Unspecified }; | |
| | | | |
| double thresh; | | double thresh; | |
| DetectMinima mini; | | DetectMinima mini; | |
| | | | |
| skipping to change at line 432 | | skipping to change at line 433 | |
| of by looking at level sets (i.e. regions where the boundaryness is bel
ow a threshold). | | of by looking at level sets (i.e. regions where the boundaryness is bel
ow a threshold). | |
| Both methods can also be combined, so that only minima below a threshol
d are returned. | | Both methods can also be combined, so that only minima below a threshol
d are returned. | |
| The particular seeding strategy is specified by the <tt>options</tt> ob
ject | | The particular seeding strategy is specified by the <tt>options</tt> ob
ject | |
| (see \ref SeedOptions). | | (see \ref SeedOptions). | |
| | | | |
| The pixel type of the input image must be <tt>LessThanComparable</tt>. | | The pixel type of the input image must be <tt>LessThanComparable</tt>. | |
| The pixel type of the output image must be large enough to hold the lab
els for all seeds. | | The pixel type of the output image must be large enough to hold the lab
els for all seeds. | |
| (typically, you will use <tt>UInt32</tt>). The function will label seed
s by consecutive integers | | (typically, you will use <tt>UInt32</tt>). The function will label seed
s by consecutive integers | |
| (starting from 1) and returns the largest label it used. | | (starting from 1) and returns the largest label it used. | |
| | | | |
|
| Pass \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode to d | | Pass \ref vigra::NeighborhoodType "IndirectNeighborhood" or \ref vigra: | |
| etermine the | | :NeighborhoodType "DirectNeighborhood" | |
| | | (first form of the function) | |
| | | or \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode (secon | |
| | | d and third forms) to determine the | |
| neighborhood where pixel values are compared. | | neighborhood where pixel values are compared. | |
| | | | |
|
| The function uses accessors. | | | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | use arbitrary-dimensional arrays: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <unsigned int N, class T, class S1, | |
| | | class Label, class S2> | |
| | | Label | |
| | | generateWatershedSeeds(MultiArrayView<N, T, S1> const & data, | |
| | | MultiArrayView<N, Label, S2> seeds, | |
| | | NeighborhoodType neighborhood = IndirectNeig | |
| | | hborhood, | |
| | | SeedOptions const & options = SeedOptions()) | |
| | | ; | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{generateWatershedSeeds} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood = EightNeighborCode> | | class Neighborhood = EightNeighborCode> | |
| unsigned int | | unsigned int | |
| generateWatershedSeeds(SrcIterator upperlefts, SrcIterator lowerrig
hts, SrcAccessor sa, | | generateWatershedSeeds(SrcIterator upperlefts, SrcIterator lowerrig
hts, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| Neighborhood neighborhood = EightNeighborCod
e(), | | Neighborhood neighborhood = EightNeighborCod
e(), | |
| SeedOptions const & options = SeedOptions())
; | | SeedOptions const & options = SeedOptions())
; | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood = EightNeighborCode> | | class Neighborhood = EightNeighborCode> | |
| unsigned int | | unsigned int | |
| generateWatershedSeeds(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | | generateWatershedSeeds(triple<SrcIterator, SrcIterator, SrcAccessor
> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| Neighborhood neighborhood = EightNeighborCod
e(), | | Neighborhood neighborhood = EightNeighborCod
e(), | |
| SeedOptions const & options = SeedOptions())
; | | SeedOptions const & options = SeedOptions())
; | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| <b>\#include</b> \<vigra/watersheds.hxx\><br> | | <b>\#include</b> \<vigra/multi_watersheds.hxx\> (MultiArray variant)<br | |
| | | > | |
| | | <b>\#include</b> \<vigra/watersheds.hxx\> (deprecated variants)<br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
|
| For detailed examples see watershedsRegionGrowing(). | | For detailed examples see \ref watershedsMultiArray() and \ref watershe
dsRegionGrowing(). | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> unsigned int generateWatershedSe
eds) | | doxygen_overloaded_function(template <...> unsigned int generateWatershedSe
eds) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood> | | class Neighborhood> | |
| unsigned int | | unsigned int | |
| generateWatershedSeeds(SrcIterator upperlefts, SrcIterator lowerrights, Src
Accessor sa, | | generateWatershedSeeds(SrcIterator upperlefts, SrcIterator lowerrights, Src
Accessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| Neighborhood neighborhood, | | Neighborhood neighborhood, | |
| | | | |
| skipping to change at line 558 | | skipping to change at line 574 | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| SeedOptions const & options = SeedOptions()) | | SeedOptions const & options = SeedOptions()) | |
| { | | { | |
| return generateWatershedSeeds(src.first, src.second, src.third, | | return generateWatershedSeeds(src.first, src.second, src.third, | |
| dest.first, dest.second, | | dest.first, dest.second, | |
| EightNeighborCode(), options); | | EightNeighborCode(), options); | |
| } | | } | |
| | | | |
| /********************************************************/ | | /********************************************************/ | |
| /* */ | | /* */ | |
|
| /* watersheds */ | | /* watershedsUnionFind */ | |
| /* */ | | /* */ | |
| /********************************************************/ | | /********************************************************/ | |
| | | | |
| /** \brief Region segmentation by means of the union-find watershed algorit
hm. | | /** \brief Region segmentation by means of the union-find watershed algorit
hm. | |
| | | | |
|
| | | Note: This function is largely obsolete, \ref watershedsMultiArray() sh | |
| | | ould be | |
| | | preferred unless top speed is required. | |
| | | | |
| This function implements the union-find version of the watershed algori
thms | | This function implements the union-find version of the watershed algori
thms | |
|
| as described in | | described as algorithm 4.7 in | |
| | | | |
|
| J. Roerdink, R. Meijster: "<em>The watershed transform: definitions, al | | J. Roerdink, R. Meijster: <em>"The watershed transform: definitions, al | |
| gorithms, | | gorithms, | |
| and parallelization strategies</em>", Fundamenta Informaticae, 41:187-2 | | and parallelization strategies"</em>, Fundamenta Informaticae, 41:187-2 | |
| 28, 2000 | | 28, 2000 | |
| | | | |
| The source image is a boundary indicator such as the gaussianGradientMa
gnitude() | | The source image is a boundary indicator such as the gaussianGradientMa
gnitude() | |
| or the trace of the \ref boundaryTensor(). Local minima of the boundary
indicator | | or the trace of the \ref boundaryTensor(). Local minima of the boundary
indicator | |
| are used as region seeds, and all other pixels are recursively assigned
to the same | | are used as region seeds, and all other pixels are recursively assigned
to the same | |
| region as their lowest neighbor. Pass \ref vigra::EightNeighborCode or | | region as their lowest neighbor. Pass \ref vigra::EightNeighborCode or | |
| \ref vigra::FourNeighborCode to determine the neighborhood where pixel
values | | \ref vigra::FourNeighborCode to determine the neighborhood where pixel
values | |
| are compared. The pixel type of the input image must be <tt>LessThanCom
parable</tt>. | | are compared. The pixel type of the input image must be <tt>LessThanCom
parable</tt>. | |
| The function uses accessors. | | The function uses accessors. | |
| | | | |
| Note that VIGRA provides an alternative implementation of the watershed
transform via | | Note that VIGRA provides an alternative implementation of the watershed
transform via | |
| \ref watershedsRegionGrowing(). It is slower, but offers many more conf
iguration options. | | \ref watershedsRegionGrowing(). It is slower, but offers many more conf
iguration options. | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood> | |
| | | unsigned int | |
| | | watershedsUnionFind(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Neighborhood neighborhood = EightNeighborCode() | |
| | | ); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{watershedsUnionFind} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood = EightNeighborCode> | | class Neighborhood = EightNeighborCode> | |
| unsigned int | | unsigned int | |
| watershedsUnionFind(SrcIterator upperlefts, SrcIterator lowerrights
, SrcAccessor sa, | | watershedsUnionFind(SrcIterator upperlefts, SrcIterator lowerrights
, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| Neighborhood neighborhood = EightNeighborCode()
) | | Neighborhood neighborhood = EightNeighborCode()
) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood = EightNeighborCode> | | class Neighborhood = EightNeighborCode> | |
| unsigned int | | unsigned int | |
| watershedsUnionFind(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | | watershedsUnionFind(triple<SrcIterator, SrcIterator, SrcAccessor> s
rc, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| Neighborhood neighborhood = EightNeighborCode()
) | | Neighborhood neighborhood = EightNeighborCode()
) | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/watersheds.hxx\><br> | | <b>\#include</b> \<vigra/watersheds.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| Example: watersheds of the gradient magnitude. | | Example: watersheds of the gradient magnitude. | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> in(w,h); | |
| | | ... // read input data | |
| | | | |
| | | // compute gradient magnitude as boundary indicator | |
| | | MultiArray<2, float> gradMag(w, h); | |
| | | gaussianGradientMagnitude(src, gradMag, 3.0); | |
| | | | |
| | | // the pixel type of the destination image must be large enough to hold | |
| | | // numbers up to 'max_region_label' to prevent overflow | |
| | | MultiArray<2, unsigned int> labeling(w,h); | |
| | | unsigned int max_region_label = watershedsUnionFind(gradMag, labeling); | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{watershedsUnionFind} | |
| | | Example: watersheds of the gradient magnitude. | |
| | | | |
| | | \code | |
| vigra::BImage in(w,h); | | vigra::BImage in(w,h); | |
| ... // read input data | | ... // read input data | |
| | | | |
| // compute gradient magnitude as boundary indicator | | // compute gradient magnitude as boundary indicator | |
| vigra::FImage gradMag(w, h); | | vigra::FImage gradMag(w, h); | |
| gaussianGradientMagnitude(srcImageRange(src), destImage(gradMag), 3.0); | | gaussianGradientMagnitude(srcImageRange(src), destImage(gradMag), 3.0); | |
| | | | |
| // the pixel type of the destination image must be large enough to hold | | // the pixel type of the destination image must be large enough to hold | |
| // numbers up to 'max_region_label' to prevent overflow | | // numbers up to 'max_region_label' to prevent overflow | |
| vigra::IImage labeling(w,h); | | vigra::IImage labeling(w,h); | |
| int max_region_label = watershedsUnionFind(srcImageRange(gradMag), dest
Image(labeling)); | | int max_region_label = watershedsUnionFind(srcImageRange(gradMag), dest
Image(labeling)); | |
| | | | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcIterator src_upperleft, src_lowerright; | | SrcIterator src_upperleft, src_lowerright; | |
| DestIterator dest_upperleft; | | DestIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| // compare src values | | // compare src values | |
| src_accessor(src_upperleft) <= src_accessor(src_upperleft) | | src_accessor(src_upperleft) <= src_accessor(src_upperleft) | |
| | | | |
| // set result | | // set result | |
| int label; | | int label; | |
| dest_accessor.set(label, dest_upperleft); | | dest_accessor.set(label, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> unsigned int watershedsUnionFind
) | | doxygen_overloaded_function(template <...> unsigned int watershedsUnionFind
) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood> | | class Neighborhood> | |
| unsigned int | | unsigned int | |
| watershedsUnionFind(SrcIterator upperlefts, SrcIterator lowerrights, SrcAcc
essor sa, | | watershedsUnionFind(SrcIterator upperlefts, SrcIterator lowerrights, SrcAcc
essor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| Neighborhood neighborhood) | | Neighborhood neighborhood) | |
| | | | |
| skipping to change at line 680 | | skipping to change at line 729 | |
| DestIterator upperleftd, DestAccessor da) | | DestIterator upperleftd, DestAccessor da) | |
| { | | { | |
| return watershedsUnionFind(upperlefts, lowerrights, sa, upperleftd, da,
EightNeighborCode()); | | return watershedsUnionFind(upperlefts, lowerrights, sa, upperleftd, da,
EightNeighborCode()); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood> | | class Neighborhood> | |
| inline unsigned int | | inline unsigned int | |
| watershedsUnionFind(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | watershedsUnionFind(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIterator, DestAccessor> dest, Neighborhood neighborhood
) | | pair<DestIterator, DestAccessor> dest, Neighborhood nei
ghborhood) | |
| { | | { | |
| return watershedsUnionFind(src.first, src.second, src.third, | | return watershedsUnionFind(src.first, src.second, src.third, | |
|
| dest.first, dest.second, neighborhood); | | dest.first, dest.second, neighborhood); | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline unsigned int | | inline unsigned int | |
| watershedsUnionFind(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | watershedsUnionFind(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
|
| pair<DestIterator, DestAccessor> dest) | | pair<DestIterator, DestAccessor> dest) | |
| { | | { | |
| return watershedsUnionFind(src.first, src.second, src.third, | | return watershedsUnionFind(src.first, src.second, src.third, | |
|
| dest.first, dest.second); | | dest.first, dest.second); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood> | |
| | | inline unsigned int | |
| | | watershedsUnionFind(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, Neighborhood neighborho | |
| | | od) | |
| | | { | |
| | | return watershedsUnionFind(srcImageRange(src), | |
| | | destImage(dest), neighborhood); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline unsigned int | |
| | | watershedsUnionFind(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "watershedsUnionFind(): shape mismatch between input and output."); | |
| | | return watershedsUnionFind(srcImageRange(src), | |
| | | destImage(dest)); | |
| } | | } | |
| | | | |
|
| /** \brief Options object for watershedsRegionGrowing(). | | /** \brief Options object for watershed algorithms. | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
|
| see watershedsRegionGrowing() for detailed examples. | | see \ref watershedsMultiArray() and watershedsRegionGrowing() for detai
led examples. | |
| */ | | */ | |
| class WatershedOptions | | class WatershedOptions | |
| { | | { | |
| public: | | public: | |
|
| | | enum Method { RegionGrowing, UnionFind }; | |
| | | | |
| double max_cost, bias; | | double max_cost, bias; | |
| SRGType terminate; | | SRGType terminate; | |
|
| | | Method method; | |
| unsigned int biased_label, bucket_count; | | unsigned int biased_label, bucket_count; | |
| SeedOptions seed_options; | | SeedOptions seed_options; | |
| | | | |
| /** \brief Create options object with default settings. | | /** \brief Create options object with default settings. | |
| | | | |
| Defaults are: perform complete grow (all pixels are assigned to
regions), | | Defaults are: perform complete grow (all pixels are assigned to
regions), | |
| use standard algorithm, assume that the destination image alrea
dy contains | | use standard algorithm, assume that the destination image alrea
dy contains | |
| region seeds. | | region seeds. | |
| */ | | */ | |
| WatershedOptions() | | WatershedOptions() | |
| : max_cost(0.0), | | : max_cost(0.0), | |
| bias(1.0), | | bias(1.0), | |
| terminate(CompleteGrow), | | terminate(CompleteGrow), | |
|
| | | method(RegionGrowing), | |
| biased_label(0), | | biased_label(0), | |
| bucket_count(0), | | bucket_count(0), | |
| seed_options(SeedOptions().unspecified()) | | seed_options(SeedOptions().unspecified()) | |
| {} | | {} | |
| | | | |
| /** \brief Perform complete grow. | | /** \brief Perform complete grow. | |
| | | | |
| That is, all pixels are assigned to regions, without explicit c
ontours | | That is, all pixels are assigned to regions, without explicit c
ontours | |
| in between. | | in between. | |
| | | | |
| | | | |
| skipping to change at line 787 | | skipping to change at line 863 | |
| when the input boundary indicator image contains integers | | when the input boundary indicator image contains integers | |
| in the range <tt>[0, ..., bucket_count-1]</tt>. Since | | in the range <tt>[0, ..., bucket_count-1]</tt>. Since | |
| these boundary indicators are typically represented as | | these boundary indicators are typically represented as | |
| UInt8 images, the default <tt>bucket_count</tt> is 256. | | UInt8 images, the default <tt>bucket_count</tt> is 256. | |
| | | | |
| Default: don't use the turbo algorithm | | Default: don't use the turbo algorithm | |
| */ | | */ | |
| WatershedOptions & turboAlgorithm(unsigned int bucket_count = 256) | | WatershedOptions & turboAlgorithm(unsigned int bucket_count = 256) | |
| { | | { | |
| this->bucket_count = bucket_count; | | this->bucket_count = bucket_count; | |
|
| | | method = RegionGrowing; | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| /** \brief Specify seed options. | | /** \brief Specify seed options. | |
| | | | |
| In this case, watershedsRegionGrowing() assumes that the destin
ation | | In this case, watershedsRegionGrowing() assumes that the destin
ation | |
| image does not yet contain seeds. It will therefore call | | image does not yet contain seeds. It will therefore call | |
| generateWatershedSeeds() and pass on the seed options. | | generateWatershedSeeds() and pass on the seed options. | |
| | | | |
| Default: don't compute seeds (i.e. assume that destination imag
e already | | Default: don't compute seeds (i.e. assume that destination imag
e already | |
| | | | |
| skipping to change at line 820 | | skipping to change at line 897 | |
| with a factor slightly below 1. | | with a factor slightly below 1. | |
| | | | |
| Default: don't bias any region. | | Default: don't bias any region. | |
| */ | | */ | |
| WatershedOptions & biasLabel(unsigned int label, double factor) | | WatershedOptions & biasLabel(unsigned int label, double factor) | |
| { | | { | |
| biased_label = label; | | biased_label = label; | |
| bias = factor; | | bias = factor; | |
| return *this; | | return *this; | |
| } | | } | |
|
| | | | |
| | | /** \brief Specify the algorithm to be used. | |
| | | | |
| | | Possible values are <tt>WatershedOptions::RegionGrowing</tt> an | |
| | | d | |
| | | <tt>WatershedOptions::UnionFind</tt>. The latter algorithm is f | |
| | | astest | |
| | | but doesn't support seeds and any of the other options. | |
| | | | |
| | | Default: RegionGrowing. | |
| | | */ | |
| | | WatershedOptions & useMethod(Method method) | |
| | | { | |
| | | this->method = method; | |
| | | return *this; | |
| | | } | |
| | | | |
| | | /** \brief Use region-growing watershed. | |
| | | | |
| | | Use this method when you want to specify seeds explicitly (seed | |
| | | ed watersheds) | |
| | | or use any of the other options. | |
| | | | |
| | | Default: true. | |
| | | */ | |
| | | WatershedOptions & regionGrowing() | |
| | | { | |
| | | method = RegionGrowing; | |
| | | return *this; | |
| | | } | |
| | | | |
| | | /** \brief Use union-find watershed. | |
| | | | |
| | | This is the fasted method, but it doesn't support seeds and any | |
| | | of the other | |
| | | options (they will be silently ignored). | |
| | | | |
| | | Default: false. | |
| | | */ | |
| | | WatershedOptions & unionFind() | |
| | | { | |
| | | method = UnionFind; | |
| | | return *this; | |
| | | } | |
| }; | | }; | |
| | | | |
| namespace detail { | | namespace detail { | |
| | | | |
| template <class CostType, class LabelType> | | template <class CostType, class LabelType> | |
| class WatershedStatistics | | class WatershedStatistics | |
| { | | { | |
| public: | | public: | |
| | | | |
| typedef SeedRgDirectValueFunctor<CostType> value_type; | | typedef SeedRgDirectValueFunctor<CostType> value_type; | |
| | | | |
| skipping to change at line 976 | | skipping to change at line 1093 | |
| } | | } | |
| | | | |
| LabelType biased_label; | | LabelType biased_label; | |
| value_type stats, biased_stats; | | value_type stats, biased_stats; | |
| }; | | }; | |
| | | | |
| } // namespace detail | | } // namespace detail | |
| | | | |
| /** \brief Region segmentation by means of a flooding-based watershed algor
ithm. | | /** \brief Region segmentation by means of a flooding-based watershed algor
ithm. | |
| | | | |
|
| | | Note: This function is largely obsolete, \ref watershedsMultiArray() sh | |
| | | ould be | |
| | | preferred unless top speed is required. | |
| | | | |
| This function implements variants of the watershed algorithm | | This function implements variants of the watershed algorithm | |
| described in | | described in | |
| | | | |
|
| L. Vincent and P. Soille: "<em>Watersheds in digital spaces: An efficie | | L. Vincent and P. Soille: <em>"Watersheds in digital spaces: An efficie | |
| nt algorithm | | nt algorithm | |
| based on immersion simulations</em>", IEEE Trans. Patt. Analysis Mach. | | based on immersion simulations"</em>, IEEE Trans. Patt. Analysis Mach. | |
| Intell. 13(6):583-598, 1991 | | Intell. 13(6):583-598, 1991 | |
| | | | |
| The source image is a boundary indicator such as the gaussianGradientMa
gnitude() | | The source image is a boundary indicator such as the gaussianGradientMa
gnitude() | |
| or the trace of the \ref boundaryTensor(), and the destination is a lab
el image | | or the trace of the \ref boundaryTensor(), and the destination is a lab
el image | |
|
| designating membership of each pixel in one of the regions. Plateaus in
the boundary | | designating membership of each point in one of the regions. Plateaus in
the boundary | |
| indicator (i.e. regions of constant gray value) are handled via a Eucli
dean distance | | indicator (i.e. regions of constant gray value) are handled via a Eucli
dean distance | |
| transform by default. | | transform by default. | |
| | | | |
| By default, the destination image is assumed to hold seeds for a seeded
watershed | | By default, the destination image is assumed to hold seeds for a seeded
watershed | |
| transform. Seeds may, for example, be created by means of generateWater
shedSeeds(). | | transform. Seeds may, for example, be created by means of generateWater
shedSeeds(). | |
| Note that the seeds will be overridden with the final watershed segment
ation. | | Note that the seeds will be overridden with the final watershed segment
ation. | |
| | | | |
| Alternatively, you may provide \ref SeedOptions in order to instruct | | Alternatively, you may provide \ref SeedOptions in order to instruct | |
| watershedsRegionGrowing() to generate its own seeds (it will call gener
ateWatershedSeeds() | | watershedsRegionGrowing() to generate its own seeds (it will call gener
ateWatershedSeeds() | |
| internally). In that case, the destination image should be zero-initial
ized. | | internally). In that case, the destination image should be zero-initial
ized. | |
| | | | |
| skipping to change at line 1022 | | skipping to change at line 1142 | |
| memory because it allocates less temporary storage. | | memory because it allocates less temporary storage. | |
| <li> Whether one region (label) is to be preferred or discouraged by bi
asing its cost | | <li> Whether one region (label) is to be preferred or discouraged by bi
asing its cost | |
| with a given factor (smaller than 1 for preference, larger than 1
for discouragement). | | with a given factor (smaller than 1 for preference, larger than 1
for discouragement). | |
| </ul> | | </ul> | |
| | | | |
| Note that VIGRA provides an alternative implementation of the watershed
transform via | | Note that VIGRA provides an alternative implementation of the watershed
transform via | |
| \ref watershedsUnionFind(). | | \ref watershedsUnionFind(). | |
| | | | |
| <b> Declarations:</b> | | <b> Declarations:</b> | |
| | | | |
|
| pass arguments explicitly: | | pass 2D array views: | |
| | | \code | |
| | | namespace vigra { | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood = EightNeighborCode> | |
| | | unsigned int | |
| | | watershedsRegionGrowing(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Neighborhood neighborhood = EightNeighborCo | |
| | | de(), | |
| | | WatershedOptions const & options = Watershe | |
| | | dOptions()); | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | unsigned int | |
| | | watershedsRegionGrowing(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | WatershedOptions const & options = Watershe | |
| | | dOptions()); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedAPI{watershedsRegionGrowing} | |
| | | pass \ref ImageIterators and \ref DataAccessors : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood = EightNeighborCode> | | class Neighborhood = EightNeighborCode> | |
| unsigned int | | unsigned int | |
| watershedsRegionGrowing(SrcIterator upperlefts, SrcIterator lowerri
ghts, SrcAccessor sa, | | watershedsRegionGrowing(SrcIterator upperlefts, SrcIterator lowerri
ghts, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| Neighborhood neighborhood = EightNeighborCo
de(), | | Neighborhood neighborhood = EightNeighborCo
de(), | |
| WatershedOptions const & options = Watershe
dOptions()); | | WatershedOptions const & options = Watershe
dOptions()); | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| unsigned int | | unsigned int | |
| watershedsRegionGrowing(SrcIterator upperlefts, SrcIterator lowerri
ghts, SrcAccessor sa, | | watershedsRegionGrowing(SrcIterator upperlefts, SrcIterator lowerri
ghts, SrcAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| WatershedOptions const & options = Watershe
dOptions()); | | WatershedOptions const & options = Watershe
dOptions()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| use argument objects in conjunction with \ref ArgumentObjectFactories : | | use argument objects in conjunction with \ref ArgumentObjectFactories : | |
| \code | | \code | |
| namespace vigra { | | namespace vigra { | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood = EightNeighborCode> | | class Neighborhood = EightNeighborCode> | |
| unsigned int | | unsigned int | |
| watershedsRegionGrowing(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | | watershedsRegionGrowing(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| Neighborhood neighborhood = EightNeighborCo
de(), | | Neighborhood neighborhood = EightNeighborCo
de(), | |
| WatershedOptions const & options = Watershe
dOptions()); | | WatershedOptions const & options = Watershe
dOptions()); | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| unsigned int | | unsigned int | |
| watershedsRegionGrowing(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | | watershedsRegionGrowing(triple<SrcIterator, SrcIterator, SrcAccesso
r> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| WatershedOptions const & options = Watershe
dOptions()); | | WatershedOptions const & options = Watershe
dOptions()); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| | | | |
| <b> Usage:</b> | | <b> Usage:</b> | |
| | | | |
| <b>\#include</b> \<vigra/watersheds.hxx\><br> | | <b>\#include</b> \<vigra/watersheds.hxx\><br> | |
| Namespace: vigra | | Namespace: vigra | |
| | | | |
| Example: watersheds of the gradient magnitude. | | Example: watersheds of the gradient magnitude. | |
| | | | |
| \code | | \code | |
|
| | | MultiArray<2, float> src(w, h); | |
| | | ... // read input data | |
| | | | |
| | | // compute gradient magnitude at scale 1.0 as a boundary indicator | |
| | | MultiArray<2, float> gradMag(w, h); | |
| | | gaussianGradientMagnitude(src, gradMag, 1.0); | |
| | | | |
| | | // example 1 | |
| | | { | |
| | | // the pixel type of the destination image must be large enough to | |
| | | hold | |
| | | // numbers up to 'max_region_label' to prevent overflow | |
| | | MultiArray<2, unsigned int> labeling(w, h); | |
| | | | |
| | | // call watershed algorithm for 4-neighborhood, leave a 1-pixel bou | |
| | | ndary between regions, | |
| | | // and autogenerate seeds from all gradient minima where the magnit | |
| | | ude is below 2.0 | |
| | | unsigned int max_region_label = | |
| | | watershedsRegionGrowing(gradMag, labeling, | |
| | | FourNeighborCode(), | |
| | | WatershedOptions().keepContours() | |
| | | .seedOptions(SeedOptions().minim | |
| | | a().threshold(2.0))); | |
| | | } | |
| | | | |
| | | // example 2 | |
| | | { | |
| | | MultiArray<2, unsigned int> labeling(w, h); | |
| | | | |
| | | // compute seeds beforehand (use connected components of all pixels | |
| | | // where the gradient is below 4.0) | |
| | | unsigned int max_region_label = | |
| | | generateWatershedSeeds(gradMag, labeling, | |
| | | SeedOptions().levelSets(4.0)); | |
| | | | |
| | | // quantize the gradient image to 256 gray levels | |
| | | MultiArray<2, unsigned char> gradMag256(w, h); | |
| | | FindMinMax<float> minmax; | |
| | | inspectImage(gradMag, minmax); // find original range | |
| | | transformImage(gradMag, gradMag256, | |
| | | linearRangeMapping(minmax, 0, 255)); | |
| | | | |
| | | // call the turbo algorithm with 256 bins, using 8-neighborhood | |
| | | watershedsRegionGrowing(gradMag256, labeling, | |
| | | WatershedOptions().turboAlgorithm(256)); | |
| | | } | |
| | | | |
| | | // example 3 | |
| | | { | |
| | | MultiArray<2, unsigned int> labeling(w, h); | |
| | | | |
| | | .. // get seeds from somewhere, e.g. an interactive labeling progra | |
| | | m, | |
| | | // make sure that label 1 corresponds to the background | |
| | | | |
| | | // bias the watershed algorithm so that the background is preferred | |
| | | // by reducing the cost for label 1 to 90% | |
| | | watershedsRegionGrowing(gradMag, labeling, | |
| | | WatershedOptions().biasLabel(1, 0.9)); | |
| | | } | |
| | | \endcode | |
| | | | |
| | | \deprecatedUsage{watershedsRegionGrowing} | |
| | | \code | |
| vigra::BImage src(w, h); | | vigra::BImage src(w, h); | |
| ... // read input data | | ... // read input data | |
| | | | |
| // compute gradient magnitude at scale 1.0 as a boundary indicator | | // compute gradient magnitude at scale 1.0 as a boundary indicator | |
| vigra::FImage gradMag(w, h); | | vigra::FImage gradMag(w, h); | |
| gaussianGradientMagnitude(srcImageRange(src), destImage(gradMag), 1.0); | | gaussianGradientMagnitude(srcImageRange(src), destImage(gradMag), 1.0); | |
| | | | |
| // example 1 | | // example 1 | |
| { | | { | |
| // the pixel type of the destination image must be large enough to
hold | | // the pixel type of the destination image must be large enough to
hold | |
| | | | |
| skipping to change at line 1129 | | skipping to change at line 1331 | |
| | | | |
| .. // get seeds from somewhere, e.g. an interactive labeling progra
m, | | .. // get seeds from somewhere, e.g. an interactive labeling progra
m, | |
| // make sure that label 1 corresponds to the background | | // make sure that label 1 corresponds to the background | |
| | | | |
| // bias the watershed algorithm so that the background is preferred | | // bias the watershed algorithm so that the background is preferred | |
| // by reducing the cost for label 1 to 90% | | // by reducing the cost for label 1 to 90% | |
| watershedsRegionGrowing(srcImageRange(gradMag), destImage(labeling)
, | | watershedsRegionGrowing(srcImageRange(gradMag), destImage(labeling)
, | |
| WatershedOptions().biasLabel(1, 0.9)); | | WatershedOptions().biasLabel(1, 0.9)); | |
| } | | } | |
| \endcode | | \endcode | |
|
| | | | |
| <b> Required Interface:</b> | | <b> Required Interface:</b> | |
|
| | | | |
| \code | | \code | |
| SrcIterator src_upperleft, src_lowerright; | | SrcIterator src_upperleft, src_lowerright; | |
| DestIterator dest_upperleft; | | DestIterator dest_upperleft; | |
| | | | |
| SrcAccessor src_accessor; | | SrcAccessor src_accessor; | |
| DestAccessor dest_accessor; | | DestAccessor dest_accessor; | |
| | | | |
| // compare src values | | // compare src values | |
| src_accessor(src_upperleft) <= src_accessor(src_upperleft) | | src_accessor(src_upperleft) <= src_accessor(src_upperleft) | |
| | | | |
| // set result | | // set result | |
| int label; | | int label; | |
| dest_accessor.set(label, dest_upperleft); | | dest_accessor.set(label, dest_upperleft); | |
| \endcode | | \endcode | |
|
| | | \deprecatedEnd | |
| */ | | */ | |
| doxygen_overloaded_function(template <...> unsigned int watershedsRegionGro
wing) | | doxygen_overloaded_function(template <...> unsigned int watershedsRegionGro
wing) | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor, | | class DestIterator, class DestAccessor, | |
| class Neighborhood> | | class Neighborhood> | |
| unsigned int | | unsigned int | |
| watershedsRegionGrowing(SrcIterator upperlefts, SrcIterator lowerrights, Sr
cAccessor sa, | | watershedsRegionGrowing(SrcIterator upperlefts, SrcIterator lowerrights, Sr
cAccessor sa, | |
| DestIterator upperleftd, DestAccessor da, | | DestIterator upperleftd, DestAccessor da, | |
| Neighborhood neighborhood, | | Neighborhood neighborhood, | |
| | | | |
| skipping to change at line 1256 | | skipping to change at line 1457 | |
| } | | } | |
| | | | |
| template <class SrcIterator, class SrcAccessor, | | template <class SrcIterator, class SrcAccessor, | |
| class DestIterator, class DestAccessor> | | class DestIterator, class DestAccessor> | |
| inline unsigned int | | inline unsigned int | |
| watershedsRegionGrowing(triple<SrcIterator, SrcIterator, SrcAccessor> src, | | watershedsRegionGrowing(triple<SrcIterator, SrcIterator, SrcAccessor> src, | |
| pair<DestIterator, DestAccessor> dest, | | pair<DestIterator, DestAccessor> dest, | |
| WatershedOptions const & options = WatershedOptions
()) | | WatershedOptions const & options = WatershedOptions
()) | |
| { | | { | |
| return watershedsRegionGrowing(src.first, src.second, src.third, | | return watershedsRegionGrowing(src.first, src.second, src.third, | |
|
| dest.first, dest.second, | | dest.first, dest.second, | |
| EightNeighborCode(), options); | | EightNeighborCode(), options); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2, | |
| | | class Neighborhood> | |
| | | inline unsigned int | |
| | | watershedsRegionGrowing(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | Neighborhood neighborhood, | |
| | | WatershedOptions const & options = WatershedOptions | |
| | | ()) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "watershedsRegionGrowing(): shape mismatch between input and output | |
| | | ."); | |
| | | return watershedsRegionGrowing(srcImageRange(src), | |
| | | destImage(dest), | |
| | | neighborhood, options); | |
| | | } | |
| | | | |
| | | template <class T1, class S1, | |
| | | class T2, class S2> | |
| | | inline unsigned int | |
| | | watershedsRegionGrowing(MultiArrayView<2, T1, S1> const & src, | |
| | | MultiArrayView<2, T2, S2> dest, | |
| | | WatershedOptions const & options = WatershedOptions | |
| | | ()) | |
| | | { | |
| | | vigra_precondition(src.shape() == dest.shape(), | |
| | | "watershedsRegionGrowing(): shape mismatch between input and output | |
| | | ."); | |
| | | return watershedsRegionGrowing(srcImageRange(src), | |
| | | destImage(dest), | |
| | | EightNeighborCode(), options); | |
| } | | } | |
| | | | |
| //@} | | //@} | |
| | | | |
| } // namespace vigra | | } // namespace vigra | |
| | | | |
| #endif // VIGRA_WATERSHEDS_HXX | | #endif // VIGRA_WATERSHEDS_HXX | |
| | | | |
End of changes. 50 change blocks. |
| 45 lines changed or deleted | | 300 lines changed or added | |
|