Commit 4247cef0 authored by Declara Denis's avatar Declara Denis Committed by Christian Schulte zu Berge

Cleaned up ConfidenceMaps code

* Removed some dead code.
* Avoided one texture copy in the ConfidenceMapsSolver Processor
* Exposed one more option to the ConfidenceMapsDemo piepline
parent 738bdd6c
......@@ -239,29 +239,6 @@ namespace cuda {
}
}
// Utility Structure to group together all the data that is needed to compute the equation system
struct ComputeLaplacianData
{
// User-tweakable parameters
float alpha, beta, gamma;
float gradientScaling;
// Image Data
const unsigned char *image;
int width, height;
// DIA matrix structure
int centralDiagonal;
int offsets[9];
// Penalty terms for each neighbour
float gammaList[9];
// Cached values for the image attenuation (controlled by alpha), so that they don't need to
// be recomputed at each pixel
std::vector<float> attenuationLUT;
};
static __device__ float d_getWeight(float v1, float v2, float gradientScaling, float beta, float gamma)
{
float grad = abs(v1 - v2) * gradientScaling / 255.0f;
......@@ -307,26 +284,26 @@ namespace cuda {
// If the pixel is at the top or at the bottom, add a value of 1 to the diagonal, to
// account for the edge to the seed points
float valueSum = 0.0f;
float weightSum = 0.0f;
if (y == 0 || y == height - 1)
valueSum = 1.0f;
weightSum = 1.0f;
for (int d = 0; d < 9; ++d) {
float value = 0.0f;
float weight = 0.0f;
if (((256>>d) & filter) != 0) {
int pidx_2 = pidx + offsets[d];
float v = image[pidx_2] * attenuations[d/3];
value = d_getWeight(centralValue, v, gradientScaling, beta, gammas[d]);
weight = d_getWeight(centralValue, v, gradientScaling, beta, gammas[d]);
}
// The matrix stores the data, so that values on the same diagonal are sequential.
// This means that all the values from [0, pitch) are on the first diagonal, [pitch, 2*pitch)
// are on the second diagonal and so on...
L[d * pitch + pidx] = -value;
valueSum += value;
L[d * pitch + pidx] = -weight;
weightSum += weight;
}
L[4 * pitch + pidx] = valueSum;
L[4 * pitch + pidx] = weightSum;
}
void CudaConfidenceMapsSystemSolver::createSystemGPU(const unsigned char* imageData, int imageWidth, int imageHeight,
......
......@@ -24,8 +24,6 @@
#include "cudaconfidencemapsdemo.h"
#include <tbb/tick_count.h>
#include "core/datastructures/imagedata.h"
#include "core/classification/geometry1dtransferfunction.h"
#include "core/classification/tfgeometry1d.h"
......@@ -46,12 +44,16 @@ namespace campvis {
, p_connectToIGTLinkServer("ConnectToIGTLink", "Connect/Disconnect to IGTLink")
, p_gaussianFilterSize("GaussianSigma", "Blur amount", 2.5f, 1.0f, 10.0f)
, p_resamplingScale("ResampleScale", "Resample Scale", 0.25f, 0.01f, 1.0f)
, p_gradientScaling("GradientScaling", "Scaling factor for gradients", 2.0f, 0.001, 10)
, p_alpha("Alpha", "Alpha", 2.0f, 0.0f, 10.0f)
, p_beta("Beta", "Beta", 20.0f, 1.0f, 200.0f)
, p_gamma("Gamma", "Gamma", 0.03f, 0.0f, 0.4f, 0.001, 4)
, p_useAlphaBetaFilter("UseAlphaBetaFilter", "Alpha-Beta-Filter", true)
, p_fanHalfAngle("FanHalfAngle", "Fan Half Angle", 37.0f, 1.0f, 90.0f)
, p_fanInnerRadius("FanInnerRadius", "Fan Inner Radius", 0.222f, 0.001f, 0.999f)
, _cgIterationsPerMsRunningAverage(1.0f)
, _cgTimeslotRunningAverage(1.0f)
, _statisticsLastUpdateTime()
{
addProcessor(&_usIgtlReader);
addProcessor(&_usBlurFilter);
......@@ -66,6 +68,7 @@ namespace campvis {
addProperty(p_connectToIGTLinkServer);
addProperty(p_gaussianFilterSize);
addProperty(p_resamplingScale);
addProperty(p_gradientScaling);
addProperty(p_alpha);
addProperty(p_beta);
addProperty(p_gamma);
......@@ -123,6 +126,7 @@ namespace campvis {
p_connectToIGTLinkServer.addSharedProperty(&_usIgtlReader.p_connect);
p_gaussianFilterSize.addSharedProperty(&_usBlurFilter.p_sigma);
p_resamplingScale.addSharedProperty(&_usResampler.p_resampleScale);
p_gradientScaling.addSharedProperty(&_usMapsSolver.p_gradientScaling);
p_alpha.addSharedProperty(&_usMapsSolver.p_paramAlpha);
p_beta.addSharedProperty(&_usMapsSolver.p_paramBeta);
p_gamma.addSharedProperty(&_usMapsSolver.p_paramGamma);
......@@ -136,9 +140,6 @@ namespace campvis {
}
void CudaConfidenceMapsDemo::executePipeline() {
static float iterationsPerMsAverage = 1.0f;
static unsigned char frame = 0;
if (p_autoIterationCount.getValue() == false) {
AutoEvaluationPipeline::executePipeline();
}
......@@ -160,10 +161,14 @@ namespace campvis {
auto solverStartTime = tbb::tick_count::now();
executeProcessorAndCheckOpenGLState(&_usMapsSolver);
auto solverEndTime = tbb::tick_count::now();
executeProcessorAndCheckOpenGLState(&_usFusion);
executeProcessorAndCheckOpenGLState(&_usFanRenderer);
if (frame % 16 == 0) {
if ((startTime - _statisticsLastUpdateTime).seconds() > 0.5f) {
_statisticsLastUpdateTime = startTime;
tbb::tick_count endTime = tbb::tick_count::now();
auto ms = (endTime - startTime).seconds() * 1000.0f;
std::stringstream string;
......@@ -172,21 +177,24 @@ namespace campvis {
string << "Error: " << _usMapsSolver.getResidualNorm() << std::endl;
_usFanRenderer.p_text.setValue(string.str());
}
frame++;
// Get the total end time (including fanRenderer) and calculate the number of
// cg iterations that can be afforded
auto endTime = tbb::tick_count::now();
auto ms = (endTime - startTime).seconds() * 1000.0f;
auto ms = (solverEndTime - solverStartTime).seconds() * 1000.0f;
auto iterationsPerMs = _usMapsSolver.getActualConjugentGradientIterations() / ms;
float mixRatio = 0.85f;
iterationsPerMsAverage = iterationsPerMsAverage * mixRatio + iterationsPerMs * (1.0f - mixRatio);
// Factor out the time needed for preprocessing the image from the time slot
float timeSlot = (p_timeSlot.getValue() - (solverStartTime - startTime).seconds() / 1000.0f);
int iterations = std::round(p_timeSlot.getValue() * iterationsPerMsAverage);
// Factor out the time needed for pre- and postprocessing the image from the time slot
float timeSlot = (p_timeSlot.getValue() -
(solverStartTime - startTime).seconds() * 1000.0f -
(endTime - solverEndTime).seconds() * 1000.0f);
// Compute the running average using an exponential filter
float expAlpha = 0.05f;
_cgIterationsPerMsRunningAverage = _cgIterationsPerMsRunningAverage * (1.0f - expAlpha) + iterationsPerMs * expAlpha;
_cgTimeslotRunningAverage = _cgTimeslotRunningAverage * (1.0f - expAlpha) + timeSlot * expAlpha;
int iterations = static_cast<int>(_cgTimeslotRunningAverage * _cgIterationsPerMsRunningAverage);
p_iterations.setValue(iterations);
}
}
......
......@@ -25,6 +25,8 @@
#ifndef CUDACONFIDENCEMAPSDEMO_H__
#define CUDACONFIDENCEMAPSDEMO_H__
#include <tbb/tick_count.h>
#include "modules/base/processors/matrixprocessor.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "modules/devil/processors/devilimagereader.h"
......@@ -77,6 +79,7 @@ namespace campvis {
AdvancedUsFusion _usFusion;
UsFanRenderer _usFanRenderer;
NumericProperty<int> p_iterations;
BoolProperty p_autoIterationCount;
FloatProperty p_timeSlot;
......@@ -86,6 +89,7 @@ namespace campvis {
FloatProperty p_gaussianFilterSize;
FloatProperty p_resamplingScale;
FloatProperty p_gradientScaling;
FloatProperty p_alpha;
FloatProperty p_beta;
FloatProperty p_gamma;
......@@ -93,6 +97,11 @@ namespace campvis {
FloatProperty p_fanHalfAngle;
FloatProperty p_fanInnerRadius;
float _cgIterationsPerMsRunningAverage;
float _cgTimeslotRunningAverage;
tbb::tick_count _statisticsLastUpdateTime;
};
}
......
......@@ -48,7 +48,6 @@ namespace campvis {
, p_useAlphaBetaFilter("UseAlphaBetaFilter", "Use Alpha-Beta-Filter", true)
, p_filterAlpha("FilterAlpha", "Filter Alpha", 0.36f, 0.0, 1.0)
, p_filterBeta("FilterBeta", "Filter Beta", 0.005f, 0.0, 1.0)
, p_printStatistics("PrintStatistics", "Print execution times and residual values", false)
, _solver()
{
......@@ -65,8 +64,6 @@ namespace campvis {
addProperty(p_useAlphaBetaFilter);
addProperty(p_filterAlpha);
addProperty(p_filterBeta);
addProperty(p_printStatistics);
}
CudaConfidenceMapsSolver::~CudaConfidenceMapsSolver() { }
......@@ -89,7 +86,6 @@ namespace campvis {
float alpha = p_paramAlpha.getValue();
float beta = p_paramBeta.getValue();
float gamma = p_paramGamma.getValue();
bool isFlipped = true;
// Setup the solver with the current Alpha-Beta-Filter settings
_solver.enableAlphaBetaFilter(p_useAlphaBetaFilter.getValue());
......@@ -104,20 +100,21 @@ namespace campvis {
const float *solution = _solver.getSolution(size.x, size.y);
float *solutionCopy = new float[elementCount];
memcpy(solutionCopy, solution, sizeof(float) * elementCount);
WeaklyTypedPointer wtpData(WeaklyTypedPointer::FLOAT, 1, solutionCopy);
// FIXME: Instead of copying the solution to a local representation first it would make
// sense to directly create an opengl representation!
ImageData *id = new ImageData(img->getParent()->getDimensionality(), size, img->getParent()->getNumChannels());
ImageRepresentationLocal::create(id, wtpData);
cgt::Texture* resultTexture = new cgt::Texture(GL_TEXTURE_2D, size, GL_R32F, cgt::Texture::LINEAR);
resultTexture->setWrapping(cgt::Texture::MIRRORED_REPEAT);
resultTexture->uploadTexture(reinterpret_cast<const GLubyte*>(solution), GL_RED, GL_FLOAT);
ImageRepresentationGL::create(id, resultTexture);
id->setMappingInformation(img->getParent()->getMappingInformation());
data.addData(p_outputConfidenceMap.getValue(), id);
if (p_printStatistics.getValue()) {
std::cout << "Residual: " << _solver.getSolutionResidualNorm() << std::endl;
std::cout << "System Creation Time: " << _solver.getSystemCreationTime() << std::endl;
std::cout << "System Solve Time: " << _solver.getSystemSolveTime() << " (" << _solver.getSolutionIterationCount() << " iterations)" << std::endl;
}
/*float *solutionCopy = new float[elementCount];
memcpy(solutionCopy, solution, sizeof(float) * elementCount);
WeaklyTypedPointer wtpData(WeaklyTypedPointer::FLOAT, 1, solutionCopy);
ImageRepresentationLocal::create(id, wtpData);*/
}
}
......
......@@ -98,9 +98,6 @@ namespace campvis {
BoolProperty p_useAlphaBetaFilter;
FloatProperty p_filterAlpha; ///< Alpha parameter for Alpha-Beta Filter
FloatProperty p_filterBeta; ///< Beta parameter for Alpha-Beta Filter
BoolProperty p_printStatistics;
protected:
void resetSolutionVector();
......
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