Commit 6f1f1bab authored by schultezub's avatar schultezub
Browse files

introducing ImageFilter processor

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@409 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 7e8b6356
...@@ -43,6 +43,7 @@ namespace campvis { ...@@ -43,6 +43,7 @@ namespace campvis {
, _gvg() , _gvg()
, _lhh() , _lhh()
, _usFusion(_effectiveRenderTargetSize) , _usFusion(_effectiveRenderTargetSize)
, _usFilter()
, _wheelHandler(&_usFusion.p_sliceNumber) , _wheelHandler(&_usFusion.p_sliceNumber)
, _tfWindowingHandler(&_usFusion.p_transferFunction) , _tfWindowingHandler(&_usFusion.p_transferFunction)
{ {
...@@ -51,6 +52,7 @@ namespace campvis { ...@@ -51,6 +52,7 @@ namespace campvis {
addProcessor(&_gvg); addProcessor(&_gvg);
//addProcessor(&_lhh); //addProcessor(&_lhh);
addProcessor(&_usFusion); addProcessor(&_usFusion);
addProcessor(&_usFilter);
addEventHandler(&_wheelHandler); addEventHandler(&_wheelHandler);
addEventHandler(&_tfWindowingHandler); addEventHandler(&_tfWindowingHandler);
} }
...@@ -66,6 +68,7 @@ namespace campvis { ...@@ -66,6 +68,7 @@ namespace campvis {
_usReader.p_targetImageID.connect(&_usFusion.p_usImageId); _usReader.p_targetImageID.connect(&_usFusion.p_usImageId);
_usReader.p_targetImageID.connect(&_gvg.p_sourceImageID); _usReader.p_targetImageID.connect(&_gvg.p_sourceImageID);
_usReader.p_targetImageID.connect(&_lhh.p_intensitiesId); _usReader.p_targetImageID.connect(&_lhh.p_intensitiesId);
_usReader.p_targetImageID.connect(&_usFilter.p_sourceImageID);
_confidenceReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\01\\Confidence_01.mhd"); _confidenceReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\01\\Confidence_01.mhd");
_confidenceReader.p_targetImageID.setValue("confidence.image"); _confidenceReader.p_targetImageID.setValue("confidence.image");
...@@ -77,6 +80,9 @@ namespace campvis { ...@@ -77,6 +80,9 @@ namespace campvis {
_usFusion.p_targetImageID.setValue("us.fused"); _usFusion.p_targetImageID.setValue("us.fused");
_usFusion.p_sliceNumber.setValue(0); _usFusion.p_sliceNumber.setValue(0);
_usFilter.p_targetImageID.setValue("us.filtered");
_usFilter.p_filterMode.selectById("gauss");
// TODO: replace this hardcoded domain by automatically determined from image min/max values // TODO: replace this hardcoded domain by automatically determined from image min/max values
Geometry1DTransferFunction* tf = new Geometry1DTransferFunction(128, tgt::vec2(0.f, 1.f)); Geometry1DTransferFunction* tf = new Geometry1DTransferFunction(128, tgt::vec2(0.f, 1.f));
tf->addGeometry(TFGeometry1D::createQuad(tgt::vec2(0.f, 1.f), tgt::col4(0, 0, 0, 0), tgt::col4(255, 255, 255, 255))); tf->addGeometry(TFGeometry1D::createQuad(tgt::vec2(0.f, 1.f), tgt::col4(0, 0, 0, 0), tgt::col4(255, 255, 255, 255)));
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "modules/advancedusvis/processors/advancedusfusion.h" #include "modules/advancedusvis/processors/advancedusfusion.h"
#include "modules/preprocessing/processors/gradientvolumegenerator.h" #include "modules/preprocessing/processors/gradientvolumegenerator.h"
#include "modules/preprocessing/processors/lhhistogram.h" #include "modules/preprocessing/processors/lhhistogram.h"
#include "modules/preprocessing/processors/imagefilter.h"
namespace campvis { namespace campvis {
class AdvancedUsVis : public VisualizationPipeline { class AdvancedUsVis : public VisualizationPipeline {
...@@ -71,6 +72,7 @@ namespace campvis { ...@@ -71,6 +72,7 @@ namespace campvis {
GradientVolumeGenerator _gvg; GradientVolumeGenerator _gvg;
LHHistogram _lhh; LHHistogram _lhh;
AdvancedUsFusion _usFusion; AdvancedUsFusion _usFusion;
ImageFilter _usFilter;
MWheelToNumericPropertyEventHandler _wheelHandler; MWheelToNumericPropertyEventHandler _wheelHandler;
TransFuncWindowingEventHandler _tfWindowingHandler; TransFuncWindowingEventHandler _tfWindowingHandler;
......
...@@ -3,9 +3,11 @@ ...@@ -3,9 +3,11 @@
# Source files: # Source files:
FILE(GLOB ThisModSources RELATIVE ${ModulesDir} FILE(GLOB ThisModSources RELATIVE ${ModulesDir}
modules/preprocessing/processors/*.cpp modules/preprocessing/processors/*.cpp
modules/preprocessing/tools/*.cpp
) )
# Header files # Header files
FILE(GLOB ThisModHeaders RELATIVE ${ModulesDir} FILE(GLOB ThisModHeaders RELATIVE ${ModulesDir}
modules/preprocessing/processors/*.h modules/preprocessing/processors/*.h
modules/preprocessing/tools/*.h
) )
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitt Mnchen
// Boltzmannstr. 3, 85748 Garching b. Mnchen, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include "imagefilter.h"
#include "tgt/glmath.h"
#include "tgt/logmanager.h"
#include "tbb/include/tbb/tbb.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
namespace campvis {
static const GenericOption<std::string> filterModes[2] = {
GenericOption<std::string>("median", "Median"),
GenericOption<std::string>("gauss", "Gauss"),
};
const std::string ImageFilter::loggerCat_ = "CAMPVis.modules.classification.ImageFilter";
ImageFilter::ImageFilter()
: AbstractProcessor()
, p_sourceImageID("InputVolume", "Input Volume ID", "volume", DataNameProperty::READ)
, p_targetImageID("OutputGradients", "Output Gradient Volume ID", "gradients", DataNameProperty::WRITE)
, p_filterMode("FilterMode", "Filter Mode", filterModes, 2)
, p_kernelSize("KernelSize", "Kernel Size", 3, 3, 15)
, p_sigma("Sigma", "Sigma", 1.f, .1f, 10.f)
{
addProperty(&p_sourceImageID);
addProperty(&p_targetImageID);
addProperty(&p_filterMode);
addProperty(&p_kernelSize);
addProperty(&p_sigma);
}
ImageFilter::~ImageFilter() {
}
void ImageFilter::process(DataContainer& data) {
ImageRepresentationLocal::ScopedRepresentation input(data, p_sourceImageID.getValue());
if (input != 0 && input->getParent()->getNumChannels() == 1) {
ImageData* id = new ImageData(input->getDimensionality(), input->getSize(), 1);
ImageRepresentationLocal* output = input->clone();
if (p_filterMode.getOptionValue() == "median") {
tbb::parallel_for(
tbb::blocked_range<size_t>(0, input->getNumElements()),
ImageFilterMedian(input, output, p_kernelSize.getValue()));
}
else if (p_filterMode.getOptionValue() == "gauss") {
tbb::parallel_for(
tbb::blocked_range<size_t>(0, input->getNumElements()),
ImageFilterGauss(input, output, p_kernelSize.getValue(), p_sigma.getValue()));
}
id->setInitialRepresentation(output);
data.addData(p_targetImageID.getValue(), id);
p_targetImageID.issueWrite();
}
else {
LDEBUG("No suitable input image found.");
}
_invalidationLevel.setValid();
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#ifndef IMAGEFILTER_H__
#define IMAGEFILTER_H__
#include <string>
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/genericproperty.h"
#include "core/properties/numericproperty.h"
#include "core/properties/optionproperty.h"
#include "modules/preprocessing/tools/abstractimagefilter.h"
namespace campvis {
/**
* Performs different filter operations on images.
*/
class ImageFilter : public AbstractProcessor {
public:
/**
* Constructs a new ImageFilter Processor
**/
ImageFilter();
/**
* Destructor
**/
virtual ~ImageFilter();
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return "ImageFilter"; };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Creates the gradient volume for the given intensity volume."; };
virtual void process(DataContainer& data);
DataNameProperty p_sourceImageID; ///< ID for input volume
DataNameProperty p_targetImageID; ///< ID for output gradient volume
GenericOptionProperty<std::string> p_filterMode; ///< Filter mode
IntProperty p_kernelSize;
FloatProperty p_sigma;
protected:
static const std::string loggerCat_;
};
}
#endif // IMAGEFILTER_H__
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitt Mnchen
// Boltzmannstr. 3, 85748 Garching b. Mnchen, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include "abstractimagefilter.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationlocal.h"
#include <algorithm>
namespace campvis {
ImageFilterMedian::ImageFilterMedian(const ImageRepresentationLocal* input, ImageRepresentationLocal* output, size_t kernelSize)
: AbstractImageFilter(input, output)
, _kernelSize(kernelSize)
{
tgtAssert(kernelSize > 0, "Kernel Size must be greater 0.");
}
void ImageFilterMedian::operator()(const tbb::blocked_range<size_t>& range) const {
size_t halfKernelDim = static_cast<size_t>(_kernelSize / 2);
const tgt::svec3& size = _input->getSize();
for (size_t index = range.begin(); index < range.end(); ++index) {
tgt::svec3 position = _input->getParent()->indexToPosition(index);
size_t zmin = position.z >= halfKernelDim ? position.z - halfKernelDim : 0;
size_t zmax = std::min(position.z+halfKernelDim, size.z-1);
size_t ymin = position.y >= halfKernelDim ? position.y - halfKernelDim : 0;
size_t ymax = std::min(position.y+halfKernelDim, size.y-1);
size_t xmin = position.x >= halfKernelDim ? position.x - halfKernelDim : 0;
size_t xmax = std::min(position.x+halfKernelDim, size.x-1);
tgt::svec3 npos;
std::vector<float> values;
for (npos.z=zmin; npos.z<=zmax; npos.z++) {
for (npos.y=ymin; npos.y<=ymax; npos.y++) {
for (npos.x=xmin; npos.x<=xmax; npos.x++) {
values.push_back(_input->getElementNormalized(npos, 0));
}
}
}
size_t medianPosition = values.size() / 2;
std::nth_element(values.begin(), values.begin() + medianPosition, values.end());
_output->setElementNormalized(index, 0, values[medianPosition]);
}
}
// ================================================================================================
ImageFilterGauss::ImageFilterGauss(const ImageRepresentationLocal* input, ImageRepresentationLocal* output, size_t kernelSize, float sigma)
: AbstractImageFilter(input, output)
, _kernelSize(kernelSize)
, _halfKernelSize(kernelSize / 2)
, _sigma(sigma)
, _norm(0.f)
{
tgtAssert(kernelSize > 0, "Kernel Size must be greater 0.");
// compute Gauss kernel and corresponding norm
// it is sufficient to compute only one half of the 1D kernel
_kernel.resize(_halfKernelSize + 1, 0.f);
for (size_t i = 0; i <= _halfKernelSize; ++i) {
float f = static_cast<float>(i);
_kernel[i] = exp(-(f * f) / (2.f * _sigma * _sigma));
_norm += _kernel[i];
}
_norm = (2.f * _norm) - _kernel[0];
}
void ImageFilterGauss::operator()(const tbb::blocked_range<size_t>& range) const {
size_t halfKernelDim = static_cast<size_t>(_kernelSize / 2);
const tgt::svec3& size = _input->getSize();
for (size_t index = range.begin(); index < range.end(); ++index) {
tgt::svec3 position = _input->getParent()->indexToPosition(index);
tgt::svec3 npos = position;
float sum = 0.f;
size_t zmin = position.z >= halfKernelDim ? position.z - halfKernelDim : 0;
size_t zmax = std::min(position.z+halfKernelDim, size.z-1);
for (npos.z = zmin; npos.z <= zmax; npos.z++) {
int i = abs(static_cast<int>(position.z) - static_cast<int>(npos.z));
sum += _input->getElementNormalized(npos, 0) * _kernel[i];
}
npos.z = position.z;
size_t ymin = position.y >= halfKernelDim ? position.y - halfKernelDim : 0;
size_t ymax = std::min(position.y+halfKernelDim, size.y-1);
for (npos.y=ymin; npos.y<=ymax; npos.y++) {
int i = abs(static_cast<int>(position.y) - static_cast<int>(npos.y));
sum += _input->getElementNormalized(npos, 0) * _kernel[i];
}
npos.y = position.y;
size_t xmin = position.x >= halfKernelDim ? position.x - halfKernelDim : 0;
size_t xmax = std::min(position.x+halfKernelDim, size.x-1);
for (npos.x=xmin; npos.x<=xmax; npos.x++) {
int i = abs(static_cast<int>(position.x) - static_cast<int>(npos.x));
sum += _input->getElementNormalized(npos, 0) * _kernel[i];
}
sum /= 3.f * _norm;
_output->setElementNormalized(index, 0, sum);
}
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#ifndef ABSTRACTIMAGEFILTER_H__
#define ABSTRACTIMAGEFILTER_H__
#include "tbb/include/tbb/tbb.h"
#include "tgt/assert.h"
#include <vector>
namespace campvis {
class ImageRepresentationLocal;
struct AbstractImageFilter {
AbstractImageFilter(const ImageRepresentationLocal* input, ImageRepresentationLocal* output)
: _input(input)
, _output(output)
{
tgtAssert(input != 0, "Input image must not be 0.");
tgtAssert(output != 0, "Output image must not be 0.");
}
virtual void operator() (const tbb::blocked_range<size_t>& range) const = 0;
protected:
const ImageRepresentationLocal* _input;
ImageRepresentationLocal* _output;
};
// ================================================================================================
struct ImageFilterMedian : public AbstractImageFilter {
public:
ImageFilterMedian(const ImageRepresentationLocal* input, ImageRepresentationLocal* output, size_t kernelSize);
void operator() (const tbb::blocked_range<size_t>& range) const;
protected:
size_t _kernelSize;
};
// ================================================================================================
struct ImageFilterGauss : public AbstractImageFilter {
public:
ImageFilterGauss(const ImageRepresentationLocal* input, ImageRepresentationLocal* output, size_t kernelSize, float sigma);
void operator() (const tbb::blocked_range<size_t>& range) const;
protected:
size_t _kernelSize;
size_t _halfKernelSize;
float _sigma;
std::vector<float> _kernel;
float _norm;
};
}
#endif // ABSTRACTIMAGEFILTER_H__
...@@ -86,7 +86,7 @@ void initGaussKernel() { ...@@ -86,7 +86,7 @@ void initGaussKernel() {
float applyDepthGaussFilter(in vec2 texCoord) { float applyDepthGaussFilter(in vec2 texCoord) {
float result = 0.0; float result = 0.0;
for (int i = -_halfKernelDimension; i <= _halfKernelDimension; ++i) { for (int i = -_halfKernelDimension; i <= _halfKernelDimension; ++i) {
// TODO: why the fuck dose abs(i) not work here?!? // TODO: why the fuck does abs(i) not work here?!?
int absi = (i < 0) ? -i : i; int absi = (i < 0) ? -i : i;
float curDepth = getElement2DNormalized(_depthPass2Texture, texCoord + (_direction * _viewportSizeRCP * i)).z; float curDepth = getElement2DNormalized(_depthPass2Texture, texCoord + (_direction * _viewportSizeRCP * i)).z;
result += curDepth * _gaussKernel[absi]; result += curDepth * _gaussKernel[absi];
......
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