Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit 1e66b5dc authored by schultezub's avatar schultezub
Browse files

* added ConcurrentGenericHistogramND documentation

 * some work on LHHistogram
 * added ImageDataLocal::get/setElementNormalized() overloads

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@308 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent c93f1676
......@@ -86,12 +86,18 @@ namespace TUMVis {
*/
virtual const WeaklyTypedPointer getWeaklyTypedPointer() const;
/// \see ImageDataLocal::getElementNormalized
virtual float getElementNormalized(size_t index, size_t channel) const;
/// \see ImageDataLocal::getElementNormalized
virtual float getElementNormalized(const tgt::svec3& position, size_t channel) const;
/// \see ImageDataLocal::getElementNormalizedLinear
virtual float getElementNormalizedLinear(const tgt::vec3& position, size_t channel) const;
/// \see ImageDataLocal::setElementNormalized
virtual void setElementNormalized(size_t index, size_t channel, float value);
/// \see ImageDataLocal::setElementNormalized
virtual void setElementNormalized(const tgt::svec3& position, size_t channel, float value);
......@@ -241,16 +247,26 @@ namespace TUMVis {
return WeaklyTypedPointer(TypeTraits<BASETYPE, NUMCHANNELS>::weaklyTypedPointerBaseType, NUMCHANNELS, _data);
}
template<typename BASETYPE, size_t NUMCHANNELS>
float TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getElementNormalized(size_t index, size_t channel) const {
tgtAssert(channel >= 0 && channel < NUMCHANNELS, "Channel out of bounds!");
return TypeNormalizer::normalizeToFloat(TypeTraits<BASETYPE, NUMCHANNELS>::getChannel(getElement(index), channel));
}
template<typename BASETYPE, size_t NUMCHANNELS>
float TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getElementNormalized(const tgt::svec3& position, size_t channel) const {
return getElementNormalized(positionToIndex(position), channel);
}
template<typename BASETYPE, size_t NUMCHANNELS>
void TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::setElementNormalized(size_t index, size_t channel, float value) {
tgtAssert(channel >= 0 && channel < NUMCHANNELS, "Channel out of bounds!");
return TypeNormalizer::normalizeToFloat(TypeTraits<BASETYPE, NUMCHANNELS>::getChannel(getElement(position), channel));
TypeTraits<BASETYPE, NUMCHANNELS>::setChannel(getElement(index), channel, TypeNormalizer::denormalizeFromFloat<BASETYPE>(value));
}
template<typename BASETYPE, size_t NUMCHANNELS>
void TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::setElementNormalized(const tgt::svec3& position, size_t channel, float value) {
tgtAssert(channel >= 0 && channel < NUMCHANNELS, "Channel out of bounds!");
TypeTraits<BASETYPE, NUMCHANNELS>::setChannel(getElement(position), channel, TypeNormalizer::denormalizeFromFloat<BASETYPE>(value));
setElementNormalized(positionToIndex(position), channel, value);
}
template<typename BASETYPE, size_t NUMCHANNELS>
......
......@@ -43,5 +43,4 @@ namespace TUMVis {
ImageDataLocal::~ImageDataLocal() {
}
}
\ No newline at end of file
......@@ -75,6 +75,23 @@ namespace TUMVis {
* \return A WeaklyTypedPointer to the image data.
*/
virtual const WeaklyTypedPointer getWeaklyTypedPointer() const = 0;
/**
* Returns the normalized value of the element at the given index and channel.
* - for \em unsigned integer types, the value range is mapped linearly to [0.0;1.0]
* - for \em signed integer types, the value range is mapped linearly to [-1.0;1.0]
* - floating point types are not mapped
*
* Simple algorithms on images might not always want to test for the actual base data type.
* For them access to the normalized element values provided here might be enough.
*
* \note This method is virtual => know the costs!
* \sa ImageDataLocal::setElementNormalized
* \param index Element index
* \param channel Image channel
* \return A normalized float representation of the element at the given position and channel.
*/
virtual float getElementNormalized(size_t index, size_t channel) const = 0;
/**
* Returns the normalized value of the element at the given position and channel.
......@@ -85,6 +102,7 @@ namespace TUMVis {
* Simple algorithms on images might not always want to test for the actual base data type.
* For them access to the normalized element values provided here might be enough.
*
* \note This method is more expensive than the version directly using the element index.
* \note This method is virtual => know the costs!
* \sa ImageDataLocal::setElementNormalized
* \param position Element position within the image
......@@ -110,6 +128,23 @@ namespace TUMVis {
*/
virtual float getElementNormalizedLinear(const tgt::vec3& position, size_t channel) const = 0;
/**
* Sets the element at the given index and channel denormalized from the given value \a value.
* - for \em unsigned integer types, the value range is mapped linearly to [0.0;1.0]
* - for \em signed integer types, the value range is mapped linearly to [-1.0;1.0]
* - floating point types are not mapped
*
* Simple algorithms on images might not always want to test for the actual base data type.
* For them access to the normalized element values provided here might be enough.
*
* \note This method is virtual => know the costs!
* \sa ImageDataLocal::getElementNormalized
* \param index Element index
* \param channel Image channel
* \param value Normalized Value to set
*/
virtual void setElementNormalized(size_t index, size_t channel, float value) = 0;
/**
* Sets the element at the given position and channel denormalized from the given value \a value.
* - for \em unsigned integer types, the value range is mapped linearly to [0.0;1.0]
......@@ -119,6 +154,7 @@ namespace TUMVis {
* Simple algorithms on images might not always want to test for the actual base data type.
* For them access to the normalized element values provided here might be enough.
*
* \note This method is more expensive than the version directly using the element index.
* \note This method is virtual => know the costs!
* \sa ImageDataLocal::getElementNormalized
* \param position Element position within the image
......
#include "tgt/assert.h"
#include "tgt/logmanager.h"
#include "tgt/tgt_math.h"
#include "tbb/include/tbb/atomic.h"
namespace TUMVis {
/**
* Generic implementation of thread-safe n-D histograms.
* After successfull creation ConcurrentGenericHistogramND ensures:
* * Calling addSample() is thread-safe.
*
* \tparam T Base data type of the histogram elements
* \tparam ND Dimensionality of the histogram
*/
template<typename T, size_t ND>
class ConcurrentGenericHistogramND {
public:
/**
* Creates a new ND-histogram with the given bounds and number of buckets.
* \param mins Array of mininum values for each dimension (must have at least ND elements)
* \param maxs Array of maximum values for each dimension (must have at least ND elements)
* \param numBuckets Array of number of buckets for each dimension (must have at least ND elements)
*/
ConcurrentGenericHistogramND(T mins[ND], T maxs[ND], size_t numBuckets[ND]);
/**
* Destructor
*/
virtual ~ConcurrentGenericHistogramND();
void addSample(T sample1[ND]);
/**
* Adds the given sample to the histogram.
* \note This method is thread-safe.
* \param sample Sample to add, array of the values for each dimension (must have at least ND elements)
*/
void addSample(T sample[ND]);
/**
* Returns a const pointer to the raw data.
* \return _buckets
*/
const tbb::atomic<size_t>* getBuckets() const { return _buckets; };
/**
* Returns the number of elements of the bucket with the given index.
* \param index Array index of the bucket to return.
* \return _buckets[index]
*/
size_t getNumElements(size_t index) const { return _buckets[index]; };
/**
* Returns the number of elements in the given bucket.
* \param bucket[ND] Array of the bucket number for each dimension (must have at least ND elements)
* \return The number of elements in the given bucket.
*/
size_t getNumElements(size_t bucket[ND]);
/**
* Get the total number of samples in this histogram.
* \return _numSamples
*/
size_t getNumSamples() const { return _numSamples; };
protected:
/**
* Transforms the sample value for the given dimension into the corresponding bucket number.
* \param dimension Dimension
* \param sample Sample value to transform
* \return The bucket number for \a sample in the given dimension.
*/
size_t getBucketNumber(size_t dimension, T sample) const;
/**
* Transforms the array of bucket numbers into the corresponding array index in _buckets.
* \param bucketNumbers Array of the bucket number for each dimension (must have at least ND elements).
* \return The array index for the given bucket numbers.
*/
size_t getArrayIndex(size_t* bucketNumbers) const;
T _min[ND];
T _max[ND];
size_t _numBuckets[ND];
size_t _arraySize;
tbb::atomic<size_t>* _buckets;
tbb::atomic<size_t> _numSamples;
T _min[ND]; ///< minimum value for each dimension
T _max[ND]; ///< maximum value for each dimension
size_t _numBuckets[ND]; ///< number of buckets for each dimension
size_t _arraySize; ///< size of _buckets (total number of buckets)
tbb::atomic<size_t>* _buckets; ///< array of the buckets storing the histogram
tbb::atomic<size_t> _numSamples; ///< total number of sampled elements
};
// ================================================================================================
......@@ -56,10 +113,10 @@ namespace TUMVis {
}
template<typename T, size_t ND>
void TUMVis::ConcurrentGenericHistogramND<T, ND>::addSample(T sample1[ND]) {
void TUMVis::ConcurrentGenericHistogramND<T, ND>::addSample(T sample[ND]) {
size_t bucketNumbers[ND];
for(int i = 0; i < ND; ++i)
bucketNumbers[i] = getBucketNumber(i, sample1[i]);
bucketNumbers[i] = getBucketNumber(i, sample[i]);
size_t index = getArrayIndex(bucketNumbers);
++(_buckets[index]);
......@@ -69,6 +126,11 @@ namespace TUMVis {
template<typename T, size_t ND>
size_t TUMVis::ConcurrentGenericHistogramND<T, ND>::getBucketNumber(size_t dimension, T sample) const {
tgtAssert(dimension < ND, "Dimension out of bounds.");
#ifdef TUMVIS_DEBUG
if (sample < _min[dimension] || sample > _max[dimension])
LWARNINGC("TUMVis.core.tools.ConcurrentGenericHistogramND", "Added sample " << sample << " out of bounds for dimension" << dimension << ".");
#endif
double ratio = static_cast<double>(sample - _min[dimension]) / static_cast<double>(_max[dimension] - _min[dimension]);
return static_cast<size_t>(tgt::clamp(static_cast<int>(ratio * _numBuckets[dimension]), static_cast<int>(0), static_cast<int>(_numBuckets[dimension] - 1)));
}
......
......@@ -59,7 +59,7 @@ namespace TUMVis {
const tgt::svec3& size = _intensities->getSize();
const tgt::vec4& gradient = _gradients->getElement(i);
float fl = _intensities->getElementNormalized(pos, 0);
float fl = _intensities->getElementNormalized(i, 0);
float fh = fl;
float forwardIntensity = integrateHeun(tgt::vec3(static_cast<float>(pos.x), static_cast<float>(pos.y), static_cast<float>(pos.z)), gradient);
......@@ -68,8 +68,8 @@ namespace TUMVis {
fh = std::max(forwardIntensity, backwardIntensity);
fl = std::min(forwardIntensity, backwardIntensity);
_fl->setElementNormalized(pos, 0, fl);
_fh->setElementNormalized(pos, 0, fh);
_fl->setElementNormalized(i, 0, fl);
_fh->setElementNormalized(i, 0, fh);
}
}
......@@ -85,12 +85,12 @@ namespace TUMVis {
float integrateHeun(tgt::vec3 position, const tgt::vec4& direction) const {
tgt::vec4 gradient1 = direction;
tgt::vec3 stepSize(1.f);
tgt::vec3 stepSize(.5f);
tgt::vec3 size(_intensities->getSize());
size_t numSteps = 0;
while (gradient1.w > _epsilon) {
tgt::vec4 gradient2 = getGradientLinear(position + tgt::normalize(gradient1.xyz()) * stepSize);
tgt::vec4 gradient2 = getGradientLinear(position + tgt::normalize(gradient1.xyz()) * stepSize/2.f);
position += tgt::normalize((gradient1 + gradient2).xyz()) * stepSize;
gradient1 = getGradientLinear(position);
++numSteps;
......@@ -125,8 +125,7 @@ namespace TUMVis {
void operator() (const tbb::blocked_range<size_t>& range) const {
for (size_t i = range.begin(); i != range.end(); ++i) {
tgt::svec3 pos = _fl->indexToPosition(i);
float values[2] = { _fl->getElementNormalized(pos, 0), _fh->getElementNormalized(pos, 0) };
float values[2] = { _fl->getElementNormalized(i, 0), _fh->getElementNormalized(i, 0) };
_histogram->addSample(values);
}
}
......@@ -164,10 +163,10 @@ namespace TUMVis {
if (intensities != 0 && gradients != 0) {
ImageDataLocal* fl = intensities->clone();
ImageDataLocal* fh = intensities->clone();
tbb::parallel_for(tbb::blocked_range<size_t>(0, intensities->getNumElements()), LHGenerator(intensities, gradients, fl, fh, .005f));
tbb::parallel_for(tbb::blocked_range<size_t>(0, intensities->getNumElements()), LHGenerator(intensities, gradients, fl, fh, .006f));
float mins[2] = { 0.f, 0.f };
float maxs[2] = { .01f, .01f };
float maxs[2] = { .1f, .1f };
size_t numBuckets[2] = { 256, 256 };
ConcurrentGenericHistogramND<float, 2> lhHistogram(mins, maxs, numBuckets);
tbb::parallel_for(tbb::blocked_range<size_t>(0, intensities->getNumElements()), LHHistogramGenerator(fl, fh, &lhHistogram));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment