Commit f077f58e authored by Maksim Shabunin's avatar Maksim Shabunin

Merge pull request #711 from AmbroiseMoreau:gsoc2016_StructuredLight

parents b7dcf141 e439f26d
set(the_description "Phase Unwrapping API")
ocv_define_module(phase_unwrapping opencv_core opencv_calib3d opencv_imgproc opencv_highgui opencv_features2d opencv_rgbd WRAP python java)
Phase Unwrapping
================
OpenCV module that can be used to unwrap two-dimensional phase map.
@article{histogramUnwrapping,
title={A novel algorithm based on histogram processing of reliability for two-dimensional phase unwrapping},
author={Lei, Hai and Chang, Xin-yu and Wang, Fei and Hu, Xiao-Tang and Hu, Xiao-Dong},
journal={Optik-International Journal for Light and Electron Optics},
volume={126},
number={18},
pages={1640--1644},
year={2015},
}
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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 Intel Corporation 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.
//
//M*/
#include "opencv2/phase_unwrapping/phase_unwrapping.hpp"
#include "opencv2/phase_unwrapping/histogramphaseunwrapping.hpp"
/** @defgroup phase_unwrapping Phase Unwrapping API
Two-dimensional phase unwrapping is found in different applications like terrain elevation estimation
in synthetic aperture radar (SAR), field mapping in magnetic resonance imaging or as a way of finding
corresponding pixels in structured light reconstruction with sinusoidal patterns.
Given a phase map, wrapped between [-pi; pi], phase unwrapping aims at finding the "true" phase map
by adding the right number of 2*pi to each pixel.
The problem is straightforward for perfect wrapped phase map, but real data are usually not noise-free.
Among the different algorithms that were developed, quality-guided phase unwrapping methods are fast
and efficient. They follow a path that unwraps high quality pixels first,
avoiding error propagation from the start.
In this module, a quality-guided phase unwrapping is implemented following the approach described in @cite histogramUnwrapping .
*/
\ No newline at end of file
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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 Intel Corporation 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.
//
//M*/
#ifndef __OPENCV_HISTOGRAM_PHASE_UNWRAPPING_HPP__
#define __OPENCV_HISTOGRAM_PHASE_UNWRAPPING_HPP__
#include "opencv2/core.hpp"
#include <opencv2/imgproc.hpp>
#include "opencv2/phase_unwrapping/phase_unwrapping.hpp"
namespace cv {
namespace phase_unwrapping {
//! @addtogroup phase_unwrapping
//! @{
/** @brief Class implementing two-dimensional phase unwrapping based on @cite histogramUnwrapping
* This algorithm belongs to the quality-guided phase unwrapping methods.
* First, it computes a reliability map from second differences between a pixel and its eight neighbours.
* Reliability values lie between 0 and 16*pi*pi. Then, this reliability map is used to compute
* the reliabilities of "edges". An edge is an entity defined by two pixels that are connected
* horizontally or vertically. Its reliability is found by adding the the reliabilities of the
* two pixels connected through it. Edges are sorted in a histogram based on their reliability values.
* This histogram is then used to unwrap pixels, starting from the highest quality pixel.
* The wrapped phase map and the unwrapped result are stored in CV_32FC1 Mat.
*/
class CV_EXPORTS_W HistogramPhaseUnwrapping : public PhaseUnwrapping
{
public:
/**
* @brief Parameters of phaseUnwrapping constructor.
* @param width Phase map width.
* @param height Phase map height.
* @param histThresh Bins in the histogram are not of equal size. Default value is 3*pi*pi. The one before "histThresh" value are smaller.
* @param nbrOfSmallBins Number of bins between 0 and "histThresh". Default value is 10.
* @param nbrOfLargeBins Number of bins between "histThresh" and 32*pi*pi (highest edge reliability value). Default value is 5.
*/
struct CV_EXPORTS Params
{
Params();
int width;
int height;
float histThresh;
int nbrOfSmallBins;
int nbrOfLargeBins;
};
/**
* @brief Constructor
* @param parameters HistogramPhaseUnwrapping parameters HistogramPhaseUnwrapping::Params: width,height of the phase map and histogram characteristics.
*/
static Ptr<HistogramPhaseUnwrapping> create( const HistogramPhaseUnwrapping::Params &parameters =
HistogramPhaseUnwrapping::Params() );
/**
* @brief Get the reliability map computed from the wrapped phase map.
* @param reliabilityMap Image where the reliability map is stored.
*/
CV_WRAP
virtual void getInverseReliabilityMap( OutputArray reliabilityMap ) = 0;
};
//! @}
}
}
#endif
\ No newline at end of file
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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 Intel Corporation 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.
//
//M*/
#ifndef __OPENCV_PHASE_UNWRAPPING_HPP__
#define __OPENCV_PHASE_UNWRAPPING_HPP__
#include "opencv2/core.hpp"
namespace cv {
namespace phase_unwrapping {
//! @addtogroup phase_unwrapping
//! @{
/**
@brief Abstract base class for phase unwrapping.
*/
class CV_EXPORTS_W PhaseUnwrapping : public virtual Algorithm
{
public:
/**
* @brief Unwraps a 2D phase map.
* @param wrappedPhaseMap The wrapped phase map that needs to be unwrapped.
* @param unwrappedPhaseMap The unwrapped phase map.
* @param shadowMask Optional parameter used when some pixels do not hold any phase information in the wrapped phase map.
*/
CV_WRAP
virtual void unwrapPhaseMap( InputArray wrappedPhaseMap, OutputArray unwrappedPhaseMap,
InputArray shadowMask = noArray() ) = 0;
};
//! @}
}
}
#endif
\ No newline at end of file
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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 Intel Corporation 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.
* //
//M*/
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/phase_unwrapping.hpp>
#include <iostream>
#include <fstream>
#include <stdio.h>
using namespace cv;
using namespace std;
static const char* keys =
{
"{@inputPath | | Path of the wrapped phase map saved in a yaml file }"
"{@outputUnwrappedName | | Path of the unwrapped phase map to be saved in a yaml file and as an 8 bit png}"
};
static void help()
{
cout << "\nThis example shows how to use the \"Phase unwrapping module\" to unwrap a phase map"
" saved in a yaml file (see extra_data\\phase_unwrapping\\data\\wrappedpeaks.yml)."
" The mat name in the file should be \"phaseValue\". The result is saved in a yaml file"
" too. Two images (wrapped.png and output_name.png) are also created"
" for visualization purpose."
"\nTo call: ./example_phase_unwrapping_unwrap <input_path> <output_unwrapped_name> \n"
<< endl;
}
int main(int argc, char **argv)
{
phase_unwrapping::HistogramPhaseUnwrapping::Params params;
CommandLineParser parser(argc, argv, keys);
String inputPath = parser.get<String>(0);
String outputUnwrappedName = parser.get<String>(1);
if( inputPath.empty() || outputUnwrappedName.empty() )
{
help();
return -1;
}
FileStorage fsInput(inputPath, FileStorage::READ);
FileStorage fsOutput(outputUnwrappedName + ".yml", FileStorage::WRITE);
Mat wPhaseMap;
Mat uPhaseMap;
Mat reliabilities;
fsInput["phaseValues"] >> wPhaseMap;
fsInput.release();
params.width = wPhaseMap.cols;
params.height = wPhaseMap.rows;
Ptr<phase_unwrapping::HistogramPhaseUnwrapping> phaseUnwrapping = phase_unwrapping::HistogramPhaseUnwrapping::create(params);
phaseUnwrapping->unwrapPhaseMap(wPhaseMap, uPhaseMap);
fsOutput << "phaseValues" << uPhaseMap;
fsOutput.release();
phaseUnwrapping->getInverseReliabilityMap(reliabilities);
Mat uPhaseMap8, wPhaseMap8, reliabilities8;
wPhaseMap.convertTo(wPhaseMap8, CV_8U, 255, 128);
uPhaseMap.convertTo(uPhaseMap8, CV_8U, 1, 128);
reliabilities.convertTo(reliabilities8, CV_8U, 255,128);
imshow("reliabilities", reliabilities);
imshow("wrapped phase map", wPhaseMap8);
imshow("unwrapped phase map", uPhaseMap8);
imwrite(outputUnwrappedName + ".png", uPhaseMap8);
imwrite("reliabilities.png", reliabilities8);
bool loop = true;
while( loop )
{
char key = (char)waitKey(0);
if( key == 27 )
{
loop = false;
}
}
return 0;
}
\ No newline at end of file
This diff is collapsed.
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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 Intel Corporation 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.
//
//M*/
#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__
#include "opencv2/phase_unwrapping.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
#endif
\ No newline at end of file
#include "test_precomp.hpp"
CV_TEST_MAIN("cv")
\ No newline at end of file
#ifdef __GNUC__
# pragma GCC diagnostic ignored "-Wmissing-declarations"
# if defined __clang__ || defined __APPLE__
# pragma GCC diagnostic ignored "-Wmissing-prototypes"
# pragma GCC diagnostic ignored "-Wextra"
# endif
#endif
#ifndef __OPENCV_TEST_PRECOMP_HPP__
#define __OPENCV_TEST_PRECOMP_HPP__
#include "opencv2/ts.hpp"
#include "opencv2/phase_unwrapping.hpp"
#include <opencv2/rgbd.hpp>
#include <iostream>
#endif
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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 Intel Corporation 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.
//
//M*/
#include "test_precomp.hpp"
using namespace std;
using namespace cv;
class CV_Unwrapping : public cvtest::BaseTest
{
public:
CV_Unwrapping();
~CV_Unwrapping();
protected:
void run(int);
};
CV_Unwrapping::CV_Unwrapping(){}
CV_Unwrapping::~CV_Unwrapping(){}
void CV_Unwrapping::run( int )
{
int rows = 600;
int cols = 800;
int max = 50;
Mat ramp(rows, cols, CV_32FC1);
Mat wrappedRamp(rows, cols, CV_32FC1);
Mat unwrappedRamp;
Mat rowValues(1, cols, CV_32FC1);
Mat wrappedRowValues(1, cols, CV_32FC1);
for( int i = 0; i < cols; ++i )
{
float v = (float)i*(float)max/(float)cols;
rowValues.at<float>(0, i) = v;
wrappedRowValues.at<float>(0, i) = atan2(sin(v), cos(v));
}
for( int i = 0; i < rows; ++i )
{
rowValues.row(0).copyTo(ramp.row(i));
wrappedRowValues.row(0).copyTo(wrappedRamp.row(i));
}
phase_unwrapping::HistogramPhaseUnwrapping::Params params;
params.width = cols;
params.height = rows;
Ptr<phase_unwrapping::HistogramPhaseUnwrapping> phaseUnwrapping = phase_unwrapping::HistogramPhaseUnwrapping::create(params);
phaseUnwrapping->unwrapPhaseMap(wrappedRamp, unwrappedRamp);
for(int i = 0; i < rows; ++i )
{
for( int j = 0; j < cols; ++ j )
{
EXPECT_NEAR(ramp.at<float>(i, j), unwrappedRamp.at<float>(i, j), 0.001);
}
}
}
TEST( HistogramPhaseUnwrapping, unwrapPhaseMap )
{
CV_Unwrapping test;
test.safe_run();
}
\ No newline at end of file
Phase Unwrapping tutorial {#tutorial_unwrap_phase_map}
=======================================================
- @subpage tutorial_unwrap
_Compatibility:_ \> OpenCV 3.0.0
_Author:_ Ambroise Moreau
You will learn how to use the phase unwrapping module.
Unwrap two-dimensional phase maps {#tutorial_unwrap}
==============
Goal
----
In this tutorial, you will learn how to use the phase unwrapping module to unwrap two-dimensional phase maps. The implementation is based on @cite histogramUnwrapping.
Code
----
@include phase_unwrapping/samples/unwrap.cpp
Explanation
-----------
To use this example, wrapped phase map values should be stored in a yml file as CV_32FC1 Mat, under the name "phaseValues". Path to the data and a name to save the unwrapped phase map must be set in the command line. The results are saved with floating point precision in a yml file and as an 8-bit image for visualization purpose.
Some parameters can be chosen by the user:
- histThresh is a parameter used to divide the histogram in two parts. Bins before histThresh are smaller than the ones after histThresh. (Default value is 3*pi*pi).
- nbrOfSmallBins is the number of bins between 0 and histThresh. (Default value is 10).
- nbrOfLargeBins is the number of bins between histThresh and 32*pi*pi. (Default value is 5).
@code{.cpp}
phase_unwrapping::HistogramPhaseUnwrapping::Params params;
CommandLineParser parser(argc, argv, keys);
String inputPath = parser.get<String>(0);
String outputUnwrappedName = parser.get<String>(1);
String outputWrappedName = parser.get<String>(2);
if( inputPath.empty() || outputUnwrappedName.empty() )
{
help();
return -1;
}
FileStorage fsInput(inputPath, FileStorage::READ);
FileStorage fsOutput(outputUnwrappedName + ".yml", FileStorage::WRITE);
Mat wPhaseMap;
Mat uPhaseMap;
Mat reliabilities;
fsInput["phaseValues"] >> wPhaseMap;
fsInput.release();
params.width = wPhaseMap.cols;
params.height = wPhaseMap.rows;
Ptr<phase_unwrapping::HistogramPhaseUnwrapping> phaseUnwrapping = phase_unwrapping::HistogramPhaseUnwrapping::create(params);
@endcode
The wrapped phase map is unwrapped and the result is saved in a yml file. We can also get the reliabilities map for visualization purpose. The unwrapped phase map and the reliabilities map are converted to 8-bit images in order to be saved as png files.
@code{.cpp}
phaseUnwrapping->unwrapPhaseMap(wPhaseMap, uPhaseMap);
fsOutput << "phaseValues" << uPhaseMap;
fsOutput.release();
phaseUnwrapping->getInverseReliabilityMap(reliabilities);
Mat uPhaseMap8, wPhaseMap8, reliabilities8;
wPhaseMap.convertTo(wPhaseMap8, CV_8U, 255, 128);
uPhaseMap.convertTo(uPhaseMap8, CV_8U, 1, 128);
reliabilities.convertTo(reliabilities8, CV_8U, 255,128);
imshow("reliabilities", reliabilities);
imshow("wrapped phase map", wPhaseMap8);
imshow("unwrapped phase map", uPhaseMap8);
imwrite(outputUnwrappedName + ".png", uPhaseMap8);
imwrite("reliabilities.png", reliabilities8);
@endcode
set(the_description "Structured Light API")
ocv_define_module(structured_light opencv_core opencv_calib3d opencv_imgproc opencv_highgui opencv_features2d opencv_rgbd OPTIONAL opencv_viz WRAP python java)
ocv_define_module(structured_light opencv_core opencv_calib3d opencv_imgproc opencv_highgui opencv_features2d opencv_rgbd opencv_phase_unwrapping OPTIONAL opencv_viz WRAP python java)
......@@ -14,3 +14,13 @@
pages = {827-849},
year = {April 2004},
}
@article{faps,
title={Accurate dynamic 3D sensing with Fourier-assisted phase shifting},
author={Cong, Pengyu and Xiong, Zhiwei and Zhang, Yueyi and Zhao, Shenghui and Wu, Feng},
journal={IEEE Journal of Selected Topics in Signal Processing},
volume={9},
number={3},
pages={396--408},
year={2015},
}
......@@ -45,6 +45,7 @@
#include "opencv2/structured_light/structured_light.hpp"
#include "opencv2/structured_light/graycodepattern.hpp"
#include "opencv2/structured_light/sinusoidalpattern.hpp"
/** @defgroup structured_light Structured Light API
......
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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 Intel Corporation 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.
//
//M*/
#ifndef __OPENCV_SINUSOIDAL_PATTERN_HPP__
#define __OPENCV_SINUSOIDAL_PATTERN_HPP__
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/structured_light/structured_light.hpp"
#include <opencv2/phase_unwrapping.hpp>
#include <opencv2/calib3d.hpp>
namespace cv {
namespace structured_light {
//! @addtogroup structured_light
//! @{
//! Type of sinusoidal pattern profilometry methods.
enum{
FTP = 0,
PSP = 1,
FAPS = 2
};
/**
* @brief Class implementing Fourier transform profilometry (FTP) , phase-shifting profilometry (PSP)
* and Fourier-assisted phase-shifting profilometry (FAPS) based on @cite faps.
* This class generates sinusoidal patterns that can be used with FTP, PSP and FAPS.
*/
class CV_EXPORTS_W SinusoidalPattern : public StructuredLightPattern
{
public:
/**
* @brief Parameters of SinusoidalPattern constructor
* @param width Projector's width.
* @param height Projector's height.
* @param nbrOfPeriods Number of period along the patterns direction.
* @param shiftValue Phase shift between two consecutive patterns.
* @param methodId Allow to choose between FTP, PSP and FAPS.
* @param nbrOfPixelsBetweenMarkers Number of pixels between two consecutive markers on the same row.
* @param setMarkers Allow to set markers on the patterns.
* @param markersLocation vector used to store markers location on the patterns.
*/
struct CV_EXPORTS Params
{
Params();
int width;
int height;
int nbrOfPeriods;
float shiftValue;
int methodId;
int nbrOfPixelsBetweenMarkers;
bool horizontal;
bool setMarkers;
std::vector<Point2f> markersLocation;
};
/**
* @brief Constructor.
* @param parameters SinusoidalPattern parameters SinusoidalPattern::Params: width, height of the projector and patterns parameters.
*
*/
static Ptr<SinusoidalPattern> create( const SinusoidalPattern::Params &parameters =
SinusoidalPattern::Params() );
/**
* @brief Compute a wrapped phase map from sinusoidal patterns.
* @param patternImages Input data to compute the wrapped phase map.
* @param wrappedPhaseMap Wrapped phase map obtained through one of the three methods.
* @param shadowMask Mask used to discard shadow regions.
* @param fundamental Fundamental matrix used to compute epipolar lines and ease the matching step.
*/
CV_WRAP
virtual void computePhaseMap( InputArrayOfArrays patternImages,
OutputArray wrappedPhaseMap,
OutputArray shadowMask = noArray(),
InputArray fundamental = noArray()) = 0;
/**
* @brief Unwrap the wrapped phase map to remove phase ambiguities.
* @param wrappedPhaseMap The wrapped phase map computed from the pattern.
* @param unwrappedPhaseMap The unwrapped phase map used to find correspondences between the two devices.
* @param camSize Resolution of the camera.
* @param shadowMask Mask used to discard shadow regions.
*/
CV_WRAP
virtual void unwrapPhaseMap( InputArrayOfArrays wrappedPhaseMap,
OutputArray unwrappedPhaseMap,
cv::Size camSize,
InputArray shadowMask = noArray() ) = 0;
/**
* @brief Find correspondences between the two devices thanks to unwrapped phase maps.
* @param projUnwrappedPhaseMap Projector's unwrapped phase map.
* @param camUnwrappedPhaseMap Camera's unwrapped phase map.
* @param matches Images used to display correspondences map.
*/
CV_WRAP
virtual void findProCamMatches( InputArray projUnwrappedPhaseMap, InputArray camUnwrappedPhaseMap,
OutputArrayOfArrays matches ) = 0;
/**
* @brief compute the data modulation term.
* @param patternImages captured images with projected patterns.
* @param dataModulationTerm Mat where the data modulation term is saved.
* @param shadowMask Mask used to discard shadow regions.
*/
CV_WRAP
virtual void computeDataModulationTerm( InputArrayOfArrays patternImages,
OutputArray dataModulationTerm,
InputArray shadowMask ) = 0;
};
//! @}
}
}
#endif
\ No newline at end of file
......@@ -78,9 +78,10 @@ class CV_EXPORTS_W StructuredLightPattern : public virtual Algorithm
@note All the images must be at the same resolution.
*/
CV_WRAP
virtual bool decode( InputArrayOfArrays patternImages, OutputArray disparityMap, InputArrayOfArrays blackImages =
noArray(),
InputArrayOfArrays whiteImages = noArray(), int flags = DECODE_3D_UNDERWORLD ) const = 0;
virtual bool decode( InputArrayOfArrays patternImages, OutputArray disparityMap,
InputArrayOfArrays blackImages = noArray(),
InputArrayOfArrays whiteImages = noArray(),
int flags = DECODE_3D_UNDERWORLD ) const = 0;
};
//! @}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2015, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// 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 Intel Corporation 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.
//
//M*/
#include <opencv2/structured_light/graycodepattern.hpp>
#include <opencv2/structured_light/sinusoidalpattern.hpp>
#include <opencv2/imgcodecs.hpp>
#include "test_precomp.hpp"
using namespace std;
using namespace cv;
const string STRUCTURED_LIGHT_DIR = "structured_light";
const string FOLDER_DATA = "data";
TEST( SinusoidalPattern, unwrapPhaseMap )
{
string folder = cvtest::TS::ptr()->get_data_path() + "/" + STRUCTURED_LIGHT_DIR + "/" + FOLDER_DATA + "/";
structured_light::SinusoidalPattern::Params paramsPsp, paramsFtp, paramsFaps;
paramsFtp.methodId = 0;
paramsPsp.methodId = 1;
paramsFaps.methodId = 2;
Ptr<structured_light::SinusoidalPattern> sinusPsp = structured_light::SinusoidalPattern::create(paramsPsp);
Ptr<structured_light::SinusoidalPattern> sinusFtp = structured_light::SinusoidalPattern::create(paramsFtp);
Ptr<structured_light::SinusoidalPattern> sinusFaps = structured_light::SinusoidalPattern::create(paramsFaps);
vector<Mat> captures(3);
Mat unwrappedPhaseMapPspRef, unwrappedPhaseMapFtpRef, unwrappedPhaseMapFapsRef;
Mat shadowMask;
Mat wrappedPhaseMap, unwrappedPhaseMap, unwrappedPhaseMap8;
captures[0] = imread(folder + "capture_sin_0.jpg", IMREAD_GRAYSCALE);
captures[1] = imread(folder + "capture_sin_1.jpg", IMREAD_GRAYSCALE);
captures[2] = imread(folder + "capture_sin_2.jpg", IMREAD_GRAYSCALE);
unwrappedPhaseMapPspRef = imread(folder + "unwrappedPspTest.jpg", IMREAD_GRAYSCALE);
unwrappedPhaseMapFtpRef = imread(folder + "unwrappedFtpTest.jpg", IMREAD_GRAYSCALE);
unwrappedPhaseMapFapsRef = imread(folder + "unwrappedFapsTest.jpg", IMREAD_GRAYSCALE);
if( !captures[0].data || !captures[1].data || !captures[2].data || !unwrappedPhaseMapFapsRef.data
|| !unwrappedPhaseMapFtpRef.data || !unwrappedPhaseMapPspRef.data )
{
cerr << "invalid test data" << endl;
}
sinusPsp->computePhaseMap(captures, wrappedPhaseMap, shadowMask);
sinusPsp->unwrapPhaseMap(wrappedPhaseMap, unwrappedPhaseMap, Size(captures[0].cols, captures[1].rows), shadowMask);
unwrappedPhaseMap.convertTo(unwrappedPhaseMap8, CV_8U, 1, 128);
int sumOfDiff = 0;
int count = 0;
float ratio = 0;
for( int i = 0; i < unwrappedPhaseMap8.rows; ++i )
{
for( int j = 0; j < unwrappedPhaseMap8.cols; ++j )
{
int ref = unwrappedPhaseMapPspRef.at<uchar>(i, j);
int comp = unwrappedPhaseMap8.at<uchar>(i, j);
sumOfDiff += (ref - comp);
count ++;
}
}
ratio = (float)(sumOfDiff / count);
EXPECT_LE( ratio, 0.003 );
sinusFtp->computePhaseMap(captures, wrappedPhaseMap, shadowMask);
sinusFtp->unwrapPhaseMap(wrappedPhaseMap, unwrappedPhaseMap, Size(captures[0].cols, captures[1].rows), shadowMask);
unwrappedPhaseMap.convertTo(unwrappedPhaseMap8, CV_8U, 1, 128);
sumOfDiff = 0;
count = 0;
ratio = 0;
for( int i = 0; i < unwrappedPhaseMap8.rows; ++i )
{
for( int j = 0; j < unwrappedPhaseMap8.cols; ++j )
{
int ref = unwrappedPhaseMapFtpRef.at<uchar>(i, j);
int comp = unwrappedPhaseMap8.at<uchar>(i, j);
sumOfDiff += (ref - comp);
count ++;
}
}
ratio = (float)(sumOfDiff / count);
EXPECT_LE( ratio, 0.003 );
sinusFaps->computePhaseMap(captures, wrappedPhaseMap, shadowMask);
sinusFaps->unwrapPhaseMap(wrappedPhaseMap, unwrappedPhaseMap, Size(captures[0].cols, captures[1].rows), shadowMask);
unwrappedPhaseMap.convertTo(unwrappedPhaseMap8, CV_8U, 1, 128);
sumOfDiff = 0;
count = 0;
ratio = 0;
for( int i = 0; i < unwrappedPhaseMap8.rows; ++i )
{
for( int j = 0; j < unwrappedPhaseMap8.cols; ++j )
{
int ref = unwrappedPhaseMapFapsRef.at<uchar>(i, j);
int comp = unwrappedPhaseMap8.at<uchar>(i, j);
sumOfDiff += (ref - comp);
count ++;
}
}
ratio = (float)(sumOfDiff / count);
EXPECT_LE( ratio, 0.003 );
}
Capture Sinusoidal pattern tutorial {#tutorial_capture_sinusoidal_pattern}
=============
Goal
----
In this tutorial, you will learn how to use the sinusoidal pattern class to:
- Generate sinusoidal patterns.
- Project the generated patterns.
- Capture the projected patterns.
- Compute a wrapped phase map from these patterns using three different algorithms (Fourier Transform Profilometry, Phase Shifting Profilometry, Fourier-assisted Phase Shifting Profilometry)
- Unwrap the previous phase map.
Code
----
@include structured_light/samples/capsinpattern.cpp
Expalantion
-----------
First, the sinusoidal patterns must be generated. *SinusoidalPattern* class parameters have to be set by the user:
- projector width and height
- number of periods in the patterns
- set cross markers in the patterns (used to convert relative phase map to absolute phase map)
- patterns direction (horizontal or vertical)
- phase shift value (usually set to 2pi/3 to enable a cyclical system)
- number of pixels between two consecutive markers on the same row/column
- id of the method used to compute the phase map (FTP = 0, PSP = 1, FAPS = 2)
The user can also choose to save the patterns and the phase map.
@code{.cpp}
structured_light::SinusoidalPattern::Params params;
params.width = parser.get<int>(0);
params.height = parser.get<int>(1);
params.nbrOfPeriods = parser.get<int>(2);
params.setMarkers = parser.get<bool>(3);
params.horizontal = parser.get<bool>(4);
params.methodId = parser.get<int>(5);
params.shiftValue = static_cast<float>(2 * CV_PI / 3);
params.nbrOfPixelsBetweenMarkers = 70;
String outputPatternPath = parser.get<String>(6);
String outputWrappedPhasePath = parser.get<String>(7);
String outputUnwrappedPhasePath = parser.get<String>(8);
Ptr<structured_light::SinusoidalPattern> sinus = structured_light::SinusoidalPattern::create(params);
// Storage for patterns
vector<Mat> patterns;
//Generate sinusoidal patterns
sinus->generate(patterns);
@endcode
The number of patterns is always equal to three, no matter the method used to compute the phase map. Those three patterns are projected in a loop which is fine since the system is cyclical.
Once the patterns have been generated, the camera is opened and the patterns are projected, using fullscreen resolution. In this tutorial, a prosilica camera is used to capture gray images. When the first pattern is displayed by the projector, the user can press any key to start the projection sequence.
@code{.cpp}
VideoCapture cap(CAP_PVAPI);
if( !cap.isOpened() )
{
cout << "Camera could not be opened" << endl;
return -1;
}
cap.set(CAP_PROP_PVAPI_PIXELFORMAT, CAP_PVAPI_PIXELFORMAT_MONO8);
namedWindow("pattern", WINDOW_NORMAL);
setWindowProperty("pattern", WND_PROP_FULLSCREEN, WINDOW_FULLSCREEN);
imshow("pattern", patterns[0]);
cout << "Press any key when ready" << endl;
waitKey(0);
@endcode
In this tutorial, 30 images are projected so, each of the three patterns is projected ten times.
The "while" loop takes care of the projection process. The captured images are stored in a vector of Mat. There is a 30 ms delay between two successive captures.
When the projection is done, the user has to press "Enter" to start computing the phase maps.
@code{.cpp}
int nbrOfImages = 30;
int count = 0;
vector<Mat> img(nbrOfImages);
Size camSize(-1, -1);
while( count < nbrOfImages )
{
for(int i = 0; i < (int)patterns.size(); ++i )
{
imshow("pattern", patterns[i]);
waitKey(30);
cap >> img[count];
count += 1;
}
}
cout << "press enter when ready" << endl;
bool loop = true;
while ( loop )
{
char c = waitKey(0);
if( c == 10 )
{
loop = false;
}
}
@endcode
The phase maps are ready to be computed according to the selected method.
For FTP, a phase map is computed for each projected pattern, but we need to compute the shadow mask from three successive patterns, as explained in @cite faps. Therefore, three patterns are set in a vector called captures. Care is taken to fill this vector with three patterns, especially when we reach the last captures. The unwrapping algorithm needs to know the size of the captured images so, we make sure to give it to the "unwrapPhaseMap" method.
The phase maps are converted to 8-bit images in order to save them as png.
@code{.cpp}
switch(params.methodId)
{
case structured_light::FTP:
for( int i = 0; i < nbrOfImages; ++i )
{
/*We need three images to compute the shadow mask, as described in the reference paper
* even if the phase map is computed from one pattern only
*/
vector<Mat> captures;
if( i == nbrOfImages - 2 )
{
captures.push_back(img[i]);
captures.push_back(img[i-1]);
captures.push_back(img[i+1]);
}
else if( i == nbrOfImages - 1 )
{
captures.push_back(img[i]);
captures.push_back(img[i-1]);
captures.push_back(img[i-2]);
}
else
{
captures.push_back(img[i]);
captures.push_back(img[i+1]);
captures.push_back(img[i+2]);
}
sinus->computePhaseMap(captures, wrappedPhaseMap, shadowMask);
if( camSize.height == -1 )
{
camSize.height = img[i].rows;
camSize.width = img[i].cols;
}
sinus->unwrapPhaseMap(wrappedPhaseMap, unwrappedPhaseMap, camSize, shadowMask);
unwrappedPhaseMap.convertTo(unwrappedPhaseMap8, CV_8U, 1, 128);
wrappedPhaseMap.convertTo(wrappedPhaseMap8, CV_8U, 255, 128);
if( !outputUnwrappedPhasePath.empty() )
{
ostringstream name;
name << i;
imwrite(outputUnwrappedPhasePath + "_FTP_" + name.str() + ".png", unwrappedPhaseMap8);
}
if( !outputWrappedPhasePath.empty() )
{
ostringstream name;
name << i;
imwrite(outputWrappedPhasePath + "_FTP_" + name.str() + ".png", wrappedPhaseMap8);
}
}
break;
@endcode
For PSP and FAPS, three projected images are used to compute a single phase map. These three images are set in "captures", a vector working as a FIFO.Here again, phase maps are converted to 8-bit images in order to save them as png.
@code{.cpp}
case structured_light::PSP:
case structured_light::FAPS:
for( int i = 0; i < nbrOfImages - 2; ++i )
{
vector<Mat> captures;
captures.push_back(img[i]);
captures.push_back(img[i+1]);
captures.push_back(img[i+2]);
sinus->computePhaseMap(captures, wrappedPhaseMap, shadowMask);
if( camSize.height == -1 )
{
camSize.height = img[i].rows;
camSize.width = img[i].cols;
}
sinus->unwrapPhaseMap(wrappedPhaseMap, unwrappedPhaseMap, camSize, shadowMask);
unwrappedPhaseMap.convertTo(unwrappedPhaseMap8, CV_8U, 1, 128);
wrappedPhaseMap.convertTo(wrappedPhaseMap8, CV_8U, 255, 128);
if( !outputUnwrappedPhasePath.empty() )
{
ostringstream name;
name << i;
if( params.methodId == structured_light::PSP )
imwrite(outputUnwrappedPhasePath + "_PSP_" + name.str() + ".png", unwrappedPhaseMap8);
else
imwrite(outputUnwrappedPhasePath + "_FAPS_" + name.str() + ".png", unwrappedPhaseMap8);
}
if( !outputWrappedPhasePath.empty() )
{
ostringstream name;
name << i;
if( params.methodId == structured_light::PSP )
imwrite(outputWrappedPhasePath + "_PSP_" + name.str() + ".png", wrappedPhaseMap8);
else
imwrite(outputWrappedPhasePath + "_FAPS_" + name.str() + ".png", wrappedPhaseMap8);
}
}
break;
@endcode
......@@ -16,3 +16,11 @@ Structured Light tutorials {#tutorial_structured_light}
_Author:_ Roberta Ravanelli
You will learn how to decode a previously acquired Gray code pattern, generating a pointcloud.
- @subpage tutorial_capture_sinusoidal_pattern
_Compatibility:_ \> OpenCV 3.0.0
_Author:_ Ambroise Moreau
You will learn how to compute phase maps using *SinusoidalPattern* class.
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