Commit 7d13acdb authored by Muresan Mircea Paul's avatar Muresan Mircea Paul

added asserts

removed unnecessary code
modified enums and other

removed class descriptor.cpp

removed white spaces and fixed warnings

Changed to kernel
parent 37478fc5
...@@ -41,50 +41,75 @@ ...@@ -41,50 +41,75 @@
//the use of this software, even if advised of the possibility of such damage. //the use of this software, even if advised of the possibility of such damage.
/*****************************************************************************************************************\ /*****************************************************************************************************************\
* The interface contains the main descriptors that will be implemented in the descriptor class * * The file contains the implemented descriptors *
\******************************************************************************************************************/ \******************************************************************************************************************/
#include "descriptor.hpp" #include "descriptor.hpp"
using namespace cv; using namespace cv;
using namespace stereo; using namespace stereo;
Descriptor::Descriptor() void cv::stereo::applyCensusOnImage(const cv::Mat &img, int kernelSize, cv::Mat &dist, const int type)
{
}
//!Implementation for computing the Census transform on the given image
void Descriptor::applyCensusOnImage(const cv::Mat &img, int kernelSize, cv::Mat &dist, const int type)
{ {
CV_Assert(img.type() == CV_8UC1);
CV_Assert(kernelSize <= 5);
CV_Assert(type < 2 && type >= 0);
int n2 = (kernelSize - 1) / 2; int n2 = (kernelSize - 1) / 2;
parallel_for_(cv::Range(n2, img.rows - n2), singleImageCensus(img.data, img.cols, img.rows, n2, (int *)dist.data, type)); parallel_for_(cv::Range(n2, img.rows - n2), singleImageCensus(img.data, img.cols, img.rows, n2, (int *)dist.data, type));
} }
/** void cv::stereo::applyCensusOnImages(const cv::Mat &im1,const cv::Mat &im2, int kernelSize, cv::Mat &dist, cv::Mat &dist2, const int type)
Two variations of census applied on input images
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 Descriptor::applyCensusOnImages(const cv::Mat &im1, cv::Mat &im2, int kernelSize, cv::Mat &dist, cv::Mat &dist2, const int type)
{ {
CV_Assert(im1.size() == im2.size());
CV_Assert(im1.type() == CV_8UC1 && im2.type() == CV_8UC1);
CV_Assert(type < 2 && type >= 0);
CV_Assert(kernelSize <= (type == 0 ? 5 : 10));
int n2 = (kernelSize - 1) / 2; int n2 = (kernelSize - 1) / 2;
parallel_for_(cv::Range(n2, im1.rows - n2), parallelCensus(im1.data, im2.data, im1.cols, im2.rows, n2, (int *)dist.data, (int *)dist2.data, type)); if(type == Dense_Census)
{
parallel_for_(cv::Range(n2, im1.rows - n2),
CombinedDescriptor<1,1,1,CensusKernel>(im1.cols, im1.rows,n2,(int *)dist.data,(int *)dist2.data,CensusKernel(im1.data, im2.data),n2));
}
else if(type == Sparse_Census)
{
parallel_for_(cv::Range(n2, im1.rows - n2),
CombinedDescriptor<2,2,1,CensusKernel>(im1.cols, im1.rows,n2,(int *)dist.data,(int *)dist2.data,CensusKernel(im1.data, im2.data),n2));
}
} }
/** void cv::stereo::applyMCTOnImages(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, int t, cv::Mat &dist, cv::Mat &dist2, 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 Descriptor::applyMCTOnImages(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, int t, cv::Mat &dist, cv::Mat &dist2, const int type)
{ {
CV_Assert(img1.size() == img2.size());
CV_Assert(img1.type() == CV_8UC1 && img2.type() == CV_8UC1);
CV_Assert(type < 2 && type >= 0);
CV_Assert(kernelSize <= 9);
int n2 = (kernelSize - 1) >> 1; int n2 = (kernelSize - 1) >> 1;
parallel_for_(cv::Range(n2, img1.rows - n2), parallelMctDescriptor(img1.data, img2.data, img1.cols, img2.rows, n2,t, (int *)dist.data, (int *)dist2.data, type)); if(type == StandardMct)
{
parallel_for_(cv::Range(n2, img1.rows - n2),
CombinedDescriptor<2,3,2,MCTKernel>(img1.cols, img1.rows,n2,(int *)dist.data,(int *)dist2.data,MCTKernel(img1.data, img2.data,t),n2));
}
else
{
//MV
}
} }
/**The classical center symetric census void cv::stereo::applySimetricCensus(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist, cv::Mat &dist2, const int type)
A modified version of cs census which is comparing a pixel with its correspondent after the center
**/
void Descriptor::applySimetricCensus(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist, cv::Mat &dist2, const int type)
{ {
CV_Assert(img1.size() == img2.size());
CV_Assert(img1.type() == CV_8UC1 && img2.type() == CV_8UC1);
CV_Assert(type < 2 && type >= 0);
CV_Assert(kernelSize <= 7);
int n2 = (kernelSize - 1) >> 1; int n2 = (kernelSize - 1) >> 1;
parallel_for_(cv::Range(n2, img1.rows - n2), parallelSymetricCensus(img1.data, img2.data, img1.cols, img2.rows, n2, (int *)dist.data, (int *)dist2.data, type)); if(type == ClassicCenterSymetricCensus)
{
parallel_for_(cv::Range(n2, img1.rows - n2), parallelSymetricCensus(img1.data, img2.data, img1.cols, img2.rows, n2, (int *)dist.data, (int *)dist2.data, type));
}
else if(type == ModifiedCenterSymetricCensus)
{
parallel_for_(cv::Range(n2, img1.rows - n2),
CombinedDescriptor<1,1,1,ModifiedCsCensus>(img1.cols, img1.rows,n2,(int *)dist.data,(int *)dist2.data,ModifiedCsCensus(img1.data, img2.data,n2),1));
}
} }
//!brief binary descriptor used in stereo correspondence void cv::stereo::applyBrifeDescriptor(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2)
void Descriptor::applyBrifeDescriptor(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2)
{ {
//TO DO //TO DO
//marked the variables in order to avoid warnings //marked the variables in order to avoid warnings
...@@ -94,8 +119,7 @@ void Descriptor::applyBrifeDescriptor(const cv::Mat &image1, const cv::Mat &imag ...@@ -94,8 +119,7 @@ void Descriptor::applyBrifeDescriptor(const cv::Mat &image1, const cv::Mat &imag
(void)dist2; (void)dist2;
(void)kernelSize; (void)kernelSize;
} }
//The classical Rank Transform void cv::stereo::applyRTDescriptor(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2)
void Descriptor::applyRTDescriptor(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2)
{ {
//TO DO //TO DO
//marked the variables in order to avoid warnings //marked the variables in order to avoid warnings
...@@ -105,7 +129,3 @@ void Descriptor::applyRTDescriptor(const cv::Mat &image1, const cv::Mat &image2 ...@@ -105,7 +129,3 @@ void Descriptor::applyRTDescriptor(const cv::Mat &image1, const cv::Mat &image2
(void)dist2; (void)dist2;
(void)kernelSize; (void)kernelSize;
} }
Descriptor::~Descriptor(void)
{
}
...@@ -54,57 +54,159 @@ namespace cv ...@@ -54,57 +54,159 @@ namespace cv
{ {
namespace stereo namespace stereo
{ {
enum ClassicCensus { Dense_Census, Sparse_Census}; enum { Dense_Census, Sparse_Census, StarCensus};
enum SymetricCensus {ClassicCenterSymetricCensus, ModifiedCenterSymetricCensus}; enum {ClassicCenterSymetricCensus, ModifiedCenterSymetricCensus};
enum MCT {StandardMct,MeanVariation}; enum {StandardMct,MeanVariation};
enum CensusImage {SSE, NonSSE}; enum {SSE, NonSSE};
//!class implemented to run the census descriptor in parralel //!Mean Variation is a robust kernel that compares a pixel
class parallelCensus :public ParallelLoopBody //!not just with the center but also with the mean of the window
struct MVKernel
{
uint8_t *image1;
uint8_t *image2;
uint8_t *integralLeft;
uint8_t *integralRight;
MVKernel(uint8_t *img, uint8_t *img2, uint8_t *integralL, uint8_t *integralR): image1(img),image2(img2),integralLeft(integralL), integralRight(integralR){}
void operator()(int rrWidth,int w2, int rWidth, int jj, int j, int &c, int &c2) const
{
}
};
//!kernel that takes the pixels from certain positions from a patch
//!offers verry good results
struct StarKernel
{
uint8_t *image1;
uint8_t *image2;
StarKernel(uint8_t *img, uint8_t *img2): image1(img),image2(img2){}
void operator()(int rrWidth,int w2, int rWidth, int jj, int j, int &c, int &c2) const
{
}
};
//!Compares pixels from a patch giving high weights to pixels in which
//!the intensity is higher. The other pixels receive a lower weight
struct MCTKernel
{
uint8_t *image1;
uint8_t *image2;
int t;
MCTKernel(uint8_t * img,uint8_t *img2, int threshold) : image1(img),image2(img2), t(threshold) {}
void operator()(int rrWidth,int w2, int rWidth, int jj, int j, int &c, int &c2) const
{
if (image1[rrWidth + jj] > image1[rWidth + j] - t)
{
c <<= 2;
c |= 0x3;
}
else if (image1[rWidth + j] - t < image1[rrWidth + jj] && image1[rWidth + j] + t >= image1[rrWidth + jj])
{
c <<= 2;
c = c + 1;
}
else
{
c <<= 2;
}
if (image2[rrWidth + jj] > image2[rWidth + j] - t)
{
c2 <<= 2;
c2 |= 0x3;
}
else if (image2[rWidth + j] - t < image2[rrWidth + jj] && image2[rWidth + j] + t >= image2[rrWidth + jj])
{
c2 <<= 2;
c2 = c2 + 1;
}
else
{
c2 <<= 2;
}
}
};
//!A madified cs census that compares a pixel with the imediat neightbour starting
//!from the center
struct ModifiedCsCensus
{
uint8_t *image1;
uint8_t *image2;
int n2;
ModifiedCsCensus(uint8_t *im1, uint8_t *im2, int ker):image1(im1),image2(im2),n2(ker){}
void operator()(int rrWidth,int w2, int rWidth, int jj, int j, int &c, int &c2) const
{
if (image1[(rrWidth + jj)] > image1[(w2 + (jj + n2))])
{
c = c + 1;
}
c = c * 2;
if (image2[(rrWidth + jj)] > image2[(w2 + (jj + n2))])
{
c2 = c2 + 1;
}
c2 = c2 * 2;
}
};
//!A kernel in which a pixel is compared with the center of the window
struct CensusKernel
{
uint8_t *image1;
uint8_t *image2;
CensusKernel(uint8_t *im1, uint8_t *im2):image1(im1),image2(im2){}
void operator()(int rrWidth,int w2, int rWidth, int jj, int j, int &c, int &c2) const
{
//compare a pixel with the center from the kernel
if (image1[rrWidth + jj] > image1[rWidth + j])
{
c = c + 1;
}
c = c * 2;
//compare pixel with center for image 2
if (image2[rrWidth + jj] > image2[rWidth + j])
{
c2 = c2 + 1;
}
c2 = c2 * 2;
}
};
//template clas which efficiently combines the descriptors
template <int step_start, int step_end, int step_inc, typename Kernel>
class CombinedDescriptor:public ParallelLoopBody
{ {
private: private:
uint8_t *image1, *image2; uint8_t *image1, *image2;
int *dst1, *dst2; int *dst1, *dst2;
int n2, width, height, type; int n2 , width, height;
int n2_stop;
Kernel kernel_;
public: public:
parallelCensus(uint8_t * img1, uint8_t * img2, int w, int h, int k2, int * distance1, int * distance2,const int t) : CombinedDescriptor(int w, int h, int k2, int * distance1, int * distance2, Kernel kernel,int k2Stop) :
image1(img1), image2(img2), dst1(distance1), dst2(distance2), n2(k2), width(w), height(h), type(t){} width(w), height(h), n2(k2),dst1(distance1), dst2(distance2), kernel_(kernel), n2_stop(k2Stop){}
virtual void operator()(const cv::Range &r) const { void operator()(const cv::Range &r) const {
int step = (type == ClassicCensus::Sparse_Census)? 2:1;
for (int i = r.start; i <= r.end ; i++) for (int i = r.start; i <= r.end ; i++)
{ {
int rWidth = i * width; int rWidth = i * width;
for (int j = n2; j <= width - n2; j++) for (int j = n2 + 2; j <= width - n2 - 2; j++)
{ {
//imitialize the costs for the 2 census descriptors
int c = 0; int c = 0;
int c2 = 0; int c2 = 0;
for (int ii = i - n2; ii <= i + n2; ii+=step) for(int step = step_start; step <= step_end; step += step_inc)
{ {
int rrWidth = ii * width; for (int ii = - n2; ii <= + n2_stop; ii += step)
for (int jj = j - n2; jj <= j + n2; jj+=step)
{ {
if (ii != i || jj != j) int rrWidth = (ii + i) * width;
{ int rrWidthC = (ii + i + n2) * width;
//compare a pixel with the center from the kernel for (int jj = j - n2; jj <= j + n2; jj += step)
if (image1[rrWidth + jj] > image1[rWidth + j])
{
c = c + 1;
}
c = c * 2;
}
if (ii != i || jj != j)
{ {
//compare pixel with center for image 2 if (ii != i || jj != j)
if (image2[rrWidth + jj] > image2[rWidth + j])
{ {
c2 = c2 + 1; kernel_(rrWidth,rrWidthC, rWidth, jj, j, c,c2);
} }
c2 = c2 * 2;
} }
} }
} }
dst1[(rWidth + j)] = c; dst1[rWidth + j] = c;
dst2[(rWidth + j)] = c2; dst2[rWidth + j] = c2;
} }
} }
} }
...@@ -119,13 +221,13 @@ namespace cv ...@@ -119,13 +221,13 @@ namespace cv
public: public:
singleImageCensus(uint8_t * img1, int w, int h, int k2, int * distance1,const int t) : singleImageCensus(uint8_t * img1, int w, int h, int k2, int * distance1,const int t) :
image(img1), dst(distance1), n2(k2), width(w), height(h), type(t){} image(img1), dst(distance1), n2(k2), width(w), height(h), type(t){}
virtual void operator()(const cv::Range &r) const { void operator()(const cv::Range &r) const {
for (int i = r.start; i <= r.end ; i++) for (int i = r.start; i <= r.end ; i++)
{ {
int rWidth = i * width; int rWidth = i * width;
for (int j = n2; j <= width - n2; j++) for (int j = n2; j <= width - n2; j++)
{ {
if (type == CensusImage::SSE) if (type == SSE)
{ {
//to do //to do
} }
...@@ -153,121 +255,6 @@ namespace cv ...@@ -153,121 +255,6 @@ namespace cv
} }
} }
}; };
//! parallel implementation of MCT type of descriptors
class parallelMctDescriptor:public ParallelLoopBody
{
private:
uint8_t *image1, *image2;
int *dst1, *dst2;
int n2,t , width, height, type;
public:
parallelMctDescriptor(uint8_t * img1, uint8_t * img2, int w, int h, int k2,int threshold, int * distance1, int * distance2,const int tip) :
image1(img1), image2(img2), dst1(distance1), dst2(distance2), n2(k2), t(threshold), width(w), height(h), type(tip){}
virtual void operator()(const cv::Range &r) const {
for (int i = r.start; i <= r.end ; i++)
{
int rWidth = i * width;
int distV = (i)* width;
for (int j = n2 + 2; j <= width - n2 - 2; j++)
{
int c = 0;
int c2 = 0;
if (type == MCT::StandardMct)
{
for (int ii = i - n2; ii <= i + n2; ii += 2)
{
int rrWidth = ii * width;
for (int jj = j - n2; jj <= j + n2; jj += 2)
{
if (ii != i || jj != j)
{
if (image1[rrWidth + jj] > image1[rWidth + j] - t)
{
c <<= 2;
c |= 0x3;
}
else if (image1[rWidth + j] - t < image1[rrWidth + jj] && image1[rWidth + j] + t >= image1[rrWidth + jj])
{
c <<= 2;
c = c + 1;
}
else
{
c <<= 2;
}
}
if (ii != i || jj != j)
{
if (image2[rrWidth + jj] > image2[rWidth + j] - t)
{
c2 <<= 2;
c2 |= 0x3;
}
else if (image2[rWidth + j] - t < image2[rrWidth + jj] && image2[rWidth + j] + t >= image2[rrWidth + jj])
{
c2 <<= 2;
c2 = c2 + 1;
}
else
{
c2 <<= 2;
}
}
}
}
for (int ii = i - n2; ii <= i + n2; ii += 4)
{
int rrWidth = ii * width;
for (int jj = j - n2; jj <= j + n2; jj += 4)
{
if (ii != i || jj != j)
{
if (image1[rrWidth + jj] > image1[rWidth + j] - t)
{
c <<= 2;
c |= 0x3;
}
else if (image1[rWidth + j] - t < image1[rrWidth + jj] && image1[rWidth + j] + t >= image1[rrWidth + jj])
{
c <<= 2;
c += 1;
}
else
{
c <<= 2;
}
}
if (ii != i || jj != j)
{
if (image2[rrWidth + jj] > image2[rWidth + j] - t)
{
c2 <<= 2;
c2 |= 0x3;
}
else if (image2[rWidth + j] - t < image2[rrWidth + jj] && image2[rWidth + j] + t >= image2[rrWidth + jj])
{
c2 <<= 2;
c2 = c2 + 1;
}
else
{
c2 <<= 2;
}
}
}
}
}
else if (type == MCT::MeanVariation)
{
//to do mean variation
}
dst1[distV + j] = c;
dst2[distV + j] = c2;
}
}
}
};
//!paralel implementation of the center symetric census //!paralel implementation of the center symetric census
class parallelSymetricCensus:public ParallelLoopBody class parallelSymetricCensus:public ParallelLoopBody
{ {
...@@ -278,9 +265,7 @@ namespace cv ...@@ -278,9 +265,7 @@ namespace cv
public: public:
parallelSymetricCensus(uint8_t * img1, uint8_t * img2, int w, int h, int k2, int * distance1, int * distance2,const int t) : parallelSymetricCensus(uint8_t * img1, uint8_t * img2, int w, int h, int k2, int * distance1, int * distance2,const int t) :
image1(img1), image2(img2), dst1(distance1), dst2(distance2), n2(k2), width(w), height(h), type(t){} image1(img1), image2(img2), dst1(distance1), dst2(distance2), n2(k2), width(w), height(h), type(t){}
void operator()(const cv::Range &r) const {
virtual void operator()(const cv::Range &r) const {
for (int i = r.start; i <= r.end ; i++) for (int i = r.start; i <= r.end ; i++)
{ {
int distV = (i)* width; int distV = (i)* width;
...@@ -289,100 +274,64 @@ namespace cv ...@@ -289,100 +274,64 @@ namespace cv
int c = 0; int c = 0;
int c2 = 0; int c2 = 0;
//the classic center symetric census which compares the curent pixel with its symetric not its center. //the classic center symetric census which compares the curent pixel with its symetric not its center.
if (type == SymetricCensus::ClassicCenterSymetricCensus) for (int ii = -n2; ii < 0; ii++)
{ {
for (int ii = -n2; ii < 0; ii++) int rrWidth = (ii + i) * width;
for (int jj = -n2; jj <= +n2; jj++)
{ {
int rrWidth = (ii + i) * width; if (image1[(rrWidth + (jj + j))] > image1[((ii * (-1) + i) * width + (-1 * jj) + j)])
for (int jj = -n2; jj <= +n2; jj++)
{
if (ii != i || jj != j)
{
if (image1[(rrWidth + (jj + j))] > image1[((ii * (-1) + i) * width + (-1 * jj) + j)])
{
c = c + 1;
}
c = c * 2;
}
if (ii != i || jj != j)
{
if (image2[(rrWidth + (jj + j))] > image2[((ii * (-1) + i) * width + (-1 * jj) + j)])
{
c2 = c2 + 1;
}
c2 = c2 * 2;
}
}
}
for (int jj = -n2; jj < 0; jj++)
{
if (image1[(i * width + (jj + j))] > image1[(i * width + (-1 * jj) + j)])
{ {
c = c + 1; c = c + 1;
} }
c = c * 2; c = c * 2;
if (image2[(i * width + (jj + j))] > image2[(i * width + (-1 * jj) + j)])
if (image2[(rrWidth + (jj + j))] > image2[((ii * (-1) + i) * width + (-1 * jj) + j)])
{ {
c2 = c2 + 1; c2 = c2 + 1;
} }
c2 = c2 * 2; c2 = c2 * 2;
} }
}//a modified version of cs census which compares each pixel with its correspondent from }
//the same distance from the center for (int jj = -n2; jj < 0; jj++)
else if (type == SymetricCensus::ModifiedCenterSymetricCensus)
{ {
for (int ii = i - n2; ii <= i + 1; ii++) if (image1[(i * width + (jj + j))] > image1[(i * width + (-1 * jj) + j)])
{ {
int rrWidth = ii * width; c = c + 1;
int rrWidthC = (ii + n2) * width;
for (int jj = j - n2; jj <= j + n2; jj += 2)
{
if (ii != i || jj != j)
{
if (image1[(rrWidth + jj)] > image1[(rrWidthC + (jj + n2))])
{
c = c + 1;
}
c = c * 2;
}
if (ii != i || jj != j)
{
if (image2[(rrWidth + jj)] > image2[(rrWidthC + (jj + n2))])
{
c2 = c2 + 1;
}
c2 = c2 * 2;
}
}
} }
} c = c * 2;
if (image2[(i * width + (jj + j))] > image2[(i * width + (-1 * jj) + j)])
{
c2 = c2 + 1;
}
c2 = c2 * 2;
}//a modified version of cs census which compares each pixel with its correspondent from
//the same distance from the center
dst1[(distV + j)] = c; dst1[(distV + j)] = c;
dst2[(distV + j)] = c2; dst2[(distV + j)] = c2;
} }
} }
} }
}; };
class Descriptor //!Implementation for computing the Census transform on the given image
{ void applyCensusOnImage(const cv::Mat &img, int kernelSize, cv::Mat &dist, const int type);
public: /**
//Implementation for computing the Census transform on the given image Two variations of census applied on input images
void applyCensusOnImage(const cv::Mat &image, int kernelSize, cv::Mat &dist, const int type = 0); Implementation of a census transform which is taking into account just the some pixels from the census kernel thus allowing for larger block sizes
//two variations of census applied on input images **/
//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 applyCensusOnImages(const cv::Mat &image1, cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2, const int type = ClassicCensus::Sparse_Census); /**
// STANDARD_MCT - Modified census which is memorizing for each pixel 2 bits and includes a tolerance to the pixel comparison 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 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 applyMCTOnImages(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, int t, cv::Mat &dist, cv::Mat &dist2, const int type = MCT::StandardMct); **/
//The classical center symetric census void applyMCTOnImages(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, int t, cv::Mat &dist, cv::Mat &dist2, const int type);
//A modified version of cs census which is comparing the a pixel with its correspondent from the after the center /**The classical center symetric census
void applySimetricCensus(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2, const int type = SymetricCensus::ClassicCenterSymetricCensus); A modified version of cs census which is comparing a pixel with its correspondent after the center
//The brief binary descriptor **/
void applyBrifeDescriptor(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2); void applySimetricCensus(const cv::Mat &img1, const cv::Mat &img2, int kernelSize, cv::Mat &dist, cv::Mat &dist2, const int type);
//The classical Rank Transform //!brief binary descriptor used in stereo correspondence
void applyRTDescriptor(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2); void applyBrifeDescriptor(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2);
Descriptor(); //The classical Rank Transform
~Descriptor(void); void applyRTDescriptor(const cv::Mat &image1, const cv::Mat &image2, int kernelSize, cv::Mat &dist, cv::Mat &dist2);
};
} }
} }
#endif #endif
......
...@@ -51,686 +51,681 @@ ...@@ -51,686 +51,681 @@
namespace cv namespace cv
{ {
namespace stereo namespace stereo
{ {
struct StereoBinaryBMParams struct StereoBinaryBMParams
{ {
StereoBinaryBMParams(int _numDisparities = 64, int _SADWindowSize = 9) StereoBinaryBMParams(int _numDisparities = 64, int _SADWindowSize = 9)
{ {
preFilterType = StereoBinaryBM::PREFILTER_XSOBEL; preFilterType = StereoBinaryBM::PREFILTER_XSOBEL;
preFilterSize = 9; preFilterSize = 9;
preFilterCap = 31; preFilterCap = 31;
SADWindowSize = _SADWindowSize; SADWindowSize = _SADWindowSize;
minDisparity = 0; minDisparity = 0;
numDisparities = _numDisparities > 0 ? _numDisparities : 64; numDisparities = _numDisparities > 0 ? _numDisparities : 64;
textureThreshold = 10; textureThreshold = 10;
uniquenessRatio = 15; uniquenessRatio = 15;
speckleRange = speckleWindowSize = 0; speckleRange = speckleWindowSize = 0;
roi1 = roi2 = Rect(0, 0, 0, 0); roi1 = roi2 = Rect(0, 0, 0, 0);
disp12MaxDiff = -1; disp12MaxDiff = -1;
dispType = CV_16S; dispType = CV_16S;
} }
int preFilterType; int preFilterType;
int preFilterSize; int preFilterSize;
int preFilterCap; int preFilterCap;
int SADWindowSize; int SADWindowSize;
int minDisparity; int minDisparity;
int numDisparities; int numDisparities;
int textureThreshold; int textureThreshold;
int uniquenessRatio; int uniquenessRatio;
int speckleRange; int speckleRange;
int speckleWindowSize; int speckleWindowSize;
Rect roi1, roi2; Rect roi1, roi2;
int disp12MaxDiff; int disp12MaxDiff;
int dispType; int dispType;
}; };
static void prefilterNorm(const Mat& src, Mat& dst, int winsize, int ftzero, uchar* buf) static void prefilterNorm(const Mat& src, Mat& dst, int winsize, int ftzero, uchar* buf)
{ {
int x, y, wsz2 = winsize / 2; int x, y, wsz2 = winsize / 2;
int* vsum = (int*)alignPtr(buf + (wsz2 + 1)*sizeof(vsum[0]), 32); int* vsum = (int*)alignPtr(buf + (wsz2 + 1)*sizeof(vsum[0]), 32);
int scale_g = winsize*winsize / 8, scale_s = (1024 + scale_g) / (scale_g * 2); int scale_g = winsize*winsize / 8, scale_s = (1024 + scale_g) / (scale_g * 2);
const int OFS = 256 * 5, TABSZ = OFS * 2 + 256; const int OFS = 256 * 5, TABSZ = OFS * 2 + 256;
uchar tab[TABSZ]; uchar tab[TABSZ];
const uchar* sptr = src.ptr(); const uchar* sptr = src.ptr();
int srcstep = (int)src.step; int srcstep = (int)src.step;
Size size = src.size(); Size size = src.size();
scale_g *= scale_s; scale_g *= scale_s;
for (x = 0; x < TABSZ; x++) for (x = 0; x < TABSZ; x++)
tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero * 2 : x - OFS + ftzero); tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero * 2 : x - OFS + ftzero);
for (x = 0; x < size.width; x++) for (x = 0; x < size.width; x++)
vsum[x] = (ushort)(sptr[x] * (wsz2 + 2)); vsum[x] = (ushort)(sptr[x] * (wsz2 + 2));
for (y = 1; y < wsz2; y++) for (y = 1; y < wsz2; y++)
{ {
for (x = 0; x < size.width; x++) for (x = 0; x < size.width; x++)
vsum[x] = (ushort)(vsum[x] + sptr[srcstep*y + x]); vsum[x] = (ushort)(vsum[x] + sptr[srcstep*y + x]);
} }
for (y = 0; y < size.height; y++)
for (y = 0; y < size.height; y++) {
{ const uchar* top = sptr + srcstep*MAX(y - wsz2 - 1, 0);
const uchar* top = sptr + srcstep*MAX(y - wsz2 - 1, 0); const uchar* bottom = sptr + srcstep*MIN(y + wsz2, size.height - 1);
const uchar* bottom = sptr + srcstep*MIN(y + wsz2, size.height - 1); const uchar* prev = sptr + srcstep*MAX(y - 1, 0);
const uchar* prev = sptr + srcstep*MAX(y - 1, 0); const uchar* curr = sptr + srcstep*y;
const uchar* curr = sptr + srcstep*y; const uchar* next = sptr + srcstep*MIN(y + 1, size.height - 1);
const uchar* next = sptr + srcstep*MIN(y + 1, size.height - 1); uchar* dptr = dst.ptr<uchar>(y);
uchar* dptr = dst.ptr<uchar>(y); for (x = 0; x < size.width; x++)
vsum[x] = (ushort)(vsum[x] + bottom[x] - top[x]);
for (x = 0; x < size.width; x++)
vsum[x] = (ushort)(vsum[x] + bottom[x] - top[x]); for (x = 0; x <= wsz2; x++)
{
for (x = 0; x <= wsz2; x++) vsum[-x - 1] = vsum[0];
{ vsum[size.width + x] = vsum[size.width - 1];
vsum[-x - 1] = vsum[0]; }
vsum[size.width + x] = vsum[size.width - 1];
} int sum = vsum[0] * (wsz2 + 1);
for (x = 1; x <= wsz2; x++)
int sum = vsum[0] * (wsz2 + 1); sum += vsum[x];
for (x = 1; x <= wsz2; x++) int val = ((curr[0] * 5 + curr[1] + prev[0] + next[0])*scale_g - sum*scale_s) >> 10;
sum += vsum[x]; dptr[0] = tab[val + OFS];
for (x = 1; x < size.width - 1; x++)
int val = ((curr[0] * 5 + curr[1] + prev[0] + next[0])*scale_g - sum*scale_s) >> 10; {
dptr[0] = tab[val + OFS]; sum += vsum[x + wsz2] - vsum[x - wsz2 - 1];
val = ((curr[x] * 4 + curr[x - 1] + curr[x + 1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10;
for (x = 1; x < size.width - 1; x++) dptr[x] = tab[val + OFS];
{ }
sum += vsum[x + wsz2] - vsum[x - wsz2 - 1];
val = ((curr[x] * 4 + curr[x - 1] + curr[x + 1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10; sum += vsum[x + wsz2] - vsum[x - wsz2 - 1];
dptr[x] = tab[val + OFS]; val = ((curr[x] * 5 + curr[x - 1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10;
} dptr[x] = tab[val + OFS];
}
sum += vsum[x + wsz2] - vsum[x - wsz2 - 1]; }
val = ((curr[x] * 5 + curr[x - 1] + prev[x] + next[x])*scale_g - sum*scale_s) >> 10;
dptr[x] = tab[val + OFS]; static void
} prefilterXSobel(const Mat& src, Mat& dst, int ftzero)
} {
int x, y;
static void const int OFS = 256 * 4, TABSZ = OFS * 2 + 256;
prefilterXSobel(const Mat& src, Mat& dst, int ftzero) uchar tab[TABSZ];
{ Size size = src.size();
int x, y;
const int OFS = 256 * 4, TABSZ = OFS * 2 + 256; for (x = 0; x < TABSZ; x++)
uchar tab[TABSZ]; tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero * 2 : x - OFS + ftzero);
Size size = src.size(); uchar val0 = tab[0 + OFS];
for (x = 0; x < TABSZ; x++)
tab[x] = (uchar)(x - OFS < -ftzero ? 0 : x - OFS > ftzero ? ftzero * 2 : x - OFS + ftzero);
uchar val0 = tab[0 + OFS];
#if CV_SSE2 #if CV_SSE2
volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2); volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2);
#endif #endif
for (y = 0; y < size.height - 1; y += 2) for (y = 0; y < size.height - 1; y += 2)
{ {
const uchar* srow1 = src.ptr<uchar>(y); const uchar* srow1 = src.ptr<uchar>(y);
const uchar* srow0 = y > 0 ? srow1 - src.step : size.height > 1 ? srow1 + src.step : srow1; const uchar* srow0 = y > 0 ? srow1 - src.step : size.height > 1 ? srow1 + src.step : srow1;
const uchar* srow2 = y < size.height - 1 ? srow1 + src.step : size.height > 1 ? srow1 - src.step : srow1; const uchar* srow2 = y < size.height - 1 ? srow1 + src.step : size.height > 1 ? srow1 - src.step : srow1;
const uchar* srow3 = y < size.height - 2 ? srow1 + src.step * 2 : srow1; const uchar* srow3 = y < size.height - 2 ? srow1 + src.step * 2 : srow1;
uchar* dptr0 = dst.ptr<uchar>(y); uchar* dptr0 = dst.ptr<uchar>(y);
uchar* dptr1 = dptr0 + dst.step; uchar* dptr1 = dptr0 + dst.step;
dptr0[0] = dptr0[size.width - 1] = dptr1[0] = dptr1[size.width - 1] = val0; dptr0[0] = dptr0[size.width - 1] = dptr1[0] = dptr1[size.width - 1] = val0;
x = 1; x = 1;
#if CV_SSE2 #if CV_SSE2
if (useSIMD) if (useSIMD)
{ {
__m128i z = _mm_setzero_si128(), ftz = _mm_set1_epi16((short)ftzero), __m128i z = _mm_setzero_si128(), ftz = _mm_set1_epi16((short)ftzero),
ftz2 = _mm_set1_epi8(cv::saturate_cast<uchar>(ftzero * 2)); ftz2 = _mm_set1_epi8(cv::saturate_cast<uchar>(ftzero * 2));
for (; x <= size.width - 9; x += 8) for (; x <= size.width - 9; x += 8)
{ {
__m128i c0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x - 1)), z); __m128i c0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x - 1)), z);
__m128i c1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x - 1)), z); __m128i c1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x - 1)), z);
__m128i d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x + 1)), z); __m128i d0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow0 + x + 1)), z);
__m128i d1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x + 1)), z); __m128i d1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow1 + x + 1)), z);
d0 = _mm_sub_epi16(d0, c0); d0 = _mm_sub_epi16(d0, c0);
d1 = _mm_sub_epi16(d1, c1); d1 = _mm_sub_epi16(d1, c1);
__m128i c2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x - 1)), z); __m128i c2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x - 1)), z);
__m128i c3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x - 1)), z); __m128i c3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x - 1)), z);
__m128i d2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x + 1)), z); __m128i d2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow2 + x + 1)), z);
__m128i d3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x + 1)), z); __m128i d3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i*)(srow3 + x + 1)), z);
d2 = _mm_sub_epi16(d2, c2); d2 = _mm_sub_epi16(d2, c2);
d3 = _mm_sub_epi16(d3, c3); d3 = _mm_sub_epi16(d3, c3);
__m128i v0 = _mm_add_epi16(d0, _mm_add_epi16(d2, _mm_add_epi16(d1, d1))); __m128i v0 = _mm_add_epi16(d0, _mm_add_epi16(d2, _mm_add_epi16(d1, d1)));
__m128i v1 = _mm_add_epi16(d1, _mm_add_epi16(d3, _mm_add_epi16(d2, d2))); __m128i v1 = _mm_add_epi16(d1, _mm_add_epi16(d3, _mm_add_epi16(d2, d2)));
v0 = _mm_packus_epi16(_mm_add_epi16(v0, ftz), _mm_add_epi16(v1, ftz)); v0 = _mm_packus_epi16(_mm_add_epi16(v0, ftz), _mm_add_epi16(v1, ftz));
v0 = _mm_min_epu8(v0, ftz2); v0 = _mm_min_epu8(v0, ftz2);
_mm_storel_epi64((__m128i*)(dptr0 + x), v0); _mm_storel_epi64((__m128i*)(dptr0 + x), v0);
_mm_storel_epi64((__m128i*)(dptr1 + x), _mm_unpackhi_epi64(v0, v0)); _mm_storel_epi64((__m128i*)(dptr1 + x), _mm_unpackhi_epi64(v0, v0));
} }
} }
#endif #endif
for (; x < size.width - 1; x++) for (; x < size.width - 1; x++)
{ {
int d0 = srow0[x + 1] - srow0[x - 1], d1 = srow1[x + 1] - srow1[x - 1], int d0 = srow0[x + 1] - srow0[x - 1], d1 = srow1[x + 1] - srow1[x - 1],
d2 = srow2[x + 1] - srow2[x - 1], d3 = srow3[x + 1] - srow3[x - 1]; d2 = srow2[x + 1] - srow2[x - 1], d3 = srow3[x + 1] - srow3[x - 1];
int v0 = tab[d0 + d1 * 2 + d2 + OFS]; int v0 = tab[d0 + d1 * 2 + d2 + OFS];
int v1 = tab[d1 + d2 * 2 + d3 + OFS]; int v1 = tab[d1 + d2 * 2 + d3 + OFS];
dptr0[x] = (uchar)v0; dptr0[x] = (uchar)v0;
dptr1[x] = (uchar)v1; dptr1[x] = (uchar)v1;
} }
} }
for (; y < size.height; y++) for (; y < size.height; y++)
{ {
uchar* dptr = dst.ptr<uchar>(y); uchar* dptr = dst.ptr<uchar>(y);
for (x = 0; x < size.width; x++) for (x = 0; x < size.width; x++)
dptr[x] = val0; dptr[x] = val0;
} }
} }
static const int DISPARITY_SHIFT = 4; static const int DISPARITY_SHIFT = 4;
static void static void
findStereoCorrespondenceBM(const Mat& left, const Mat& right, findStereoCorrespondenceBM(const Mat& left, const Mat& right,
Mat& disp, Mat& cost, const StereoBinaryBMParams& state, Mat& disp, Mat& cost, const StereoBinaryBMParams& state,
uchar* buf, int _dy0, int _dy1) uchar* buf, int _dy0, int _dy1)
{ {
const int ALIGN = 16; const int ALIGN = 16;
int x, y, d; int x, y, d;
int wsz = state.SADWindowSize, wsz2 = wsz / 2; int wsz = state.SADWindowSize, wsz2 = wsz / 2;
int dy0 = MIN(_dy0, wsz2 + 1), dy1 = MIN(_dy1, wsz2 + 1); int dy0 = MIN(_dy0, wsz2 + 1), dy1 = MIN(_dy1, wsz2 + 1);
int ndisp = state.numDisparities; int ndisp = state.numDisparities;
int mindisp = state.minDisparity; int mindisp = state.minDisparity;
int lofs = MAX(ndisp - 1 + mindisp, 0); int lofs = MAX(ndisp - 1 + mindisp, 0);
int rofs = -MIN(ndisp - 1 + mindisp, 0); int rofs = -MIN(ndisp - 1 + mindisp, 0);
int width = left.cols, height = left.rows; int width = left.cols, height = left.rows;
int width1 = width - rofs - ndisp + 1; int width1 = width - rofs - ndisp + 1;
int ftzero = state.preFilterCap; int ftzero = state.preFilterCap;
int textureThreshold = state.textureThreshold; int textureThreshold = state.textureThreshold;
int uniquenessRatio = state.uniquenessRatio; int uniquenessRatio = state.uniquenessRatio;
short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT); short FILTERED = (short)((mindisp - 1) << DISPARITY_SHIFT);
int *sad, *hsad0, *hsad, *hsad_sub, *htext; int *sad, *hsad0, *hsad, *hsad_sub, *htext;
uchar *cbuf0, *cbuf; uchar *cbuf0, *cbuf;
const uchar* lptr0 = left.ptr() + lofs; const uchar* lptr0 = left.ptr() + lofs;
const uchar* rptr0 = right.ptr() + rofs; const uchar* rptr0 = right.ptr() + rofs;
const uchar *lptr, *lptr_sub, *rptr; const uchar *lptr, *lptr_sub, *rptr;
short* dptr = disp.ptr<short>(); short* dptr = disp.ptr<short>();
int sstep = (int)left.step; int sstep = (int)left.step;
int dstep = (int)(disp.step / sizeof(dptr[0])); int dstep = (int)(disp.step / sizeof(dptr[0]));
int cstep = (height + dy0 + dy1)*ndisp; int cstep = (height + dy0 + dy1)*ndisp;
int costbuf = 0; int costbuf = 0;
int coststep = cost.data ? (int)(cost.step / sizeof(costbuf)) : 0; int coststep = cost.data ? (int)(cost.step / sizeof(costbuf)) : 0;
const int TABSZ = 256; const int TABSZ = 256;
uchar tab[TABSZ]; uchar tab[TABSZ];
sad = (int*)alignPtr(buf + sizeof(sad[0]), ALIGN); sad = (int*)alignPtr(buf + sizeof(sad[0]), ALIGN);
hsad0 = (int*)alignPtr(sad + ndisp + 1 + dy0*ndisp, ALIGN); hsad0 = (int*)alignPtr(sad + ndisp + 1 + dy0*ndisp, ALIGN);
htext = (int*)alignPtr((int*)(hsad0 + (height + dy1)*ndisp) + wsz2 + 2, ALIGN); htext = (int*)alignPtr((int*)(hsad0 + (height + dy1)*ndisp) + wsz2 + 2, ALIGN);
cbuf0 = (uchar*)alignPtr((uchar*)(htext + height + wsz2 + 2) + dy0*ndisp, ALIGN); cbuf0 = (uchar*)alignPtr((uchar*)(htext + height + wsz2 + 2) + dy0*ndisp, ALIGN);
for (x = 0; x < TABSZ; x++) for (x = 0; x < TABSZ; x++)
tab[x] = (uchar)std::abs(x - ftzero); tab[x] = (uchar)std::abs(x - ftzero);
// initialize buffers // initialize buffers
memset(hsad0 - dy0*ndisp, 0, (height + dy0 + dy1)*ndisp*sizeof(hsad0[0])); memset(hsad0 - dy0*ndisp, 0, (height + dy0 + dy1)*ndisp*sizeof(hsad0[0]));
memset(htext - wsz2 - 1, 0, (height + wsz + 1)*sizeof(htext[0])); memset(htext - wsz2 - 1, 0, (height + wsz + 1)*sizeof(htext[0]));
for (x = -wsz2 - 1; x < wsz2; x++) for (x = -wsz2 - 1; x < wsz2; x++)
{ {
hsad = hsad0 - dy0*ndisp; cbuf = cbuf0 + (x + wsz2 + 1)*cstep - dy0*ndisp; hsad = hsad0 - dy0*ndisp; cbuf = cbuf0 + (x + wsz2 + 1)*cstep - dy0*ndisp;
lptr = lptr0 + std::min(std::max(x, -lofs), width - lofs - 1) - dy0*sstep; lptr = lptr0 + std::min(std::max(x, -lofs), width - lofs - 1) - dy0*sstep;
rptr = rptr0 + std::min(std::max(x, -rofs), width - rofs - 1) - dy0*sstep; rptr = rptr0 + std::min(std::max(x, -rofs), width - rofs - 1) - dy0*sstep;
for (y = -dy0; y < height + dy1; y++, hsad += ndisp, cbuf += ndisp, lptr += sstep, rptr += sstep) for (y = -dy0; y < height + dy1; y++, hsad += ndisp, cbuf += ndisp, lptr += sstep, rptr += sstep)
{ {
int lval = lptr[0]; int lval = lptr[0];
for (d = 0; d < ndisp; d++) for (d = 0; d < ndisp; d++)
{ {
int diff = std::abs(lval - rptr[d]); int diff = std::abs(lval - rptr[d]);
cbuf[d] = (uchar)diff; cbuf[d] = (uchar)diff;
hsad[d] = (int)(hsad[d] + diff); hsad[d] = (int)(hsad[d] + diff);
} }
htext[y] += tab[lval]; htext[y] += tab[lval];
} }
} }
// initialize the left and right borders of the disparity map // initialize the left and right borders of the disparity map
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
{ {
for (x = 0; x < lofs; x++) for (x = 0; x < lofs; x++)
dptr[y*dstep + x] = FILTERED; dptr[y*dstep + x] = FILTERED;
for (x = lofs + width1; x < width; x++) for (x = lofs + width1; x < width; x++)
dptr[y*dstep + x] = FILTERED; dptr[y*dstep + x] = FILTERED;
} }
dptr += lofs; dptr += lofs;
for (x = 0; x < width1; x++, dptr++) for (x = 0; x < width1; x++, dptr++)
{ {
int* costptr = cost.data ? cost.ptr<int>() + lofs + x : &costbuf; int* costptr = cost.data ? cost.ptr<int>() + lofs + x : &costbuf;
int x0 = x - wsz2 - 1, x1 = x + wsz2; int x0 = x - wsz2 - 1, x1 = x + wsz2;
const uchar* cbuf_sub = cbuf0 + ((x0 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp; const uchar* cbuf_sub = cbuf0 + ((x0 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp;
cbuf = cbuf0 + ((x1 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp; cbuf = cbuf0 + ((x1 + wsz2 + 1) % (wsz + 1))*cstep - dy0*ndisp;
hsad = hsad0 - dy0*ndisp; hsad = hsad0 - dy0*ndisp;
lptr_sub = lptr0 + MIN(MAX(x0, -lofs), width - 1 - lofs) - dy0*sstep; lptr_sub = lptr0 + MIN(MAX(x0, -lofs), width - 1 - lofs) - dy0*sstep;
lptr = lptr0 + MIN(MAX(x1, -lofs), width - 1 - lofs) - dy0*sstep; lptr = lptr0 + MIN(MAX(x1, -lofs), width - 1 - lofs) - dy0*sstep;
rptr = rptr0 + MIN(MAX(x1, -rofs), width - 1 - rofs) - dy0*sstep; rptr = rptr0 + MIN(MAX(x1, -rofs), width - 1 - rofs) - dy0*sstep;
for (y = -dy0; y < height + dy1; y++, cbuf += ndisp, cbuf_sub += ndisp, for (y = -dy0; y < height + dy1; y++, cbuf += ndisp, cbuf_sub += ndisp,
hsad += ndisp, lptr += sstep, lptr_sub += sstep, rptr += sstep) hsad += ndisp, lptr += sstep, lptr_sub += sstep, rptr += sstep)
{ {
int lval = lptr[0]; int lval = lptr[0];
for (d = 0; d < ndisp; d++) for (d = 0; d < ndisp; d++)
{ {
int diff = std::abs(lval - rptr[d]); int diff = std::abs(lval - rptr[d]);
cbuf[d] = (uchar)diff; cbuf[d] = (uchar)diff;
hsad[d] = hsad[d] + diff - cbuf_sub[d]; hsad[d] = hsad[d] + diff - cbuf_sub[d];
} }
htext[y] += tab[lval] - tab[lptr_sub[0]]; htext[y] += tab[lval] - tab[lptr_sub[0]];
} }
// fill borders // fill borders
for (y = dy1; y <= wsz2; y++) for (y = dy1; y <= wsz2; y++)
htext[height + y] = htext[height + dy1 - 1]; htext[height + y] = htext[height + dy1 - 1];
for (y = -wsz2 - 1; y < -dy0; y++) for (y = -wsz2 - 1; y < -dy0; y++)
htext[y] = htext[-dy0]; htext[y] = htext[-dy0];
// initialize sums // initialize sums
int tsum = 0; int tsum = 0;
{ {
for (d = 0; d < ndisp; d++) for (d = 0; d < ndisp; d++)
sad[d] = (int)(hsad0[d - ndisp*dy0] * (wsz2 + 2 - dy0)); sad[d] = (int)(hsad0[d - ndisp*dy0] * (wsz2 + 2 - dy0));
hsad = hsad0 + (1 - dy0)*ndisp; hsad = hsad0 + (1 - dy0)*ndisp;
for (y = 1 - dy0; y < wsz2; y++, hsad += ndisp) for (y = 1 - dy0; y < wsz2; y++, hsad += ndisp)
for (d = 0; d < ndisp; d++) for (d = 0; d < ndisp; d++)
sad[d] = (int)(sad[d] + hsad[d]); sad[d] = (int)(sad[d] + hsad[d]);
for (y = -wsz2 - 1; y < wsz2; y++) for (y = -wsz2 - 1; y < wsz2; y++)
tsum += htext[y]; tsum += htext[y];
} }
// finally, start the real processing // finally, start the real processing
{ {
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
{ {
int minsad = INT_MAX, mind = -1; int minsad = INT_MAX, mind = -1;
hsad = hsad0 + MIN(y + wsz2, height + dy1 - 1)*ndisp; hsad = hsad0 + MIN(y + wsz2, height + dy1 - 1)*ndisp;
hsad_sub = hsad0 + MAX(y - wsz2 - 1, -dy0)*ndisp; hsad_sub = hsad0 + MAX(y - wsz2 - 1, -dy0)*ndisp;
for (d = 0; d < ndisp; d++) for (d = 0; d < ndisp; d++)
{ {
int currsad = sad[d] + hsad[d] - hsad_sub[d]; int currsad = sad[d] + hsad[d] - hsad_sub[d];
sad[d] = currsad; sad[d] = currsad;
if (currsad < minsad) if (currsad < minsad)
{ {
minsad = currsad; minsad = currsad;
mind = d; mind = d;
} }
} }
tsum += htext[y + wsz2] - htext[y - wsz2 - 1]; tsum += htext[y + wsz2] - htext[y - wsz2 - 1];
if (tsum < textureThreshold) if (tsum < textureThreshold)
{ {
dptr[y*dstep] = FILTERED; dptr[y*dstep] = FILTERED;
continue; continue;
} }
if (uniquenessRatio > 0) if (uniquenessRatio > 0)
{ {
int thresh = minsad + (minsad * uniquenessRatio / 100); int thresh = minsad + (minsad * uniquenessRatio / 100);
for (d = 0; d < ndisp; d++) for (d = 0; d < ndisp; d++)
{ {
if ((d < mind - 1 || d > mind + 1) && sad[d] <= thresh) if ((d < mind - 1 || d > mind + 1) && sad[d] <= thresh)
break; break;
} }
if (d < ndisp) if (d < ndisp)
{ {
dptr[y*dstep] = FILTERED; dptr[y*dstep] = FILTERED;
continue; continue;
} }
} }
{ {
sad[-1] = sad[1]; sad[-1] = sad[1];
sad[ndisp] = sad[ndisp - 2]; sad[ndisp] = sad[ndisp - 2];
int p = sad[mind + 1], n = sad[mind - 1]; int p = sad[mind + 1], n = sad[mind - 1];
d = p + n - 2 * sad[mind] + std::abs(p - n); d = p + n - 2 * sad[mind] + std::abs(p - n);
dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp) * 256 + (d != 0 ? (p - n) * 256 / d : 0) + 15) >> 4); dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp) * 256 + (d != 0 ? (p - n) * 256 / d : 0) + 15) >> 4);
costptr[y*coststep] = sad[mind]; costptr[y*coststep] = sad[mind];
} }
} }
} }
} }
} }
struct PrefilterInvoker : public ParallelLoopBody struct PrefilterInvoker : public ParallelLoopBody
{ {
PrefilterInvoker(const Mat& left0, const Mat& right0, Mat& left, Mat& right, PrefilterInvoker(const Mat& left0, const Mat& right0, Mat& left, Mat& right,
uchar* buf0, uchar* buf1, StereoBinaryBMParams* _state) uchar* buf0, uchar* buf1, StereoBinaryBMParams* _state)
{ {
imgs0[0] = &left0; imgs0[1] = &right0; imgs0[0] = &left0; imgs0[1] = &right0;
imgs[0] = &left; imgs[1] = &right; imgs[0] = &left; imgs[1] = &right;
buf[0] = buf0; buf[1] = buf1; buf[0] = buf0; buf[1] = buf1;
state = _state; state = _state;
} }
void operator()(const Range& range) const void operator()(const Range& range) const
{ {
for (int i = range.start; i < range.end; i++) for (int i = range.start; i < range.end; i++)
{ {
if (state->preFilterType == StereoBinaryBM::PREFILTER_NORMALIZED_RESPONSE) if (state->preFilterType == StereoBinaryBM::PREFILTER_NORMALIZED_RESPONSE)
prefilterNorm(*imgs0[i], *imgs[i], state->preFilterSize, state->preFilterCap, buf[i]); prefilterNorm(*imgs0[i], *imgs[i], state->preFilterSize, state->preFilterCap, buf[i]);
else else
prefilterXSobel(*imgs0[i], *imgs[i], state->preFilterCap); prefilterXSobel(*imgs0[i], *imgs[i], state->preFilterCap);
} }
} }
const Mat* imgs0[2]; const Mat* imgs0[2];
Mat* imgs[2]; Mat* imgs[2];
uchar* buf[2]; uchar* buf[2];
StereoBinaryBMParams* state; StereoBinaryBMParams* state;
}; };
struct FindStereoCorrespInvoker : public ParallelLoopBody struct FindStereoCorrespInvoker : public ParallelLoopBody
{ {
FindStereoCorrespInvoker(const Mat& _left, const Mat& _right, FindStereoCorrespInvoker(const Mat& _left, const Mat& _right,
Mat& _disp, StereoBinaryBMParams* _state, Mat& _disp, StereoBinaryBMParams* _state,
int _nstripes, size_t _stripeBufSize, int _nstripes, size_t _stripeBufSize,
bool _useShorts, Rect _validDisparityRect, bool _useShorts, Rect _validDisparityRect,
Mat& _slidingSumBuf, Mat& _cost) Mat& _slidingSumBuf, Mat& _cost)
{ {
left = &_left; right = &_right; left = &_left; right = &_right;
disp = &_disp; state = _state; disp = &_disp; state = _state;
nstripes = _nstripes; stripeBufSize = _stripeBufSize; nstripes = _nstripes; stripeBufSize = _stripeBufSize;
useShorts = _useShorts; useShorts = _useShorts;
validDisparityRect = _validDisparityRect; validDisparityRect = _validDisparityRect;
slidingSumBuf = &_slidingSumBuf; slidingSumBuf = &_slidingSumBuf;
cost = &_cost; cost = &_cost;
} }
void operator()(const Range& range) const void operator()(const Range& range) const
{ {
int cols = left->cols, rows = left->rows; int cols = left->cols, rows = left->rows;
int _row0 = std::min(cvRound(range.start * rows / nstripes), rows); int _row0 = std::min(cvRound(range.start * rows / nstripes), rows);
int _row1 = std::min(cvRound(range.end * rows / nstripes), rows); int _row1 = std::min(cvRound(range.end * rows / nstripes), rows);
uchar *ptr = slidingSumBuf->ptr() + range.start * stripeBufSize; uchar *ptr = slidingSumBuf->ptr() + range.start * stripeBufSize;
int FILTERED = (state->minDisparity - 1) * 16; int FILTERED = (state->minDisparity - 1) * 16;
Rect roi = validDisparityRect & Rect(0, _row0, cols, _row1 - _row0); Rect roi = validDisparityRect & Rect(0, _row0, cols, _row1 - _row0);
if (roi.height == 0) if (roi.height == 0)
return; return;
int row0 = roi.y; int row0 = roi.y;
int row1 = roi.y + roi.height; int row1 = roi.y + roi.height;
Mat part; Mat part;
if (row0 > _row0) if (row0 > _row0)
{ {
part = disp->rowRange(_row0, row0); part = disp->rowRange(_row0, row0);
part = Scalar::all(FILTERED); part = Scalar::all(FILTERED);
} }
if (_row1 > row1) if (_row1 > row1)
{ {
part = disp->rowRange(row1, _row1); part = disp->rowRange(row1, _row1);
part = Scalar::all(FILTERED); part = Scalar::all(FILTERED);
} }
Mat left_i = left->rowRange(row0, row1); Mat left_i = left->rowRange(row0, row1);
Mat right_i = right->rowRange(row0, row1); Mat right_i = right->rowRange(row0, row1);
Mat disp_i = disp->rowRange(row0, row1); Mat disp_i = disp->rowRange(row0, row1);
Mat cost_i = state->disp12MaxDiff >= 0 ? cost->rowRange(row0, row1) : Mat(); Mat cost_i = state->disp12MaxDiff >= 0 ? cost->rowRange(row0, row1) : Mat();
findStereoCorrespondenceBM(left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1); findStereoCorrespondenceBM(left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1);
if (state->disp12MaxDiff >= 0) if (state->disp12MaxDiff >= 0)
validateDisparity(disp_i, cost_i, state->minDisparity, state->numDisparities, state->disp12MaxDiff); validateDisparity(disp_i, cost_i, state->minDisparity, state->numDisparities, state->disp12MaxDiff);
if (roi.x > 0) if (roi.x > 0)
{ {
part = disp_i.colRange(0, roi.x); part = disp_i.colRange(0, roi.x);
part = Scalar::all(FILTERED); part = Scalar::all(FILTERED);
} }
if (roi.x + roi.width < cols) if (roi.x + roi.width < cols)
{ {
part = disp_i.colRange(roi.x + roi.width, cols); part = disp_i.colRange(roi.x + roi.width, cols);
part = Scalar::all(FILTERED); part = Scalar::all(FILTERED);
} }
} }
protected: protected:
const Mat *left, *right; const Mat *left, *right;
Mat* disp, *slidingSumBuf, *cost; Mat* disp, *slidingSumBuf, *cost;
StereoBinaryBMParams *state; StereoBinaryBMParams *state;
int nstripes; int nstripes;
size_t stripeBufSize; size_t stripeBufSize;
bool useShorts; bool useShorts;
Rect validDisparityRect; Rect validDisparityRect;
}; };
class StereoBinaryBMImpl : public StereoBinaryBM class StereoBinaryBMImpl : public StereoBinaryBM
{ {
public: public:
StereoBinaryBMImpl() StereoBinaryBMImpl()
{ {
params = StereoBinaryBMParams(); params = StereoBinaryBMParams();
} }
StereoBinaryBMImpl(int _numDisparities, int _SADWindowSize) StereoBinaryBMImpl(int _numDisparities, int _SADWindowSize)
{ {
params = StereoBinaryBMParams(_numDisparities, _SADWindowSize); params = StereoBinaryBMParams(_numDisparities, _SADWindowSize);
} }
void compute(InputArray leftarr, InputArray rightarr, OutputArray disparr) void compute(InputArray leftarr, InputArray rightarr, OutputArray disparr)
{ {
int dtype = disparr.fixedType() ? disparr.type() : params.dispType; int dtype = disparr.fixedType() ? disparr.type() : params.dispType;
Size leftsize = leftarr.size(); Size leftsize = leftarr.size();
if (leftarr.size() != rightarr.size()) if (leftarr.size() != rightarr.size())
CV_Error(Error::StsUnmatchedSizes, "All the images must have the same size"); CV_Error(Error::StsUnmatchedSizes, "All the images must have the same size");
if (leftarr.type() != CV_8UC1 || rightarr.type() != CV_8UC1) if (leftarr.type() != CV_8UC1 || rightarr.type() != CV_8UC1)
CV_Error(Error::StsUnsupportedFormat, "Both input images must have CV_8UC1"); CV_Error(Error::StsUnsupportedFormat, "Both input images must have CV_8UC1");
if (dtype != CV_16SC1 && dtype != CV_32FC1) if (dtype != CV_16SC1 && dtype != CV_32FC1)
CV_Error(Error::StsUnsupportedFormat, "Disparity image must have CV_16SC1 or CV_32FC1 format"); CV_Error(Error::StsUnsupportedFormat, "Disparity image must have CV_16SC1 or CV_32FC1 format");
if (params.preFilterType != PREFILTER_NORMALIZED_RESPONSE && if (params.preFilterType != PREFILTER_NORMALIZED_RESPONSE &&
params.preFilterType != PREFILTER_XSOBEL) params.preFilterType != PREFILTER_XSOBEL)
CV_Error(Error::StsOutOfRange, "preFilterType must be = CV_STEREO_BM_NORMALIZED_RESPONSE"); CV_Error(Error::StsOutOfRange, "preFilterType must be = CV_STEREO_BM_NORMALIZED_RESPONSE");
if (params.preFilterSize < 5 || params.preFilterSize > 255 || params.preFilterSize % 2 == 0) if (params.preFilterSize < 5 || params.preFilterSize > 255 || params.preFilterSize % 2 == 0)
CV_Error(Error::StsOutOfRange, "preFilterSize must be odd and be within 5..255"); CV_Error(Error::StsOutOfRange, "preFilterSize must be odd and be within 5..255");
if (params.preFilterCap < 1 || params.preFilterCap > 63) if (params.preFilterCap < 1 || params.preFilterCap > 63)
CV_Error(Error::StsOutOfRange, "preFilterCap must be within 1..63"); CV_Error(Error::StsOutOfRange, "preFilterCap must be within 1..63");
if (params.SADWindowSize < 5 || params.SADWindowSize > 255 || params.SADWindowSize % 2 == 0 || if (params.SADWindowSize < 5 || params.SADWindowSize > 255 || params.SADWindowSize % 2 == 0 ||
params.SADWindowSize >= std::min(leftsize.width, leftsize.height)) params.SADWindowSize >= std::min(leftsize.width, leftsize.height))
CV_Error(Error::StsOutOfRange, "SADWindowSize must be odd, be within 5..255 and be not larger than image width or height"); CV_Error(Error::StsOutOfRange, "SADWindowSize must be odd, be within 5..255 and be not larger than image width or height");
if (params.numDisparities <= 0 || params.numDisparities % 16 != 0) if (params.numDisparities <= 0 || params.numDisparities % 16 != 0)
CV_Error(Error::StsOutOfRange, "numDisparities must be positive and divisble by 16"); CV_Error(Error::StsOutOfRange, "numDisparities must be positive and divisble by 16");
if (params.textureThreshold < 0) if (params.textureThreshold < 0)
CV_Error(Error::StsOutOfRange, "texture threshold must be non-negative"); CV_Error(Error::StsOutOfRange, "texture threshold must be non-negative");
if (params.uniquenessRatio < 0) if (params.uniquenessRatio < 0)
CV_Error(Error::StsOutOfRange, "uniqueness ratio must be non-negative"); CV_Error(Error::StsOutOfRange, "uniqueness ratio must be non-negative");
int FILTERED = (params.minDisparity - 1) << DISPARITY_SHIFT; int FILTERED = (params.minDisparity - 1) << DISPARITY_SHIFT;
Mat left0 = leftarr.getMat(), right0 = rightarr.getMat(); Mat left0 = leftarr.getMat(), right0 = rightarr.getMat();
disparr.create(left0.size(), dtype); disparr.create(left0.size(), dtype);
Mat disp0 = disparr.getMat(); Mat disp0 = disparr.getMat();
preFilteredImg0.create(left0.size(), CV_8U); preFilteredImg0.create(left0.size(), CV_8U);
preFilteredImg1.create(left0.size(), CV_8U); preFilteredImg1.create(left0.size(), CV_8U);
cost.create(left0.size(), CV_16S); cost.create(left0.size(), CV_16S);
Mat left = preFilteredImg0, right = preFilteredImg1; Mat left = preFilteredImg0, right = preFilteredImg1;
int mindisp = params.minDisparity; int mindisp = params.minDisparity;
int ndisp = params.numDisparities; int ndisp = params.numDisparities;
int width = left0.cols; int width = left0.cols;
int height = left0.rows; int height = left0.rows;
int lofs = std::max(ndisp - 1 + mindisp, 0); int lofs = std::max(ndisp - 1 + mindisp, 0);
int rofs = -std::min(ndisp - 1 + mindisp, 0); int rofs = -std::min(ndisp - 1 + mindisp, 0);
int width1 = width - rofs - ndisp + 1; int width1 = width - rofs - ndisp + 1;
if (lofs >= width || rofs >= width || width1 < 1) if (lofs >= width || rofs >= width || width1 < 1)
{ {
disp0 = Scalar::all(FILTERED * (disp0.type() < CV_32F ? 1 : 1. / (1 << DISPARITY_SHIFT))); disp0 = Scalar::all(FILTERED * (disp0.type() < CV_32F ? 1 : 1. / (1 << DISPARITY_SHIFT)));
return; return;
} }
Mat disp = disp0; Mat disp = disp0;
if (dtype == CV_32F) if (dtype == CV_32F)
{ {
dispbuf.create(disp0.size(), CV_16S); dispbuf.create(disp0.size(), CV_16S);
disp = dispbuf; disp = dispbuf;
} }
int wsz = params.SADWindowSize; int wsz = params.SADWindowSize;
int bufSize0 = (int)((ndisp + 2)*sizeof(int)); int bufSize0 = (int)((ndisp + 2)*sizeof(int));
bufSize0 += (int)((height + wsz + 2)*ndisp*sizeof(int)); bufSize0 += (int)((height + wsz + 2)*ndisp*sizeof(int));
bufSize0 += (int)((height + wsz + 2)*sizeof(int)); bufSize0 += (int)((height + wsz + 2)*sizeof(int));
bufSize0 += (int)((height + wsz + 2)*ndisp*(wsz + 2)*sizeof(uchar) + 256); bufSize0 += (int)((height + wsz + 2)*ndisp*(wsz + 2)*sizeof(uchar) + 256);
int bufSize1 = (int)((width + params.preFilterSize + 2) * sizeof(int) + 256); int bufSize1 = (int)((width + params.preFilterSize + 2) * sizeof(int) + 256);
int bufSize2 = 0; int bufSize2 = 0;
if (params.speckleRange >= 0 && params.speckleWindowSize > 0) if (params.speckleRange >= 0 && params.speckleWindowSize > 0)
bufSize2 = width*height*(sizeof(Point_<short>) + sizeof(int) + sizeof(uchar)); bufSize2 = width*height*(sizeof(Point_<short>) + sizeof(int) + sizeof(uchar));
#if CV_SSE2 #if CV_SSE2
bool useShorts = params.preFilterCap <= 31 && params.SADWindowSize <= 21 && checkHardwareSupport(CV_CPU_SSE2); bool useShorts = params.preFilterCap <= 31 && params.SADWindowSize <= 21 && checkHardwareSupport(CV_CPU_SSE2);
#else #else
const bool useShorts = false; const bool useShorts = false;
#endif #endif
const double SAD_overhead_coeff = 10.0;
const double SAD_overhead_coeff = 10.0; double N0 = 8000000 / (useShorts ? 1 : 4); // approx tbb's min number instructions reasonable for one thread
double N0 = 8000000 / (useShorts ? 1 : 4); // approx tbb's min number instructions reasonable for one thread double maxStripeSize = std::min(std::max(N0 / (width * ndisp), (wsz - 1) * SAD_overhead_coeff), (double)height);
double maxStripeSize = std::min(std::max(N0 / (width * ndisp), (wsz - 1) * SAD_overhead_coeff), (double)height); int nstripes = cvCeil(height / maxStripeSize);
int nstripes = cvCeil(height / maxStripeSize); int bufSize = std::max(bufSize0 * nstripes, std::max(bufSize1 * 2, bufSize2));
int bufSize = std::max(bufSize0 * nstripes, std::max(bufSize1 * 2, bufSize2));
if (slidingSumBuf.cols < bufSize)
if (slidingSumBuf.cols < bufSize) slidingSumBuf.create(1, bufSize, CV_8U);
slidingSumBuf.create(1, bufSize, CV_8U);
uchar *_buf = slidingSumBuf.ptr();
uchar *_buf = slidingSumBuf.ptr();
parallel_for_(Range(0, 2), PrefilterInvoker(left0, right0, left, right, _buf, _buf + bufSize1, &params), 1);
parallel_for_(Range(0, 2), PrefilterInvoker(left0, right0, left, right, _buf, _buf + bufSize1, &params), 1);
Rect validDisparityRect(0, 0, width, height), R1 = params.roi1, R2 = params.roi2;
Rect validDisparityRect(0, 0, width, height), R1 = params.roi1, R2 = params.roi2; validDisparityRect = getValidDisparityROI(R1.area() > 0 ? Rect(0, 0, width, height) : validDisparityRect,
validDisparityRect = getValidDisparityROI(R1.area() > 0 ? Rect(0, 0, width, height) : validDisparityRect, R2.area() > 0 ? Rect(0, 0, width, height) : validDisparityRect,
R2.area() > 0 ? Rect(0, 0, width, height) : validDisparityRect, params.minDisparity, params.numDisparities,
params.minDisparity, params.numDisparities, params.SADWindowSize);
params.SADWindowSize);
parallel_for_(Range(0, nstripes),
parallel_for_(Range(0, nstripes), FindStereoCorrespInvoker(left, right, disp, &params, nstripes,
FindStereoCorrespInvoker(left, right, disp, &params, nstripes, bufSize0, useShorts, validDisparityRect,
bufSize0, useShorts, validDisparityRect, slidingSumBuf, cost));
slidingSumBuf, cost));
if (params.speckleRange >= 0 && params.speckleWindowSize > 0)
if (params.speckleRange >= 0 && params.speckleWindowSize > 0) filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf);
filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf);
if (disp0.data != disp.data)
if (disp0.data != disp.data) disp.convertTo(disp0, disp0.type(), 1. / (1 << DISPARITY_SHIFT), 0);
disp.convertTo(disp0, disp0.type(), 1. / (1 << DISPARITY_SHIFT), 0); }
}
int getMinDisparity() const { return params.minDisparity; }
int getMinDisparity() const { return params.minDisparity; } void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; }
void setMinDisparity(int minDisparity) { params.minDisparity = minDisparity; }
int getNumDisparities() const { return params.numDisparities; }
int getNumDisparities() const { return params.numDisparities; } void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; }
void setNumDisparities(int numDisparities) { params.numDisparities = numDisparities; }
int getBlockSize() const { return params.SADWindowSize; }
int getBlockSize() const { return params.SADWindowSize; } void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; }
void setBlockSize(int blockSize) { params.SADWindowSize = blockSize; }
int getSpeckleWindowSize() const { return params.speckleWindowSize; }
int getSpeckleWindowSize() const { return params.speckleWindowSize; } void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; }
void setSpeckleWindowSize(int speckleWindowSize) { params.speckleWindowSize = speckleWindowSize; }
int getSpeckleRange() const { return params.speckleRange; }
int getSpeckleRange() const { return params.speckleRange; } void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; }
void setSpeckleRange(int speckleRange) { params.speckleRange = speckleRange; }
int getDisp12MaxDiff() const { return params.disp12MaxDiff; }
int getDisp12MaxDiff() const { return params.disp12MaxDiff; } void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; }
void setDisp12MaxDiff(int disp12MaxDiff) { params.disp12MaxDiff = disp12MaxDiff; }
int getPreFilterType() const { return params.preFilterType; }
int getPreFilterType() const { return params.preFilterType; } void setPreFilterType(int preFilterType) { params.preFilterType = preFilterType; }
void setPreFilterType(int preFilterType) { params.preFilterType = preFilterType; }
int getPreFilterSize() const { return params.preFilterSize; }
int getPreFilterSize() const { return params.preFilterSize; } void setPreFilterSize(int preFilterSize) { params.preFilterSize = preFilterSize; }
void setPreFilterSize(int preFilterSize) { params.preFilterSize = preFilterSize; }
int getPreFilterCap() const { return params.preFilterCap; }
int getPreFilterCap() const { return params.preFilterCap; } void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; }
void setPreFilterCap(int preFilterCap) { params.preFilterCap = preFilterCap; }
int getTextureThreshold() const { return params.textureThreshold; }
int getTextureThreshold() const { return params.textureThreshold; } void setTextureThreshold(int textureThreshold) { params.textureThreshold = textureThreshold; }
void setTextureThreshold(int textureThreshold) { params.textureThreshold = textureThreshold; }
int getUniquenessRatio() const { return params.uniquenessRatio; }
int getUniquenessRatio() const { return params.uniquenessRatio; } void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; }
void setUniquenessRatio(int uniquenessRatio) { params.uniquenessRatio = uniquenessRatio; }
int getSmallerBlockSize() const { return 0; }
int getSmallerBlockSize() const { return 0; } void setSmallerBlockSize(int) {}
void setSmallerBlockSize(int) {}
Rect getROI1() const { return params.roi1; }
Rect getROI1() const { return params.roi1; } void setROI1(Rect roi1) { params.roi1 = roi1; }
void setROI1(Rect roi1) { params.roi1 = roi1; }
Rect getROI2() const { return params.roi2; }
Rect getROI2() const { return params.roi2; } void setROI2(Rect roi2) { params.roi2 = roi2; }
void setROI2(Rect roi2) { params.roi2 = roi2; }
void write(FileStorage& fs) const
void write(FileStorage& fs) const {
{ fs << "name" << name_
fs << "name" << name_ << "minDisparity" << params.minDisparity
<< "minDisparity" << params.minDisparity << "numDisparities" << params.numDisparities
<< "numDisparities" << params.numDisparities << "blockSize" << params.SADWindowSize
<< "blockSize" << params.SADWindowSize << "speckleWindowSize" << params.speckleWindowSize
<< "speckleWindowSize" << params.speckleWindowSize << "speckleRange" << params.speckleRange
<< "speckleRange" << params.speckleRange << "disp12MaxDiff" << params.disp12MaxDiff
<< "disp12MaxDiff" << params.disp12MaxDiff << "preFilterType" << params.preFilterType
<< "preFilterType" << params.preFilterType << "preFilterSize" << params.preFilterSize
<< "preFilterSize" << params.preFilterSize << "preFilterCap" << params.preFilterCap
<< "preFilterCap" << params.preFilterCap << "textureThreshold" << params.textureThreshold
<< "textureThreshold" << params.textureThreshold << "uniquenessRatio" << params.uniquenessRatio;
<< "uniquenessRatio" << params.uniquenessRatio; }
}
void read(const FileNode& fn)
void read(const FileNode& fn) {
{ FileNode n = fn["name"];
FileNode n = fn["name"]; CV_Assert(n.isString() && String(n) == name_);
CV_Assert(n.isString() && String(n) == name_); params.minDisparity = (int)fn["minDisparity"];
params.minDisparity = (int)fn["minDisparity"]; params.numDisparities = (int)fn["numDisparities"];
params.numDisparities = (int)fn["numDisparities"]; params.SADWindowSize = (int)fn["blockSize"];
params.SADWindowSize = (int)fn["blockSize"]; params.speckleWindowSize = (int)fn["speckleWindowSize"];
params.speckleWindowSize = (int)fn["speckleWindowSize"]; params.speckleRange = (int)fn["speckleRange"];
params.speckleRange = (int)fn["speckleRange"]; params.disp12MaxDiff = (int)fn["disp12MaxDiff"];
params.disp12MaxDiff = (int)fn["disp12MaxDiff"]; params.preFilterType = (int)fn["preFilterType"];
params.preFilterType = (int)fn["preFilterType"]; params.preFilterSize = (int)fn["preFilterSize"];
params.preFilterSize = (int)fn["preFilterSize"]; params.preFilterCap = (int)fn["preFilterCap"];
params.preFilterCap = (int)fn["preFilterCap"]; params.textureThreshold = (int)fn["textureThreshold"];
params.textureThreshold = (int)fn["textureThreshold"]; params.uniquenessRatio = (int)fn["uniquenessRatio"];
params.uniquenessRatio = (int)fn["uniquenessRatio"]; params.roi1 = params.roi2 = Rect();
params.roi1 = params.roi2 = Rect(); }
}
StereoBinaryBMParams params;
StereoBinaryBMParams params; Mat preFilteredImg0, preFilteredImg1, cost, dispbuf;
Mat preFilteredImg0, preFilteredImg1, cost, dispbuf; Mat slidingSumBuf;
Mat slidingSumBuf;
static const char* name_;
static const char* name_; };
};
const char* StereoBinaryBMImpl::name_ = "StereoMatcher.BM";
const char* StereoBinaryBMImpl::name_ = "StereoMatcher.BM";
Ptr<StereoBinaryBM> StereoBinaryBM::create(int _numDisparities, int _SADWindowSize)
Ptr<StereoBinaryBM> StereoBinaryBM::create(int _numDisparities, int _SADWindowSize) {
{ return makePtr<StereoBinaryBMImpl>(_numDisparities, _SADWindowSize);
return makePtr<StereoBinaryBMImpl>(_numDisparities, _SADWindowSize); }
} }
}
} }
/* End of file. */ /* End of file. */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment