Commit 7e8b6356 authored by schultezub's avatar schultezub
Browse files

Introducing AdvancedUsVis module with AdvancedUsFusion processor

Added colorspace tools shader

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@408 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent f0a6d3d4
......@@ -28,7 +28,7 @@
// ================================================================================================
#include "application/campvisapplication.h"
#include "modules/vis/pipelines/advancedusvis.h"
#include "modules/advancedusvis/pipelines/advancedusvis.h"
#include "modules/vis/pipelines/ixpvdemo.h"
#include "modules/vis/pipelines/dvrvis.h"
#include "modules/vis/pipelines/slicevis.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.
//
// ================================================================================================
/**
* Converts a color from RGB space to HSV space.
* Using the efficient implementation from http://chilliant.blogspot.de/2010/11/rgbhsv-in-hlsl.html.
* \param colorRGB color in RGB space
* \return The given color in HSV space.
*/
vec3 rgb2hsv(vec3 colorRGB) {
vec3 HSV = vec3(0.0);
HSV.z = max(colorRGB.r, max(colorRGB.g, colorRGB.b));
float M = min(colorRGB.r, min(colorRGB.g, colorRGB.b));
float difference = HSV.z - M;
if (difference != 0) {
HSV.y = difference / HSV.z;
vec3 delta = (HSV.z - colorRGB) / difference;
delta.rgb -= delta.brg;
delta.rg += vec2(2.0, 4.0);
if (colorRGB.r >= HSV.z)
HSV.x = delta.b;
else if (colorRGB.g >= HSV.z)
HSV.x = delta.r;
else
HSV.x = delta.g;
HSV.x = fract(HSV.x / 6.0);
}
return HSV;
}
/**
* Converts a color from HSV space to RGB space.
* Using the efficient implementation from http://chilliant.blogspot.de/2010/11/rgbhsv-in-hlsl.html.
* \param colorHSV color in HSV space.
* \return The given color in RGB space.
*/
vec3 hsv2rgb(vec3 colorHSV) {
float R = abs(colorHSV.x * 6.0 - 3.0) - 1.0;
float G = 2.0 - abs(colorHSV.x * 6.0 - 2.0);
float B = 2.0 - abs(colorHSV.x * 6.0 - 4.0);
vec3 toReturn = clamp(vec3(R, G, B), 0.0, 1.0);
return ((toReturn - 1.0) * colorHSV.y + 1.0) * colorHSV.z;
}
/**
* Converts a color from RGB space to CIEXYZ space.
* \see http://wiki.labomedia.org/images/1/10/Orange_Book_-_OpenGL_Shading_Language_2nd_Edition.pdf
* \param colorRGB color in RGB space
* \return The given color in CIEXYZ space.
*/
vec3 rgb2ciexyz(in vec3 colorRGB) {
const mat3 conversionMatrix = mat3(
0.412453, 0.212671, 0.019334,
0.357580, 0.715160, 0.119193,
0.180423, 0.072169, 0.950227);
return colorRGB * conversionMatrix;
}
/**
* Converts a color from CIEXYZ space to RGB space.
* \see http://wiki.labomedia.org/images/1/10/Orange_Book_-_OpenGL_Shading_Language_2nd_Edition.pdf
* \param colorCIEXYZ color in CIEXYZ space
* \return The given color in RGB space.
*/
vec3 ciexyz2rgb(in vec3 colorCIEXYZ) {
const mat3 conversionMatrix = mat3(
3.240479, -0.969256, 0.055648,
-1.537150, 1.875992, -0.204043,
-0.498535, 0.041556, 1.057311);
return colorCIEXYZ * conversionMatrix;
}
# CMake file for AdvancedUsVis module
# Source files:
FILE(GLOB ThisModSources RELATIVE ${ModulesDir}
modules/advancedusvis/pipelines/*.cpp
modules/advancedusvis/processors/*.cpp
)
# Header files (including GLSL files so that they'll appear in VS projects)
FILE(GLOB ThisModHeaders RELATIVE ${ModulesDir}
modules/advancedusvis/glsl/*.frag
modules/advancedusvis/glsl/*.vert
modules/advancedusvis/pipelines/*.h
modules/advancedusvis/processors/*.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 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.
//
// ================================================================================================
#version 330
in vec3 ex_TexCoord;
out vec4 out_Color;
#include "tools/colorspace.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
uniform Texture3D _usImage;
uniform Texture3D _confidenceMap;
uniform Texture3D _gradientMap;
uniform TransferFunction1D _transferFunction;
uniform int _sliceNumber;
void main() {
vec3 texCoord = vec3(ex_TexCoord.xy, _usImage._sizeRCP.z * (_sliceNumber + 0.5));
vec4 texel = getElement3DNormalized(_usImage, texCoord);
vec4 gradient = getElement3DNormalized(_gradientMap, texCoord);
float confidence = getElement3DNormalized(_confidenceMap, texCoord).a;
out_Color = lookupTF(_transferFunction, texel.a);
vec3 hsv = rgb2hsv(out_Color.xyz);
hsv.y = 1.0 - confidence;
out_Color.xyz = hsv2rgb(hsv);
}
......@@ -42,15 +42,15 @@ namespace campvis {
, _confidenceReader()
, _gvg()
, _lhh()
, _sliceExtractor(_effectiveRenderTargetSize)
, _wheelHandler(&_sliceExtractor.p_sliceNumber)
, _tfWindowingHandler(&_sliceExtractor.p_transferFunction)
, _usFusion(_effectiveRenderTargetSize)
, _wheelHandler(&_usFusion.p_sliceNumber)
, _tfWindowingHandler(&_usFusion.p_transferFunction)
{
addProcessor(&_usReader);
addProcessor(&_confidenceReader);
addProcessor(&_gvg);
addProcessor(&_lhh);
addProcessor(&_sliceExtractor);
//addProcessor(&_lhh);
addProcessor(&_usFusion);
addEventHandler(&_wheelHandler);
addEventHandler(&_tfWindowingHandler);
}
......@@ -63,24 +63,26 @@ namespace campvis {
_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(&_usFusion.p_usImageId);
_usReader.p_targetImageID.connect(&_gvg.p_sourceImageID);
_usReader.p_targetImageID.connect(&_lhh.p_intensitiesId);
_confidenceReader.p_url.setValue("D:\\Medical Data\\US Confidence Vis\\01\\Confidence_01.mhd");
_confidenceReader.p_targetImageID.setValue("confidence.image");
_confidenceReader.p_targetImageID.connect(&_usFusion.p_confidenceImageID);
_gvg.p_targetImageID.connect(&_lhh.p_gradientsId);
_gvg.p_targetImageID.connect(&_usFusion.p_gradientImageID);
_sliceExtractor.p_sliceNumber.setValue(0);
_usFusion.p_targetImageID.setValue("us.fused");
_usFusion.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, 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);
_usFusion.p_transferFunction.replaceTF(tf);
_renderTargetID.setValue("renderTarget");
_renderTargetID.addSharedProperty(&(_sliceExtractor.p_targetImageID));
_usFusion.p_targetImageID.addSharedProperty(&(_renderTargetID));
}
void AdvancedUsVis::execute() {
......@@ -103,8 +105,8 @@ namespace campvis {
// if (! _lhh.getInvalidationLevel().isValid()) {
// lockGLContextAndExecuteProcessor(&_lhh);
// }
// if (! _sliceExtractor.getInvalidationLevel().isValid()) {
// lockGLContextAndExecuteProcessor(&_sliceExtractor);
// if (! _usFusion.getInvalidationLevel().isValid()) {
// lockGLContextAndExecuteProcessor(&_usFusion);
// }
}
......@@ -112,10 +114,10 @@ namespace campvis {
if (e->pressed()) {
switch (e->keyCode()) {
case tgt::KeyEvent::K_UP:
_sliceExtractor.p_sliceNumber.increment();
_usFusion.p_sliceNumber.increment();
break;
case tgt::KeyEvent::K_DOWN:
_sliceExtractor.p_sliceNumber.decrement();
_usFusion.p_sliceNumber.decrement();
break;
}
}
......
......@@ -35,7 +35,7 @@
#include "core/eventhandlers/transfuncwindowingeventhandler.h"
#include "core/pipeline/visualizationpipeline.h"
#include "modules/io/processors/mhdimagereader.h"
#include "modules/vis/processors/sliceextractor.h"
#include "modules/advancedusvis/processors/advancedusfusion.h"
#include "modules/preprocessing/processors/gradientvolumegenerator.h"
#include "modules/preprocessing/processors/lhhistogram.h"
......@@ -70,7 +70,7 @@ namespace campvis {
MhdImageReader _confidenceReader;
GradientVolumeGenerator _gvg;
LHHistogram _lhh;
SliceExtractor _sliceExtractor;
AdvancedUsFusion _usFusion;
MWheelToNumericPropertyEventHandler _wheelHandler;
TransFuncWindowingEventHandler _tfWindowingHandler;
......
// ================================================================================================
//
// 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 "advancedusfusion.h"
#include "tgt/logmanager.h"
#include "tgt/shadermanager.h"
#include "tgt/textureunit.h"
#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"
#include "core/tools/quadrenderer.h"
namespace campvis {
const std::string AdvancedUsFusion::loggerCat_ = "CAMPVis.modules.vis.AdvancedUsFusion";
AdvancedUsFusion::AdvancedUsFusion(GenericProperty<tgt::ivec2>& canvasSize)
: VisualizationProcessor(canvasSize)
, p_usImageId("UsImageId", "Ultrasound Input Image", "", DataNameProperty::READ)
, p_gradientImageID("GradientImageId", "Gradient Input Image", "", DataNameProperty::READ)
, p_confidenceImageID("ConfidenceImageId", "Confidence Map Input", "", DataNameProperty::READ)
, p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE)
, p_sliceNumber("sliceNumber", "Slice Number", 0, 0, 0)
, p_transferFunction("transferFunction", "Transfer Function", new SimpleTransferFunction(256))
, _shader(0)
{
addProperty(&p_usImageId);
addProperty(&p_gradientImageID);
addProperty(&p_confidenceImageID);
addProperty(&p_targetImageID);
addProperty(&p_sliceNumber);
addProperty(&p_transferFunction);
decoratePropertyCollection(this);
}
AdvancedUsFusion::~AdvancedUsFusion() {
}
void AdvancedUsFusion::init() {
VisualizationProcessor::init();
_shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "modules/advancedusvis/glsl/advancedusfusion.frag", "", false);
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
}
void AdvancedUsFusion::deinit() {
VisualizationProcessor::deinit();
ShdrMgr.dispose(_shader);
}
void AdvancedUsFusion::process(DataContainer& data) {
ImageRepresentationGL::ScopedRepresentation img(data, p_usImageId.getValue());
ImageRepresentationGL::ScopedRepresentation confidence(data, p_confidenceImageID.getValue());
ImageRepresentationGL::ScopedRepresentation gradients(data, p_gradientImageID.getValue());
if (img != 0 && gradients != 0 && confidence != 0) {
if (img->getDimensionality() == 3) {
if (img.getDataHandle().getTimestamp() != _sourceImageTimestamp) {
// source DataHandle has changed
updateProperties(img.getDataHandle());
_sourceImageTimestamp = img.getDataHandle().getTimestamp();
}
std::pair<ImageData*, ImageRepresentationRenderTarget*> rt = ImageRepresentationRenderTarget::createWithImageData(_renderTargetSize.getValue());
_shader->activate();
decorateRenderProlog(data, _shader);
_shader->setUniform("_sliceNumber", p_sliceNumber.getValue());
tgt::TextureUnit usUnit, confidenceUnit, gradientUnit, tfUnit;
img->bind(_shader, usUnit, "_usImage");
confidence->bind(_shader, confidenceUnit, "_confidenceMap");
gradients->bind(_shader, gradientUnit, "_gradientMap");
p_transferFunction.getTF()->bind(_shader, tfUnit);
rt.second->activate();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QuadRdr.renderQuad();
rt.second->deactivate();
decorateRenderEpilog(_shader);
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
data.addData(p_targetImageID.getValue(), rt.first);
p_targetImageID.issueWrite();
}
else {
LERROR("Input image must have dimensionality of 3.");
}
}
else {
LERROR("No suitable input image found.");
}
_invalidationLevel.setValid();
}
void AdvancedUsFusion::updateProperties(DataHandle img) {
p_transferFunction.getTF()->setImageHandle(img);
const tgt::svec3& imgSize = static_cast<const ImageData*>(img.getData())->getSize();
if (p_sliceNumber.getMaxValue() != imgSize.z - 1){
p_sliceNumber.setMaxValue(imgSize.z - 1);
}
}
}
// ================================================================================================
//
// 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 ADVANCEDUSFUSION_H__
#define ADVANCEDUSFUSION_H__
#include <string>
#include "core/pipeline/abstractprocessordecorator.h"
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/genericproperty.h"
#include "core/properties/numericproperty.h"
#include "core/properties/transferfunctionproperty.h"
namespace tgt {
class Shader;
}
namespace campvis {
class ImageData;
/**
* Extracts a slice from a 3D image and renders it into a rendertarget.
*/
class AdvancedUsFusion : public VisualizationProcessor, public HasProcessorDecorators {
public:
/**
* Constructs a new AdvancedUsFusion Processor
**/
AdvancedUsFusion(GenericProperty<tgt::ivec2>& canvasSize);
/**
* Destructor
**/
virtual ~AdvancedUsFusion();
/// \see AbstractProcessor::init
virtual void init();
/// \see AbstractProcessor::deinit
virtual void deinit();
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return "AdvancedUsFusion"; };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Extracts a single slice from the input image and renders it using a transfer function."; };
/// \see AbstractProcessor::process()
virtual void process(DataContainer& data);
DataNameProperty p_usImageId; ///< image ID for input image
DataNameProperty p_gradientImageID;
DataNameProperty p_confidenceImageID;
DataNameProperty p_targetImageID; ///< image ID for output image
IntProperty p_sliceNumber; ///< number of the slice to extract
TransferFunctionProperty p_transferFunction; ///< Transfer function
protected:
/// adapts the range of the p_sliceNumber property to the image
void updateProperties(DataHandle img);
tgt::Shader* _shader; ///< Shader for slice rendering
static const std::string loggerCat_;
private:
clock_t _sourceImageTimestamp;
};
}
#endif // ADVANCEDUSFUSION_H__
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