added the SGBM and asserts in bm

removed warnings

clip tab warning fixed

fixed tab size warning

added a new sample

the new sample

fixed spacing problem

added a testing for the penalties

fixed sample warning

fixed last warnings

added tests and modified a bit the sources

added the tests

fixed warning

removed redundant samples

Rename Sample3.cpp to sample.cpp

renamed from Sample3 to sample

refactored sample

repaired descriptor test

added test data

usless info erased from test block matching

added last tests

did some modifications to the files

whitespace removal

did some modifications to the testing files

fixed test descriptor issue

Revert "whitespace removal"

This reverts commit 76d4aa530fee8f7444de6c80ecb4fc9c80ec0677.

corrected part of the comments

made modifications so the sources build successfully

fixed some issue for sub pixel

refactored sample

fixed small issue at testing

added some performance files

performance tests and other corrections

corrected the paths and added some images

fixed a bug

Delete imgKitty.bmp

Delete imgKittyl.bmp

performance tests again....

added larger images

fixed issues

did some last changes

added the copyright notice

fixed some linux errors
pull/326/head
Muresan Mircea Paul 10 years ago
parent 707beb3ff6
commit a102eeb1e7
  1. 2
      modules/README.md
  2. 31
      modules/stereo/include/opencv2/stereo.hpp
  3. 118
      modules/stereo/perf/perf_bm.cpp
  4. 143
      modules/stereo/perf/perf_descriptor.cpp
  5. 44
      modules/stereo/perf/perf_main.cpp
  6. 32
      modules/stereo/perf/perf_precomp.hpp
  7. 78
      modules/stereo/samples/Sample1.cpp
  8. 61
      modules/stereo/samples/Sample2.cpp
  9. 185
      modules/stereo/samples/sample.cpp
  10. 18
      modules/stereo/src/descriptor.cpp
  11. 16
      modules/stereo/src/descriptor.hpp
  12. 89
      modules/stereo/src/matching.hpp
  13. 63
      modules/stereo/src/stereo_binary_bm.cpp
  14. 402
      modules/stereo/src/stereo_binary_sgbm.cpp
  15. 238
      modules/stereo/test/test_block_matching.cpp
  16. 466
      modules/stereo/test/test_descriptors.cpp
  17. 5
      modules/stereo/test/test_precomp.hpp
  18. BIN
      modules/stereo/testdata/groundtruth.bmp
  19. BIN
      modules/stereo/testdata/imL2.bmp
  20. BIN
      modules/stereo/testdata/imL2l.bmp
  21. BIN
      modules/stereo/testdata/imgKitty.bmp
  22. BIN
      modules/stereo/testdata/imgKittyl.bmp
  23. BIN
      modules/stereo/testdata/rezult0.bmp
  24. BIN
      modules/stereo/testdata/rezult0l.bmp

@ -52,4 +52,4 @@ $ cmake -D OPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules -D BUILD_opencv_re
22. **opencv_xphoto**: Additional photo processing algorithms: Color balance / Denoising / Inpainting.
23. **opencv_stereo**: Stereo Correspondence done with different descriptors: Census / CS-Census / MCT / BRIEF / MV / RT.
23. **opencv_stereo**: Stereo Correspondence done with different descriptors: Census / CS-Census / MCT / BRIEF / MV.

@ -59,14 +59,10 @@ namespace cv
{
namespace stereo
{
//! @addtogroup stereo
//! @{
// void correctMatches( InputArray F, InputArray points1, InputArray points2,
// OutputArray newPoints1, OutputArray newPoints2 );
enum {
CV_SPECKLE_REMOVAL_ALGORITHM, CV_SPECKLE_REMOVAL_AVG_ALGORITHM
};
/** @brief Filters off small noise blobs (speckles) in the disparity map
@param img The input 16-bit signed disparity image
@param newVal The disparity value used to paint-off the speckles
@ -117,8 +113,14 @@ namespace cv
virtual void setDisp12MaxDiff(int disp12MaxDiff) = 0;
};
//!speckle removal algorithms. These algorithms have the purpose of removing small regions
enum {
CV_SPECKLE_REMOVAL_ALGORITHM, CV_SPECKLE_REMOVAL_AVG_ALGORITHM
};
//!subpixel interpolationm methods for disparities.
enum{
CV_QUADRATIC_INTERPOLATION, CV_SIMETRICV_INTERPOLATION
};
/** @brief Class for computing stereo correspondence using the block matching algorithm, introduced and
contributed to OpenCV by K. Konolige.
*/
@ -174,7 +176,7 @@ namespace cv
The function create StereoBM object. You can then call StereoBM::compute() to compute disparity for
a specific stereo pair.
*/
CV_EXPORTS static Ptr< cv::stereo::StereoBinaryBM > create(int numDisparities = 0, int blockSize = 21);
CV_EXPORTS static Ptr< cv::stereo::StereoBinaryBM > create(int numDisparities = 0, int blockSize = 9);
};
/** @brief The class implements the modified H. Hirschmuller algorithm @cite HH08 that differs from the original
@ -219,6 +221,15 @@ namespace cv
virtual int getMode() const = 0;
virtual void setMode(int mode) = 0;
virtual int getSpekleRemovalTechnique() const = 0 ;
virtual void setSpekleRemovalTechnique(int factor) = 0;
virtual int getBinaryKernelType() const = 0;
virtual void setBinaryKernelType(int value) = 0;
virtual int getSubPixelInterpolationMethod() const = 0;
virtual void setSubPixelInterpolationMethod(int value) = 0;
/** @brief Creates StereoSGBM object
@param minDisparity Minimum possible disparity value. Normally, it is zero but sometimes
@ -257,9 +268,9 @@ namespace cv
to a custom value.
*/
CV_EXPORTS static Ptr<cv::stereo::StereoBinarySGBM> create(int minDisparity, int numDisparities, int blockSize,
int P1 = 100, int P2 = 1000, int disp12MaxDiff = 0,
int preFilterCap = 0, int uniquenessRatio = 0,
int speckleWindowSize = 0, int speckleRange = 0,
int P1 = 100, int P2 = 1000, int disp12MaxDiff = 1,
int preFilterCap = 0, int uniquenessRatio = 5,
int speckleWindowSize = 400, int speckleRange = 200,
int mode = StereoBinarySGBM::MODE_SGBM);
};
//! @}

@ -0,0 +1,118 @@
/*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) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., 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 "perf_precomp.hpp"
using namespace std;
using namespace cv;
using namespace cv::stereo;
using namespace perf;
typedef std::tr1::tuple<Size, MatType, MatDepth> s_bm_test_t;
typedef perf::TestBaseWithParam<s_bm_test_t> s_bm;
PERF_TEST_P( s_bm, sgm_perf,
testing::Combine(
testing::Values( cv::Size(512, 283), cv::Size(320, 240)),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_8UC1,CV_8U,CV_16S )
)
)
{
Size sz = std::tr1::get<0>(GetParam());
int matType = std::tr1::get<1>(GetParam());
int sdepth = std::tr1::get<2>(GetParam());
Mat left(sz, matType);
Mat right(sz, matType);
Mat out1(sz, sdepth);
Ptr<StereoBinarySGBM> sgbm = StereoBinarySGBM::create(0, 16, 5);
sgbm->setBinaryKernelType(CV_DENSE_CENSUS);
declare.in(left, WARMUP_RNG)
.out(out1)
.time(0.1)
.iterations(20);
TEST_CYCLE()
{
sgbm->compute(left, right, out1);
}
SANITY_CHECK(out1);
}
PERF_TEST_P( s_bm, bm_perf,
testing::Combine(
testing::Values( cv::Size(512, 383), cv::Size(320, 240) ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_8UC1,CV_8U )
)
)
{
Size sz = std::tr1::get<0>(GetParam());
int matType = std::tr1::get<1>(GetParam());
int sdepth = std::tr1::get<2>(GetParam());
Mat left(sz, matType);
Mat right(sz, matType);
Mat out1(sz, sdepth);
Ptr<StereoBinaryBM> sbm = StereoBinaryBM::create(16, 9);
// we set the corresponding parameters
sbm->setPreFilterCap(31);
sbm->setMinDisparity(0);
sbm->setTextureThreshold(10);
sbm->setUniquenessRatio(0);
sbm->setSpeckleWindowSize(400);
sbm->setDisp12MaxDiff(0);
sbm->setAgregationWindowSize(11);
// the user can choose between the average speckle removal algorithm or
// the classical version that was implemented in OpenCV
sbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM);
sbm->setUsePrefilter(false);
declare.in(left, WARMUP_RNG)
.out(out1)
.time(0.1)
.iterations(20);
TEST_CYCLE()
{
sbm->compute(left, right, out1);
}
SANITY_CHECK(out1);
}

@ -0,0 +1,143 @@
/*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) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., 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 "perf_precomp.hpp"
using namespace std;
using namespace cv;
using namespace cv::stereo;
using namespace perf;
typedef std::tr1::tuple<Size, MatType, MatDepth> descript_params_t;
typedef perf::TestBaseWithParam<descript_params_t> descript_params;
PERF_TEST_P( descript_params, census_sparse_descriptor,
testing::Combine(
testing::Values( TYPICAL_MAT_SIZES ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_32SC4,CV_32S )
)
)
{
Size sz = std::tr1::get<0>(GetParam());
int matType = std::tr1::get<1>(GetParam());
int sdepth = std::tr1::get<2>(GetParam());
Mat left(sz, matType);
Mat out1(sz, sdepth);
declare.in(left, WARMUP_RNG)
.out(out1)
.time(0.01);
TEST_CYCLE()
{
censusTransform(left,9,out1,CV_SPARSE_CENSUS);
}
SANITY_CHECK(out1);
}
PERF_TEST_P( descript_params, star_census_transform,
testing::Combine(
testing::Values( TYPICAL_MAT_SIZES ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_32SC4,CV_32S )
)
)
{
Size sz = std::tr1::get<0>(GetParam());
int matType = std::tr1::get<1>(GetParam());
int sdepth = std::tr1::get<2>(GetParam());
Mat left(sz, matType);
Mat out1(sz, sdepth);
declare.in(left, WARMUP_RNG)
.out(out1)
.time(0.01);
TEST_CYCLE()
{
starCensusTransform(left,9,out1);
}
SANITY_CHECK(out1);
}
PERF_TEST_P( descript_params, modified_census_transform,
testing::Combine(
testing::Values( TYPICAL_MAT_SIZES ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_32SC4,CV_32S )
)
)
{
Size sz = std::tr1::get<0>(GetParam());
int matType = std::tr1::get<1>(GetParam());
int sdepth = std::tr1::get<2>(GetParam());
Mat left(sz, matType);
Mat out1(sz, sdepth);
declare.in(left, WARMUP_RNG)
.out(out1)
.time(0.01);
TEST_CYCLE()
{
modifiedCensusTransform(left,9,out1,CV_MODIFIED_CENSUS_TRANSFORM);
}
SANITY_CHECK(out1);
}
PERF_TEST_P( descript_params, center_symetric_census,
testing::Combine(
testing::Values( TYPICAL_MAT_SIZES ),
testing::Values( CV_8UC1,CV_8U ),
testing::Values( CV_32SC4,CV_32S )
)
)
{
Size sz = std::tr1::get<0>(GetParam());
int matType = std::tr1::get<1>(GetParam());
int sdepth = std::tr1::get<2>(GetParam());
Mat left(sz, matType);
Mat out1(sz, sdepth);
declare.in(left, WARMUP_RNG)
.out(out1)
.time(0.01);
TEST_CYCLE()
{
symetricCensusTransform(left,7,out1,CV_CS_CENSUS);
}
SANITY_CHECK(out1);
}

@ -0,0 +1,44 @@
/*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) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., 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 "perf_precomp.hpp"
CV_PERF_TEST_MAIN(stereo)

@ -0,0 +1,32 @@
#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_PERF_PRECOMP_HPP__
#define __OPENCV_PERF_PRECOMP_HPP__
#include <iostream>
#include "opencv2/ts.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/stereo.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features2d.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/core/private.hpp"
#include "opencv2/core/cvdef.h"
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/calib3d.hpp"
#include <algorithm>
#include <cmath>
#ifdef GTEST_CREATE_SHARED_LIBRARY
#error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined
#endif
#endif

@ -1,78 +0,0 @@
#include <iostream>
#include "opencv2/stereo.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace stereo;
using namespace std;
//in this example we will load a sequence of images from a file process them and display the result on the screen
//the descriptor used is the modified_census transform
int main(int, char**)
{
//begin the program
cout << " Running Main function \n";
//declare 2 images
Mat image1, image2;
// -- 1. Call the constructor for StereoBinaryBM
int ndisparities = 32; /**< Range of disparity */
int kernelSize = 9; /**< Size of the block window. Must be odd */
Ptr<StereoBinaryBM> sbm = StereoBinaryBM::create(ndisparities, kernelSize);
// -- 2. Set parameters
sbm->setPreFilterCap(31);
sbm->setMinDisparity(0);
sbm->setTextureThreshold(10);
sbm->setUniquenessRatio(0);
sbm->setSpeckleWindowSize(400);//speckle size
sbm->setSpeckleRange(200);
sbm->setDisp12MaxDiff(0);
sbm->setScalleFactor(4);//the scalling factor
sbm->setBinaryKernelType(CV_MODIFIED_CENSUS_TRANSFORM);//binary descriptor kernel
sbm->setAgregationWindowSize(9);
sbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM);//speckle removal algorithm
sbm->setUsePrefilter(false);//prefilter or not the images prior to making the transformations
for(int i = 0 ; i < 200; i++)
{
string path = "D:\\WorkingSec";
string left = "l.bmp";
string right = ".bmp";
std::string s;
std::stringstream out;
out << i;
s = out.str();
string finLeft = path + "\\rezult" + s + left;
string finRigth = path + "\\rezult" + s + right;
image1 = imread(finLeft, CV_8UC1);
image2 = imread(finRigth, CV_8UC1);
//set a certain region of interest
Rect region_of_interest = Rect(0, 20, image1.cols, (image1.rows - 20 - 110));
Mat imgLeft = image1(region_of_interest);
Mat imgRight = image2(region_of_interest);
Mat imgDisparity8U = Mat(imgLeft.rows, imgLeft.cols, CV_8UC1);
if (imgLeft.empty() || imgRight.empty())
{
std::cout << " --(!) Error reading images \n" ; return -1;
}
////-- 3. Calculate the disparity image
sbm->compute(imgLeft, imgRight, imgDisparity8U);
imshow("RealImage", image1);
imshow("Disparity", imgDisparity8U);
waitKey(1);
}
waitKey(0);
return 0;
}

