From Jose Delport, a MRT example implementing stereo matching.

This commit is contained in:
Robert Osfield 2008-04-11 11:58:27 +00:00
parent 9cec69981d
commit 98a2289a59
8 changed files with 1172 additions and 0 deletions

View File

@ -84,6 +84,7 @@ IF(DYNAMIC_OPENSCENEGRAPH)
ADD_SUBDIRECTORY(osgspheresegment)
ADD_SUBDIRECTORY(osgspotlight)
ADD_SUBDIRECTORY(osgstereoimage)
ADD_SUBDIRECTORY(osgstereomatch)
ADD_SUBDIRECTORY(osgteapot)
ADD_SUBDIRECTORY(osgterrain)
ADD_SUBDIRECTORY(osgtessellate)#)

View File

@ -0,0 +1,13 @@
SET(TARGET_SRC
StereoPass.cpp
StereoMultipass.cpp
osgstereomatch.cpp
)
SET(TARGET_H
StereoPass.h
StereoMultipass.h
)
#### end var setup ###
SETUP_EXAMPLE(osgstereomatch)

View File

@ -0,0 +1,62 @@
The osgstereomatch example illustrates how multiple render passes and multiple render targets on the GPU can be used in stereo vision disparity map calculation.
A simple algorithm is implemented in both a single- and multi-pass way to show the differences in speed of execution.
The normal osgviewer is used for display and one can obtain the time spent on the GPU by pressing the "s" key twice.
The sample data was downloaded from the Middlebury Stereo Vision Page at http://vision.middlebury.edu/stereo/
Usage examples:
---------------
osgstereomatch --left tsukubaL.png --right tsukubaR.png --min 0 --max 15 --window 5
osgstereomatch --left tsukubaL.png --right tsukubaR.png --min 0 --max 15 --window 5 --single
osgstereomatch --left teddyL.png --right teddyR.png --min 10 --max 57 --window 7
Algorithm and implementation details:
-------------------------------------
The algorithm uses the sum of absolute differences between pixels (often referred to as SAD in the literature) to find matching areas in the left and right stereo images. The algorithm is definitely not state of the art, but illustrates stereo matching concepts.
The algorithm assumes that the input images are already rectified and undistorted.
Inputs to the algorithm are:
* Window size -- The size (width and height) of a rectangular window around the current pixel that is used for comparison.
* Minimum disparity -- The minimum pixel offset at which to start searching for matching areas in the right image.
* Maximum disparity -- The maximum pixel offset at which to stop searching for matching areas in the right image.
The offsets can be visualised as shifting the right stereo image to the right by the specified number of pixels.
The following pseudo-code describes the algorithm:
for every pixel in the left image:
for the complete range of disparity values:
pixel-wise sum the absolute differences between the left and right windows
(the right window is shifted by the current disparity value evaluated)
store the disparity value where the sum is the smallest
assign the stored disparity value to the disparity image pixel
The algorithm was implemented using GLSL shaders. Two implementation of the algorithm was created to compare the execution speed using two different approaches. The first version uses a single shader and a single rendering pass, while the second approach utilises several shaders and rendering passes to create a disparity image.
Single Pass
-----------
The single pass algorithm implements the pseudo-code directly as presented earlier. The code for the algorithm can be found in the ``stereopass.frag'' source file.
Multiple Pass
-------------
The single pass algorithm often re-computes the same absolute differences between left and right image pixels. For example, when shifting a 3x3 window one pixel horizontally, 6 absolute difference values would be recomputed. In the multi-pass algorithm, the absolute differences between pixels are pre-computed before doing the summation over a window.
The algorithm consists of 4 passes:
1) Clear pass -- Two floating point textures are created for storing the minimum sum (SAD) and best disparity value calculated so far (called disparity textures in the following discussion). The minimum sum is stored in the first channel of the images and the best disparity is stored in the second channel. Two textures are needed, because shaders cannot read and write to the same texture during calculation. One texture is used as input and the other as output. After a calculation, the input and output textures are swapped. The technique is known as ping-ponging or flip-flopping the textures. The clear pass initialises the two textures. The code can be found in ``clear.frag''.
2) Subtract pass -- Sixteen disparity values are considered and the shifted right image is subtracted from the left image. The absolute difference of the pixel values are stored in one of the four channels of one of four output images. The multiple render target (MRT) capabilities of modern graphics cards are utilised during this pass. The code can be found in ``subtract.frag''.
3) Aggregate pass -- The sixteen images generated during the subtract pass is used as input for this pass. For each of the images, a sum over the window centered at the current output pixel is computed and stored. The minimum sum of the sixteen images is then compared with the lowest sum calculated during previous passes (read from the input disparity texture). If it is lower, the output disparity texture is updated with the new sum and the new disparity value, if not, the old values are copied. The code can be found in ``aggregate.frag''.
4) Select pass -- The final disparity texture contains the best disparity value found in the second (green) channel. This pass merely copies the second channel to all the colour channels of the output image. The code can be found in ``select.frag''.
The subtract and aggregate passes are executed multiple times to cover the complete requested disparity range. Disparity range divided by 16 combinations of these passes are needed. Despite the apparent complexity of the algorithm, it executes faster than the single pass algorithm.
J.P. Delport 2008/04

