Commit f0a6d3d4 authored by schultezub's avatar schultezub

further work on AdvancedUsVis pipeline

SliceExtractor supports multi-channel images

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@407 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 78620129
......@@ -64,11 +64,13 @@ namespace campvis {
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);
float backwardIntensity = integrateHeun(tgt::vec3(static_cast<float>(pos.x), static_cast<float>(pos.y), static_cast<float>(pos.z)), gradient * -1.f);
if (gradient.w > 0) {
float forwardIntensity = integrateHeun(tgt::vec3(static_cast<float>(pos.x), static_cast<float>(pos.y), static_cast<float>(pos.z)), gradient);
float backwardIntensity = integrateHeun(tgt::vec3(static_cast<float>(pos.x), static_cast<float>(pos.y), static_cast<float>(pos.z)), gradient * -1.f);
fh = std::max(forwardIntensity, backwardIntensity);
fl = std::min(forwardIntensity, backwardIntensity);
fh = std::max(forwardIntensity, backwardIntensity);
fl = std::min(forwardIntensity, backwardIntensity);
}
_fl->setElementNormalized(i, 0, fl);
_fh->setElementNormalized(i, 0, fh);
......@@ -91,7 +93,7 @@ namespace campvis {
tgt::vec3 size(_intensities->getSize());
size_t numSteps = 0;
while (gradient1.w > _epsilon) {
while (abs(gradient1.w) < _epsilon) {
tgt::vec4 gradient2 = getGradientLinear(position + tgt::normalize(gradient1.xyz()) * stepSize/2.f);
position += tgt::normalize((gradient1 + gradient2).xyz()) * stepSize;
gradient1 = getGradientLinear(position);
......@@ -143,13 +145,13 @@ namespace campvis {
LHHistogram::LHHistogram()
: AbstractProcessor()
, p_inputVolume("InputVolume", "Input Volume ID", "volume", DataNameProperty::READ)
, p_inputGradients("InputGradients", "Input Gradient Volume ID", "gradients", DataNameProperty::READ)
, p_intensitiesId("InputVolume", "Input Volume ID", "volume", DataNameProperty::READ)
, p_gradientsId("InputGradients", "Input Gradient Volume ID", "gradients", DataNameProperty::READ)
, p_outputFL("OutputFL", "FL Output Volume", "fl", DataNameProperty::WRITE)
, p_outputFH("OutputFH", "FH Output Volume", "fh", DataNameProperty::WRITE)
{
addProperty(&p_inputVolume);
addProperty(&p_inputGradients);
addProperty(&p_intensitiesId);
addProperty(&p_gradientsId);
addProperty(&p_outputFL);
addProperty(&p_outputFH);
}
......@@ -159,40 +161,50 @@ namespace campvis {
}
void LHHistogram::process(DataContainer& data) {
//ImageRepresentationLocal::ScopedRepresentation intensities(data, p_inputVolume.getValue());
//GenericImageRepresentationLocal<float, 4>::ScopedRepresentation gradients(data, p_inputGradients.getValue());
//if (intensities != 0 && gradients != 0) {
// ImageRepresentationLocal* fl = intensities->clone();
// ImageRepresentationLocal* fh = intensities->clone();
// 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] = { .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));
// // TODO: ugly hack...
// float* tmp = new float[256*256];
// for (size_t i = 0; i < 256*256; ++i)
// tmp[i] = static_cast<float>(lhHistogram.getBuckets()[i]) / static_cast<float>(lhHistogram.getMaxFilling());
// WeaklyTypedPointer wtp(WeaklyTypedPointer::FLOAT, 1, tmp);
// ImageRepresentationGL* tex = new ImageRepresentationGL(2, tgt::svec3(256, 256, 1), wtp);
// delete [] tmp;
// data.addData("foo", tex);
// data.addData(p_outputFH.getValue(), fh);
// data.addData(p_outputFL.getValue(), fl);
// p_outputFH.issueWrite();
// p_outputFL.issueWrite();
//}
//else {
// LDEBUG("No suitable intensities image found.");
//}
//_invalidationLevel.setValid();
ImageRepresentationLocal::ScopedRepresentation intensities(data, p_intensitiesId.getValue());
GenericImageRepresentationLocal<float, 4>::ScopedRepresentation gradients(data, p_gradientsId.getValue());
if (intensities != 0 && gradients != 0) {
ImageData* imgFl = new ImageData(intensities->getDimensionality(), intensities->getSize(), 1);
ImageRepresentationLocal* fl = new GenericImageRepresentationLocal<float, 1>(imgFl, 0);
imgFl->setInitialRepresentation(fl);
ImageData* imgFh = new ImageData(intensities->getDimensionality(), intensities->getSize(), 1);
ImageRepresentationLocal* fh = new GenericImageRepresentationLocal<float, 1>(imgFh, 0);
imgFh->setInitialRepresentation(fh);
const GenericImageRepresentationLocal<float, 4>* ggg = gradients;
tbb::parallel_for(tbb::blocked_range<size_t>(0, intensities->getNumElements()), LHGenerator(intensities, ggg, fl, fh, .003f));
Interval<float> interval = intensities->getNormalizedIntensityRange();
float mins[2] = { interval.getLeft(), interval.getLeft() };
float maxs[2] = { interval.getRight(), interval.getRight() };
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));
// TODO: ugly hack...
float* tmp = new float[256*256];
for (size_t i = 0; i < 256*256; ++i)
tmp[i] = static_cast<float>(lhHistogram.getBuckets()[i]) / static_cast<float>(lhHistogram.getMaxFilling());
WeaklyTypedPointer wtp(WeaklyTypedPointer::FLOAT, 1, tmp);
ImageData* imgTex = new ImageData(2, tgt::svec3(256, 256, 1), 1);
ImageRepresentationGL* tex = new ImageRepresentationGL(imgTex, wtp);
imgTex->setInitialRepresentation(tex);
delete [] tmp;
data.addData("foo", imgTex);
data.addData(p_outputFH.getValue(), imgFh);
data.addData(p_outputFL.getValue(), imgFl);
p_outputFH.issueWrite();
p_outputFL.issueWrite();
}
else {
LDEBUG("No suitable intensities image found.");
}
_invalidationLevel.setValid();
}
}
......@@ -62,8 +62,8 @@ namespace campvis {
virtual void process(DataContainer& data);
DataNameProperty p_inputVolume; ///< ID for input volume
DataNameProperty p_inputGradients; ///< ID for input gradient volume
DataNameProperty p_intensitiesId; ///< ID for input volume
DataNameProperty p_gradientsId; ///< ID for input gradient volume
DataNameProperty p_outputFL; ///< ID for output FL volume
DataNameProperty p_outputFH; ///< ID for output FH volume
......
......@@ -56,10 +56,10 @@ void main() {
float drrFull = getElement2DNormalized(_drrFullColor, ex_TexCoord.xy).r;
float drrClipped = getElement2DNormalized(_drrClippedColor, ex_TexCoord.xy).r;
float weightingFactor = 0.0;
if (drrClipped > 0)
weightingFactor = clamp(drrClipped / drrFull, 0.0, 1.0);
float weightingFactor = 0.0;
if (drrClipped > 0)
weightingFactor = clamp(drrClipped / drrFull, 0.0, 1.0);
float fragDepth = weightingFactor;
if (weightingFactor == 0.0)
......
......@@ -32,6 +32,7 @@
in vec3 ex_TexCoord;
out vec4 out_Color;
//#include "tools/background.frag"
#include "tools/texture2d.frag"
#include "tools/transferfunction.frag"
......@@ -39,6 +40,18 @@ uniform Texture2D _texture;
uniform TransferFunction1D _transferFunction;
void main() {
float intensity = getElement2DNormalized(_texture, ex_TexCoord.xy).a;
out_Color = lookupTF(_transferFunction, intensity);
vec4 texel = getElement2DNormalized(_texture, ex_TexCoord.xy);
if (_texture._numChannels == 1) {
out_Color = lookupTF(_transferFunction, texel.a);
}
else if (_texture._numChannels == 3) {
out_Color = vec4(abs(texel.rgb), 1.0);
}
else if (_texture._numChannels == 4) {
out_Color = (abs(texel) - vec4(_transferFunction._intensityDomain.x)) / (_transferFunction._intensityDomain.y - _transferFunction._intensityDomain.x);
}
//if (out_Color.a == 0) {
// renderBackground(ex_TexCoord.xy, out_Color);
//}
}
......@@ -38,16 +38,18 @@ namespace campvis {
AdvancedUsVis::AdvancedUsVis()
: VisualizationPipeline()
, _imageReader()
, _usReader()
, _confidenceReader()
, _gvg()
, _lhh()
, _sliceExtractor(_effectiveRenderTargetSize)
, _wheelHandler(&_sliceExtractor.p_sliceNumber)
, _tfWindowingHandler(&_sliceExtractor.p_transferFunction)
{
addProcessor(&_imageReader);
// addProcessor(&_gvg);
// addProcessor(&_lhh);
addProcessor(&_usReader);
addProcessor(&_confidenceReader);
addProcessor(&_gvg);
addProcessor(&_lhh);
addProcessor(&_sliceExtractor);
addEventHandler(&_wheelHandler);
addEventHandler(&_tfWindowingHandler);
......@@ -59,19 +61,21 @@ namespace campvis {
void AdvancedUsVis::init() {
VisualizationPipeline::init();
_imageReader.p_url.setValue("D:\\Medical Data\\Dentalscan\\dental.mhd");
_imageReader.p_targetImageID.setValue("reader.output");
_usReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\01\\BMode_01.mhd");
_usReader.p_targetImageID.setValue("us.image");
_usReader.p_targetImageID.connect(&_sliceExtractor.p_sourceImageID);
_usReader.p_targetImageID.connect(&_gvg.p_sourceImageID);
_usReader.p_targetImageID.connect(&_lhh.p_intensitiesId);
_gvg.p_inputVolume.setValue("reader.output");
_confidenceReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\01\\Confidence_01.mhd");
_confidenceReader.p_targetImageID.setValue("confidence.image");
// _lhh.p_inputVolume.setValue("se.input");
// _gvg._outputGradients.connect(&_lhh._inputGradients);
_gvg.p_targetImageID.connect(&_lhh.p_gradientsId);
_sliceExtractor.p_sourceImageID.setValue("reader.output");
_sliceExtractor.p_sliceNumber.setValue(0);
// TODO: replace this hardcoded domain by automatically determined from image min/max values
Geometry1DTransferFunction* tf = new Geometry1DTransferFunction(128, tgt::vec2(0.f, .08f));
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)));
_sliceExtractor.p_transferFunction.replaceTF(tf);
......@@ -85,24 +89,23 @@ namespace campvis {
_invalidationLevel.setValid();
// TODO: think whether we want to lock all processors already here.
}
if (! _imageReader.getInvalidationLevel().isValid()) {
executeProcessor(&_imageReader);
// convert data
ImageRepresentationLocal::ScopedRepresentation img(_data, "reader.output");
if (img != 0) {
_sliceExtractor.p_transferFunction.getTF()->setImageHandle(img.getDataHandle());
}
for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
if (! (*it)->getInvalidationLevel().isValid())
lockGLContextAndExecuteProcessor(*it);
}
// if (! _usReader.getInvalidationLevel().isValid()) {
// executeProcessor(&_usReader);
// }
// if (! _gvg.getInvalidationLevel().isValid()) {
// executeProcessor(&_gvg);
// }
// if (! _lhh.getInvalidationLevel().isValid()) {
// lockGLContextAndExecuteProcessor(&_lhh);
// }
if (! _sliceExtractor.getInvalidationLevel().isValid()) {
lockGLContextAndExecuteProcessor(&_sliceExtractor);
}
// if (! _sliceExtractor.getInvalidationLevel().isValid()) {
// lockGLContextAndExecuteProcessor(&_sliceExtractor);
// }
}
void AdvancedUsVis::keyEvent(tgt::KeyEvent* e) {
......
......@@ -66,7 +66,8 @@ namespace campvis {
virtual void keyEvent(tgt::KeyEvent* e);
protected:
MhdImageReader _imageReader;
MhdImageReader _usReader;
MhdImageReader _confidenceReader;
GradientVolumeGenerator _gvg;
LHHistogram _lhh;
SliceExtractor _sliceExtractor;
......
......@@ -62,7 +62,7 @@ namespace campvis {
_imageReader.p_url.setValue("D:\\Medical Data\\Dentalscan\\dental.mhd");
_imageReader.p_targetImageID.setValue("reader.output");
_imageReader.p_targetImageID.connect(&_gvg.p_sourceImageID);
_imageReader.p_targetImageID.connect(&_lhh.p_inputVolume);
_imageReader.p_targetImageID.connect(&_lhh.p_intensitiesId);
_imageReader.p_targetImageID.connect(&_sliceExtractor.p_sourceImageID);
// _gvg._outputGradients.connect(&_lhh._inputGradients);
......
......@@ -35,7 +35,7 @@
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/imagerepresentationrendertarget.h"
#include "core/pipeline/processordecoratorbackground.h"
#include "core/classification/simpletransferfunction.h"
......@@ -56,6 +56,9 @@ namespace campvis {
addProperty(&p_targetImageID);
addProperty(&p_sliceNumber);
addProperty(&p_transferFunction);
//addDecorator(new ProcessorDecoratorBackground());
decoratePropertyCollection(this);
}
SliceExtractor::~SliceExtractor() {
......@@ -65,6 +68,8 @@ namespace campvis {
void SliceExtractor::init() {
VisualizationProcessor::init();
_shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "modules/vis/glsl/sliceextractor.frag", "", false);
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
}
void SliceExtractor::deinit() {
......@@ -90,17 +95,17 @@ namespace campvis {
std::pair<ImageData*, ImageRepresentationRenderTarget*> rt = ImageRepresentationRenderTarget::createWithImageData(_renderTargetSize.getValue());
_shader->activate();
decorateRenderProlog(data, _shader);
tgt::TextureUnit inputUnit, tfUnit;
glData->bind(_shader, inputUnit);
p_transferFunction.getTF()->bind(_shader, tfUnit);
rt.second->activate();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
QuadRdr.renderQuad();
rt.second->deactivate();
decorateRenderEpilog(_shader);
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
......
......@@ -32,6 +32,7 @@
#include <string>
#include "core/pipeline/abstractprocessordecorator.h"
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/genericproperty.h"
......@@ -48,7 +49,7 @@ namespace campvis {
/**
* Extracts a slice from a 3D image and renders it into a rendertarget.
*/
class SliceExtractor : public VisualizationProcessor {
class SliceExtractor : public VisualizationProcessor, public HasProcessorDecorators {
public:
/**
* Constructs a new SliceExtractor Processor
......
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