@ -1,61 +0,0 @@
#include <iostream>
#include "opencv2/stereo.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
using namespace cv;
using namespace stereo;
using namespace std;
int main(int, char**)
{
//begin the program
cout << " Running Main function \n";
//declare 2 images
Mat image1, image2;
// -- 1. Call the constructor for StereoBinaryBM
int ndisparities = 32; /**< Range of disparity */
int kernelSize = 9; /**< Size of the block window. Must be odd */
Ptr<StereoBinaryBM> sbm = StereoBinaryBM::create(ndisparities, kernelSize);
// -- 2. Set parameters
sbm->setPreFilterCap(31);
sbm->setMinDisparity(0);
sbm->setTextureThreshold(10);
sbm->setUniquenessRatio(0);
sbm->setSpeckleWindowSize(400);//speckle size
sbm->setSpeckleRange(200);
sbm->setDisp12MaxDiff(0);
sbm->setScalleFactor(4);//the scalling factor
sbm->setBinaryKernelType(CV_MEAN_VARIATION);//binary descriptor kernel
sbm->setAgregationWindowSize(9);
sbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM);//speckle removal algorithm
sbm->setUsePrefilter(false);//prefilter or not the images prior to making the transformations
//load 2 images from disc
image1 = imread("D:\\rezult0l.bmp", CV_8UC1);
image2 = imread("D:\\rezult0.bmp", CV_8UC1);
//set a certain region of interest
Rect region_of_interest = Rect(0, 20, image1.cols, (image1.rows - 20 - 110));
Mat imgLeft = image1(region_of_interest);
Mat imgRight = image2(region_of_interest);
Mat imgDisparity8U = Mat(imgLeft.rows, imgLeft.cols, CV_8UC1);
if (imgLeft.empty() || imgRight.empty())
{
std::cout << " --(!) Error reading images \n" ; return -1;
}
////-- 3. Calculate the disparity image
sbm->compute(imgLeft, imgRight, imgDisparity8U);
imshow("RealImage", image1);
imshow("Disparity", imgDisparity8U);
waitKey(0);
return 0;
}

@ -0,0 +1,185 @@
#include "opencv2/stereo.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::stereo;
enum { STEREO_BINARY_BM, STEREO_BINARY_SGM };
static cv::CommandLineParser parse_argument_values(int argc, char **argv, string &left, string &right, int &kernel_size, int &number_of_disparities,
int &aggregation_window, int &P1, int &P2, float &scale, int &algo, int &binary_descriptor_type);
int main(int argc, char** argv)
{
string left, right;
int kernel_size = 0, number_of_disparities = 0, aggregation_window = 0, P1 = 0, P2 = 0;
float scale = 4;
int algo = STEREO_BINARY_BM;
int binary_descriptor_type = 0;
// here we extract the values that were added as arguments
// we also test to see if they are provided correcly
cv::CommandLineParser parser =
parse_argument_values(argc, argv, left, right,
kernel_size,
number_of_disparities,
aggregation_window,
P1, P2,
scale,
algo, binary_descriptor_type);
if (!parser.check())
{
parser.printMessage();
return 1;
}
int fail = 0;
//TEST if the provided parameters are correct
if(binary_descriptor_type == CV_DENSE_CENSUS && kernel_size > 5)
{
cout << "For the dense census transform the maximum kernel size should be 5\n";
fail = 1;
}
if((binary_descriptor_type == CV_MEAN_VARIATION || binary_descriptor_type == CV_MODIFIED_CENSUS_TRANSFORM || binary_descriptor_type == CV_STAR_KERNEL) && kernel_size != 9)
{
cout <<" For Mean variation and the modified census transform the kernel size should be equal to 9\n";
fail = 1;
}
if((binary_descriptor_type == CV_CS_CENSUS || binary_descriptor_type == CV_MODIFIED_CS_CENSUS) && kernel_size > 7)
{
cout << " The kernel size should be smaller or equal to 7 for the CS census and modified center symetric census\n";
fail = 1;
}
if(binary_descriptor_type == CV_SPARSE_CENSUS && kernel_size > 11)
{
cout << "The kernel size for the sparse census must be smaller or equal to 11\n";
fail = 1;
}
if(number_of_disparities < 10)
{
cout << "Number of disparities should be greater than 10\n";
fail = 1;
}
if(P2 / P1 < 2)
{
cout << "You should probabilly choose a greater P2 penalty\n";
fail = 1;
}
if(fail == 1)
{
return 1;
}
// verify if the user inputs the correct number of parameters
Mat image1, image2;
// we read a pair of images from the disk
image1 = imread(left, CV_8UC1);
image2 = imread(right, CV_8UC1);
// verify if they are loaded correctly
if (image1.empty() || image2.empty())
{
cout << " --(!) Error reading images \n";
parser.printMessage();
return 1;
}
// we display the parsed parameters
const char *b[7] = { "CV_DENSE_CENSUS", "CV_SPARSE_CENSUS", "CV_CS_CENSUS", "CV_MODIFIED_CS_CENSUS",
"CV_MODIFIED_CENSUS_TRANSFORM", "CV_MEAN_VARIATION", "CV_STAR_KERNEL" };
cout << "Program Name: " << argv[0];
cout << "\nPath to left image " << left << " \n" << "Path to right image " << right << "\n";
cout << "\nkernel size " << kernel_size << "\n"
<< "numberOfDisparities " << number_of_disparities << "\n"
<< "aggregationWindow " << aggregation_window << "\n"
<< "scallingFactor " << scale << "\n" << "Descriptor name : " << b[binary_descriptor_type] << "\n";
Mat imgDisparity16S2 = Mat(image1.rows, image1.cols, CV_16S);
Mat imgDisparity8U2 = Mat(image1.rows, image1.cols, CV_8UC1);
imshow("Original Left image", image1);
if (algo == STEREO_BINARY_BM)
{
Ptr<StereoBinaryBM> sbm = StereoBinaryBM::create(number_of_disparities, kernel_size);
// we set the corresponding parameters
sbm->setPreFilterCap(31);
sbm->setMinDisparity(0);
sbm->setTextureThreshold(10);
sbm->setUniquenessRatio(0);
sbm->setSpeckleWindowSize(400); // speckle size
sbm->setSpeckleRange(200);
sbm->setDisp12MaxDiff(0);
sbm->setScalleFactor((int)scale); // the scaling factor
sbm->setBinaryKernelType(binary_descriptor_type); // binary descriptor kernel
sbm->setAgregationWindowSize(aggregation_window);
// the user can choose between the average speckle removal algorithm or
// the classical version that was implemented in OpenCV
sbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM);
sbm->setUsePrefilter(false);
//-- calculate the disparity image
sbm->compute(image1, image2, imgDisparity8U2);
imshow("Disparity", imgDisparity8U2);
}
else if (algo == STEREO_BINARY_SGM)
{
// we set the corresponding parameters
Ptr<StereoBinarySGBM> sgbm = StereoBinarySGBM::create(0, number_of_disparities, kernel_size);
// setting the penalties for sgbm
sgbm->setP1(P1);
sgbm->setP2(P2);
sgbm->setMinDisparity(0);
sgbm->setUniquenessRatio(5);
sgbm->setSpeckleWindowSize(400);
sgbm->setSpeckleRange(0);
sgbm->setDisp12MaxDiff(1);
sgbm->setBinaryKernelType(binary_descriptor_type);
sgbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM);
sgbm->setSubPixelInterpolationMethod(CV_SIMETRICV_INTERPOLATION);
sgbm->compute(image1, image2, imgDisparity16S2);
/*Alternative for scalling
imgDisparity16S2.convertTo(imgDisparity8U2, CV_8UC1, scale);
*/
double minVal; double maxVal;
minMaxLoc(imgDisparity16S2, &minVal, &maxVal);
imgDisparity16S2.convertTo(imgDisparity8U2, CV_8UC1, 255 / (maxVal - minVal));
//show the disparity image
imshow("Windowsgm", imgDisparity8U2);
}
waitKey(0);
return 0;
}
static cv::CommandLineParser parse_argument_values(int argc, char **argv, string &left, string &right, int &kernel_size, int &number_of_disparities,
int &aggregation_window, int &P1, int &P2, float &scale, int &algo, int &binary_descriptor_type)
{
static const char* keys =
"{ @left | | }"
"{ @right | | }"
"{ k kernel_size | 9 | }"
"{ d disparity | 128 | }"
"{ w aggregation_window | 9 | }"
"{ P1 | 100 | }"
"{ P2 | 1000 | }"
"{ b binary_descriptor | 4 | Index of the descriptor type:\n 0 - CV_DENSE_CENSUS,\n 1 - CV_SPARSE_CENSUS,\n 2 - CV_CS_CENSUS,\n 3 - CV_MODIFIED_CS_CENSUS,\n 4 - CV_MODIFIED_CENSUS_TRANSFORM,\n 5 - CV_MEAN_VARIATION,\n 6 - CV_STAR_KERNEL}"
"{ s scale | 1.01593 | }"
"{ a algorithm | sgm | }"
;
cv::CommandLineParser parser( argc, argv, keys );
left = parser.get<string>(0);
right = parser.get<string>(1);
kernel_size = parser.get<int>("kernel_size");
number_of_disparities = parser.get<int>("disparity");
aggregation_window = parser.get<int>("aggregation_window");
P1 = parser.get<int>("P1");
P2 = parser.get<int>("P2");
binary_descriptor_type = parser.get<int>("binary_descriptor");
scale = parser.get<float>("scale");
algo = parser.get<string>("algorithm") == "sgm" ? STEREO_BINARY_SGM : STEREO_BINARY_BM;
parser.about("\nDemo stereo matching converting L and R images into disparity images using BM and SGBM\n");
return parser;
}

