05.11., 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Added a GlStructuralSimilarity processor to compute the SSIM of two 2D images....

Added a GlStructuralSimilarity processor to compute the SSIM of two 2D images. This processor is not thoroughly tested yet.
parent 01fa8683
// ================================================================================================
//
// 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 "tools/texture2d.frag"
in vec3 ex_TexCoord;
out vec4 out_Color;
uniform sampler2D _image1;
uniform TextureParameters2D _image1Params;
uniform sampler2D _image2;
uniform TextureParameters2D _image2Params;
#define WINDOW_SIZE 4
#define WINDOW_SIZE_SQ 16
void main() {
vec4 toReturn = vec4(0.0);
const float L = 255;
const float c1 = (0.01 * L) * (0.01 * L);
const float c2 = (0.03 * L) * (0.03 * L);
vec4 xMean = vec4(0);
vec4 yMean = vec4(0);
vec4 xM2 = vec4(0);
vec4 yM2 = vec4(0);
vec4 cov = vec4(0);
float n = 0;
for (int i = -WINDOW_SIZE_SQ; i <= WINDOW_SIZE_SQ; ++i) {
vec2 iOffset = vec2(i % WINDOW_SIZE, i / WINDOW_SIZE) * _image1Params._sizeRCP;
vec4 xi = texture(_image1, ex_TexCoord.xy + iOffset);
vec4 yi = texture(_image2, ex_TexCoord.xy + iOffset);
for (int j = i+1; j <= WINDOW_SIZE_SQ; ++j) {
vec2 jOffset = vec2(j % WINDOW_SIZE, j / WINDOW_SIZE) * _image1Params._sizeRCP;
vec4 xj = texture(_image1, ex_TexCoord.xy + jOffset);
vec4 yj = texture(_image2, ex_TexCoord.xy + jOffset);
cov += (xi - xj) * (yi - yj);
}
// compute mean and variance with Knuth's algorithm
// https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
n = n+1;
vec4 xDelta = xi - xMean;
xMean += xDelta/n;
xM2 += xDelta * (xi - xMean);
vec4 yDelta = yi - yMean;
yMean += yDelta/n;
yM2 += yDelta * (yi - yMean);
}
vec4 xVar = xM2 / (n-1);
vec4 yVar = yM2 / (n-1);
vec4 ssim = ((2*xMean*yMean + c1) * (2*cov + c2)) / ((xMean * xMean + yMean * yMean + c1) * (xVar + yVar + c2));
out_Color = vec4(ssim);
}
// ================================================================================================
//
// 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 "ssimdemo.h"
#include "cgt/shadermanager.h"
namespace campvis {
SsimDemo::SsimDemo(DataContainer& dc)
: AutoEvaluationPipeline(dc, getId())
, _imageReader()
, _gaussian(&_canvasSize)
, _ssim(&_canvasSize)
{
addProcessor(&_imageReader);
addProcessor(&_gaussian);
addProcessor(&_ssim);
}
SsimDemo::~SsimDemo() {
}
void SsimDemo::init() {
AutoEvaluationPipeline::init();
_ssim.p_outputImage.setValue("result");
_renderTargetID.setValue("result");
_imageReader.p_url.setValue(ShdrMgr.completePath("/modules/"));
_imageReader.p_targetImageID.setValue("reader.output");
_imageReader.p_targetImageID.addSharedProperty(&_gaussian.p_inputImage);
_gaussian.p_outputImage.setValue("blurred");
}
}
\ No newline at end of file
// ================================================================================================
//
// 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 SSIMDEMO_H__
#define SSIMDEMO_H__
#include "core/pipeline/autoevaluationpipeline.h"
#include "modules/modulesapi.h"
#include "modules/devil/processors/devilimagereader.h"
#include "modules/preprocessing/processors/glgaussianfilter.h"
#include "modules/preprocessing/processors/glstructuralsimilarity.h"
namespace campvis {
class CAMPVIS_MODULES_API SsimDemo : public AutoEvaluationPipeline {
public:
/**
* Creates a SsimDemo pipeline.
* \param dataContainer Reference to the DataContainer containing local working set of data
* for this pipeline, must be valid the whole lifetime of this pipeline.
*/
explicit SsimDemo(DataContainer& dataContainer);
/**
* Virtual Destructor
**/
virtual ~SsimDemo();
/// \see AutoEvaluationPipeline::init()
virtual void init();
static const std::string getId() { return "SsimDemo"; };
protected:
DevilImageReader _imageReader;
GlGaussianFilter _gaussian;
GlStructuralSimilarity _ssim;
};
}
#endif // SSIMDEMO_H__
......@@ -27,6 +27,7 @@
#include "modules/preprocessing/pipelines/morphologyfilterdemo.h"
#include "modules/preprocessing/pipelines/resamplingdemo.h"
#include "modules/preprocessing/pipelines/ssimdemo.h"
#include "modules/preprocessing/processors/glgaussianfilter.h"
#include "modules/preprocessing/processors/glgradientvolumegenerator.h"
......@@ -35,6 +36,7 @@
#include "modules/preprocessing/processors/glintensityquantizer.h"
#include "modules/preprocessing/processors/glmorphologyfilter.h"
#include "modules/preprocessing/processors/glsignaltonoiseratiofilter.h"
#include "modules/preprocessing/processors/glstructuralsimilarity.h"
#include "modules/preprocessing/processors/glvesselnessfilter.h"
#include "modules/preprocessing/processors/gradientvolumegenerator.h"
......@@ -43,6 +45,7 @@ namespace campvis {
// explicitly instantiate templates to register the pipelines
template class PipelineRegistrar<MorphologyDemo>;
template class PipelineRegistrar<ResamplingDemo>;
template class PipelineRegistrar<SsimDemo>;
template class SmartProcessorRegistrar<GlGaussianFilter>;
template class SmartProcessorRegistrar<GlGradientVolumeGenerator>;
......@@ -51,6 +54,7 @@ namespace campvis {
template class SmartProcessorRegistrar<GlIntensityQuantizer>;
template class SmartProcessorRegistrar<GlMorphologyFilter>;
template class SmartProcessorRegistrar<GlSignalToNoiseRatioFilter>;
template class SmartProcessorRegistrar<GlStructuralSimilarity>;
template class SmartProcessorRegistrar<GlVesselnessFilter>;
template class SmartProcessorRegistrar<GradientVolumeGenerator>;
......
// ================================================================================================
//
// 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 "glstructuralsimilarity.h"
#include "cgt/logmanager.h"
#include "cgt/shadermanager.h"
#include "cgt/textureunit.h"
#include "cgt/texture.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/renderdata.h"
#include "core/tools/quadrenderer.h"
namespace campvis {
const std::string GlStructuralSimilarity::loggerCat_ = "CAMPVis.modules.classification.GlStructuralSimilarity";
GlStructuralSimilarity::GlStructuralSimilarity(IVec2Property* viewportSizeProp)
: VisualizationProcessor(viewportSizeProp)
, p_inputImage1("InputImage1", "Input Image 1", "", DataNameProperty::READ)
, p_inputImage2("InputImage2", "Input Image 2", "", DataNameProperty::READ)
, p_outputImage("OutputImage", "Output Image", "GlStructuralSimilarity.out", DataNameProperty::WRITE)
, _shader2D(nullptr)
{
addProperty(p_inputImage1, INVALID_RESULT);
addProperty(p_inputImage2, INVALID_RESULT);
addProperty(p_outputImage);
}
GlStructuralSimilarity::~GlStructuralSimilarity() {
}
void GlStructuralSimilarity::init() {
VisualizationProcessor::init();
_shader2D = ShdrMgr.load("core/glsl/passthrough.vert", "modules/preprocessing/glsl/glstructuralsimilarity.frag", "");
}
void GlStructuralSimilarity::deinit() {
ShdrMgr.dispose(_shader2D);
VisualizationProcessor::deinit();
}
void GlStructuralSimilarity::updateResult(DataContainer& data) {
ImageRepresentationGL::ScopedRepresentation img1(data, p_inputImage1.getValue());
ImageRepresentationGL::ScopedRepresentation img2(data, p_inputImage2.getValue());
if (img1 && img2) {
cgt::vec3 originalSize(img1->getSize());
cgt::TextureUnit img1Unit, img2Unit;
img1Unit.activate();
// create texture for result
cgt::Texture* resultTexture = new cgt::Texture(GL_TEXTURE_2D, originalSize, img1->getTexture()->getInternalFormat(), cgt::Texture::LINEAR);
LGL_ERROR;
// activate shader and bind textures
_shader2D->activate();
img1->bind(_shader2D, img1Unit, "_image1", "_image1Params");
img2->bind(_shader2D, img2Unit, "_image2", "_image2Params");
LGL_ERROR;
// activate FBO and attach texture
_fbo->activate();
_fbo->attachTexture(resultTexture);
glViewport(0, 0, static_cast<GLsizei>(originalSize.x), static_cast<GLsizei>(originalSize.y));
QuadRdr.renderQuad();
LGL_ERROR;
_fbo->detachAll();
_fbo->deactivate();
_shader2D->deactivate();
// put resulting image into DataContainer
ImageData* id = new ImageData(img1->getParent()->getDimensionality(), originalSize, img1->getParent()->getNumChannels());
ImageRepresentationGL::create(id, resultTexture);
id->setMappingInformation(img1->getParent()->getMappingInformation());
data.addData(p_outputImage.getValue(), id);
cgt::TextureUnit::setZeroUnit();
LGL_ERROR;
}
else {
LDEBUG("No suitable input image found.");
}
}
}
// ================================================================================================
//
// 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 GLSTRUCTURALSIMILARITY_H__
#define GLSTRUCTURALSIMILARITY_H__
#include <string>
#include "core/pipeline/abstractprocessordecorator.h"
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/datanameproperty.h"
#include "core/properties/floatingpointproperty.h"
#include "modules/modulesapi.h"
namespace cgt {
class Shader;
}
namespace campvis {
/**
* Computes the Structural Similarity Index Measure (SSIM) of two 2D images using OpenGL.
*/
class CAMPVIS_MODULES_API GlStructuralSimilarity : public VisualizationProcessor {
public:
/**
* Constructs a new GlStructuralSimilarity Processor
**/
explicit GlStructuralSimilarity(IVec2Property* viewportSizeProp);
/**
* Destructor
**/
virtual ~GlStructuralSimilarity();
/// \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 "GlStructuralSimilarity"; };
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return getId(); };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Computes the Structural Similarity Index Measure (SSIM) of two 2D images using OpenGL."; };
/// \see AbstractProcessor::getAuthor()
virtual const std::string getAuthor() const { return "Christian Schulte zu Berge <christian.szb@in.tum.de>"; };
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::EXPERIMENTAL; };
DataNameProperty p_inputImage1; ///< ID for first input volume
DataNameProperty p_inputImage2; ///< ID for second input volume
DataNameProperty p_outputImage; ///< ID for output gradient volume
protected:
/// \see AbstractProcessor::updateResult
virtual void updateResult(DataContainer& dataContainer);
cgt::Shader* _shader2D; ///< Shader for resampling 2D textures
static const std::string loggerCat_;
};
}
#endif // GLSTRUCTURALSIMILARITY_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