1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 00:03:03 +04:00

Merge remote-tracking branch 'upstream/3.4' into merge-3.4

This commit is contained in:
Alexander Alekhin
2020-02-10 19:40:29 +03:00
26 changed files with 1517 additions and 1313 deletions
+160 -100
View File
@@ -48,8 +48,10 @@
#include "precomp.hpp"
#include <stdio.h>
#include <limits>
#include <vector>
#include "opencl_kernels_calib3d.hpp"
#include "opencv2/core/hal/intrin.hpp"
#include "opencv2/core/utils/buffer_area.private.hpp"
namespace cv
{
@@ -85,6 +87,19 @@ struct StereoBMParams
Rect roi1, roi2;
int disp12MaxDiff;
int dispType;
inline bool useShorts() const
{
return preFilterCap <= 31 && SADWindowSize <= 21;
}
inline bool useFilterSpeckles() const
{
return speckleRange >= 0 && speckleWindowSize > 0;
}
inline bool useNormPrefilter() const
{
return preFilterType == StereoBM::PREFILTER_NORMALIZED_RESPONSE;
}
};
#ifdef HAVE_OPENCL
@@ -110,10 +125,10 @@ static bool ocl_prefilter_norm(InputArray _input, OutputArray _output, int winsi
}
#endif
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, int *buf )
{
int x, y, wsz2 = winsize/2;
int* vsum = (int*)alignPtr(buf + (wsz2 + 1)*sizeof(vsum[0]), 32);
int* vsum = buf + (wsz2 + 1);
int scale_g = winsize*winsize/8, scale_s = (1024 + scale_g)/(scale_g*2);
const int OFS = 256*5, TABSZ = OFS*2 + 256;
uchar tab[TABSZ];
@@ -309,13 +324,77 @@ inline int dispDescale(int v1, int v2, int d)
return (int)(v1*256 + (d != 0 ? v2*256/d : 0)); // no need to add 127, this will be converted to float
}
class BufferBM
{
static const int TABSZ = 256;
public:
std::vector<int*> sad;
std::vector<int*> hsad;
std::vector<int*> htext;
std::vector<uchar*> cbuf0;
std::vector<ushort*> sad_short;
std::vector<ushort*> hsad_short;
int *prefilter[2];
uchar tab[TABSZ];
private:
utils::BufferArea area;
public:
BufferBM(size_t nstripes, size_t width, size_t height, const StereoBMParams& params)
: sad(nstripes, NULL),
hsad(nstripes, NULL),
htext(nstripes, NULL),
cbuf0(nstripes, NULL),
sad_short(nstripes, NULL),
hsad_short(nstripes, NULL)
{
const int wsz = params.SADWindowSize;
const int ndisp = params.numDisparities;
const int ftzero = params.preFilterCap;
for (size_t i = 0; i < nstripes; ++i)
{
// 1D: [1][ ndisp ][1]
#if CV_SIMD
if (params.useShorts())
area.allocate(sad_short[i], ndisp + 2);
else
#endif
area.allocate(sad[i], ndisp + 2);
// 2D: [ wsz/2 + 1 ][ height ][ wsz/2 + 1 ] * [ ndisp ]
#if CV_SIMD
if (params.useShorts())
area.allocate(hsad_short[i], (height + wsz + 2) * ndisp);
else
#endif
area.allocate(hsad[i], (height + wsz + 2) * ndisp);
// 1D: [ wsz/2 + 1 ][ height ][ wsz/2 + 1 ]
area.allocate(htext[i], (height + wsz + 2));
// 3D: [ wsz/2 + 1 ][ height ][ wsz/2 + 1 ] * [ ndisp ] * [ wsz/2 + 1 ][ wsz/2 + 1 ]
area.allocate(cbuf0[i], ((height + wsz + 2) * ndisp * (wsz + 2) + 256));
}
if (params.useNormPrefilter())
{
for (size_t i = 0; i < 2; ++i)
area.allocate(prefilter[0], width + params.preFilterSize + 2);
}
area.commit();
// static table
for (int x = 0; x < TABSZ; x++)
tab[x] = (uchar)std::abs(x - ftzero);
}
};
#if CV_SIMD
template <typename dType>
static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
Mat& disp, Mat& cost, StereoBMParams& state,
uchar* buf, int _dy0, int _dy1 )
Mat& disp, Mat& cost, const StereoBMParams& state,
int _dy0, int _dy1, const BufferBM & bufX, size_t bufNum )
{
const int ALIGN = CV_SIMD_WIDTH;
int x, y, d;
int wsz = state.SADWindowSize, wsz2 = wsz/2;
int dy0 = MIN(_dy0, wsz2+1), dy1 = MIN(_dy1, wsz2+1);
@@ -325,15 +404,13 @@ static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
int rofs = -MIN(ndisp - 1 + mindisp, 0);
int width = left.cols, height = left.rows;
int width1 = width - rofs - ndisp + 1;
int ftzero = state.preFilterCap;
int textureThreshold = state.textureThreshold;
int uniquenessRatio = state.uniquenessRatio;
const int disp_shift = dispShiftTemplate<dType>::value;
dType FILTERED = (dType)((mindisp - 1) << disp_shift);
ushort *sad, *hsad0, *hsad, *hsad_sub;
int *htext;
uchar *cbuf0, *cbuf;
ushort *hsad, *hsad_sub;
uchar *cbuf;
const uchar* lptr0 = left.ptr() + lofs;
const uchar* rptr0 = right.ptr() + rofs;
const uchar *lptr, *lptr_sub, *rptr;
@@ -343,23 +420,20 @@ static void findStereoCorrespondenceBM_SIMD( const Mat& left, const Mat& right,
int cstep = (height + dy0 + dy1)*ndisp;
short costbuf = 0;
int coststep = cost.data ? (int)(cost.step/sizeof(costbuf)) : 0;
const int TABSZ = 256;
uchar tab[TABSZ];
const uchar * tab = bufX.tab;
short v_seq[v_int16::nlanes];
for (short i = 0; i < v_int16::nlanes; ++i)
v_seq[i] = i;
sad = (ushort*)alignPtr(buf + sizeof(sad[0]), ALIGN);
hsad0 = (ushort*)alignPtr(sad + ndisp + 1 + dy0*ndisp, ALIGN);
htext = (int*)alignPtr((int*)(hsad0 + (height+dy1)*ndisp) + wsz2 + 2, ALIGN);
cbuf0 = (uchar*)alignPtr((uchar*)(htext + height + wsz2 + 2) + dy0*ndisp, ALIGN);
for( x = 0; x < TABSZ; x++ )
tab[x] = (uchar)std::abs(x - ftzero);
ushort *sad = bufX.sad_short[bufNum] + 1;
ushort *hsad0 = bufX.hsad_short[bufNum] + (wsz2 + 1) * ndisp;
int *htext = bufX.htext[bufNum] + (wsz2 + 1);
uchar *cbuf0 = bufX.cbuf0[bufNum] + (wsz2 + 1) * ndisp;
// initialize buffers
memset( hsad0 - dy0*ndisp, 0, (height + dy0 + dy1)*ndisp*sizeof(hsad0[0]) );
memset( htext - wsz2 - 1, 0, (height + wsz + 1)*sizeof(htext[0]) );
memset(sad - 1, 0, (ndisp + 2) * sizeof(sad[0]));
memset(hsad0 - dy0 * ndisp, 0, (height + wsz + 2) * ndisp * sizeof(hsad[0]));
memset(htext - dy0, 0, (height + wsz + 2) * sizeof(htext[0]));
for( x = -wsz2-1; x < wsz2; x++ )
{
@@ -594,10 +668,9 @@ template <typename mType>
static void
findStereoCorrespondenceBM( const Mat& left, const Mat& right,
Mat& disp, Mat& cost, const StereoBMParams& state,
uchar* buf, int _dy0, int _dy1 )
int _dy0, int _dy1, const BufferBM & bufX, size_t bufNum )
{
const int ALIGN = CV_SIMD_WIDTH;
int x, y, d;
int wsz = state.SADWindowSize, wsz2 = wsz/2;
int dy0 = MIN(_dy0, wsz2+1), dy1 = MIN(_dy1, wsz2+1);
@@ -607,14 +680,13 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
int rofs = -MIN(ndisp - 1 + mindisp, 0);
int width = left.cols, height = left.rows;
int width1 = width - rofs - ndisp + 1;
int ftzero = state.preFilterCap;
int textureThreshold = state.textureThreshold;
int uniquenessRatio = state.uniquenessRatio;
const int disp_shift = dispShiftTemplate<mType>::value;
mType FILTERED = (mType)((mindisp - 1) << disp_shift);
int *sad, *hsad0, *hsad, *hsad_sub, *htext;
uchar *cbuf0, *cbuf;
int *hsad, *hsad_sub;
uchar *cbuf;
const uchar* lptr0 = left.ptr() + lofs;
const uchar* rptr0 = right.ptr() + rofs;
const uchar *lptr, *lptr_sub, *rptr;
@@ -624,8 +696,7 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
int cstep = (height+dy0+dy1)*ndisp;
int costbuf = 0;
int coststep = cost.data ? (int)(cost.step/sizeof(costbuf)) : 0;
const int TABSZ = 256;
uchar tab[TABSZ];
const uchar * tab = bufX.tab;
#if CV_SIMD
int v_seq[v_int32::nlanes];
@@ -634,17 +705,15 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
v_int32 d0_4 = vx_load(v_seq), dd_4 = vx_setall_s32(v_int32::nlanes);
#endif
sad = (int*)alignPtr(buf + sizeof(sad[0]), ALIGN);
hsad0 = (int*)alignPtr(sad + ndisp + 1 + dy0*ndisp, ALIGN);
htext = (int*)alignPtr((int*)(hsad0 + (height+dy1)*ndisp) + wsz2 + 2, ALIGN);
cbuf0 = (uchar*)alignPtr((uchar*)(htext + height + wsz2 + 2) + dy0*ndisp, ALIGN);
for( x = 0; x < TABSZ; x++ )
tab[x] = (uchar)std::abs(x - ftzero);
int *sad = bufX.sad[bufNum] + 1;
int *hsad0 = bufX.hsad[bufNum] + (wsz2 + 1) * ndisp;
int *htext = bufX.htext[bufNum] + (wsz2 + 1);
uchar *cbuf0 = bufX.cbuf0[bufNum] + (wsz2 + 1) * ndisp;
// initialize buffers
memset( hsad0 - dy0*ndisp, 0, (height + dy0 + dy1)*ndisp*sizeof(hsad0[0]) );
memset( htext - wsz2 - 1, 0, (height + wsz + 1)*sizeof(htext[0]) );
memset(sad - 1, 0, (ndisp + 2) * sizeof(sad[0]));
memset(hsad0 - dy0 * ndisp, 0, (height + wsz + 2) * ndisp * sizeof(hsad[0]));
memset(htext - dy0, 0, (height + wsz + 2) * sizeof(htext[0]));
for( x = -wsz2-1; x < wsz2; x++ )
{
@@ -890,7 +959,7 @@ findStereoCorrespondenceBM( const Mat& left, const Mat& right,
#ifdef HAVE_OPENCL
static bool ocl_prefiltering(InputArray left0, InputArray right0, OutputArray left, OutputArray right, StereoBMParams* state)
{
if( state->preFilterType == StereoBM::PREFILTER_NORMALIZED_RESPONSE )
if (state->useNormPrefilter())
{
if(!ocl_prefilter_norm( left0, left, state->preFilterSize, state->preFilterCap))
return false;
@@ -911,29 +980,28 @@ static bool ocl_prefiltering(InputArray left0, InputArray right0, OutputArray le
struct PrefilterInvoker : public ParallelLoopBody
{
PrefilterInvoker(const Mat& left0, const Mat& right0, Mat& left, Mat& right,
uchar* buf0, uchar* buf1, StereoBMParams* _state)
const BufferBM &bufX_, const StereoBMParams &state_)
: bufX(bufX_), state(state_)
{
imgs0[0] = &left0; imgs0[1] = &right0;
imgs[0] = &left; imgs[1] = &right;
buf[0] = buf0; buf[1] = buf1;
state = _state;
}
void operator()(const Range& range) const CV_OVERRIDE
{
for( int i = range.start; i < range.end; i++ )
{
if( state->preFilterType == StereoBM::PREFILTER_NORMALIZED_RESPONSE )
prefilterNorm( *imgs0[i], *imgs[i], state->preFilterSize, state->preFilterCap, buf[i] );
if (state.useNormPrefilter())
prefilterNorm( *imgs0[i], *imgs[i], state.preFilterSize, state.preFilterCap, bufX.prefilter[i] );
else
prefilterXSobel( *imgs0[i], *imgs[i], state->preFilterCap );
prefilterXSobel( *imgs0[i], *imgs[i], state.preFilterCap );
}
}
const Mat* imgs0[2];
Mat* imgs[2];
uchar* buf[2];
StereoBMParams* state;
const BufferBM &bufX;
const StereoBMParams &state;
};
#ifdef HAVE_OPENCL
@@ -986,18 +1054,17 @@ static bool ocl_stereobm( InputArray _left, InputArray _right,
struct FindStereoCorrespInvoker : public ParallelLoopBody
{
FindStereoCorrespInvoker( const Mat& _left, const Mat& _right,
Mat& _disp, StereoBMParams* _state,
int _nstripes, size_t _stripeBufSize,
bool _useShorts, Rect _validDisparityRect,
Mat& _slidingSumBuf, Mat& _cost )
Mat& _disp, const StereoBMParams &_state,
int _nstripes,
Rect _validDisparityRect,
Mat& _cost, const BufferBM & buf_ )
: state(_state), buf(buf_)
{
CV_Assert( _disp.type() == CV_16S || _disp.type() == CV_32S );
left = &_left; right = &_right;
disp = &_disp; state = _state;
nstripes = _nstripes; stripeBufSize = _stripeBufSize;
useShorts = _useShorts;
disp = &_disp;
nstripes = _nstripes;
validDisparityRect = _validDisparityRect;
slidingSumBuf = &_slidingSumBuf;
cost = &_cost;
}
@@ -1006,11 +1073,10 @@ struct FindStereoCorrespInvoker : public ParallelLoopBody
int cols = left->cols, rows = left->rows;
int _row0 = std::min(cvRound(range.start * rows / nstripes), rows);
int _row1 = std::min(cvRound(range.end * rows / nstripes), rows);
uchar *ptr = slidingSumBuf->ptr() + range.start * stripeBufSize;
int dispShift = disp->type() == CV_16S ? DISPARITY_SHIFT_16S :
DISPARITY_SHIFT_32S;
int FILTERED = (state->minDisparity - 1) << dispShift;
int FILTERED = (state.minDisparity - 1) << dispShift;
Rect roi = validDisparityRect & Rect(0, _row0, cols, _row1 - _row0);
if( roi.height == 0 )
@@ -1033,27 +1099,27 @@ struct FindStereoCorrespInvoker : public ParallelLoopBody
Mat left_i = left->rowRange(row0, row1);
Mat right_i = right->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();
#if CV_SIMD
if (useShorts)
if (state.useShorts())
{
if( disp_i.type() == CV_16S)
findStereoCorrespondenceBM_SIMD<short>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
findStereoCorrespondenceBM_SIMD<short>( left_i, right_i, disp_i, cost_i, state, row0, rows - row1, buf, range.start );
else
findStereoCorrespondenceBM_SIMD<int>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1);
findStereoCorrespondenceBM_SIMD<int>( left_i, right_i, disp_i, cost_i, state, row0, rows - row1, buf, range.start);
}
else
#endif
{
if( disp_i.type() == CV_16S )
findStereoCorrespondenceBM<short>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
findStereoCorrespondenceBM<short>( left_i, right_i, disp_i, cost_i, state, row0, rows - row1, buf, range.start );
else
findStereoCorrespondenceBM<int>( left_i, right_i, disp_i, cost_i, *state, ptr, row0, rows - row1 );
findStereoCorrespondenceBM<int>( left_i, right_i, disp_i, cost_i, state, row0, rows - row1, buf, range.start );
}
if( state->disp12MaxDiff >= 0 )
validateDisparity( disp_i, cost_i, state->minDisparity, state->numDisparities, state->disp12MaxDiff );
if( state.disp12MaxDiff >= 0 )
validateDisparity( disp_i, cost_i, state.minDisparity, state.numDisparities, state.disp12MaxDiff );
if( roi.x > 0 )
{
@@ -1069,13 +1135,12 @@ struct FindStereoCorrespInvoker : public ParallelLoopBody
protected:
const Mat *left, *right;
Mat* disp, *slidingSumBuf, *cost;
StereoBMParams *state;
Mat* disp, *cost;
const StereoBMParams &state;
int nstripes;
size_t stripeBufSize;
bool useShorts;
Rect validDisparityRect;
const BufferBM & buf;
};
class StereoBMImpl CV_FINAL : public StereoBM
@@ -1149,7 +1214,7 @@ public:
disp_shift = DISPARITY_SHIFT_16S;
FILTERED = (params.minDisparity - 1) << disp_shift;
if( params.speckleRange >= 0 && params.speckleWindowSize > 0 )
if (params.useFilterSpeckles())
filterSpeckles(disparr.getMat(), FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf);
if (dtype == CV_32F)
disparr.getUMat().convertTo(disparr, CV_32FC1, 1./(1 << disp_shift), 0);
@@ -1192,44 +1257,39 @@ public:
disp = dispbuf;
}
int wsz = params.SADWindowSize;
int bufSize0 = (int)((ndisp + 2)*sizeof(int));
bufSize0 += (int)((height+wsz+2)*ndisp*sizeof(int));
bufSize0 += (int)((height + wsz + 2)*sizeof(int));
bufSize0 += (int)((height+wsz+2)*ndisp*(wsz+2)*sizeof(uchar) + 256);
{
const double SAD_overhead_coeff = 10.0;
const double N0 = 8000000 / (params.useShorts() ? 1 : 4); // approx tbb's min number instructions reasonable for one thread
const double maxStripeSize = std::min(
std::max(
N0 / (width * ndisp),
(params.SADWindowSize-1) * SAD_overhead_coeff
),
(double)height
);
const int nstripes = cvCeil(height / maxStripeSize);
BufferBM localBuf(nstripes, width, height, params);
int bufSize1 = (int)((width + params.preFilterSize + 2) * sizeof(int) + 256);
int bufSize2 = 0;
if( params.speckleRange >= 0 && params.speckleWindowSize > 0 )
bufSize2 = width*height*(sizeof(Point_<short>) + sizeof(int) + sizeof(uchar));
// Prefiltering
parallel_for_(Range(0, 2), PrefilterInvoker(left0, right0, left, right, localBuf, params), 1);
bool useShorts = params.preFilterCap <= 31 && params.SADWindowSize <= 21;
const double SAD_overhead_coeff = 10.0;
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);
int nstripes = cvCeil(height / maxStripeSize);
int bufSize = std::max(bufSize0 * nstripes, std::max(bufSize1 * 2, bufSize2));
if( slidingSumBuf.cols < bufSize )
slidingSumBuf.create( 1, bufSize, CV_8U );
Rect validDisparityRect(0, 0, width, height), R1 = params.roi1, R2 = params.roi2;
validDisparityRect = getValidDisparityROI(!R1.empty() ? R1 : validDisparityRect,
!R2.empty() ? R2 : validDisparityRect,
params.minDisparity, params.numDisparities,
params.SADWindowSize);
uchar *_buf = slidingSumBuf.ptr();
FindStereoCorrespInvoker invoker(left, right, disp, params, nstripes, validDisparityRect, cost, localBuf);
parallel_for_(Range(0, nstripes), invoker);
parallel_for_(Range(0, 2), PrefilterInvoker(left0, right0, left, right, _buf, _buf + bufSize1, &params), 1);
if (params.useFilterSpeckles())
{
slidingSumBuf.create( 1, width * height * (sizeof(Point_<short>) + sizeof(int) + sizeof(uchar)), CV_8U );
filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf);
}
Rect validDisparityRect(0, 0, width, height), R1 = params.roi1, R2 = params.roi2;
validDisparityRect = getValidDisparityROI(!R1.empty() ? R1 : validDisparityRect,
!R2.empty() ? R2 : validDisparityRect,
params.minDisparity, params.numDisparities,
params.SADWindowSize);
parallel_for_(Range(0, nstripes),
FindStereoCorrespInvoker(left, right, disp, &params, nstripes,
bufSize0, useShorts, validDisparityRect,
slidingSumBuf, cost));
if( params.speckleRange >= 0 && params.speckleWindowSize > 0 )
filterSpeckles(disp, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf);
}
if (disp0.data != disp.data)
disp.convertTo(disp0, disp0.type(), 1./(1 << disp_shift), 0);