@ -52,7 +52,7 @@ namespace cv
{
//function that performs the census transform on two images.
//Two variants of census are offered a sparse version whcih takes every second pixel as well as dense version
void censusTransform(const Mat &image1, const Mat &image2, int kernelSize, Mat &dist1, Mat &dist2, const int type)
CV_EXPORTS void censusTransform(const Mat &image1, const Mat &image2, int kernelSize, Mat &dist1, Mat &dist2, const int type)
{
CV_Assert(image1.size() == image2.size());
CV_Assert(kernelSize % 2 != 0);
@ -75,7 +75,7 @@ namespace cv
}
}
//function that performs census on one image
void censusTransform(const Mat &image1, int kernelSize, Mat &dist1, const int type)
CV_EXPORTS void censusTransform(const Mat &image1, int kernelSize, Mat &dist1, const int type)
{
CV_Assert(image1.size() == dist1.size());
CV_Assert(kernelSize % 2 != 0);
@ -98,7 +98,7 @@ namespace cv
}
}
//in a 9x9 kernel only certain positions are choosen for comparison
void starCensusTransform(const Mat &img1, const Mat &img2, int kernelSize, Mat &dist1, Mat &dist2)
CV_EXPORTS void starCensusTransform(const Mat &img1, const Mat &img2, int kernelSize, Mat &dist1, Mat &dist2)
{
CV_Assert(img1.size() == img2.size());
CV_Assert(kernelSize % 2 != 0);
@ -110,7 +110,7 @@ namespace cv
parallel_for_(Range(n2, img1.rows - n2), StarKernelCensus<2>(images, n2,date));
}
//single version of star census
void starCensusTransform(const Mat &img1, int kernelSize, Mat &dist)
CV_EXPORTS void starCensusTransform(const Mat &img1, int kernelSize, Mat &dist)
{
CV_Assert(img1.size() == dist.size());
CV_Assert(kernelSize % 2 != 0);
@ -126,7 +126,7 @@ namespace cv
//the sencond modified census transform is invariant to noise; i.e.
//if the current pixel with whom we are dooing the comparison is a noise, this descriptor will provide a better result by comparing with the mean of the window
//otherwise if the pixel is not noise the information is strengthend
void modifiedCensusTransform(const Mat &img1, const Mat &img2, int kernelSize, Mat &dist1,Mat &dist2, const int type, int t, const Mat &IntegralImage1, const Mat &IntegralImage2 )
CV_EXPORTS void modifiedCensusTransform(const Mat &img1, const Mat &img2, int kernelSize, Mat &dist1,Mat &dist2, const int type, int t, const Mat &IntegralImage1, const Mat &IntegralImage2 )
{
CV_Assert(img1.size() == img2.size());
CV_Assert(kernelSize % 2 != 0);
@ -153,7 +153,7 @@ namespace cv
CombinedDescriptor<2,3,2,2, MVKernel<2> >(img1.cols, img1.rows,stride,n2,date,MVKernel<2>(images,integral),n2));
}
}
void modifiedCensusTransform(const Mat &img1, int kernelSize, Mat &dist, const int type, int t , Mat const &IntegralImage)
CV_EXPORTS void modifiedCensusTransform(const Mat &img1, int kernelSize, Mat &dist, const int type, int t , Mat const &IntegralImage)
{
CV_Assert(img1.size() == dist.size());
CV_Assert(kernelSize % 2 != 0);
@ -168,7 +168,7 @@ namespace cv
{
//MCT
parallel_for_(Range(n2, img1.rows - n2),
CombinedDescriptor<2,3,2, 1,MCTKernel<1> >(img1.cols, img1.rows,stride,n2,date,MCTKernel<1>(images,t),n2));
CombinedDescriptor<2,4,2, 1,MCTKernel<1> >(img1.cols, img1.rows,stride,n2,date,MCTKernel<1>(images,t),n2));
}
else if(type == CV_MEAN_VARIATION)
{
@ -180,7 +180,7 @@ namespace cv
}
//different versions of simetric census
//These variants since they do not compare with the center they are invariant to noise
void symetricCensusTransform(const Mat &img1, const Mat &img2, int kernelSize, Mat &dist1, Mat &dist2, const int type)
CV_EXPORTS void symetricCensusTransform(const Mat &img1, const Mat &img2, int kernelSize, Mat &dist1, Mat &dist2, const int type)
{
CV_Assert(img1.size() == img2.size());
CV_Assert(kernelSize % 2 != 0);
@ -202,7 +202,7 @@ namespace cv
CombinedDescriptor<1,1,1,2,ModifiedCsCensus<2> >(img1.cols, img1.rows,stride,n2,date,ModifiedCsCensus<2>(images,n2),1));
}
}
void symetricCensusTransform(const Mat &img1, int kernelSize, Mat &dist1, const int type)
CV_EXPORTS void symetricCensusTransform(const Mat &img1, int kernelSize, Mat &dist1, const int type)
{
CV_Assert(img1.size() == dist1.size());
CV_Assert(kernelSize % 2 != 0);

@ -424,26 +424,26 @@ namespace cv
Implementation of a census transform which is taking into account just the some pixels from the census kernel thus allowing for larger block sizes
**/
//void applyCensusOnImages(const cv::Mat &im1,const cv::Mat &im2, int kernelSize, cv::Mat &dist, cv::Mat &dist2, const int type);
void censusTransform(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist1, cv::Mat &dist2, const int type);
CV_EXPORTS void censusTransform(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist1, cv::Mat &dist2, const int type);
//single image census transform
void censusTransform(const cv::Mat &image1, int kernelSize, cv::Mat &dist1, const int type);
CV_EXPORTS void censusTransform(const cv::Mat &image1, int kernelSize, cv::Mat &dist1, const int type);
/**
STANDARD_MCT - Modified census which is memorizing for each pixel 2 bits and includes a tolerance to the pixel comparison
MCT_MEAN_VARIATION - Implementation of a modified census transform which is also taking into account the variation to the mean of the window not just the center pixel
**/
void modifiedCensusTransform(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist1,cv::Mat &dist2, const int type, int t = 0 , const cv::Mat &IntegralImage1 = cv::Mat::zeros(100,100,CV_8UC1), const cv::Mat &IntegralImage2 = cv::Mat::zeros(100,100,CV_8UC1));
CV_EXPORTS void modifiedCensusTransform(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist1,cv::Mat &dist2, const int type, int t = 0 , const cv::Mat &IntegralImage1 = cv::Mat::zeros(100,100,CV_8UC1), const cv::Mat &IntegralImage2 = cv::Mat::zeros(100,100,CV_8UC1));
//single version of modified census transform descriptor
void modifiedCensusTransform(const cv::Mat &img1, int kernelSize, cv::Mat &dist, const int type, int t = 0 ,const cv::Mat &IntegralImage = cv::Mat::zeros(100,100,CV_8UC1));
CV_EXPORTS void modifiedCensusTransform(const cv::Mat &img1, int kernelSize, cv::Mat &dist, const int type, int t = 0 ,const cv::Mat &IntegralImage = cv::Mat::zeros(100,100,CV_8UC1));
/**The classical center symetric census
A modified version of cs census which is comparing a pixel with its correspondent after the center
**/
void symetricCensusTransform(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist1, cv::Mat &dist2, const int type);
CV_EXPORTS void symetricCensusTransform(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist1, cv::Mat &dist2, const int type);
//single version of census transform
void symetricCensusTransform(const cv::Mat &img1, int kernelSize, cv::Mat &dist1, const int type);
CV_EXPORTS void symetricCensusTransform(const cv::Mat &img1, int kernelSize, cv::Mat &dist1, const int type);
//in a 9x9 kernel only certain positions are choosen
void starCensusTransform(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist1,cv::Mat &dist2);
CV_EXPORTS void starCensusTransform(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist1,cv::Mat &dist2);
//single image version of star kernel
void starCensusTransform(const cv::Mat &img1, int kernelSize, cv::Mat &dist);
CV_EXPORTS void starCensusTransform(const cv::Mat &img1, int kernelSize, cv::Mat &dist);
//integral image computation used in the Mean Variation Census Transform
void imageMeanKernelSize(const cv::Mat &img, int windowSize, cv::Mat &c);
}