View File

@ -0,0 +1,541 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* OpenSceneGraph example, osgstereomatch.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "StereoMultipass.h"
#include <osgDB/FileUtils>
#include <iostream>
SubtractPass::SubtractPass(osg::TextureRectangle *left_tex,
osg::TextureRectangle *right_tex,
int width, int height,
int start_disparity) :
_TextureWidth(width),
_TextureHeight(height),
_StartDisparity(start_disparity)
{
_RootGroup = new osg::Group;
_InTextureLeft = left_tex;
_InTextureRight = right_tex;
createOutputTextures();
_Camera = new osg::Camera;
setupCamera();
_Camera->addChild(createTexturedQuad().get());
_RootGroup->addChild(_Camera.get());
setShader("shaders/stereomatch_subtract.frag");
}
SubtractPass::~SubtractPass()
{
}
osg::ref_ptr<osg::Group> SubtractPass::createTexturedQuad()
{
osg::ref_ptr<osg::Group> top_group = new osg::Group;
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
// counter-clockwise
quad_coords->push_back(osg::Vec3d(0, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 1, -1));
quad_coords->push_back(osg::Vec3d(0, 1, -1));
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
quad_tcoords->push_back(osg::Vec2(0, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
osg::ref_ptr<osg::Vec4Array> quad_colors = new osg::Vec4Array;
quad_colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
quad_geom->setVertexArray(quad_coords.get());
quad_geom->setTexCoordArray(0, quad_tcoords.get());
quad_geom->addPrimitiveSet(quad_da.get());
quad_geom->setColorArray(quad_colors.get());
quad_geom->setColorBinding(osg::Geometry::BIND_OVERALL);
_StateSet = quad_geom->getOrCreateStateSet();
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
_StateSet->setTextureAttributeAndModes(0, _InTextureLeft.get(), osg::StateAttribute::ON);
_StateSet->setTextureAttributeAndModes(1, _InTextureRight.get(), osg::StateAttribute::ON);
_StateSet->addUniform(new osg::Uniform("textureLeft", 0));
_StateSet->addUniform(new osg::Uniform("textureRight", 1));
_StateSet->addUniform(new osg::Uniform("start_disparity", _StartDisparity));
quad_geode->addDrawable(quad_geom.get());
top_group->addChild(quad_geode.get());
return top_group;
}
void SubtractPass::setupCamera()
{
// clearing
_Camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// projection and view
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
_Camera->setViewMatrix(osg::Matrix::identity());
// viewport
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
// attach the 4 textures
for (int i=0; i<4; i++) {
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+i), _OutTexture[i].get());
}
}
void SubtractPass::createOutputTextures()
{
for (int i=0; i<4; i++) {
_OutTexture[i] = new osg::TextureRectangle;
_OutTexture[i]->setTextureSize(_TextureWidth, _TextureHeight);
_OutTexture[i]->setInternalFormat(GL_RGBA);
_OutTexture[i]->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
_OutTexture[i]->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
}
}
void SubtractPass::setShader(std::string filename)
{
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
_FragmentProgram = 0;
_FragmentProgram = new osg::Program;
_FragmentProgram->addShader(fshader.get());
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
}
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
AggregatePass::AggregatePass(osg::TextureRectangle *diff_tex0,
osg::TextureRectangle *diff_tex1,
osg::TextureRectangle *diff_tex2,
osg::TextureRectangle *diff_tex3,
osg::TextureRectangle *agg_tex_in,
osg::TextureRectangle *agg_tex_out,
int width, int height,
int start_disparity, int window_size):
_TextureWidth(width),
_TextureHeight(height),
_StartDisparity(start_disparity),
_WindowSize(window_size)
{
_RootGroup = new osg::Group;
_InTextureDifference[0] = diff_tex0;
_InTextureDifference[1] = diff_tex1;
_InTextureDifference[2] = diff_tex2;
_InTextureDifference[3] = diff_tex3;
_InTextureAggregate = agg_tex_in;
_OutTextureAggregate = agg_tex_out;
_OutTexture = _OutTextureAggregate;
_Camera = new osg::Camera;
setupCamera();
_Camera->addChild(createTexturedQuad().get());
_RootGroup->addChild(_Camera.get());
setShader("shaders/stereomatch_aggregate.frag");
}
AggregatePass::~AggregatePass()
{
}
osg::ref_ptr<osg::Group> AggregatePass::createTexturedQuad()
{
osg::ref_ptr<osg::Group> top_group = new osg::Group;
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
// counter-clockwise
quad_coords->push_back(osg::Vec3d(0, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 1, -1));
quad_coords->push_back(osg::Vec3d(0, 1, -1));
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
quad_tcoords->push_back(osg::Vec2(0, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
osg::ref_ptr<osg::Vec4Array> quad_colors = new osg::Vec4Array;
quad_colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
quad_geom->setVertexArray(quad_coords.get());
quad_geom->setTexCoordArray(0, quad_tcoords.get());
quad_geom->addPrimitiveSet(quad_da.get());
quad_geom->setColorArray(quad_colors.get());
quad_geom->setColorBinding(osg::Geometry::BIND_OVERALL);
_StateSet = quad_geom->getOrCreateStateSet();
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
_StateSet->setTextureAttributeAndModes(0, _InTextureDifference[0].get(), osg::StateAttribute::ON);
_StateSet->setTextureAttributeAndModes(1, _InTextureDifference[1].get(), osg::StateAttribute::ON);
_StateSet->setTextureAttributeAndModes(2, _InTextureDifference[2].get(), osg::StateAttribute::ON);
_StateSet->setTextureAttributeAndModes(3, _InTextureDifference[3].get(), osg::StateAttribute::ON);
_StateSet->setTextureAttributeAndModes(4, _InTextureAggregate.get(), osg::StateAttribute::ON);
_StateSet->addUniform(new osg::Uniform("textureDiff0", 0));
_StateSet->addUniform(new osg::Uniform("textureDiff1", 1));
_StateSet->addUniform(new osg::Uniform("textureDiff2", 2));
_StateSet->addUniform(new osg::Uniform("textureDiff3", 3));
_StateSet->addUniform(new osg::Uniform("textureAggIn", 4));
_StateSet->addUniform(new osg::Uniform("start_disparity", _StartDisparity));
_StateSet->addUniform(new osg::Uniform("window_size", _WindowSize));
quad_geode->addDrawable(quad_geom.get());
top_group->addChild(quad_geode.get());
return top_group;
}
void AggregatePass::setupCamera()
{
// clearing
_Camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// projection and view
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
_Camera->setViewMatrix(osg::Matrix::identity());
// viewport
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+0), _OutTexture.get());
}
void AggregatePass::setShader(std::string filename)
{
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
_FragmentProgram = 0;
_FragmentProgram = new osg::Program;
_FragmentProgram->addShader(fshader.get());
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
SelectPass::SelectPass(osg::TextureRectangle *in_tex,
int width, int height,
int min_disparity, int max_disparity) :
_TextureWidth(width),
_TextureHeight(height),
_MinDisparity(min_disparity),
_MaxDisparity(max_disparity)
{
_RootGroup = new osg::Group;
_InTexture = in_tex;
createOutputTextures();
_Camera = new osg::Camera;
setupCamera();
_Camera->addChild(createTexturedQuad().get());
_RootGroup->addChild(_Camera.get());
setShader("shaders/stereomatch_select.frag");
}
SelectPass::~SelectPass()
{
}
osg::ref_ptr<osg::Group> SelectPass::createTexturedQuad()
{
osg::ref_ptr<osg::Group> top_group = new osg::Group;
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
// counter-clockwise
quad_coords->push_back(osg::Vec3d(0, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 1, -1));
quad_coords->push_back(osg::Vec3d(0, 1, -1));
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
quad_tcoords->push_back(osg::Vec2(0, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
osg::ref_ptr<osg::Vec4Array> quad_colors = new osg::Vec4Array;
quad_colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
quad_geom->setVertexArray(quad_coords.get());
quad_geom->setTexCoordArray(0, quad_tcoords.get());
quad_geom->addPrimitiveSet(quad_da.get());
quad_geom->setColorArray(quad_colors.get());
quad_geom->setColorBinding(osg::Geometry::BIND_OVERALL);
_StateSet = quad_geom->getOrCreateStateSet();
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
_StateSet->setTextureAttributeAndModes(0, _InTexture.get(), osg::StateAttribute::ON);
_StateSet->addUniform(new osg::Uniform("textureIn", 0));
_StateSet->addUniform(new osg::Uniform("min_disparity", _MinDisparity));
_StateSet->addUniform(new osg::Uniform("max_disparity", _MaxDisparity));
quad_geode->addDrawable(quad_geom.get());
top_group->addChild(quad_geode.get());
return top_group;
}
void SelectPass::setupCamera()
{
// clearing
_Camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// projection and view
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
_Camera->setViewMatrix(osg::Matrix::identity());
// viewport
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+0), _OutTexture.get());
}
void SelectPass::createOutputTextures()
{
_OutTexture = new osg::TextureRectangle;
_OutTexture->setTextureSize(_TextureWidth, _TextureHeight);
_OutTexture->setInternalFormat(GL_RGBA);
_OutTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
_OutTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
}
void SelectPass::setShader(std::string filename)
{
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
_FragmentProgram = 0;
_FragmentProgram = new osg::Program;
_FragmentProgram->addShader(fshader.get());
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
}
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
StereoMultipass::StereoMultipass(osg::TextureRectangle *left_tex,
osg::TextureRectangle *right_tex,
int width, int height,
int min_disparity, int max_disparity, int window_size) :
_TextureWidth(width),
_TextureHeight(height)
{
_RootGroup = new osg::Group;
createOutputTextures();
_Camera = new osg::Camera;
setupCamera();
_Camera->addChild(createTexturedQuad().get());
_RootGroup->addChild(_Camera.get());
setShader("shaders/stereomatch_clear.frag");
flip=1;
flop=0;
// we can do 16 differences in one pass,
// but we must ping-pong the aggregate textures between passes
// add passes until we cover the disparity range
for (int i=min_disparity; i<=max_disparity; i+=16) {
SubtractPass *subp = new SubtractPass(left_tex, right_tex,
width, height,
i);
AggregatePass *aggp = new AggregatePass(subp->getOutputTexture(0).get(),
subp->getOutputTexture(1).get(),
subp->getOutputTexture(2).get(),
subp->getOutputTexture(3).get(),
_OutTexture[flip].get(),
_OutTexture[flop].get(),
width, height,
i, window_size);
_RootGroup->addChild(subp->getRoot().get());
_RootGroup->addChild(aggp->getRoot().get());
flip = flip ? 0 : 1;
flop = flop ? 0 : 1;
}
// add select pass
_SelectPass = new SelectPass(_OutTexture[flip].get(),
width, height,
min_disparity, max_disparity);
_RootGroup->addChild(_SelectPass->getRoot().get());
}
StereoMultipass::~StereoMultipass()
{
}
osg::ref_ptr<osg::Group> StereoMultipass::createTexturedQuad()
{
osg::ref_ptr<osg::Group> top_group = new osg::Group;
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
// counter-clockwise
quad_coords->push_back(osg::Vec3d(0, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 1, -1));
quad_coords->push_back(osg::Vec3d(0, 1, -1));
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
quad_tcoords->push_back(osg::Vec2(0, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
osg::ref_ptr<osg::Vec4Array> quad_colors = new osg::Vec4Array;
quad_colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
quad_geom->setVertexArray(quad_coords.get());
quad_geom->setTexCoordArray(0, quad_tcoords.get());
quad_geom->addPrimitiveSet(quad_da.get());
quad_geom->setColorArray(quad_colors.get());
quad_geom->setColorBinding(osg::Geometry::BIND_OVERALL);
_StateSet = quad_geom->getOrCreateStateSet();
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
quad_geode->addDrawable(quad_geom.get());
top_group->addChild(quad_geode.get());
return top_group;
}
void StereoMultipass::setupCamera()
{
// clearing
_Camera->setClearColor(osg::Vec4(10.0f,0.0f,0.0f,1.0f));
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// projection and view
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
_Camera->setViewMatrix(osg::Matrix::identity());
// viewport
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
// attach two textures for aggregating results
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+0), _OutTexture[0].get());
_Camera->attach(osg::Camera::BufferComponent(osg::Camera::COLOR_BUFFER0+1), _OutTexture[1].get());
}
void StereoMultipass::createOutputTextures()
{
for (int i=0; i<2; i++) {
_OutTexture[i] = new osg::TextureRectangle;
_OutTexture[i]->setTextureSize(_TextureWidth, _TextureHeight);
_OutTexture[i]->setInternalFormat(GL_RGBA);
_OutTexture[i]->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
_OutTexture[i]->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
// hdr, we want to store floats
_OutTexture[i]->setInternalFormat(GL_RGBA16F_ARB);
//_OutTexture[i]->setInternalFormat(GL_FLOAT_RGBA32_NV);
//_OutTexture[i]->setInternalFormat(GL_FLOAT_RGBA16_NV);
_OutTexture[i]->setSourceFormat(GL_RGBA);
_OutTexture[i]->setSourceType(GL_FLOAT);
}
}
void StereoMultipass::setShader(std::string filename)
{
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
_FragmentProgram = 0;
_FragmentProgram = new osg::Program;
_FragmentProgram->addShader(fshader.get());
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
}

View File

@ -0,0 +1,154 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* OpenSceneGraph example, osgstereomatch.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef STEREOMULTIPASS_H
#define STEREOMULTIPASS_H 1
#include <osg/ref_ptr>
#include <osg/Group>
#include <osg/Camera>
#include <osg/MatrixTransform>
#include <osg/Projection>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/TextureRectangle>
class SubtractPass {
public:
SubtractPass(osg::TextureRectangle *left_tex,
osg::TextureRectangle *right_tex,
int width, int height,
int start_disparity);
~SubtractPass();
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
osg::ref_ptr<osg::TextureRectangle> getOutputTexture(int i) { return _OutTexture[i]; }
void setShader(std::string filename);
private:
osg::ref_ptr<osg::Group> createTexturedQuad();
void createOutputTextures();
void setupCamera();
osg::ref_ptr<osg::Group> _RootGroup;
osg::ref_ptr<osg::Camera> _Camera;
osg::ref_ptr<osg::TextureRectangle> _InTextureLeft;
osg::ref_ptr<osg::TextureRectangle> _InTextureRight;
osg::ref_ptr<osg::TextureRectangle> _OutTexture[4];
int _TextureWidth;
int _TextureHeight;
int _StartDisparity;
osg::ref_ptr<osg::Program> _FragmentProgram;
osg::ref_ptr<osg::StateSet> _StateSet;
};
class AggregatePass {
public:
AggregatePass(osg::TextureRectangle *diff_tex0,
osg::TextureRectangle *diff_tex1,
osg::TextureRectangle *diff_tex2,
osg::TextureRectangle *diff_tex3,
osg::TextureRectangle *agg_tex_in,
osg::TextureRectangle *agg_tex_out,
int width, int height,
int start_disparity, int window_size);
~AggregatePass();
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
osg::ref_ptr<osg::TextureRectangle> getOutputTexture() { return _OutTexture; }
void setShader(std::string filename);
private:
osg::ref_ptr<osg::Group> createTexturedQuad();
void setupCamera();
osg::ref_ptr<osg::Group> _RootGroup;
osg::ref_ptr<osg::Camera> _Camera;
osg::ref_ptr<osg::TextureRectangle> _InTextureDifference[4];
osg::ref_ptr<osg::TextureRectangle> _InTextureAggregate;
osg::ref_ptr<osg::TextureRectangle> _OutTextureAggregate;
osg::ref_ptr<osg::TextureRectangle> _OutTexture;
int _TextureWidth;
int _TextureHeight;
int _StartDisparity;
int _WindowSize;
osg::ref_ptr<osg::Program> _FragmentProgram;
osg::ref_ptr<osg::StateSet> _StateSet;
};
class SelectPass {
public:
SelectPass(osg::TextureRectangle *in_tex,
int width, int height,
int min_disparity, int max_disparity);
~SelectPass();
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
osg::ref_ptr<osg::TextureRectangle> getOutputTexture() { return _OutTexture; }
void setShader(std::string filename);
private:
osg::ref_ptr<osg::Group> createTexturedQuad();
void createOutputTextures();
void setupCamera();
osg::ref_ptr<osg::Group> _RootGroup;
osg::ref_ptr<osg::Camera> _Camera;
osg::ref_ptr<osg::TextureRectangle> _InTexture;
osg::ref_ptr<osg::TextureRectangle> _OutTexture;
osg::ref_ptr<osg::Image> _OutImage;
int _TextureWidth;
int _TextureHeight;
int _MinDisparity;
int _MaxDisparity;
osg::ref_ptr<osg::Program> _FragmentProgram;
osg::ref_ptr<osg::StateSet> _StateSet;
};
class StereoMultipass {
public:
StereoMultipass(osg::TextureRectangle *left_tex,
osg::TextureRectangle *right_tex,
int width, int height,
int min_disparity, int max_disparity, int window_size);
~StereoMultipass();
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
osg::ref_ptr<osg::TextureRectangle> getOutputTexture() { return _SelectPass->getOutputTexture().get(); }
void setShader(std::string filename);
private:
osg::ref_ptr<osg::Group> createTexturedQuad();
void createOutputTextures();
void setupCamera();
osg::ref_ptr<osg::Group> _RootGroup;
osg::ref_ptr<osg::Camera> _Camera;
osg::ref_ptr<osg::TextureRectangle> _InTexture;
osg::ref_ptr<osg::TextureRectangle> _OutTexture[2];
int _TextureWidth;
int _TextureHeight;
osg::ref_ptr<osg::Program> _FragmentProgram;
osg::ref_ptr<osg::StateSet> _StateSet;
SelectPass *_SelectPass;
int flip;
int flop;
};
#endif //STEREOMULTIPASS_H

View File

@ -0,0 +1,141 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* OpenSceneGraph example, osgstereomatch.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "StereoPass.h"
#include <osgDB/FileUtils>
#include <iostream>
StereoPass::StereoPass(osg::TextureRectangle *left_tex,
osg::TextureRectangle *right_tex,
int width, int height,
int min_disparity, int max_disparity, int window_size):
_TextureWidth(width),
_TextureHeight(height),
_MinDisparity(min_disparity),
_MaxDisparity(max_disparity),
_WindowSize(window_size)
{
_RootGroup = new osg::Group;
_InTextureLeft = left_tex;
_InTextureRight = right_tex;
createOutputTextures();
_Camera = new osg::Camera;
setupCamera();
_Camera->addChild(createTexturedQuad().get());
_RootGroup->addChild(_Camera.get());
setShader("shaders/stereomatch_stereopass.frag");
}
StereoPass::~StereoPass()
{
}
osg::ref_ptr<osg::Group> StereoPass::createTexturedQuad()
{
osg::ref_ptr<osg::Group> top_group = new osg::Group;
osg::ref_ptr<osg::Geode> quad_geode = new osg::Geode;
osg::ref_ptr<osg::Vec3Array> quad_coords = new osg::Vec3Array; // vertex coords
// counter-clockwise
quad_coords->push_back(osg::Vec3d(0, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 0, -1));
quad_coords->push_back(osg::Vec3d(1, 1, -1));
quad_coords->push_back(osg::Vec3d(0, 1, -1));
osg::ref_ptr<osg::Vec2Array> quad_tcoords = new osg::Vec2Array; // texture coords
quad_tcoords->push_back(osg::Vec2(0, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, 0));
quad_tcoords->push_back(osg::Vec2(_TextureWidth, _TextureHeight));
quad_tcoords->push_back(osg::Vec2(0, _TextureHeight));
osg::ref_ptr<osg::Geometry> quad_geom = new osg::Geometry;
osg::ref_ptr<osg::DrawArrays> quad_da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
quad_geom->setVertexArray(quad_coords.get());
quad_geom->setTexCoordArray(0, quad_tcoords.get());
quad_geom->addPrimitiveSet(quad_da.get());
_StateSet = quad_geom->getOrCreateStateSet();
_StateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
_StateSet->setTextureAttributeAndModes(0, _InTextureLeft.get(), osg::StateAttribute::ON);
_StateSet->setTextureAttributeAndModes(1, _InTextureRight.get(), osg::StateAttribute::ON);
_StateSet->addUniform(new osg::Uniform("textureID0", 0));
_StateSet->addUniform(new osg::Uniform("textureID1", 1));
_StateSet->addUniform(new osg::Uniform("min_disparity", _MinDisparity));
_StateSet->addUniform(new osg::Uniform("max_disparity", _MaxDisparity));
_StateSet->addUniform(new osg::Uniform("window_size", _WindowSize));
quad_geode->addDrawable(quad_geom.get());
top_group->addChild(quad_geode.get());
return top_group;
}
void StereoPass::setupCamera()
{
// clearing
_Camera->setClearColor(osg::Vec4(1.0f,0.0f,0.0f,1.0f));
_Camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// projection and view
_Camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
_Camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
_Camera->setViewMatrix(osg::Matrix::identity());
// viewport
_Camera->setViewport(0, 0, _TextureWidth, _TextureHeight);
_Camera->setRenderOrder(osg::Camera::PRE_RENDER);
_Camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
// attach the output texture and use it as the color buffer.
_Camera->attach(osg::Camera::COLOR_BUFFER, _OutTexture.get());
}
void StereoPass::createOutputTextures()
{
_OutTexture = new osg::TextureRectangle;
_OutTexture->setTextureSize(_TextureWidth, _TextureHeight);
_OutTexture->setInternalFormat(GL_RGBA);
_OutTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
_OutTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
}
void StereoPass::setShader(std::string filename)
{
osg::ref_ptr<osg::Shader> fshader = new osg::Shader( osg::Shader::FRAGMENT );
fshader->loadShaderSourceFromFile(osgDB::findDataFile(filename));
_FragmentProgram = 0;
_FragmentProgram = new osg::Program;
_FragmentProgram->addShader(fshader.get());
_StateSet->setAttributeAndModes(_FragmentProgram.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
}

View File

@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* OpenSceneGraph example, osgstereomatch.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef STEREOPASS_H
#define STEREOPASS_H 1
#include <osg/ref_ptr>
#include <osg/Group>
#include <osg/Camera>
#include <osg/MatrixTransform>
#include <osg/Projection>
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Texture2D>
#include <osg/TextureRectangle>
class StereoPass {
public:
StereoPass(osg::TextureRectangle *left_tex,
osg::TextureRectangle *right_tex,
int width, int height,
int min_disparity, int max_disparity, int window_size);
~StereoPass();
osg::ref_ptr<osg::Group> getRoot() { return _RootGroup; }
osg::ref_ptr<osg::TextureRectangle> getOutputTexture() { return _OutTexture; }
void setShader(std::string filename);
private:
osg::ref_ptr<osg::Group> createTexturedQuad();
void createOutputTextures();
void setupCamera();
osg::ref_ptr<osg::Group> _RootGroup;
osg::ref_ptr<osg::Camera> _Camera;
osg::ref_ptr<osg::TextureRectangle> _InTextureLeft;
osg::ref_ptr<osg::TextureRectangle> _InTextureRight;
osg::ref_ptr<osg::TextureRectangle> _OutTexture;
int _TextureWidth;
int _TextureHeight;
int _MinDisparity;
int _MaxDisparity;
int _WindowSize;
osg::ref_ptr<osg::Program> _FragmentProgram;
osg::ref_ptr<osg::StateSet> _StateSet;
};
#endif //STEREOPASS_H

View File

@ -0,0 +1,194 @@
/* OpenSceneGraph example, osgstereomatch.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Quat>
#include <osg/Matrix>
#include <osg/ShapeDrawable>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/TextureRectangle>
#include <osgDB/FileUtils>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <iostream>
#include "StereoPass.h"
#include "StereoMultipass.h"
osg::Node* createScene(osg::Image *left, osg::Image *right, unsigned int min_disp, unsigned int max_disp, unsigned int window_size, bool single_pass)
{
int width = left->s();
int height = left->t();
osg::Group* topnode = new osg::Group;
// create four quads so we can display up to four images
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
// each geom will contain a quad
osg::ref_ptr<osg::DrawArrays> da = new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4);
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
osg::ref_ptr<osg::Vec2Array> tcoords = new osg::Vec2Array; // texture coords
tcoords->push_back(osg::Vec2(0, 0));
tcoords->push_back(osg::Vec2(width, 0));
tcoords->push_back(osg::Vec2(width, height));
tcoords->push_back(osg::Vec2(0, height));
osg::ref_ptr<osg::StateSet> geomss[4]; // stateset where we can attach textures
osg::ref_ptr<osg::TextureRectangle> texture[4];
for (int i=0;i<4;i++) {
osg::ref_ptr<osg::Vec3Array> vcoords = new osg::Vec3Array; // vertex coords
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
// tile the quads on the screen
// 2 3
// 0 1
int xoff, zoff;
xoff = (i%2);
zoff = i>1 ? 1 : 0;
// initial viewer camera looks along y
vcoords->push_back(osg::Vec3d(0+(xoff * width), 0, 0+(zoff * height)));
vcoords->push_back(osg::Vec3d(width+(xoff * width), 0, 0+(zoff * height)));
vcoords->push_back(osg::Vec3d(width+(xoff * width), 0, height+(zoff * height)));
vcoords->push_back(osg::Vec3d(0+(xoff * width), 0, height+(zoff * height)));
geom->setVertexArray(vcoords.get());
geom->setTexCoordArray(0,tcoords.get());
geom->addPrimitiveSet(da.get());
geom->setColorArray(colors.get());
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
geomss[i] = geom->getOrCreateStateSet();
geomss[i]->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
texture[i] = new osg::TextureRectangle;
texture[i]->setResizeNonPowerOfTwoHint(false);
texture[i]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
texture[i]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
geode->addDrawable(geom.get());
}
// attach the input images to the bottom textures of the view
texture[0]->setImage(left);
texture[1]->setImage(right);
geomss[0]->setTextureAttributeAndModes(0, texture[0].get(), osg::StateAttribute::ON);
geomss[1]->setTextureAttributeAndModes(0, texture[1].get(), osg::StateAttribute::ON);
topnode->addChild(geode.get());
// create the processing passes
if (single_pass) {
StereoPass *stereopass = new StereoPass(texture[0].get(), texture[1].get(),
width, height,
min_disp, max_disp, window_size);
topnode->addChild(stereopass->getRoot().get());
// attach the output of the processing to the top left geom
geomss[2]->setTextureAttributeAndModes(0,
stereopass->getOutputTexture().get(),
osg::StateAttribute::ON);
} else {
StereoMultipass *stereomp = new StereoMultipass(texture[0].get(), texture[1].get(),
width, height,
min_disp, max_disp, window_size);
topnode->addChild(stereomp->getRoot().get());
// attach the output of the processing to the top left geom
geomss[2]->setTextureAttributeAndModes(0,
stereomp->getOutputTexture().get(),
osg::StateAttribute::ON);
}
return topnode;
}
int main(int argc, char *argv[])
{
// use an ArgumentParser object to manage the program arguments.
osg::ArgumentParser arguments(&argc,argv);
// set up the usage document, in case we need to print out how to use this program.
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates a stereo matching algorithm. It uses multiple render targets and multiple passes with texture ping-pong.");
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] --left left_image --right right_image --min min_disparity --max max_disparity --window window_size");
arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
arguments.getApplicationUsage()->addCommandLineOption("--left","The left image of the stereo pair to load.");
arguments.getApplicationUsage()->addCommandLineOption("--right","The right image of the stereo pair to load.");
arguments.getApplicationUsage()->addCommandLineOption("--min","The minimum disparity to start matching pixels.");
arguments.getApplicationUsage()->addCommandLineOption("--max","The maximum disparity to stop matching pixels.");
arguments.getApplicationUsage()->addCommandLineOption("--window","The window size used to match areas around pixels.");
arguments.getApplicationUsage()->addCommandLineOption("--single","Use a single pass instead on multiple passes.");
// if user request help write it out to cout.
if (arguments.read("-h") || arguments.read("--help"))
{
arguments.getApplicationUsage()->write(std::cout);
return 1;
}
std::string leftName("");
while(arguments.read("--left", leftName)) {}
std::string rightName("");
while(arguments.read("--right", rightName)) {}
unsigned int minDisparity = 0;
while (arguments.read("--min", minDisparity)) {}
unsigned int maxDisparity = 31;
while (arguments.read("--max", maxDisparity)) {}
unsigned int windowSize = 5;
while (arguments.read("--window", windowSize)) {}
bool useSinglePass = false;
while (arguments.read("--single")) { useSinglePass = true; }
if (leftName == "" || rightName=="") {
arguments.getApplicationUsage()->write(std::cout);
return 1;
}
// load the images
osg::ref_ptr<osg::Image> leftIm = osgDB::readImageFile(leftName);
osg::ref_ptr<osg::Image> rightIm = osgDB::readImageFile(rightName);
osg::Node* scene = createScene(leftIm.get(), rightIm.get(), minDisparity, maxDisparity, windowSize, useSinglePass);
// construct the viewer.
osgViewer::Viewer viewer;
viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);
// add the stats handler
viewer.addEventHandler(new osgViewer::StatsHandler);
viewer.setSceneData(scene);
return viewer.run();
}