Notice: If you are member of any public project or group, please make sure that your GitLab username is not the same as the LRZ identifier/Kennung (see https://gitlab.lrz.de/profile/account). Please change your username if necessary. For more information see the section "Public projects / Öffentliche Projekte" at https://doku.lrz.de/display/PUBLIC/GitLab . Thank you!

Commit 466e5bb9 authored by Jakob Weiss's avatar Jakob Weiss

Stereo module, extended DevilImageReader with builtin filters, minor fix to...

Stereo module, extended DevilImageReader with builtin filters, minor fix to PredicateDemoSmallHeart pipeline
parent 8f7b61ab
......@@ -108,7 +108,7 @@ namespace campvis {
Geometry1DTransferFunction* dvrTF = new Geometry1DTransferFunction(128, cgt::vec2(0.00f, .06f));
dvrTF->addGeometry(TFGeometry1D::createQuad(cgt::vec2(0.f, 1.f), cgt::col4(0, 0, 0, 0), cgt::col4(255, 255, 255, 255)));
static_cast<TransferFunctionProperty*>(_ve.getNestedProperty("VolumeRendererProperties::RaycasterProps::TransferFunction"))->replaceTF(dvrTF);
static_cast<FloatProperty*>(_ve.getNestedProperty("VolumeRendererProperties::RaycasterProps::GradientLod"))->setValue(0.5f);
//static_cast<FloatProperty*>(_ve.getNestedProperty("VolumeRendererProperties::RaycasterProps::GradientLod"))->setValue(0.5f);
// static_cast<Vec4Property*>(_ve.getNestedProperty("backgroundColor1"))->setValue(cgt::vec4(1.f));
// static_cast<Vec4Property*>(_ve.getNestedProperty("backgroundColor2"))->setValue(cgt::vec4(1.f));
......
......@@ -26,6 +26,7 @@
#include <IL/il.h>
#include <IL/ilu.h>
#include <cstring>
#include <vector>
......@@ -58,7 +59,23 @@ namespace campvis {
, p_importType("ImportType", "Import Type", importOptions, 3)
, p_importSimilar("ImportSimilar", "Import All Similar Files", false)
, p_voxelSpacing("VoxelSpacing", "Pixel/Voxel Spacing", cgt::vec3(1.0f), cgt::vec3(0.0f), cgt::vec3(1e9f))
, _shader(nullptr)
, p_imageFilter("ImageFilter", "Apply Image Filter", {
{ "none", "No Filter", DevILFilterType::NONE},
{ "BlurAVG", "Average Blur", DevILFilterType::BLUR_AVG },
{ "BlurGauss", "Gaussian Blur", DevILFilterType::BLUR_GAUSSIAN },
{ "EdgeDetectP", "Edge Detection P", DevILFilterType::EDGEDETECT_P},
{ "EdgeDetectS", "Edge Detection S", DevILFilterType::EDGEDETECT_S},
{ "Emboss", "Emboss", DevILFilterType::EMBOSS},
{ "GammaCorrect", "Gamma Correction", DevILFilterType::GAMMACORRECT},
{ "Negative", "Negative", DevILFilterType::NEGATIVE},
{ "Noise", "Noise", DevILFilterType::NOISE},
{ "Pixelize", "Pixelize", DevILFilterType::PIXELIZE},
{ "Sharpen", "Sharpen", DevILFilterType::SHARPEN}
})
, p_iterations("Iterations", "Iterations", 1, 1, 20)
, p_gamma("Gamma", "Gamma", 1.f, 0.f, 10.f)
, p_sharpeningFactor("SharpeningFactor", "Sharpening Factor", 1.0, 0.0, 2.5)
, p_pixelizationSize("PixelizationSize", "Pixelization Size", 5, 1, 50)
{
// Just some selected formats
this->_ext.push_back("bmp");
......@@ -82,6 +99,13 @@ namespace campvis {
addProperty(p_importType);
addProperty(p_importSimilar);
addProperty(p_voxelSpacing);
addProperty(p_imageFilter, INVALID_RESULT | INVALID_PROPERTIES);
addProperty(p_iterations);
addProperty(p_gamma);
addProperty(p_sharpeningFactor);
addProperty(p_pixelizationSize);
invalidate(INVALID_PROPERTIES);
}
DevilImageReader::~DevilImageReader() {
......@@ -89,12 +113,10 @@ namespace campvis {
void DevilImageReader::init() {
AbstractImageReader::init();
_shader = ShdrMgr.load("core/glsl/passthrough.vert", "core/glsl/copyimage.frag", "#define NO_DEPTH\n");
}
void DevilImageReader::deinit() {
AbstractImageReader::deinit();
ShdrMgr.dispose(_shader);
}
void DevilImageReader::updateResult(DataContainer& data) {
......@@ -232,6 +254,8 @@ namespace campvis {
}
}
applyFilter(p_imageFilter.getOptionValue());
// get data from image and transform to single intensity image:
ilCopyPixels(0, 0, 0, imageSize.x, imageSize.y, 1, devilFormat, devilDataType, buffer + (WeaklyTypedPointer::numBytes(campvisDataType, numChannels) * i * imageSize.x * imageSize.y));
ILint err = ilGetError();
......@@ -275,4 +299,62 @@ namespace campvis {
data.addData(p_targetImageID.getValue(), id);
}
}
}
\ No newline at end of file
void DevilImageReader::applyFilter(DevILFilterType filterType)
{
switch (filterType) {
case DevILFilterType::BLUR_AVG:
iluBlurAvg(p_iterations.getValue());
break;
case DevILFilterType::BLUR_GAUSSIAN:
iluBlurGaussian(p_iterations.getValue());
break;
case DevILFilterType::EDGEDETECT_P:
iluEdgeDetectP();
break;
case DevILFilterType::EDGEDETECT_S:
iluEdgeDetectS();
break;
case DevILFilterType::EMBOSS:
iluEmboss();
break;
case DevILFilterType::GAMMACORRECT:
iluGammaCorrect(p_gamma.getValue());
break;
case DevILFilterType::NEGATIVE:
iluNegative();
break;
case DevILFilterType::NOISE:
iluNoisify(p_gamma.getValue());
break;
case DevILFilterType::EQUALIZE:
iluEqualize();
break;
case DevILFilterType::SHARPEN:
iluSharpen(p_sharpeningFactor.getValue(), p_iterations.getValue());
break;
case DevILFilterType::PIXELIZE:
iluPixelize(p_pixelizationSize.getValue());
break;
case DevILFilterType::NONE:
break;
default:
LWARNING("Filter " << p_imageFilter.getOption()._title << " is not implemented!");
}
ILint err = ilGetError();
if (err != IL_NO_ERROR) {
LERROR("Error applying filter: " << iluErrorString(err));
return;
}
}
void DevilImageReader::updateProperties(DataContainer & dataContainer)
{
const auto imgFilt = p_imageFilter.getOptionValue();
p_iterations.setVisible(imgFilt == DevILFilterType::BLUR_AVG || imgFilt == DevILFilterType::BLUR_GAUSSIAN || imgFilt == DevILFilterType::SHARPEN);
p_gamma.setVisible(imgFilt == DevILFilterType::GAMMACORRECT || imgFilt == DevILFilterType::NOISE);
p_pixelizationSize.setVisible(imgFilt == DevILFilterType::PIXELIZE);
p_sharpeningFactor.setVisible(imgFilt == DevILFilterType::SHARPEN);
}
}
......@@ -49,6 +49,10 @@ namespace campvis {
*/
class CAMPVIS_MODULES_API DevilImageReader : public AbstractImageReader {
public:
enum class DevILFilterType {
NONE, BLUR_AVG, BLUR_GAUSSIAN, EDGEDETECT_P, EDGEDETECT_S, EMBOSS, GAMMACORRECT, NEGATIVE, NOISE, PIXELIZE, SHARPEN, EQUALIZE
};
/**
* Constructs a new DevilImageReader Processor
**/
......@@ -72,23 +76,34 @@ namespace campvis {
static const std::string getId() { return "DevILImageReader"; };
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return "DevilImageReader"; };
virtual const std::string getName() const override { return "DevilImageReader"; };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Reads an image file into the pipeline using the DevIL library."; };
virtual const std::string getDescription() const override { return "Reads an image file into the pipeline using the DevIL library."; };
/// \see AbstractProcessor::getAuthor()
virtual const std::string getAuthor() const { return "Christian Schulte zu Berge <christian.szb@in.tum.de>"; };
virtual const std::string getAuthor() const override { return "Christian Schulte zu Berge <christian.szb@in.tum.de>"; };
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::EXPERIMENTAL; };
virtual ProcessorState getProcessorState() const override { return AbstractProcessor::EXPERIMENTAL; };
GenericOptionProperty<std::string> p_importType;
BoolProperty p_importSimilar;
Vec3Property p_voxelSpacing;
GenericOptionProperty<DevILFilterType> p_imageFilter;
IntProperty p_iterations;
FloatProperty p_gamma;
IntProperty p_pixelizationSize;
FloatProperty p_sharpeningFactor;
protected:
/// \see AbstractProcessor::updateResult
virtual void updateResult(DataContainer& dataContainer);
virtual void updateResult(DataContainer& dataContainer) override;
void applyFilter(DevILFilterType filterType);
cgt::Shader* _shader;
/// \see AbstractProcessor::updateProperties
virtual void updateProperties(DataContainer& dataContainer) override;
static const std::string loggerCat_;
};
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2015, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "stereocompositor.h"
#include "cgt/logmanager.h"
#include "cgt/shadermanager.h"
#include "cgt/textureunit.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/renderdata.h"
#include "core/datastructures/scopedtypeddata.h"
#include "core/tools/quadrenderer.h"
namespace campvis {
const std::string StereoCompositor::loggerCat_ = "CAMPVis.modules.stereo.StereoCompositor";
StereoCompositor::StereoCompositor(IVec2Property* viewportSizeProp)
: VisualizationProcessor(viewportSizeProp)
, p_inputLeft("InputLeft", "Left Input Image", "rendered.left", DataNameProperty::READ)
, p_inputRight("InputRight", "Right Input Image", "rendered.right", DataNameProperty::READ)
, p_outputImage("OutputImage", "Output Image", "stereo.output", DataNameProperty::WRITE)
, p_compositingMode("CompositingMode", "Compositing Mode", {
{"MODE_SIDEBYSIDE_HORIZ", "Side By Side, Horizontal", StereoCompositor::StereoCompositingMode::SIDEBYSIDE_HORIZ},
{"MODE_SIDEBYSIDE_VERT", "Side By Side, Vertical", StereoCompositor::StereoCompositingMode::SIDEBYSIDE_VERT},
{"MODE_INTERLACE_HORIZ", "Interlaced, Horizontal", StereoCompositor::StereoCompositingMode::INTERLACED_HORIZ},
{"MODE_INTERLACE_VERT", "Interlaced, Vertical", StereoCompositor::StereoCompositingMode::INTERLACED_VERT},
{"MODE_ANAGLYPH_MCALLISTER", "Anaglyph [McAllister]", StereoCompositor::StereoCompositingMode::ANAGLYPH_MCALLISTER},
{"MODE_ANAGLYPH_HALFCOLOR", "Anaglyph [Half Color]", StereoCompositor::StereoCompositingMode::ANAGLYPH_HALFCOLOR},
{"MODE_ANAGLYPH_WIMMER", "Anaglyph [Wimmer]", StereoCompositor::StereoCompositingMode::ANAGLYPH_WIMMER}
})
, p_preferredInputViewports("PreferredInputViewportSize", "Preferred Input Viewport Size", cgt::ivec2(100, 100), cgt::ivec2(1,1), cgt::ivec2(10000,10000))
, p_inputViewportScaling("InputViewportScaling", "Preferred Viewport Scaling", 0.8f, 0.2f, 1.5f)
, _shader(nullptr)
{
addProperty(p_inputLeft);
addProperty(p_inputRight);
addProperty(p_outputImage);
addProperty(p_compositingMode, INVALID_RESULT | INVALID_SHADER);
addProperty(p_preferredInputViewports, VALID);
addProperty(p_inputViewportScaling, INVALID_PROPERTIES);
}
StereoCompositor::~StereoCompositor() {
}
void StereoCompositor::init() {
VisualizationProcessor::init();
updateShader();
}
void StereoCompositor::deinit() {
VisualizationProcessor::deinit();
if (_shader)
ShdrMgr.dispose(_shader);
}
void StereoCompositor::updateResult(DataContainer& data)
{
ScopedTypedData<RenderData> rtLeft(data, p_inputLeft.getValue(), true);
ScopedTypedData<RenderData> rtRight(data, p_inputRight.getValue(), true);
ImageRepresentationGL::ScopedRepresentation imageLeft(data, p_inputLeft.getValue(), true);
ImageRepresentationGL::ScopedRepresentation imageRight(data, p_inputRight.getValue(), true);
if ((!rtRight && !imageRight) || (!rtLeft && !imageLeft)) {
LDEBUG("Left or Right input image are missing.");
return;
}
FramebufferActivationGuard fag(this);
createAndAttachColorTexture();
cgt::TextureUnit colorUnitLeft, colorUnitRight;
_shader->activate();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// bind the images
if(rtLeft)
rtLeft->getColorTexture(0)->getRepresentation<ImageRepresentationGL>()->bind(_shader, colorUnitLeft, "_colorTextureLeft");
else
imageLeft->bind(_shader, colorUnitLeft, "_colorTextureLeft");
if(rtRight)
rtRight->getColorTexture(0)->getRepresentation<ImageRepresentationGL>()->bind(_shader, colorUnitRight, "_colorTextureRight");
else
imageRight->bind(_shader, colorUnitRight, "_colorTextureRight");
_shader->setUniform("_viewMatrix", cgt::mat4::createIdentity());
QuadRdr.renderQuad11();
_shader->deactivate();
cgt::TextureUnit::setZeroUnit();
LGL_ERROR;
data.addData(p_outputImage.getValue(), new RenderData(_fbo));
}
void StereoCompositor::updateShader()
{
if (_shader)
ShdrMgr.dispose(_shader);
std::stringstream ss;
ss << "#define " << p_compositingMode.getOptionId() << std::endl;
_shader = ShdrMgr.load("core/glsl/passthrough.vert", "modules/stereo/glsl/stereocompositor.frag", ss.str());
}
void StereoCompositor::updateProperties(DataContainer& dataContainer) {
auto outputViewportSize = _viewportSizeProperty->getValue();
float s = p_inputViewportScaling.getValue();
switch (p_compositingMode.getOptionValue())
{
case StereoCompositingMode::INTERLACED_HORIZ:
case StereoCompositingMode::SIDEBYSIDE_VERT:
p_preferredInputViewports.setValue(cgt::ivec2(static_cast<int>(s * outputViewportSize.x), static_cast<int>(s * outputViewportSize.y / 2)));
break;
case StereoCompositingMode::INTERLACED_VERT:
case StereoCompositingMode::SIDEBYSIDE_HORIZ:
p_preferredInputViewports.setValue(cgt::ivec2(static_cast<int>(s * outputViewportSize.x / 2), static_cast<int>(s * outputViewportSize.y)));
break;
case StereoCompositingMode::ANAGLYPH_MCALLISTER:
case StereoCompositingMode::ANAGLYPH_HALFCOLOR:
case StereoCompositingMode::ANAGLYPH_WIMMER:
default:
p_preferredInputViewports.setValue(cgt::ivec2(s * cgt::vec2(outputViewportSize)));
break;
}
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2015, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#ifndef STEREOCOMPOSITOR_H__
#define STEREOCOMPOSITOR_H__
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/numericproperty.h"
#include "core/properties/optionproperty.h"
#include "core/properties/floatingpointproperty.h"
#include "modules/modulesapi.h"
namespace cgt {
class Shader;
}
namespace campvis {
/**
* Combines up two render targets for a left and a right eye into one render target. Supports different modi to compose the two images.
*/
class CAMPVIS_MODULES_API StereoCompositor : public VisualizationProcessor {
public:
enum class StereoCompositingMode {
SIDEBYSIDE_HORIZ,
SIDEBYSIDE_VERT,
INTERLACED_HORIZ,
INTERLACED_VERT,
ANAGLYPH_MCALLISTER,
ANAGLYPH_HALFCOLOR,
ANAGLYPH_WIMMER
};
/**
* Constructs a new StereoCompositor Processor
**/
explicit StereoCompositor(IVec2Property* viewportSizeProp);
/**
* Destructor
**/
virtual ~StereoCompositor();
/// \see AbstractProcessor::init
virtual void init();
/// \see AbstractProcessor::deinit
virtual void deinit();
/**
* To be used in ProcessorFactory static methods
*/
static const std::string getId() { return "StereoCompositor"; };
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return getId(); };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Combines two textures to a stereo image."; };
/// \see AbstractProcessor::getAuthor()
virtual const std::string getAuthor() const { return "Jakob Weiss <jakob.weiss@in.tum.de>"; };
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::TESTING; };
DataNameProperty p_inputLeft; ///< image ID for left input image
DataNameProperty p_inputRight; ///< image ID for right input image
DataNameProperty p_outputImage; ///< image ID for output image
GenericOptionProperty<StereoCompositingMode> p_compositingMode;
IVec2Property p_preferredInputViewports; ///< the optimal input viewport size
FloatProperty p_inputViewportScaling; ///< up/downscaling factor for input viewport, can be used to reduce computational costs
protected:
/// \see AbstractProcessor::updateResult
virtual void updateResult(DataContainer& dataContainer) override;
/// \see AbstractProcessor::updateShader
virtual void updateShader() override;
/// \see AbstractProcessor::updateProperties
virtual void updateProperties(DataContainer& dataContainer) override;
cgt::Shader* _shader; ///< Shader for slice rendering
static const std::string loggerCat_;
};
}
#endif // STEREOCOMPOSITOR_H__
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2015, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "core/pipeline/pipelinefactory.h"
#include "core/pipeline/processorfactory.h"
#include "modules/stereo/pipelines/stereorenderdemo.h"
#include "modules/stereo/pipelines/stereopipeline.h"
#include "modules/vis/pipelines/geometryrendererdemo.h"
#include "modules/stereo/processors/stereocameragenerator.h"
#include "modules/stereo/processors/stereocompositor.h"
namespace campvis {
// explicitly instantiate templates to register the pipelines
template class PipelineRegistrar<StereoRenderDemo>;
template class SmartProcessorRegistrar<StereoCameraGenerator>;
template class SmartProcessorRegistrar<StereoCompositor>;
}
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