@ -67,7 +67,7 @@ namespace cv
//!the LUT used in case SSE is not available
int hamLut[65537];
//!function used for getting the minimum disparity from the cost volume"
static int minim(int *c, int iwpj, int widthDisp,const double confidence, const int search_region)
static int minim(short *c, int iwpj, int widthDisp,const double confidence, const int search_region)
{
double mini, mini2, mini3;
mini = mini2 = mini3 = DBL_MAX;
@ -101,7 +101,7 @@ namespace cv
}
//!Interpolate in order to obtain better results
//!function for refining the disparity at sub pixel using simetric v
static double symetricVInterpolation(int *c, int iwjp, int widthDisp, int winDisp,const int search_region)
static double symetricVInterpolation(short *c, int iwjp, int widthDisp, int winDisp,const int search_region)
{
if (winDisp == 0 || winDisp == widthDisp - 1)
return winDisp;
@ -146,12 +146,13 @@ namespace cv
class hammingDistance : public ParallelLoopBody
{
private:
int *left, *right, *c;
int *left, *right;
short *c;
int v,kernelSize, width, height;
int MASK;
int *hammLut;
public :
hammingDistance(const Mat &leftImage, const Mat &rightImage, int *cost, int maxDisp, int kerSize, int *hammingLUT):
hammingDistance(const Mat &leftImage, const Mat &rightImage, short *cost, int maxDisp, int kerSize, int *hammingLUT):
left((int *)leftImage.data), right((int *)rightImage.data), c(cost), v(maxDisp),kernelSize(kerSize),width(leftImage.cols), height(leftImage.rows), MASK(65535), hammLut(hammingLUT){}
void operator()(const cv::Range &r) const {
for (int i = r.start; i <= r.end ; i++)
@ -168,63 +169,31 @@ namespace cv
j2 = (0 > j - d) ? (0) : (j - d);
xorul = left[(iwj)] ^ right[(iw + j2)];
#if CV_SSE4_1
c[(iwj)* (v + 1) + d] = _mm_popcnt_u32(xorul);
c[(iwj)* (v + 1) + d] = (short)_mm_popcnt_u32(xorul);
#else
c[(iwj)* (v + 1) + d] = hammLut[xorul & MASK] + hammLut[xorul >> 16];
c[(iwj)* (v + 1) + d] = (short)(hammLut[xorul & MASK] + hammLut[xorul >> 16]);
#endif
}
}
}
}
};
//!preprocessing used for agregation
class costGatheringHorizontal:public ParallelLoopBody
{
private:
int *c, *ham;
int width, maxDisp;
public:
costGatheringHorizontal(const Mat &hamimg,const int maxDispa, Mat &output)
{
ham = (int *)hamimg.data;
c = (int *)output.data;
maxDisp = maxDispa;
width = output.cols / ( maxDisp + 1) - 1;
}
void operator()(const cv::Range &r) const {
for (int i = r.start; i <= r.end; i++)
{
int iw = i * width;
int iwi = (i - 1) * width;
for (int j = 1; j <= width; j++)
{
int iwj = (iw + j) * (maxDisp + 1);
int iwjmu = (iw + j - 1) * (maxDisp + 1);
int iwijmu = (iwi + j - 1) * (maxDisp + 1);
for (int d = 0; d <= maxDisp; d++)
{
c[iwj + d] = ham[iwijmu + d] + c[iwjmu + d];
}
}
}
}
};
//!cost aggregation
class agregateCost:public ParallelLoopBody
{
private:
int win;
int *c, *parSum;
short *c, *parSum;
int maxDisp,width, height;
public:
agregateCost(const Mat &partialSums, int windowSize, int maxDispa, Mat &cost)
{
win = windowSize / 2;
c = (int *)cost.data;
c = (short *)cost.data;
maxDisp = maxDispa;
width = cost.cols / ( maxDisp + 1) - 1;
height = cost.rows - 1;
parSum = (int *)partialSums.data;
parSum = (short *)partialSums.data;
}
void operator()(const cv::Range &r) const {
for (int i = r.start; i <= r.end; i++)
@ -255,11 +224,11 @@ namespace cv
int width,disparity,scallingFact,th;
double confCheck;
uint8_t *map;
int *c;
short *c;
public:
makeMap(const Mat &costVolume, int threshold, int maxDisp, double confidence,int scale, Mat &mapFinal)
{
c = (int *)costVolume.data;
c = (short *)costVolume.data;
map = mapFinal.data;
disparity = maxDisp;
width = costVolume.cols / ( disparity + 1) - 1;
@ -393,6 +362,7 @@ namespace cv
int *specklePointX;
int *specklePointY;
long long *pus;
int previous_size;
//!method for setting the maximum disparity
void setMaxDisparity(int val)
{
@ -436,22 +406,37 @@ namespace cv
CV_Assert(kernelSize % 2 != 0);
CV_Assert(cost.rows == leftImage.rows);
CV_Assert(cost.cols / (maxDisparity + 1) == leftImage.cols);
int *c = (int *)cost.data;
short *c = (short *)cost.data;
memset(c, 0, sizeof(c[0]) * leftImage.cols * leftImage.rows * (maxDisparity + 1));
parallel_for_(cv::Range(kernelSize / 2,leftImage.rows - kernelSize / 2), hammingDistance(leftImage,rightImage,(int *)cost.data,maxDisparity,kernelSize / 2,hamLut));
parallel_for_(cv::Range(kernelSize / 2,leftImage.rows - kernelSize / 2), hammingDistance(leftImage,rightImage,(short *)cost.data,maxDisparity,kernelSize / 2,hamLut));
}
//preprocessing the cost volume in order to get it ready for aggregation
void costGathering(const Mat &hammingDistanceCost, Mat &cost)
{
CV_Assert(hammingDistanceCost.rows == hammingDistanceCost.rows);
CV_Assert(hammingDistanceCost.type() == CV_32SC4);
CV_Assert(cost.type() == CV_32SC4);
CV_Assert(hammingDistanceCost.type() == CV_16S);
CV_Assert(cost.type() == CV_16S);
int maxDisp = maxDisparity;
int width = cost.cols / ( maxDisp + 1) - 1;
int height = cost.rows - 1;
int *c = (int *)cost.data;
short *c = (short *)cost.data;
short *ham = (short *)hammingDistanceCost.data;
memset(c, 0, sizeof(c[0]) * (width + 1) * (height + 1) * (maxDisp + 1));
parallel_for_(cv::Range(1,height), costGatheringHorizontal(hammingDistanceCost,maxDisparity,cost));
for (int i = 1; i <= height; i++)
{
int iw = i * width;
int iwi = (i - 1) * width;
for (int j = 1; j <= width; j++)
{
int iwj = (iw + j) * (maxDisp + 1);
int iwjmu = (iw + j - 1) * (maxDisp + 1);
int iwijmu = (iwi + j - 1) * (maxDisp + 1);
for (int d = 0; d <= maxDisp; d++)
{
c[iwj + d] = ham[iwijmu + d] + c[iwjmu + d];
}
}
}
for (int i = 1; i <= height; i++)
{
for (int j = 1; j <= width; j++)
@ -472,7 +457,7 @@ namespace cv
CV_Assert(partialSums.rows == cost.rows);
CV_Assert(partialSums.cols == cost.cols);
int win = windowSize / 2;
int *c = (int *)cost.data;
short *c = (short *)cost.data;
int maxDisp = maxDisparity;
int width = cost.cols / ( maxDisp + 1) - 1;
int height = cost.rows - 1;
@ -484,8 +469,8 @@ namespace cv
{
CV_Assert(currentMap.cols == out.cols);
CV_Assert(currentMap.rows == out.rows);
CV_Assert(t > 0);
memset(pus, 0, sizeof(pus));
CV_Assert(t >= 0);
memset(pus, 0, previous_size * sizeof(pus[0]));
uint8_t *map = currentMap.data;
uint8_t *outputMap = out.data;
int height = currentMap.rows;

@ -269,7 +269,7 @@ namespace cv
class StereoBinaryBMImpl : public StereoBinaryBM, public Matching
{
public:
StereoBinaryBMImpl()
StereoBinaryBMImpl(): Matching(64)
{
params = StereoBinaryBMParams();
}
@ -322,20 +322,6 @@ namespace cv
Mat left0 = leftarr.getMat(), right0 = rightarr.getMat();
Mat disp0 = disparr.getMat();
censusImage[0].create(left0.rows,left0.cols,CV_32SC4);
censusImage[1].create(left0.rows,left0.cols,CV_32SC4);
partialSumsLR.create(left0.rows + 1,(left0.cols + 1) * (params.numDisparities + 1),CV_32SC4);
agregatedHammingLRCost.create(left0.rows + 1,(left0.cols + 1) * (params.numDisparities + 1),CV_32SC4);
hammingDistance.create(left0.rows, left0.cols * (params.numDisparities + 1),CV_32SC4);
preFilteredImg0.create(left0.size(), CV_8U);
preFilteredImg1.create(left0.size(), CV_8U);
Mat left = preFilteredImg0, right = preFilteredImg1;
int ndisp = params.numDisparities;
int width = left0.cols;
int height = left0.rows;
@ -345,8 +331,22 @@ namespace cv
specklePointX = new int[width * height];
specklePointY = new int[width * height];
pus = new long long[width * height];
censusImage[0].create(left0.rows,left0.cols,CV_32SC4);
censusImage[1].create(left0.rows,left0.cols,CV_32SC4);
partialSumsLR.create(left0.rows + 1,(left0.cols + 1) * (params.numDisparities + 1),CV_16S);
agregatedHammingLRCost.create(left0.rows + 1,(left0.cols + 1) * (params.numDisparities + 1),CV_16S);
hammingDistance.create(left0.rows, left0.cols * (params.numDisparities + 1),CV_16S);
preFilteredImg0.create(left0.size(), CV_8U);
preFilteredImg1.create(left0.size(), CV_8U);
}
Mat left = preFilteredImg0, right = preFilteredImg1;
int ndisp = params.numDisparities;
int wsz = params.kernelSize;
int bufSize0 = (int)((ndisp + 2)*sizeof(int));
bufSize0 += (int)((height + wsz + 2)*ndisp*sizeof(int));
@ -419,52 +419,52 @@ namespace cv
}
}
int getAgregationWindowSize() const { return params.agregationWindowSize;}
void setAgregationWindowSize(int value = 9) { params.agregationWindowSize = value;}
void setAgregationWindowSize(int value = 9) { CV_Assert(value % 2 != 0); params.agregationWindowSize = value;}
int getBinaryKernelType() const { return params.kernelType;}
void setBinaryKernelType(int value = CV_MODIFIED_CENSUS_TRANSFORM) { params.kernelType = value; }
void setBinaryKernelType(int value = CV_MODIFIED_CENSUS_TRANSFORM) { CV_Assert(value < 7); params.kernelType = value; }
int getSpekleRemovalTechnique() const { return params.regionRemoval;}
void setSpekleRemovalTechnique(int factor = CV_SPECKLE_REMOVAL_AVG_ALGORITHM) { params.regionRemoval = factor; }
void setSpekleRemovalTechnique(int factor = CV_SPECKLE_REMOVAL_AVG_ALGORITHM) {CV_Assert(factor < 2); params.regionRemoval = factor; }
bool getUsePrefilter() const { return params.usePrefilter;}
void setUsePrefilter(bool value = false) { params.usePrefilter = value;}
int getScalleFactor() const { return params.scalling;}
void setScalleFactor(int factor) {params.scalling = factor; setScallingFactor(factor);}
void setScalleFactor(int factor = 4) {CV_Assert(factor > 0); params.scalling = factor; setScallingFactor(factor);}
int getMinDisparity() const { return params.minDisparity; }
void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; }
void setMinDisparity(int minDisparity) {CV_Assert(minDisparity >= 0); params.minDisparity = minDisparity; }
int getNumDisparities() const { return params.numDisparities; }
void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; }
void setNumDisparities(int numDisparities) {CV_Assert(numDisparities > 0); params.numDisparities = numDisparities; }
int getBlockSize() const { return params.kernelSize; }
void setBlockSize(int blockSize) { params.kernelSize = blockSize; }
void setBlockSize(int blockSize) {CV_Assert(blockSize % 2 != 0); params.kernelSize = blockSize; }
int getSpeckleWindowSize() const { return params.speckleWindowSize; }
void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; }
void setSpeckleWindowSize(int speckleWindowSize) {CV_Assert(speckleWindowSize >= 0); params.speckleWindowSize = speckleWindowSize; }
int getSpeckleRange() const { return params.speckleRange; }
void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; }
void setSpeckleRange(int speckleRange) {CV_Assert(speckleRange >= 0); params.speckleRange = speckleRange; }
int getDisp12MaxDiff() const { return params.disp12MaxDiff; }
void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; }
void setDisp12MaxDiff(int disp12MaxDiff) {CV_Assert(disp12MaxDiff >= 0); params.disp12MaxDiff = disp12MaxDiff; }
int getPreFilterType() const { return params.preFilterType; }
void setPreFilterType(int preFilterType) { params.preFilterType = preFilterType; }
void setPreFilterType(int preFilterType) { CV_Assert(preFilterType >= 0); params.preFilterType = preFilterType; }
int getPreFilterSize() const { return params.preFilterSize; }
void setPreFilterSize(int preFilterSize) { params.preFilterSize = preFilterSize; }
void setPreFilterSize(int preFilterSize) { CV_Assert(preFilterSize >= 0); params.preFilterSize = preFilterSize; }
int getPreFilterCap() const { return params.preFilterCap; }
void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; }
void setPreFilterCap(int preFilterCap) {CV_Assert(preFilterCap >= 0); params.preFilterCap = preFilterCap; }
int getTextureThreshold() const { return params.textureThreshold; }
void setTextureThreshold(int textureThreshold) { params.textureThreshold = textureThreshold; }
void setTextureThreshold(int textureThreshold) {CV_Assert(textureThreshold >= 0); params.textureThreshold = textureThreshold; }
int getUniquenessRatio() const { return params.uniquenessRatio; }
void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; }
void setUniquenessRatio(int uniquenessRatio) {CV_Assert(uniquenessRatio >= 0); params.uniquenessRatio = uniquenessRatio; }
int getSmallerBlockSize() const { return 0; }
void setSmallerBlockSize(int) {}
@ -506,12 +506,11 @@ namespace cv
Mat preFilteredImg0, preFilteredImg1, cost, dispbuf;
Mat slidingSumBuf;
Mat parSumsIntensityImage[2];
Mat Integral[2];
Mat censusImage[2];
Mat hammingDistance;
Mat partialSumsLR;
Mat agregatedHammingLRCost;
Mat Integral[2];
int previous_size;
static const char* name_;
};

@ -47,8 +47,11 @@ by Heiko Hirschmuller.
We match blocks rather than individual pixels, thus the algorithm is called
SGBM (Semi-global block matching)
*/
#include "precomp.hpp"
#include <limits.h>
#include <descriptor.hpp>
#include <matching.hpp>
namespace cv
{
@ -58,12 +61,13 @@ namespace cv
typedef short CostType;
typedef short DispType;
enum { NR = 16, NR2 = NR/2 };
struct StereoBinarySGBMParams
{
StereoBinarySGBMParams()
{
minDisparity = numDisparities = 0;
SADWindowSize = 0;
kernelSize = 0;
P1 = P2 = 0;
disp12MaxDiff = 0;
preFilterCap = 0;
@ -79,7 +83,7 @@ namespace cv
{
minDisparity = _minDisparity;
numDisparities = _numDisparities;
SADWindowSize = _SADWindowSize;
kernelSize = _SADWindowSize;
P1 = _P1;
P2 = _P2;
disp12MaxDiff = _disp12MaxDiff;
@ -88,10 +92,13 @@ namespace cv
speckleWindowSize = _speckleWindowSize;
speckleRange = _speckleRange;
mode = _mode;
regionRemoval = 1;
kernelType = CV_MODIFIED_CENSUS_TRANSFORM;
subpixelInterpolationMethod = CV_QUADRATIC_INTERPOLATION;
}
int minDisparity;
int numDisparities;
int SADWindowSize;
int kernelSize;
int preFilterCap;
int uniquenessRatio;
int P1;
@ -100,163 +107,11 @@ namespace cv
int speckleRange;
int disp12MaxDiff;
int mode;
int regionRemoval;
int kernelType;
int subpixelInterpolationMethod;
};
/*
For each pixel row1[x], max(-maxD, 0) <= minX <= x < maxX <= width - max(0, -minD),
and for each disparity minD<=d<maxD the function
computes the cost (cost[(x-minX)*(maxD - minD) + (d - minD)]), depending on the difference between
row1[x] and row2[x-d]. The subpixel algorithm from
"Depth Discontinuities by Pixel-to-Pixel Stereo" by Stan Birchfield and C. Tomasi
is used, hence the suffix BT.
the temporary buffer should contain width2*2 elements
*/
static void calcPixelCostBT( const Mat& img1, const Mat& img2, int y,
int minD, int maxD, CostType* cost,
PixType* buffer, const PixType* tab,
int tabOfs, int )
{
int x, c, width = img1.cols, cn = img1.channels();
int minX1 = std::max(-maxD, 0), maxX1 = width + std::min(minD, 0);
int minX2 = std::max(minX1 - maxD, 0), maxX2 = std::min(maxX1 - minD, width);
int D = maxD - minD, width1 = maxX1 - minX1, width2 = maxX2 - minX2;
const PixType *row1 = img1.ptr<PixType>(y), *row2 = img2.ptr<PixType>(y);
PixType *prow1 = buffer + width2*2, *prow2 = prow1 + width*cn*2;
tab += tabOfs;
for( c = 0; c < cn*2; c++ )
{
prow1[width*c] = prow1[width*c + width-1] =
prow2[width*c] = prow2[width*c + width-1] = tab[0];
}
int n1 = y > 0 ? -(int)img1.step : 0, s1 = y < img1.rows-1 ? (int)img1.step : 0;
int n2 = y > 0 ? -(int)img2.step : 0, s2 = y < img2.rows-1 ? (int)img2.step : 0;
if( cn == 1 )
{
for( x = 1; x < width-1; x++ )
{
prow1[x] = tab[(row1[x+1] - row1[x-1])*2 + row1[x+n1+1] - row1[x+n1-1] + row1[x+s1+1] - row1[x+s1-1]];
prow2[width-1-x] = tab[(row2[x+1] - row2[x-1])*2 + row2[x+n2+1] - row2[x+n2-1] + row2[x+s2+1] - row2[x+s2-1]];
prow1[x+width] = row1[x];
prow2[width-1-x+width] = row2[x];
}
}
else
{
for( x = 1; x < width-1; x++ )
{
prow1[x] = tab[(row1[x*3+3] - row1[x*3-3])*2 + row1[x*3+n1+3] - row1[x*3+n1-3] + row1[x*3+s1+3] - row1[x*3+s1-3]];
prow1[x+width] = tab[(row1[x*3+4] - row1[x*3-2])*2 + row1[x*3+n1+4] - row1[x*3+n1-2] + row1[x*3+s1+4] - row1[x*3+s1-2]];
prow1[x+width*2] = tab[(row1[x*3+5] - row1[x*3-1])*2 + row1[x*3+n1+5] - row1[x*3+n1-1] + row1[x*3+s1+5] - row1[x*3+s1-1]];
prow2[width-1-x] = tab[(row2[x*3+3] - row2[x*3-3])*2 + row2[x*3+n2+3] - row2[x*3+n2-3] + row2[x*3+s2+3] - row2[x*3+s2-3]];
prow2[width-1-x+width] = tab[(row2[x*3+4] - row2[x*3-2])*2 + row2[x*3+n2+4] - row2[x*3+n2-2] + row2[x*3+s2+4] - row2[x*3+s2-2]];
prow2[width-1-x+width*2] = tab[(row2[x*3+5] - row2[x*3-1])*2 + row2[x*3+n2+5] - row2[x*3+n2-1] + row2[x*3+s2+5] - row2[x*3+s2-1]];
prow1[x+width*3] = row1[x*3];
prow1[x+width*4] = row1[x*3+1];
prow1[x+width*5] = row1[x*3+2];
prow2[width-1-x+width*3] = row2[x*3];
prow2[width-1-x+width*4] = row2[x*3+1];
prow2[width-1-x+width*5] = row2[x*3+2];
}
}
memset( cost, 0, width1*D*sizeof(cost[0]) );
buffer -= minX2;
cost -= minX1*D + minD; // simplify the cost indices inside the loop
#if CV_SSE2
volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2);
#endif
#if 1
for( c = 0; c < cn*2; c++, prow1 += width, prow2 += width )
{
int diff_scale = c < cn ? 0 : 2;
// precompute
// v0 = min(row2[x-1/2], row2[x], row2[x+1/2]) and
// v1 = max(row2[x-1/2], row2[x], row2[x+1/2]) and
for( x = minX2; x < maxX2; x++ )
{
int v = prow2[x];
int vl = x > 0 ? (v + prow2[x-1])/2 : v;
int vr = x < width-1 ? (v + prow2[x+1])/2 : v;
int v0 = std::min(vl, vr); v0 = std::min(v0, v);
int v1 = std::max(vl, vr); v1 = std::max(v1, v);
buffer[x] = (PixType)v0;
buffer[x + width2] = (PixType)v1;
}
for( x = minX1; x < maxX1; x++ )
{
int u = prow1[x];
int ul = x > 0 ? (u + prow1[x-1])/2 : u;
int ur = x < width-1 ? (u + prow1[x+1])/2 : u;
int u0 = std::min(ul, ur); u0 = std::min(u0, u);
int u1 = std::max(ul, ur); u1 = std::max(u1, u);
#if CV_SSE2
if( useSIMD )
{
__m128i _u = _mm_set1_epi8((char)u), _u0 = _mm_set1_epi8((char)u0);
__m128i _u1 = _mm_set1_epi8((char)u1), z = _mm_setzero_si128();
__m128i ds = _mm_cvtsi32_si128(diff_scale);
for( int d = minD; d < maxD; d += 16 )
{
__m128i _v = _mm_loadu_si128((const __m128i*)(prow2 + width-x-1 + d));
__m128i _v0 = _mm_loadu_si128((const __m128i*)(buffer + width-x-1 + d));
__m128i _v1 = _mm_loadu_si128((const __m128i*)(buffer + width-x-1 + d + width2));
__m128i c0 = _mm_max_epu8(_mm_subs_epu8(_u, _v1), _mm_subs_epu8(_v0, _u));
__m128i c1 = _mm_max_epu8(_mm_subs_epu8(_v, _u1), _mm_subs_epu8(_u0, _v));
__m128i diff = _mm_min_epu8(c0, c1);
c0 = _mm_load_si128((__m128i*)(cost + x*D + d));
c1 = _mm_load_si128((__m128i*)(cost + x*D + d + 8));
_mm_store_si128((__m128i*)(cost + x*D + d), _mm_adds_epi16(c0, _mm_srl_epi16(_mm_unpacklo_epi8(diff,z), ds)));
_mm_store_si128((__m128i*)(cost + x*D + d + 8), _mm_adds_epi16(c1, _mm_srl_epi16(_mm_unpackhi_epi8(diff,z), ds)));
}
}
else
#endif
{
for( int d = minD; d < maxD; d++ )
{
int v = prow2[width-x-1 + d];
int v0 = buffer[width-x-1 + d];
int v1 = buffer[width-x-1 + d + width2];
int c0 = std::max(0, u - v1); c0 = std::max(c0, v0 - u);
int c1 = std::max(0, v - u1); c1 = std::max(c1, u0 - v);
cost[x*D + d] = (CostType)(cost[x*D+d] + (std::min(c0, c1) >> diff_scale));
}
}
}
}
#else
for( c = 0; c < cn*2; c++, prow1 += width, prow2 += width )
{
for( x = minX1; x < maxX1; x++ )
{
int u = prow1[x];
#if CV_SSE2
if( useSIMD )
{
__m128i _u = _mm_set1_epi8(u), z = _mm_setzero_si128();
for( int d = minD; d < maxD; d += 16 )
{
__m128i _v = _mm_loadu_si128((const __m128i*)(prow2 + width-1-x + d));
__m128i diff = _mm_adds_epu8(_mm_subs_epu8(_u,_v), _mm_subs_epu8(_v,_u));
__m128i c0 = _mm_load_si128((__m128i*)(cost + x*D + d));
__m128i c1 = _mm_load_si128((__m128i*)(cost + x*D + d + 8));
_mm_store_si128((__m128i*)(cost + x*D + d), _mm_adds_epi16(c0, _mm_unpacklo_epi8(diff,z)));
_mm_store_si128((__m128i*)(cost + x*D + d + 8), _mm_adds_epi16(c1, _mm_unpackhi_epi8(diff,z)));
}
}
else
#endif
{
for( int d = minD; d < maxD; d++ )
{
int v = prow2[width-1-x + d];
cost[x*D + d] = (CostType)(cost[x*D + d] + (CostType)std::abs(u - v));
}
}
}
}
#endif
}
/*
computes disparity for "roi" in img1 w.r.t. img2 and write it to disp1buf.
that is, disp1buf(x, y)=d means that img1(x+roi.x, y+roi.y) ~ img2(x+roi.x-d, y+roi.y).
@ -276,7 +131,7 @@ namespace cv
*/
static void computeDisparityBinarySGBM( const Mat& img1, const Mat& img2,
Mat& disp1, const StereoBinarySGBMParams& params,
Mat& buffer )
Mat& buffer,const Mat& hamDist)
{
#if CV_SSE2
static const uchar LSBTab[] =
@ -293,14 +148,14 @@ namespace cv
volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2);
#endif
const int ALIGN = 16;
const int DISP_SHIFT = StereoMatcher::DISP_SHIFT;
const int DISP_SCALE = (1 << DISP_SHIFT);
const CostType MAX_COST = SHRT_MAX;
int minD = params.minDisparity, maxD = minD + params.numDisparities;
Size SADWindowSize;
SADWindowSize.width = SADWindowSize.height = params.SADWindowSize > 0 ? params.SADWindowSize : 5;
int ftzero = std::max(params.preFilterCap, 15) | 1;
Size kernelSize;
kernelSize.width = kernelSize.height = params.kernelSize > 0 ? params.kernelSize : 5;
int uniquenessRatio = params.uniquenessRatio >= 0 ? params.uniquenessRatio : 10;
int disp12MaxDiff = params.disp12MaxDiff > 0 ? params.disp12MaxDiff : 1;
int P1 = params.P1 > 0 ? params.P1 : 2, P2 = std::max(params.P2 > 0 ? params.P2 : 5, P1+1);
@ -308,13 +163,10 @@ namespace cv
int minX1 = std::max(-maxD, 0), maxX1 = width + std::min(minD, 0);
int D = maxD - minD, width1 = maxX1 - minX1;
int INVALID_DISP = minD - 1, INVALID_DISP_SCALED = INVALID_DISP*DISP_SCALE;
int SW2 = SADWindowSize.width/2, SH2 = SADWindowSize.height/2;
int SW2 = kernelSize.width/2, SH2 = kernelSize.height/2;
bool fullDP = params.mode == StereoBinarySGBM::MODE_HH;
int npasses = fullDP ? 2 : 1;
const int TAB_OFS = 256*4, TAB_SIZE = 256 + TAB_OFS*2;
PixType clipTab[TAB_SIZE];
for( k = 0; k < TAB_SIZE; k++ )
clipTab[k] = (PixType)(std::min(std::max(k - TAB_OFS, -ftzero), ftzero) + ftzero);
if( minX1 >= maxX1 )
{
disp1 = Scalar::all(INVALID_DISP_SCALED);
@ -329,6 +181,9 @@ namespace cv
// the previous row, i.e. 2 rows in total
const int NLR = 2;
const int LrBorder = NLR - 1;
int ww = img2.cols;
short *ham;
ham = (short *)hamDist.data;
// for each possible stereo match (img1(x,y) <=> img2(x-d,y))
// we keep pixel difference cost (C) and the summary cost over NR directions (S).
// we also keep all the partial costs for the previous line L_r(x,d) and also min_k L_r(x, k)
@ -351,7 +206,7 @@ namespace cv
CostType* pixDiff = hsumBuf + costBufSize*hsumBufNRows;
CostType* disp2cost = pixDiff + costBufSize + (LrSize + minLrSize)*NLR;
DispType* disp2ptr = (DispType*)(disp2cost + width);
PixType* tempBuf = (PixType*)(disp2ptr + width);
// PixType* tempBuf = (PixType*)(disp2ptr + width);
// add P2 to every C(x,y). it saves a few operations in the inner loops
for( k = 0; k < width1*D; k++ )
Cbuf[k] = (CostType)P2;
@ -393,10 +248,15 @@ namespace cv
for( k = dy1; k <= dy2; k++ )
{
CostType* hsumAdd = hsumBuf + (std::min(k, height-1) % hsumBufNRows)*costBufSize;
if( k < height )
{
calcPixelCostBT( img1, img2, k, minD, maxD, pixDiff, tempBuf, clipTab, TAB_OFS, ftzero );
for(int ii = 0; ii <= ww; ii++)
{
for(int dd = 0; dd <= params.numDisparities; dd++)
{
pixDiff[ii * (params.numDisparities)+ dd] = (CostType)(ham[(k * (ww) + ii) * (params.numDisparities +1) + dd]);
}
}
memset(hsumAdd, 0, D*sizeof(CostType));
for( x = 0; x <= SW2*D; x += D )
{
@ -404,14 +264,17 @@ namespace cv
for( d = 0; d < D; d++ )
hsumAdd[d] = (CostType)(hsumAdd[d] + pixDiff[x + d]*scale);
}
if( y > 0 )
{
const CostType* hsumSub = hsumBuf + (std::max(y - SH2 - 1, 0) % hsumBufNRows)*costBufSize;
const CostType* Cprev = !fullDP || y == 0 ? C : C - costBufSize;
for( x = D; x < width1*D; x += D )
{
const CostType* pixAdd = pixDiff + std::min(x + SW2*D, (width1-1)*D);
const CostType* pixSub = pixDiff + std::max(x - (SW2+1)*D, 0);
#if CV_SSE2
if( useSIMD )
{
@ -554,21 +417,28 @@ namespace cv
#endif
{
int minL0 = MAX_COST, minL1 = MAX_COST, minL2 = MAX_COST, minL3 = MAX_COST;
for( d = 0; d < D; d++ )
{
int Cpd = Cp[d], L0, L1, L2, L3;
L0 = Cpd + std::min((int)Lr_p0[d], std::min(Lr_p0[d-1] + P1, std::min(Lr_p0[d+1] + P1, delta0))) - delta0;
L1 = Cpd + std::min((int)Lr_p1[d], std::min(Lr_p1[d-1] + P1, std::min(Lr_p1[d+1] + P1, delta1))) - delta1;
L2 = Cpd + std::min((int)Lr_p2[d], std::min(Lr_p2[d-1] + P1, std::min(Lr_p2[d+1] + P1, delta2))) - delta2;
L3 = Cpd + std::min((int)Lr_p3[d], std::min(Lr_p3[d-1] + P1, std::min(Lr_p3[d+1] + P1, delta3))) - delta3;
Lr_p[d] = (CostType)L0;
minL0 = std::min(minL0, L0);
Lr_p[d + D2] = (CostType)L1;
minL1 = std::min(minL1, L1);
Lr_p[d + D2*2] = (CostType)L2;
minL2 = std::min(minL2, L2);
Lr_p[d + D2*3] = (CostType)L3;
minL3 = std::min(minL3, L3);
Sp[d] = saturate_cast<CostType>(Sp[d] + L0 + L1 + L2 + L3);
}
minLr[0][xm] = (CostType)minL0;
@ -577,6 +447,7 @@ namespace cv
minLr[0][xm+3] = (CostType)minL3;
}
}
if( pass == npasses )
{
for( x = 0; x < width; x++ )
@ -593,6 +464,7 @@ namespace cv
if( npasses == 1 )
{
int xm = x*NR2, xd = xm*D2;
int minL0 = MAX_COST;
int delta0 = minLr[0][xm + NR2] + P2;
CostType* Lr_p0 = Lr[0] + xd + NRD2;
@ -685,11 +557,42 @@ namespace cv
}
if( 0 < d && d < D-1 )
{
// do subpixel quadratic interpolation:
// fit parabola into (x1=d-1, y1=Sp[d-1]), (x2=d, y2=Sp[d]), (x3=d+1, y3=Sp[d+1])
// then find minimum of the parabola.
int denom2 = std::max(Sp[d-1] + Sp[d+1] - 2*Sp[d], 1);
d = d*DISP_SCALE + ((Sp[d-1] - Sp[d+1])*DISP_SCALE + denom2)/(denom2*2);
if(params.subpixelInterpolationMethod == CV_SIMETRICV_INTERPOLATION)
{
double m2m1, m3m1, m3, m2, m1;
m2 = Sp[d - 1];
m3 = Sp[d + 1];
m1 = Sp[d];
m2m1 = m2 - m1;
m3m1 = m3 - m1;
if (!(m2m1 == 0 || m3m1 == 0))
{
double p;
p = 0;
if (m2 > m3)
{
p = (0.5 - 0.25 * ((m3m1 * m3m1) / (m2m1 * m2m1) + (m3m1 / m2m1)));
}
else
{
p = -1 * (0.5 - 0.25 * ((m2m1 * m2m1) / (m3m1 * m3m1) + (m2m1 / m3m1)));
}
if (p >= -0.5 && p <= 0.5)
d = (int)(d * DISP_SCALE + p * DISP_SCALE );
}
else
{
d *= DISP_SCALE;
}
}
else if(params.subpixelInterpolationMethod == CV_QUADRATIC_INTERPOLATION)
{
// do subpixel quadratic interpolation:
// fit parabola into (x1=d-1, y1=Sp[d-1]), (x2=d, y2=Sp[d]), (x3=d+1, y3=Sp[d+1])
// then find minimum of the parabola.
int denom2 = std::max(Sp[d-1] + Sp[d+1] - 2*Sp[d], 1);
d = d*DISP_SCALE + ((Sp[d-1] - Sp[d+1])*DISP_SCALE + denom2)/(denom2*2);
}
}
else
d *= DISP_SCALE;
@ -717,17 +620,17 @@ namespace cv
}
}
}
class StereoBinarySGBMImpl : public StereoBinarySGBM
class StereoBinarySGBMImpl : public StereoBinarySGBM, public Matching
{
public:
StereoBinarySGBMImpl()
StereoBinarySGBMImpl():Matching()
{
params = StereoBinarySGBMParams();
}
StereoBinarySGBMImpl( int _minDisparity, int _numDisparities, int _SADWindowSize,
int _P1, int _P2, int _disp12MaxDiff, int _preFilterCap,
int _uniquenessRatio, int _speckleWindowSize, int _speckleRange,
int _mode )
int _mode ):Matching(_numDisparities)
{
params = StereoBinarySGBMParams( _minDisparity, _numDisparities, _SADWindowSize,
_P1, _P2, _disp12MaxDiff, _preFilterCap,
@ -741,41 +644,132 @@ namespace cv
left.depth() == CV_8U );
disparr.create( left.size(), CV_16S );
Mat disp = disparr.getMat();
computeDisparityBinarySGBM( left, right, disp, params, buffer );
// medianBlur(disp, disp, 3);
if( params.speckleWindowSize > 0 )
filterSpeckles(disp, (params.minDisparity - 1)*StereoMatcher::DISP_SCALE, params.speckleWindowSize,
StereoMatcher::DISP_SCALE*params.speckleRange, buffer);
censusImageLeft.create(left.rows,left.cols,CV_32SC4);
censusImageRight.create(left.rows,left.cols,CV_32SC4);
hamDist.create(left.rows, left.cols * (params.numDisparities + 1),CV_16S);
if(params.kernelType == CV_SPARSE_CENSUS)
{
censusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_SPARSE_CENSUS);
}
else if(params.kernelType == CV_DENSE_CENSUS)
{
censusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_SPARSE_CENSUS);
}
else if(params.kernelType == CV_CS_CENSUS)
{
symetricCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_CS_CENSUS);
}
else if(params.kernelType == CV_MODIFIED_CS_CENSUS)
{
symetricCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_MODIFIED_CS_CENSUS);
}
else if(params.kernelType == CV_MODIFIED_CENSUS_TRANSFORM)
{
modifiedCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_MODIFIED_CENSUS_TRANSFORM,0);
}
else if(params.kernelType == CV_MEAN_VARIATION)
{
parSumsIntensityImage[0].create(left.rows, left.cols,CV_32SC4);
parSumsIntensityImage[1].create(left.rows, left.cols,CV_32SC4);
Integral[0].create(left.rows,left.cols,CV_32SC4);
Integral[1].create(left.rows,left.cols,CV_32SC4);
integral(left, parSumsIntensityImage[0],CV_32S);
integral(right, parSumsIntensityImage[1],CV_32S);
imageMeanKernelSize(parSumsIntensityImage[0], params.kernelSize,Integral[0]);
imageMeanKernelSize(parSumsIntensityImage[1], params.kernelSize, Integral[1]);
modifiedCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight,CV_MEAN_VARIATION,0,Integral[0], Integral[1]);
}
else if(params.kernelType == CV_STAR_KERNEL)
{
starCensusTransform(left,right,params.kernelSize,censusImageLeft,censusImageRight);
}
hammingDistanceBlockMatching(censusImageLeft, censusImageRight, hamDist);
computeDisparityBinarySGBM( left, right, disp, params, buffer,hamDist);
if(params.regionRemoval == CV_SPECKLE_REMOVAL_AVG_ALGORITHM)
{
int width = left.cols;
int height = left.rows;
if(previous_size != width * height)
{
previous_size = width * height;
specklePointX = new int[width * height];
specklePointY = new int[width * height];
pus = new long long[width * height];
}
double minVal; double maxVal;
Mat imgDisparity8U2;
imgDisparity8U2.create(height,width,CV_8UC1);
Mat aux;
aux.create(height,width,CV_8UC1);
minMaxLoc(disp, &minVal, &maxVal);
disp.convertTo(imgDisparity8U2, CV_8UC1, 255 / (maxVal - minVal));
Median1x9Filter(imgDisparity8U2, aux);
Median9x1Filter(aux,imgDisparity8U2);
smallRegionRemoval(imgDisparity8U2,params.speckleWindowSize,imgDisparity8U2);
imgDisparity8U2.convertTo(disp, CV_16S);
}
else if(params.regionRemoval == CV_SPECKLE_REMOVAL_ALGORITHM)
{
int width = left.cols;
int height = left.rows;
double minVal; double maxVal;
Mat imgDisparity8U2;
imgDisparity8U2.create(height,width,CV_8UC1);
Mat aux;
aux.create(height,width,CV_8UC1);
minMaxLoc(disp, &minVal, &maxVal);
disp.convertTo(imgDisparity8U2, CV_8UC1, 255 / (maxVal - minVal));
Median1x9Filter(imgDisparity8U2, aux);
Median9x1Filter(aux,imgDisparity8U2);
imgDisparity8U2.convertTo(disp, CV_16S);
if( params.speckleWindowSize > 0 )
filterSpeckles(disp, (params.minDisparity - 1) * StereoMatcher::DISP_SCALE, params.speckleWindowSize,
StereoMatcher::DISP_SCALE * params.speckleRange, buffer);
}
}
int getSubPixelInterpolationMethod() const { return params.subpixelInterpolationMethod;}
void setSubPixelInterpolationMethod(int value = CV_QUADRATIC_INTERPOLATION) { CV_Assert(value < 2); params.subpixelInterpolationMethod = value;}
int getBinaryKernelType() const { return params.kernelType;}
void setBinaryKernelType(int value = CV_MODIFIED_CENSUS_TRANSFORM) { CV_Assert(value < 7); params.kernelType = value; }
int getSpekleRemovalTechnique() const { return params.regionRemoval;}
void setSpekleRemovalTechnique(int factor = CV_SPECKLE_REMOVAL_AVG_ALGORITHM) { CV_Assert(factor < 2); params.regionRemoval = factor; }
int getMinDisparity() const { return params.minDisparity; }
void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; }
void setMinDisparity(int minDisparity) {CV_Assert(minDisparity >= 0); params.minDisparity = minDisparity; }
int getNumDisparities() const { return params.numDisparities; }
void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; }
void setNumDisparities(int numDisparities) { CV_Assert(numDisparities > 0); params.numDisparities = numDisparities; }
int getBlockSize() const { return params.SADWindowSize; }
void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; }
int getBlockSize() const { return params.kernelSize; }
void setBlockSize(int blockSize) {CV_Assert(blockSize % 2 != 0); params.kernelSize = blockSize; }
int getSpeckleWindowSize() const { return params.speckleWindowSize; }
void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; }
void setSpeckleWindowSize(int speckleWindowSize) {CV_Assert(speckleWindowSize >= 0); params.speckleWindowSize = speckleWindowSize; }
int getSpeckleRange() const { return params.speckleRange; }
void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; }
void setSpeckleRange(int speckleRange) { CV_Assert(speckleRange >= 0); params.speckleRange = speckleRange; }
int getDisp12MaxDiff() const { return params.disp12MaxDiff; }
void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; }
void setDisp12MaxDiff(int disp12MaxDiff) {CV_Assert(disp12MaxDiff > 0); params.disp12MaxDiff = disp12MaxDiff; }
int getPreFilterCap() const { return params.preFilterCap; }
void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; }
void setPreFilterCap(int preFilterCap) { CV_Assert(preFilterCap > 0); params.preFilterCap = preFilterCap; }
int getUniquenessRatio() const { return params.uniquenessRatio; }
void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; }
void setUniquenessRatio(int uniquenessRatio) { CV_Assert(uniquenessRatio >= 0); params.uniquenessRatio = uniquenessRatio; }
int getP1() const { return params.P1; }
void setP1(int P1) { params.P1 = P1; }
void setP1(int P1) { CV_Assert(P1 > 0); params.P1 = P1; }
int getP2() const { return params.P2; }
void setP2(int P2) { params.P2 = P2; }
void setP2(int P2) {CV_Assert(P2 > 0); CV_Assert(P2 >= 2 * params.P1); params.P2 = P2; }
int getMode() const { return params.mode; }
void setMode(int mode) { params.mode = mode; }
@ -785,7 +779,7 @@ namespace cv
fs << "name" << name_
<< "minDisparity" << params.minDisparity
<< "numDisparities" << params.numDisparities
<< "blockSize" << params.SADWindowSize
<< "blockSize" << params.kernelSize
<< "speckleWindowSize" << params.speckleWindowSize
<< "speckleRange" << params.speckleRange
<< "disp12MaxDiff" << params.disp12MaxDiff
@ -795,13 +789,14 @@ namespace cv
<< "P2" << params.P2
<< "mode" << params.mode;
}
void read(const FileNode& fn)
{
FileNode n = fn["name"];
CV_Assert( n.isString() && String(n) == name_ );
params.minDisparity = (int)fn["minDisparity"];
params.numDisparities = (int)fn["numDisparities"];
params.SADWindowSize = (int)fn["blockSize"];
params.kernelSize = (int)fn["blockSize"];
params.speckleWindowSize = (int)fn["speckleWindowSize"];
params.speckleRange = (int)fn["speckleRange"];
params.disp12MaxDiff = (int)fn["disp12MaxDiff"];
@ -811,24 +806,35 @@ namespace cv
params.P2 = (int)fn["P2"];
params.mode = (int)fn["mode"];
}
StereoBinarySGBMParams params;
Mat buffer;
static const char* name_;
Mat censusImageLeft;
Mat censusImageRight;
Mat partialSumsLR;
Mat agregatedHammingLRCost;
Mat hamDist;
Mat parSumsIntensityImage[2];
Mat Integral[2];
};
const char* StereoBinarySGBMImpl::name_ = "StereoMatcher.SGBM";
Ptr<StereoBinarySGBM> StereoBinarySGBM::create(int minDisparity, int numDisparities, int SADWindowSize,
Ptr<StereoBinarySGBM> StereoBinarySGBM::create(int minDisparity, int numDisparities, int kernelSize,
int P1, int P2, int disp12MaxDiff,
int preFilterCap, int uniquenessRatio,
int speckleWindowSize, int speckleRange,
int mode)
{
return Ptr<StereoBinarySGBM>(
new StereoBinarySGBMImpl(minDisparity, numDisparities, SADWindowSize,
new StereoBinarySGBMImpl(minDisparity, numDisparities, kernelSize,
P1, P2, disp12MaxDiff,
preFilterCap, uniquenessRatio,
speckleWindowSize, speckleRange,
mode));
}
typedef cv::Point_<short> Point2s;
}
}

@ -0,0 +1,238 @@
/*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.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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"
#include <limits.h>
using namespace cv;
using namespace cv::stereo;
using namespace std;
class CV_BlockMatchingTest : public cvtest::BaseTest
{
public:
CV_BlockMatchingTest();
~CV_BlockMatchingTest();
protected:
void run(int /* idx */);
};
CV_BlockMatchingTest::CV_BlockMatchingTest(){}
CV_BlockMatchingTest::~CV_BlockMatchingTest(){}
static double errorLevel(const Mat &ideal, Mat &actual)
{
uint8_t *date, *harta;
harta = actual.data;
date = ideal.data;
int stride, h;
stride = (int)ideal.step;
h = ideal.rows;
int error = 0;
for (int i = 0; i < ideal.rows; i++)
{
for (int j = 0; j < ideal.cols; j++)
{
if (date[i * stride + j] != 0)
if (abs(date[i * stride + j] - harta[i * stride + j]) > 2 * 16)
{
error += 1;
}
}
}
return ((double)((error * 100) * 1.0) / (stride * h));
}
void CV_BlockMatchingTest::run(int )
{
Mat image1, image2, gt;
//some test images can be found in the test data folder
image1 = imread(ts->get_data_path() + "testdata/imL2l.bmp", CV_8UC1);
image2 = imread(ts->get_data_path() + "testdata/imL2.bmp", CV_8UC1);
gt = imread(ts->get_data_path() + "testdata/groundtruth.bmp", CV_8UC1);
if(image1.empty() || image2.empty() || gt.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(image1.rows != image2.rows || image1.cols != image2.cols || gt.cols != gt.cols || gt.rows != gt.rows)
{
ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
RNG range;
//set the parameters
int binary_descriptor_type = range.uniform(0,8);
int kernel_size, aggregation_window;
if(binary_descriptor_type == 0)
kernel_size = 5;
else if(binary_descriptor_type == 2 || binary_descriptor_type == 3)
kernel_size = 7;
else if(binary_descriptor_type == 1)
kernel_size = 11;
else
kernel_size = 9;
if(binary_descriptor_type == 3)
aggregation_window = 13;
else
aggregation_window = 11;
Mat test = Mat(image1.rows, image1.cols, CV_8UC1);
Ptr<StereoBinaryBM> sbm = StereoBinaryBM::create(16, kernel_size);
//we set the corresponding parameters
sbm->setPreFilterCap(31);
sbm->setMinDisparity(0);
sbm->setTextureThreshold(10);
sbm->setUniquenessRatio(0);
sbm->setSpeckleWindowSize(400);//speckle size
sbm->setSpeckleRange(200);
sbm->setDisp12MaxDiff(0);
sbm->setScalleFactor(16);//the scaling factor
sbm->setBinaryKernelType(binary_descriptor_type);//binary descriptor kernel
sbm->setAgregationWindowSize(aggregation_window);
//speckle removal algorithm the user can choose between the average speckle removal algorithm
//or the classical version that was implemented in open cv
sbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM);
sbm->setUsePrefilter(false);//pre-filter or not the images prior to making the transformations
//-- calculate the disparity image
sbm->compute(image1, image2, test);
if(test.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
return;
}
if(errorLevel(gt,test) > 20)
{
ts->printf( cvtest::TS::LOG,
"Too big error\n");
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
return;
}
}
class CV_SGBlockMatchingTest : public cvtest::BaseTest
{
public:
CV_SGBlockMatchingTest();
~CV_SGBlockMatchingTest();
protected:
void run(int /* idx */);
};
CV_SGBlockMatchingTest::CV_SGBlockMatchingTest(){}
CV_SGBlockMatchingTest::~CV_SGBlockMatchingTest(){}
void CV_SGBlockMatchingTest::run(int )
{
Mat image1, image2, gt;
//some test images can be found in the test data folder
image1 = imread(ts->get_data_path() + "testdata/imL2l.bmp", CV_8UC1);
image2 = imread(ts->get_data_path() + "testdata/imL2.bmp", CV_8UC1);
gt = imread(ts->get_data_path() + "testdata/groundtruth.bmp", CV_8UC1);
if(image1.empty() || image2.empty() || gt.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(image1.rows != image2.rows || image1.cols != image2.cols || gt.cols != gt.cols || gt.rows != gt.rows)
{
ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
RNG range;
//set the parameters
int binary_descriptor_type = range.uniform(0,8);
int kernel_size;
if(binary_descriptor_type == 0)
kernel_size = 5;
else if(binary_descriptor_type == 2 || binary_descriptor_type == 3)
kernel_size = 7;
else if(binary_descriptor_type == 1)
kernel_size = 11;
else
kernel_size = 9;
Mat test = Mat(image1.rows, image1.cols, CV_8UC1);
Mat imgDisparity16S2 = Mat(image1.rows, image1.cols, CV_16S);
Ptr<StereoBinarySGBM> sgbm = StereoBinarySGBM::create(0, 16, kernel_size);
//setting the penalties for sgbm
sgbm->setP1(10);
sgbm->setP2(100);
sgbm->setMinDisparity(0);
sgbm->setNumDisparities(16);//set disparity number
sgbm->setUniquenessRatio(1);
sgbm->setSpeckleWindowSize(400);
sgbm->setSpeckleRange(200);
sgbm->setDisp12MaxDiff(1);
sgbm->setBinaryKernelType(binary_descriptor_type);//set the binary descriptor
sgbm->setSpekleRemovalTechnique(CV_SPECKLE_REMOVAL_AVG_ALGORITHM); //the avg speckle removal algorithm
sgbm->setSubPixelInterpolationMethod(CV_SIMETRICV_INTERPOLATION);// the SIMETRIC V interpolation method
sgbm->compute(image1, image2, imgDisparity16S2);
double minVal; double maxVal;
minMaxLoc(imgDisparity16S2, &minVal, &maxVal);
imgDisparity16S2.convertTo(test, CV_8UC1, 255 / (maxVal - minVal));
if(test.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
return;
}
double error = errorLevel(gt,test);
if(error > 10)
{
ts->printf( cvtest::TS::LOG,
"Too big error\n");
ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
return;
}
}
TEST(block_matching_simple_test, accuracy) { CV_BlockMatchingTest test; test.safe_run(); }
TEST(SG_block_matching_simple_test, accuracy) { CV_SGBlockMatchingTest test; test.safe_run(); }

@ -0,0 +1,466 @@
/*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.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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"
#include <limits.h>
using namespace cv;
using namespace cv::stereo;
using namespace std;
class CV_DescriptorBaseTest : public cvtest::BaseTest
{
public:
CV_DescriptorBaseTest();
~CV_DescriptorBaseTest();
protected:
virtual void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2) = 0;
virtual void imageTransformation(const Mat &img1, Mat &out1) = 0;
void testROI(const Mat &img);
void testMonotonicity(const Mat &img, Mat &out);
void run(int );
Mat censusImage[2];
Mat censusImageSingle[2];
Mat left;
Mat right;
int kernel_size, descriptor_type;
};
//we test to see if the descriptor applied on a roi
//has the same value with the descriptor from the original image
//tested at the roi boundaries
void CV_DescriptorBaseTest::testROI(const Mat &img)
{
int pt, pb,w,h;
//initialize random values for the roi top and bottom
pt = rand() % 100;
pb = rand() % 100;
//calculate the new width and height
w = img.cols;
h = img.rows - pt - pb;
int start = pt + kernel_size / 2 + 1;
int stop = h - kernel_size/2 - 1;
//set the region of interest according to above values
Rect region_of_interest = Rect(0, pt, w, h);
Mat image_roi1 = img(region_of_interest);
Mat p1,p2;
//create 2 images where to put our output
p1.create(image_roi1.rows, image_roi1.cols, CV_32SC4);
p2.create(img.rows, img.cols, CV_32SC4);
imageTransformation(image_roi1,p1);
imageTransformation(img,p2);
int *roi_data = (int *)p1.data;
int *img_data = (int *)p2.data;
//verify result
for(int i = start; i < stop; i++)
{
for(int j = 0; j < w ; j++)
{
if(roi_data[(i - pt) * w + j] != img_data[(i) * w + j])
{
ts->printf(cvtest::TS::LOG, "Something wrong with ROI \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
return;
}
}
}
}
CV_DescriptorBaseTest::~CV_DescriptorBaseTest()
{
left.release();
right.release();
censusImage[0].release();
censusImage[1].release();
censusImageSingle[0].release();
censusImageSingle[1].release();
}
CV_DescriptorBaseTest::CV_DescriptorBaseTest()
{
//read 2 images from file
//two test images can be found in the test data folder
left = imread(ts->get_data_path() + "testdata/imL2l.bmp", CV_8UC1);
right = imread(ts->get_data_path() + "testdata/imL2.bmp", CV_8UC1);
if(left.empty() || right.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
ts->printf(cvtest::TS::LOG, "Data loaded \n");
}
//verify if we don't have an image with all pixels the same( except when all input pixels are equal)
void CV_DescriptorBaseTest::testMonotonicity(const Mat &img, Mat &out)
{
//verify if input data is correct
if(img.rows != out.rows || img.cols != out.cols || img.empty() || out.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output dimension \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
//verify that for an input image with different pxels the values of the
//output pixels are not the same
int same = 0;
uint8_t *data = img.data;
uint8_t val = data[1];
int stride = (int)img.step;
for(int i = 0 ; i < img.rows && !same; i++)
{
for(int j = 0; j < img.cols; j++)
{
if(val != data[i * stride + j])
{
same = 1;
break;
}
}
}
int value_descript = out.data[1];
int accept = 0;
uint8_t *outData = out.data;
for(int i = 0 ; i < img.rows && !accept; i++)
{
for(int j = 0; j < img.cols; j++)
{
//we verify for the output image if the iage pixels are not all the same of an input
//image with different pixels
if(value_descript != outData[i * stride + j] && same)
{
//if we found a value that is different we accept
accept = 1;
break;
}
}
}
if(accept == 1 && same == 0)
{
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
ts->printf(cvtest::TS::LOG, "The image has all values the same \n");
return;
}
if(accept == 0 && same == 1)
{
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
ts->printf(cvtest::TS::LOG, "For correct image we get all descriptor values the same \n");
return;
}
ts->set_failed_test_info(cvtest::TS::OK);
}
///////////////////////////////////
//census transform
class CV_CensusTransformTest: public CV_DescriptorBaseTest
{
public:
CV_CensusTransformTest();
protected:
void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2);
void imageTransformation(const Mat &img1, Mat &out1);
};
CV_CensusTransformTest::CV_CensusTransformTest()
{
kernel_size = 11;
descriptor_type = CV_SPARSE_CENSUS;
}
void CV_CensusTransformTest::imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2)
{
//verify if input data is correct
if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty()
|| img2.rows != out2.rows || img2.cols != out2.cols || img2.empty() || out2.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(kernel_size % 2 == 0)
{
ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
censusTransform(img1,img2,kernel_size,out1,out2,descriptor_type);
}
void CV_CensusTransformTest::imageTransformation(const Mat &img1, Mat &out1)
{
//verify if input data is correct
if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(kernel_size % 2 == 0)
{
ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
censusTransform(img1,kernel_size,out1,descriptor_type);
}
//////////////////////////////////
//symetric census
class CV_SymetricCensusTest: public CV_DescriptorBaseTest
{
public:
CV_SymetricCensusTest();
protected:
void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2);
void imageTransformation(const Mat &img1, Mat &out1);
};
CV_SymetricCensusTest::CV_SymetricCensusTest()
{
kernel_size = 7;
descriptor_type = CV_CS_CENSUS;
}
void CV_SymetricCensusTest::imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2)
{
//verify if input data is correct
if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty()
|| img2.rows != out2.rows || img2.cols != out2.cols || img2.empty() || out2.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(kernel_size % 2 == 0)
{
ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
symetricCensusTransform(img1,img2,kernel_size,out1,out2,descriptor_type);
}
void CV_SymetricCensusTest::imageTransformation(const Mat &img1, Mat &out1)
{
//verify if input data is correct
if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(kernel_size % 2 == 0)
{
ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
symetricCensusTransform(img1,kernel_size,out1,descriptor_type);
}
//////////////////////////////////
//modified census transform
class CV_ModifiedCensusTransformTest: public CV_DescriptorBaseTest
{
public:
CV_ModifiedCensusTransformTest();
protected:
void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2);
void imageTransformation(const Mat &img1, Mat &out1);
};
CV_ModifiedCensusTransformTest::CV_ModifiedCensusTransformTest()
{
kernel_size = 9;
descriptor_type = CV_MODIFIED_CENSUS_TRANSFORM;
}
void CV_ModifiedCensusTransformTest::imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2)
{
//verify if input data is correct
if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty()
|| img2.rows != out2.rows || img2.cols != out2.cols || img2.empty() || out2.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(kernel_size % 2 == 0)
{
ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
modifiedCensusTransform(img1,img2,kernel_size,out1,out2,descriptor_type);
}
void CV_ModifiedCensusTransformTest::imageTransformation(const Mat &img1, Mat &out1)
{
if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(kernel_size % 2 == 0)
{
ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
modifiedCensusTransform(img1,kernel_size,out1,descriptor_type);
}
//////////////////////////////////
//star kernel census
class CV_StarKernelCensusTest: public CV_DescriptorBaseTest
{
public:
CV_StarKernelCensusTest();
protected:
void imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2);
void imageTransformation(const Mat &img1, Mat &out1);
};
CV_StarKernelCensusTest :: CV_StarKernelCensusTest()
{
kernel_size = 9;
descriptor_type = CV_STAR_KERNEL;
}
void CV_StarKernelCensusTest :: imageTransformation(const Mat &img1, const Mat &img2, Mat &out1, Mat &out2)
{
//verify if input data is correct
if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty()
|| img2.rows != out2.rows || img2.cols != out2.cols || img2.empty() || out2.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(kernel_size % 2 == 0)
{
ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
starCensusTransform(img1,img2,kernel_size,out1,out2);
}
void CV_StarKernelCensusTest::imageTransformation(const Mat &img1, Mat &out1)
{
if(img1.rows != out1.rows || img1.cols != out1.cols || img1.empty() || out1.empty())
{
ts->printf(cvtest::TS::LOG, "Wrong input / output data \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
if(kernel_size % 2 == 0)
{
ts->printf(cvtest::TS::LOG, "Wrong kernel size;Kernel should be odd \n");
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
starCensusTransform(img1,kernel_size,out1);
}
void CV_DescriptorBaseTest::run(int )
{
if (left.empty() || right.empty())
{
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
ts->printf(cvtest::TS::LOG, "No input images detected\n");
return;
}
testROI(left);
censusImage[0].create(left.rows, left.cols, CV_32SC4);
censusImage[1].create(left.rows, left.cols, CV_32SC4);
censusImageSingle[0].create(left.rows, left.cols, CV_32SC4);
censusImageSingle[1].create(left.rows, left.cols, CV_32SC4);
censusImage[0].setTo(0);
censusImage[1].setTo(0);
censusImageSingle[0].setTo(0);
censusImageSingle[1].setTo(0);
imageTransformation(left, right, censusImage[0], censusImage[1]);
imageTransformation(left, censusImageSingle[0]);
imageTransformation(right, censusImageSingle[1]);
testMonotonicity(left,censusImage[0]);
testMonotonicity(right,censusImage[1]);
testMonotonicity(left,censusImageSingle[0]);
testMonotonicity(right,censusImageSingle[1]);
if (censusImage[0].empty() || censusImage[1].empty() || censusImageSingle[0].empty() || censusImageSingle[1].empty())
{
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
ts->printf(cvtest::TS::LOG, "The descriptor images are empty \n");
return;
}
int *datl1 = (int *)censusImage[0].data;
int *datr1 = (int *)censusImage[1].data;
int *datl2 = (int *)censusImageSingle[0].data;
int *datr2 = (int *)censusImageSingle[1].data;
for(int i = 0; i < censusImage[0].rows - kernel_size/ 2; i++)
{
for(int j = 0; j < censusImage[0].cols; j++)
{
if(datl1[i * censusImage[0].cols + j] != datl2[i * censusImage[0].cols + j])
{
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
ts->printf(cvtest::TS::LOG, "Mismatch for left images %d \n",descriptor_type);
return;
}
if(datr1[i * censusImage[0].cols + j] != datr2[i * censusImage[0].cols + j])
{
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
ts->printf(cvtest::TS::LOG, "Mismatch for right images %d \n",descriptor_type);
return;
}
}
}
int min = numeric_limits<int>::min();
int max = numeric_limits<int>::max();
//check if all values are between int min and int max and not NAN
if (0 != cvtest::check(censusImage[0], min, max, 0))
{
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return;
}
//check if all values are between int min and int max and not NAN
if (0 != cvtest::check(censusImage[1], min, max, 0))
{
ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
return ;
}
}
TEST(census_transform_testing, accuracy) { CV_CensusTransformTest test; test.safe_run(); }
TEST(symetric_census_testing, accuracy) { CV_SymetricCensusTest test; test.safe_run(); }
TEST(modified_census_testing, accuracy) { CV_ModifiedCensusTransformTest test; test.safe_run(); }
TEST(star_kernel_testing, accuracy) { CV_StarKernelCensusTest test; test.safe_run(); }

@ -12,8 +12,6 @@
#include <iostream>
#include "opencv2/ts.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/stereo.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/features2d.hpp"
@ -22,10 +20,9 @@
#include "opencv2/core/cvdef.h"
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/calib3d.hpp"
#include <algorithm>
#include <cmath>
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Loading…
Cancel
Save