mirror of
https://github.com/opencv/opencv.git
synced 2026-07-22 11:53:04 +04:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82f8176b06 | |||
| a03b7575ba | |||
| 8bae39ce8a | |||
| aa89881321 | |||
| 30b01a2d29 | |||
| dc328451eb | |||
| a49600cb24 | |||
| 0157ff0bc3 | |||
| 7e71666a0b | |||
| 7b677bb017 | |||
| 9b954de175 | |||
| 7f3af2b2d9 | |||
| fd63c60418 | |||
| 1c34941537 | |||
| b0f0194595 | |||
| 8484c8af7c | |||
| 51cfa51924 | |||
| f1c5d8364f | |||
| 19f4c4403a | |||
| e89405d48f | |||
| eaf0b04530 | |||
| cbae431752 | |||
| 0239c195d8 | |||
| a32aec5ba6 | |||
| dd131219b2 | |||
| 2cf58febf8 | |||
| 99091a6246 | |||
| 0354d01e79 | |||
| 45d3aac730 | |||
| 318ac6b8c9 | |||
| 7d332100a4 | |||
| 56072c4406 | |||
| cd64b504b8 | |||
| 443059e371 | |||
| 8f9c4d23e0 | |||
| 8b90db3f25 | |||
| ec16307632 | |||
| fdefc4b09d | |||
| 61d8292652 | |||
| 43f1b72e92 | |||
| 1f4b8c2785 |
@@ -61,7 +61,9 @@ if(NOT DEFINED OpenCV_CUDA)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if(DEFINED OpenCV_ARCH AND DEFINED OpenCV_RUNTIME)
|
||||
# custom overrided values
|
||||
elseif(MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
set(OpenCV_ARCH x64)
|
||||
set(OpenCV_TBB_ARCH intel64)
|
||||
@@ -81,7 +83,7 @@ if(MSVC)
|
||||
set(OpenCV_RUNTIME vc12)
|
||||
elseif(MSVC_VERSION EQUAL 1900)
|
||||
set(OpenCV_RUNTIME vc14)
|
||||
elseif(MSVC_VERSION EQUAL 1910 OR MSVC_VERSION EQUAL 1911)
|
||||
elseif(MSVC_VERSION MATCHES "^191[0-9]$")
|
||||
set(OpenCV_RUNTIME vc15)
|
||||
endif()
|
||||
elseif(MINGW)
|
||||
|
||||
@@ -82,7 +82,9 @@ if(NOT DEFINED OpenCV_STATIC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
if(DEFINED OpenCV_ARCH AND DEFINED OpenCV_RUNTIME)
|
||||
# custom overrided values
|
||||
elseif(MSVC)
|
||||
if(CMAKE_CL_64)
|
||||
set(OpenCV_ARCH x64)
|
||||
else()
|
||||
@@ -100,7 +102,7 @@ if(MSVC)
|
||||
set(OpenCV_RUNTIME vc12)
|
||||
elseif(MSVC_VERSION EQUAL 1900)
|
||||
set(OpenCV_RUNTIME vc14)
|
||||
elseif(MSVC_VERSION EQUAL 1910 OR MSVC_VERSION EQUAL 1911)
|
||||
elseif(MSVC_VERSION MATCHES "^191[0-9]$")
|
||||
set(OpenCV_RUNTIME vc15)
|
||||
endif()
|
||||
elseif(MINGW)
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
#include <android/log.h>
|
||||
#include <cctype>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <opencv2/core/version.hpp>
|
||||
#include "camera_activity.hpp"
|
||||
#include "camera_wrapper.h"
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
#define CV_VERSION_EPOCH 2
|
||||
#define CV_VERSION_MAJOR 4
|
||||
#define CV_VERSION_MINOR 13
|
||||
#define CV_VERSION_REVISION 5
|
||||
#define CV_VERSION_REVISION 7
|
||||
|
||||
#define CVAUX_STR_EXP(__A) #__A
|
||||
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
|
||||
|
||||
@@ -2994,6 +2994,7 @@ PCA& PCA::computeVar(InputArray _data, InputArray __mean, int flags, double reta
|
||||
{
|
||||
CV_Assert( _mean.size() == mean_sz );
|
||||
_mean.convertTo(mean, ctype);
|
||||
covar_flags |= CV_COVAR_USE_AVG;
|
||||
}
|
||||
|
||||
calcCovarMatrix( data, covar, mean, covar_flags, ctype );
|
||||
|
||||
@@ -164,7 +164,7 @@ void Core_EigenTest_32::run(int) { check_full(CV_32FC1); }
|
||||
void Core_EigenTest_64::run(int) { check_full(CV_64FC1); }
|
||||
|
||||
Core_EigenTest::Core_EigenTest()
|
||||
: eps_val_32(1e-3f), eps_vec_32(1e-2f),
|
||||
: eps_val_32(1e-3f), eps_vec_32(2e-2f),
|
||||
eps_val_64(1e-4f), eps_vec_64(1e-3f), ntests(100) {}
|
||||
Core_EigenTest::~Core_EigenTest() {}
|
||||
|
||||
|
||||
@@ -272,9 +272,8 @@ void SimpleBlobDetector::findBlobs(const cv::Mat &image, const cv::Mat &binaryIm
|
||||
#endif
|
||||
}
|
||||
|
||||
void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, const cv::Mat&) const
|
||||
void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask) const
|
||||
{
|
||||
//TODO: support mask
|
||||
keypoints.clear();
|
||||
Mat grayscaleImage;
|
||||
if (image.channels() == 3)
|
||||
@@ -355,6 +354,11 @@ void SimpleBlobDetector::detectImpl(const cv::Mat& image, std::vector<cv::KeyPoi
|
||||
keypoints.push_back(kpt);
|
||||
}
|
||||
|
||||
if (!mask.empty())
|
||||
{
|
||||
KeyPointsFilter::runByPixelsMask(keypoints, mask);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BLOB_DETECTOR
|
||||
namedWindow("keypoints", CV_WINDOW_NORMAL);
|
||||
Mat outImg = image.clone();
|
||||
|
||||
@@ -132,7 +132,12 @@ public:
|
||||
/* Construct the randomized trees. */
|
||||
for (int i = 0; i < trees_; i++) {
|
||||
/* Randomize the order of vectors to allow for unbiased sampling. */
|
||||
#ifndef OPENCV_FLANN_USE_STD_RAND
|
||||
cv::randShuffle(vind_);
|
||||
#else
|
||||
std::random_shuffle(vind_.begin(), vind_.end());
|
||||
#endif
|
||||
|
||||
tree_roots_[i] = divideTree(&vind_[0], int(size_) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,12 @@ public:
|
||||
indices.resize( feature_size_ * CHAR_BIT );
|
||||
for (size_t j = 0; j < feature_size_ * CHAR_BIT; ++j)
|
||||
indices[j] = j;
|
||||
|
||||
#ifndef OPENCV_FLANN_USE_STD_RAND
|
||||
cv::randShuffle(indices);
|
||||
#else
|
||||
std::random_shuffle(indices.begin(), indices.end());
|
||||
#endif
|
||||
}
|
||||
|
||||
lsh::LshTable<ElementType>& table = tables_[i];
|
||||
|
||||
@@ -40,13 +40,31 @@
|
||||
namespace cvflann
|
||||
{
|
||||
|
||||
inline int rand()
|
||||
{
|
||||
#ifndef OPENCV_FLANN_USE_STD_RAND
|
||||
# if INT_MAX == RAND_MAX
|
||||
int v = cv::theRNG().next() & INT_MAX;
|
||||
# else
|
||||
int v = cv::theRNG().uniform(0, RAND_MAX + 1);
|
||||
# endif
|
||||
#else
|
||||
int v = std::rand();
|
||||
#endif // OPENCV_FLANN_USE_STD_RAND
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seeds the random number generator
|
||||
* @param seed Random seed
|
||||
*/
|
||||
inline void seed_random(unsigned int seed)
|
||||
{
|
||||
srand(seed);
|
||||
#ifndef OPENCV_FLANN_USE_STD_RAND
|
||||
cv::theRNG() = cv::RNG(seed);
|
||||
#else
|
||||
std::srand(seed);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -60,7 +78,7 @@ inline void seed_random(unsigned int seed)
|
||||
*/
|
||||
inline double rand_double(double high = 1.0, double low = 0)
|
||||
{
|
||||
return low + ((high-low) * (std::rand() / (RAND_MAX + 1.0)));
|
||||
return low + ((high-low) * (rand() / (RAND_MAX + 1.0)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +89,7 @@ inline double rand_double(double high = 1.0, double low = 0)
|
||||
*/
|
||||
inline int rand_int(int high = RAND_MAX, int low = 0)
|
||||
{
|
||||
return low + (int) ( double(high-low) * (std::rand() / (RAND_MAX + 1.0)));
|
||||
return low + (int) ( double(high-low) * (rand() / (RAND_MAX + 1.0)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +125,11 @@ public:
|
||||
for (int i = 0; i < size_; ++i) vals_[i] = i;
|
||||
|
||||
// shuffle the elements in the array
|
||||
#ifndef OPENCV_FLANN_USE_STD_RAND
|
||||
cv::randShuffle(vals_);
|
||||
#else
|
||||
std::random_shuffle(vals_.begin(), vals_.end());
|
||||
#endif
|
||||
|
||||
counter_ = 0;
|
||||
}
|
||||
|
||||
@@ -1824,6 +1824,9 @@ public:
|
||||
void sparse(const GpuMat& prevImg, const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts,
|
||||
GpuMat& status, GpuMat* err = 0);
|
||||
|
||||
void sparse_multi(const GpuMat& prevImg, const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts,
|
||||
GpuMat& status, Stream& stream, GpuMat* err = 0);
|
||||
|
||||
void dense(const GpuMat& prevImg, const GpuMat& nextImg, GpuMat& u, GpuMat& v, GpuMat* err = 0);
|
||||
|
||||
void releaseMemory();
|
||||
|
||||
@@ -303,6 +303,88 @@ PERF_TEST_P(ImagePair_Gray_NPts_WinSz_Levels_Iters, Video_PyrLKOpticalFlowSparse
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// PyrLKOpticalFlowSparseMulti
|
||||
|
||||
#if defined(HAVE_TBB) && defined(HAVE_CUDA)
|
||||
|
||||
DEF_PARAM_TEST(ImagePair_Gray_NPts_WinSz_Levels_Iters, pair_string, bool, int, int, int, int);
|
||||
|
||||
PERF_TEST_P(ImagePair_Gray_NPts_WinSz_Levels_Iters, Video_PyrLKOpticalFlowSparseMulti,
|
||||
Combine(Values<pair_string>(make_pair("gpu/opticalflow/frame0.png", "gpu/opticalflow/frame1.png")),
|
||||
Bool(),
|
||||
Values(8000),
|
||||
Values(21),
|
||||
Values(1, 3),
|
||||
Values(1, 30)))
|
||||
{
|
||||
declare.time(20.0);
|
||||
|
||||
const pair_string imagePair = GET_PARAM(0);
|
||||
const bool useGray = GET_PARAM(1);
|
||||
const int points = GET_PARAM(2);
|
||||
const int winSize = GET_PARAM(3);
|
||||
const int levels = GET_PARAM(4);
|
||||
const int iters = GET_PARAM(5);
|
||||
|
||||
const cv::Mat frame0 = readImage(imagePair.first, useGray ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR);
|
||||
ASSERT_FALSE(frame0.empty());
|
||||
|
||||
const cv::Mat frame1 = readImage(imagePair.second, useGray ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR);
|
||||
ASSERT_FALSE(frame1.empty());
|
||||
|
||||
cv::Mat gray_frame;
|
||||
if (useGray)
|
||||
gray_frame = frame0;
|
||||
else
|
||||
cv::cvtColor(frame0, gray_frame, cv::COLOR_BGR2GRAY);
|
||||
|
||||
cv::Mat pts;
|
||||
cv::goodFeaturesToTrack(gray_frame, pts, points, 0.01, 0.0);
|
||||
|
||||
if (PERF_RUN_GPU())
|
||||
{
|
||||
const cv::gpu::GpuMat d_pts(pts.reshape(2, 1));
|
||||
|
||||
cv::gpu::PyrLKOpticalFlow d_pyrLK;
|
||||
d_pyrLK.winSize = cv::Size(winSize, winSize);
|
||||
d_pyrLK.maxLevel = levels - 1;
|
||||
d_pyrLK.iters = iters;
|
||||
|
||||
const cv::gpu::GpuMat d_frame0(frame0);
|
||||
const cv::gpu::GpuMat d_frame1(frame1);
|
||||
cv::gpu::GpuMat nextPts;
|
||||
cv::gpu::GpuMat status;
|
||||
|
||||
cv::gpu::Stream stream;
|
||||
TEST_CYCLE()
|
||||
{
|
||||
d_pyrLK.sparse_multi(d_frame0, d_frame1, d_pts, nextPts, status, stream);
|
||||
stream.waitForCompletion();
|
||||
}
|
||||
|
||||
GPU_SANITY_CHECK(nextPts);
|
||||
GPU_SANITY_CHECK(status);
|
||||
}
|
||||
else
|
||||
{
|
||||
cv::Mat nextPts;
|
||||
cv::Mat status;
|
||||
|
||||
TEST_CYCLE()
|
||||
{
|
||||
cv::calcOpticalFlowPyrLK(frame0, frame1, pts, nextPts, status, cv::noArray(),
|
||||
cv::Size(winSize, winSize), levels - 1,
|
||||
cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, iters, 0.01));
|
||||
}
|
||||
|
||||
CPU_SANITY_CHECK(nextPts);
|
||||
CPU_SANITY_CHECK(status);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_TBB
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// PyrLKOpticalFlowDense
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
#include "opencv2/gpu/device/vec_math.hpp"
|
||||
#include "opencv2/gpu/device/reduce.hpp"
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
|
||||
#include "cvconfig.h"
|
||||
|
||||
using namespace cv::gpu;
|
||||
using namespace cv::gpu::device;
|
||||
|
||||
@@ -60,12 +64,54 @@ namespace pyrlk
|
||||
__constant__ int c_halfWin_y;
|
||||
__constant__ int c_iters;
|
||||
|
||||
texture<float, cudaTextureType2D, cudaReadModeElementType> tex_If(false, cudaFilterModeLinear, cudaAddressModeClamp);
|
||||
texture<float4, cudaTextureType2D, cudaReadModeElementType> tex_If4(false, cudaFilterModeLinear, cudaAddressModeClamp);
|
||||
texture<uchar, cudaTextureType2D, cudaReadModeElementType> tex_Ib(false, cudaFilterModePoint, cudaAddressModeClamp);
|
||||
#define CUDA_CONSTANTS(index) \
|
||||
__constant__ int c_winSize_x##index; \
|
||||
__constant__ int c_winSize_y##index; \
|
||||
__constant__ int c_halfWin_x##index; \
|
||||
__constant__ int c_halfWin_y##index; \
|
||||
__constant__ int c_iters##index;
|
||||
|
||||
texture<float, cudaTextureType2D, cudaReadModeElementType> tex_Jf(false, cudaFilterModeLinear, cudaAddressModeClamp);
|
||||
texture<float4, cudaTextureType2D, cudaReadModeElementType> tex_Jf4(false, cudaFilterModeLinear, cudaAddressModeClamp);
|
||||
CUDA_CONSTANTS(0)
|
||||
CUDA_CONSTANTS(1)
|
||||
CUDA_CONSTANTS(2)
|
||||
CUDA_CONSTANTS(3)
|
||||
CUDA_CONSTANTS(4)
|
||||
|
||||
template <int index> struct c_multi_winSize_x;
|
||||
template <int index> struct c_multi_winSize_y;
|
||||
template <int index> struct c_multi_halfWin_x;
|
||||
template <int index> struct c_multi_halfWin_y;
|
||||
template <int index> struct c_multi_iters;
|
||||
|
||||
#define CUDA_CONSTANTS_ACCESSOR(index) \
|
||||
template <> struct c_multi_winSize_x<index> \
|
||||
{ static __device__ __forceinline__ int get(void){ return c_winSize_x##index;} }; \
|
||||
template <> struct c_multi_winSize_y<index> \
|
||||
{ static __device__ __forceinline__ int get(void){ return c_winSize_y##index;} }; \
|
||||
template <> struct c_multi_halfWin_x<index> \
|
||||
{ static __device__ __forceinline__ int get(void){ return c_halfWin_x##index;} }; \
|
||||
template <> struct c_multi_halfWin_y<index> \
|
||||
{ static __device__ __forceinline__ int get(void){ return c_halfWin_y##index;} }; \
|
||||
template <> struct c_multi_iters<index> \
|
||||
{ static __device__ __forceinline__ int get(void){ return c_iters##index;} };
|
||||
|
||||
CUDA_CONSTANTS_ACCESSOR(0)
|
||||
CUDA_CONSTANTS_ACCESSOR(1)
|
||||
CUDA_CONSTANTS_ACCESSOR(2)
|
||||
CUDA_CONSTANTS_ACCESSOR(3)
|
||||
CUDA_CONSTANTS_ACCESSOR(4)
|
||||
|
||||
texture<float, cudaTextureType2D, cudaReadModeElementType>
|
||||
tex_If(false, cudaFilterModeLinear, cudaAddressModeClamp);
|
||||
texture<float4, cudaTextureType2D, cudaReadModeElementType>
|
||||
tex_If4(false, cudaFilterModeLinear, cudaAddressModeClamp);
|
||||
texture<uchar, cudaTextureType2D, cudaReadModeElementType>
|
||||
tex_Ib(false, cudaFilterModePoint, cudaAddressModeClamp);
|
||||
|
||||
texture<float, cudaTextureType2D, cudaReadModeElementType>
|
||||
tex_Jf(false, cudaFilterModeLinear, cudaAddressModeClamp);
|
||||
texture<float4, cudaTextureType2D, cudaReadModeElementType>
|
||||
tex_Jf4(false, cudaFilterModeLinear, cudaAddressModeClamp);
|
||||
|
||||
template <int cn> struct Tex_I;
|
||||
template <> struct Tex_I<1>
|
||||
@@ -99,6 +145,57 @@ namespace pyrlk
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#define CUDA_DECL_TEX_MULTI(texname, type, filtermode) \
|
||||
texture<type, cudaTextureType2D, cudaReadModeElementType> \
|
||||
texname##_multi0(false, filtermode, cudaAddressModeClamp); \
|
||||
texture<type, cudaTextureType2D, cudaReadModeElementType> \
|
||||
texname##_multi1(false, filtermode, cudaAddressModeClamp); \
|
||||
texture<type, cudaTextureType2D, cudaReadModeElementType> \
|
||||
texname##_multi2(false, filtermode, cudaAddressModeClamp); \
|
||||
texture<type, cudaTextureType2D, cudaReadModeElementType> \
|
||||
texname##_multi3(false, filtermode, cudaAddressModeClamp); \
|
||||
texture<type, cudaTextureType2D, cudaReadModeElementType> \
|
||||
texname##_multi4(false, filtermode, cudaAddressModeClamp); \
|
||||
|
||||
CUDA_DECL_TEX_MULTI(tex_If1, float, cudaFilterModeLinear)
|
||||
CUDA_DECL_TEX_MULTI(tex_If4, float4, cudaFilterModeLinear)
|
||||
CUDA_DECL_TEX_MULTI(tex_Ib1, uchar, cudaFilterModePoint)
|
||||
CUDA_DECL_TEX_MULTI(tex_Jf1, float, cudaFilterModeLinear)
|
||||
CUDA_DECL_TEX_MULTI(tex_Jf4, float4, cudaFilterModeLinear)
|
||||
|
||||
template <int cn, int index> struct Tex_I_multi;
|
||||
template <int cn, int index> struct Tex_J_multi;
|
||||
template <int cn, int index> struct Tex_B_multi;
|
||||
|
||||
#define CUDA_DECL_TEX_MULTI_ACCESS(accessorname, texname, cn, returntype) \
|
||||
template <> struct accessorname##_multi<cn, 0> \
|
||||
{ static __device__ __forceinline__ returntype read(float x, float y) \
|
||||
{ return tex2D(texname##cn##_multi0, x, y); } }; \
|
||||
template <> struct accessorname##_multi<cn, 1> \
|
||||
{ static __device__ __forceinline__ returntype read(float x, float y) \
|
||||
{ return tex2D(texname##cn##_multi1, x, y); } }; \
|
||||
template <> struct accessorname##_multi<cn, 2> \
|
||||
{ static __device__ __forceinline__ returntype read(float x, float y) \
|
||||
{ return tex2D(texname##cn##_multi2, x, y); } }; \
|
||||
template <> struct accessorname##_multi<cn, 3> \
|
||||
{ static __device__ __forceinline__ returntype read(float x, float y) \
|
||||
{ return tex2D(texname##cn##_multi3, x, y); } }; \
|
||||
template <> struct accessorname##_multi<cn, 4> \
|
||||
{ static __device__ __forceinline__ returntype read(float x, float y) \
|
||||
{ return tex2D(texname##cn##_multi4, x, y); } };
|
||||
|
||||
CUDA_DECL_TEX_MULTI_ACCESS(Tex_I, tex_If, 1, float)
|
||||
CUDA_DECL_TEX_MULTI_ACCESS(Tex_I, tex_If, 4, float4)
|
||||
|
||||
CUDA_DECL_TEX_MULTI_ACCESS(Tex_B, tex_Ib, 1, uchar)
|
||||
|
||||
CUDA_DECL_TEX_MULTI_ACCESS(Tex_J, tex_Jf, 1, float)
|
||||
CUDA_DECL_TEX_MULTI_ACCESS(Tex_J, tex_Jf, 4, float4)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
__device__ __forceinline__ void accum(float& dst, float val)
|
||||
{
|
||||
dst += val;
|
||||
@@ -309,6 +406,200 @@ namespace pyrlk
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_TBB)
|
||||
template <int cn, int index, int PATCH_X, int PATCH_Y, bool calcErr>
|
||||
__global__ void sparseKernel_multi(const float2* prevPts, float2* nextPts, uchar* status, float* err, const int level, const int rows, const int cols)
|
||||
{
|
||||
#if __CUDA_ARCH__ <= 110
|
||||
const int BLOCK_SIZE = 128;
|
||||
#else
|
||||
const int BLOCK_SIZE = 256;
|
||||
#endif
|
||||
|
||||
__shared__ float smem1[BLOCK_SIZE];
|
||||
__shared__ float smem2[BLOCK_SIZE];
|
||||
__shared__ float smem3[BLOCK_SIZE];
|
||||
|
||||
const unsigned int tid = threadIdx.y * blockDim.x + threadIdx.x;
|
||||
|
||||
float2 prevPt = prevPts[blockIdx.x];
|
||||
prevPt.x *= (1.0f / (1 << level));
|
||||
prevPt.y *= (1.0f / (1 << level));
|
||||
|
||||
if (prevPt.x < 0 || prevPt.x >= cols || prevPt.y < 0 || prevPt.y >= rows)
|
||||
{
|
||||
if (tid == 0 && level == 0)
|
||||
status[blockIdx.x] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
prevPt.x -= c_multi_halfWin_x<index>::get();
|
||||
prevPt.y -= c_multi_halfWin_y<index>::get();
|
||||
|
||||
// extract the patch from the first image, compute covariation matrix of derivatives
|
||||
|
||||
float A11 = 0;
|
||||
float A12 = 0;
|
||||
float A22 = 0;
|
||||
|
||||
typedef typename TypeVec<float, cn>::vec_type work_type;
|
||||
|
||||
work_type I_patch [PATCH_Y][PATCH_X];
|
||||
work_type dIdx_patch[PATCH_Y][PATCH_X];
|
||||
work_type dIdy_patch[PATCH_Y][PATCH_X];
|
||||
|
||||
for (int yBase = threadIdx.y, i = 0; yBase < c_multi_winSize_y<index>::get(); yBase += blockDim.y, ++i)
|
||||
{
|
||||
for (int xBase = threadIdx.x, j = 0; xBase < c_multi_winSize_x<index>::get(); xBase += blockDim.x, ++j)
|
||||
{
|
||||
float x = prevPt.x + xBase + 0.5f;
|
||||
float y = prevPt.y + yBase + 0.5f;
|
||||
|
||||
I_patch[i][j] = Tex_I_multi<cn,index>::read(x, y);
|
||||
|
||||
// Sharr Deriv
|
||||
|
||||
work_type dIdx = 3.0f * Tex_I_multi<cn,index>::read(x+1, y-1) + 10.0f * Tex_I_multi<cn,index>::read(x+1, y) + 3.0f * Tex_I_multi<cn,index>::read(x+1, y+1) -
|
||||
(3.0f * Tex_I_multi<cn,index>::read(x-1, y-1) + 10.0f * Tex_I_multi<cn,index>::read(x-1, y) + 3.0f * Tex_I_multi<cn,index>::read(x-1, y+1));
|
||||
|
||||
work_type dIdy = 3.0f * Tex_I_multi<cn,index>::read(x-1, y+1) + 10.0f * Tex_I_multi<cn,index>::read(x, y+1) + 3.0f * Tex_I_multi<cn,index>::read(x+1, y+1) -
|
||||
(3.0f * Tex_I_multi<cn,index>::read(x-1, y-1) + 10.0f * Tex_I_multi<cn,index>::read(x, y-1) + 3.0f * Tex_I_multi<cn,index>::read(x+1, y-1));
|
||||
|
||||
dIdx_patch[i][j] = dIdx;
|
||||
dIdy_patch[i][j] = dIdy;
|
||||
|
||||
accum(A11, dIdx * dIdx);
|
||||
accum(A12, dIdx * dIdy);
|
||||
accum(A22, dIdy * dIdy);
|
||||
}
|
||||
}
|
||||
|
||||
reduce<BLOCK_SIZE>(smem_tuple(smem1, smem2, smem3), thrust::tie(A11, A12, A22), tid, thrust::make_tuple(plus<float>(), plus<float>(), plus<float>()));
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
if (tid == 0)
|
||||
{
|
||||
smem1[0] = A11;
|
||||
smem2[0] = A12;
|
||||
smem3[0] = A22;
|
||||
}
|
||||
#endif
|
||||
|
||||
__syncthreads();
|
||||
|
||||
A11 = smem1[0];
|
||||
A12 = smem2[0];
|
||||
A22 = smem3[0];
|
||||
|
||||
float D = A11 * A22 - A12 * A12;
|
||||
|
||||
if (abs_(D) < numeric_limits<float>::epsilon())
|
||||
{
|
||||
if (tid == 0 && level == 0)
|
||||
status[blockIdx.x] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
D = 1.f / D;
|
||||
|
||||
A11 *= D;
|
||||
A12 *= D;
|
||||
A22 *= D;
|
||||
|
||||
float2 nextPt = nextPts[blockIdx.x];
|
||||
nextPt.x *= 2.f;
|
||||
nextPt.y *= 2.f;
|
||||
|
||||
nextPt.x -= c_multi_halfWin_x<index>::get();
|
||||
nextPt.y -= c_multi_halfWin_y<index>::get();
|
||||
|
||||
for (int k = 0; k < c_multi_iters<index>::get(); ++k)
|
||||
{
|
||||
if (nextPt.x < -c_multi_halfWin_x<index>::get() || nextPt.x >= cols || nextPt.y < -c_multi_halfWin_y<index>::get() || nextPt.y >= rows)
|
||||
{
|
||||
if (tid == 0 && level == 0)
|
||||
status[blockIdx.x] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
float b1 = 0;
|
||||
float b2 = 0;
|
||||
|
||||
for (int y = threadIdx.y, i = 0; y < c_multi_winSize_y<index>::get(); y += blockDim.y, ++i)
|
||||
{
|
||||
for (int x = threadIdx.x, j = 0; x < c_multi_winSize_x<index>::get(); x += blockDim.x, ++j)
|
||||
{
|
||||
work_type I_val = I_patch[i][j];
|
||||
work_type J_val = Tex_J_multi<cn,index>::read(nextPt.x + x + 0.5f, nextPt.y + y + 0.5f);
|
||||
|
||||
work_type diff = (J_val - I_val) * 32.0f;
|
||||
|
||||
accum(b1, diff * dIdx_patch[i][j]);
|
||||
accum(b2, diff * dIdy_patch[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
reduce<BLOCK_SIZE>(smem_tuple(smem1, smem2), thrust::tie(b1, b2), tid, thrust::make_tuple(plus<float>(), plus<float>()));
|
||||
|
||||
#if __CUDA_ARCH__ >= 300
|
||||
if (tid == 0)
|
||||
{
|
||||
smem1[0] = b1;
|
||||
smem2[0] = b2;
|
||||
}
|
||||
#endif
|
||||
|
||||
__syncthreads();
|
||||
|
||||
b1 = smem1[0];
|
||||
b2 = smem2[0];
|
||||
|
||||
float2 delta;
|
||||
delta.x = A12 * b2 - A22 * b1;
|
||||
delta.y = A12 * b1 - A11 * b2;
|
||||
|
||||
nextPt.x += delta.x;
|
||||
nextPt.y += delta.y;
|
||||
|
||||
if (::fabs(delta.x) < 0.01f && ::fabs(delta.y) < 0.01f)
|
||||
break;
|
||||
}
|
||||
|
||||
float errval = 0;
|
||||
if (calcErr)
|
||||
{
|
||||
for (int y = threadIdx.y, i = 0; y < c_multi_winSize_y<index>::get(); y += blockDim.y, ++i)
|
||||
{
|
||||
for (int x = threadIdx.x, j = 0; x < c_multi_winSize_x<index>::get(); x += blockDim.x, ++j)
|
||||
{
|
||||
work_type I_val = I_patch[i][j];
|
||||
work_type J_val = Tex_J_multi<cn,index>::read(nextPt.x + x + 0.5f, nextPt.y + y + 0.5f);
|
||||
|
||||
work_type diff = J_val - I_val;
|
||||
|
||||
accum(errval, abs_(diff));
|
||||
}
|
||||
}
|
||||
|
||||
reduce<BLOCK_SIZE>(smem1, errval, tid, plus<float>());
|
||||
}
|
||||
|
||||
if (tid == 0)
|
||||
{
|
||||
nextPt.x += c_multi_halfWin_x<index>::get();
|
||||
nextPt.y += c_multi_halfWin_y<index>::get();
|
||||
|
||||
nextPts[blockIdx.x] = nextPt;
|
||||
|
||||
if (calcErr)
|
||||
err[blockIdx.x] = static_cast<float>(errval) / (cn * c_multi_winSize_x<index>::get() * c_multi_winSize_y<index>::get());
|
||||
}
|
||||
}
|
||||
#endif // defined(HAVE_TBB)
|
||||
|
||||
template <int cn, int PATCH_X, int PATCH_Y>
|
||||
void sparse_caller(int rows, int cols, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, cudaStream_t stream)
|
||||
@@ -326,6 +617,26 @@ namespace pyrlk
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
#if defined(HAVE_TBB)
|
||||
template <int cn, int index, int PATCH_X, int PATCH_Y>
|
||||
void sparse_caller_multi(int rows, int cols, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, cudaStream_t stream)
|
||||
{
|
||||
dim3 grid(ptcount);
|
||||
|
||||
if (level == 0 && err)
|
||||
sparseKernel_multi<cn, index, PATCH_X, PATCH_Y, true><<<grid, block>>>(prevPts, nextPts, status, err, level, rows, cols);
|
||||
else
|
||||
sparseKernel_multi<cn, index, PATCH_X, PATCH_Y, false><<<grid, block>>>(prevPts, nextPts, status, err, level, rows, cols);
|
||||
|
||||
cudaSafeCall( cudaGetLastError() );
|
||||
|
||||
if (stream == 0)
|
||||
cudaSafeCall( cudaDeviceSynchronize() );
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_TBB)
|
||||
|
||||
template <bool calcErr>
|
||||
__global__ void denseKernel(PtrStepf u, PtrStepf v, const PtrStepf prevU, const PtrStepf prevV, PtrStepf err, const int rows, const int cols)
|
||||
{
|
||||
@@ -484,6 +795,30 @@ namespace pyrlk
|
||||
cudaSafeCall( cudaMemcpyToSymbol(c_iters, &iters, sizeof(int)) );
|
||||
}
|
||||
|
||||
#if defined(HAVE_TBB)
|
||||
void loadConstants_multi(int2 winSize, int iters, int index, cudaStream_t stream = 0)
|
||||
{
|
||||
int2 halfWin;
|
||||
#define COPY_TO_SYMBOL_CALL(index) \
|
||||
cudaSafeCall( cudaMemcpyToSymbolAsync(c_winSize_x##index, &winSize.x, sizeof(int), 0, cudaMemcpyHostToDevice, stream) ); \
|
||||
cudaSafeCall( cudaMemcpyToSymbolAsync(c_winSize_y##index, &winSize.y, sizeof(int), 0, cudaMemcpyHostToDevice, stream) ); \
|
||||
halfWin = make_int2((winSize.x - 1) / 2, (winSize.y - 1) / 2); \
|
||||
cudaSafeCall( cudaMemcpyToSymbolAsync(c_halfWin_x##index, &halfWin.x, sizeof(int), 0, cudaMemcpyHostToDevice, stream) ); \
|
||||
cudaSafeCall( cudaMemcpyToSymbolAsync(c_halfWin_y##index, &halfWin.y, sizeof(int), 0, cudaMemcpyHostToDevice, stream) ); \
|
||||
cudaSafeCall( cudaMemcpyToSymbolAsync(c_iters##index, &iters, sizeof(int), 0, cudaMemcpyHostToDevice, stream) );
|
||||
|
||||
switch(index)
|
||||
{
|
||||
case 0: COPY_TO_SYMBOL_CALL(0) break;
|
||||
case 1: COPY_TO_SYMBOL_CALL(1) break;
|
||||
case 2: COPY_TO_SYMBOL_CALL(2) break;
|
||||
case 3: COPY_TO_SYMBOL_CALL(3) break;
|
||||
case 4: COPY_TO_SYMBOL_CALL(4) break;
|
||||
default: CV_Error(CV_StsBadArg, "invalid execution line index"); break;
|
||||
}
|
||||
}
|
||||
#endif // defined(HAVE_TBB)
|
||||
|
||||
void sparse1(PtrStepSzf I, PtrStepSzf J, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, dim3 patch, cudaStream_t stream)
|
||||
{
|
||||
@@ -528,6 +863,161 @@ namespace pyrlk
|
||||
level, block, stream);
|
||||
}
|
||||
|
||||
#if defined(HAVE_TBB)
|
||||
void sparse1_multi(PtrStepSzf I, PtrStepSzf J, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, dim3 patch, cudaStream_t stream, int index)
|
||||
{
|
||||
typedef void (*func_t)(int rows, int cols, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, cudaStream_t stream);
|
||||
|
||||
static const func_t funcs[5][5][5] =
|
||||
{
|
||||
{ // index 0
|
||||
{sparse_caller_multi<1, 0, 1, 1>, sparse_caller_multi<1, 0, 2, 1>, sparse_caller_multi<1, 0, 3, 1>, sparse_caller_multi<1, 0, 4, 1>, sparse_caller_multi<1, 0, 5, 1>},
|
||||
{sparse_caller_multi<1, 0, 1, 2>, sparse_caller_multi<1, 0, 2, 2>, sparse_caller_multi<1, 0, 3, 2>, sparse_caller_multi<1, 0, 4, 2>, sparse_caller_multi<1, 0, 5, 2>},
|
||||
{sparse_caller_multi<1, 0, 1, 3>, sparse_caller_multi<1, 0, 2, 3>, sparse_caller_multi<1, 0, 3, 3>, sparse_caller_multi<1, 0, 4, 3>, sparse_caller_multi<1, 0, 5, 3>},
|
||||
{sparse_caller_multi<1, 0, 1, 4>, sparse_caller_multi<1, 0, 2, 4>, sparse_caller_multi<1, 0, 3, 4>, sparse_caller_multi<1, 0, 4, 4>, sparse_caller_multi<1, 0, 5, 4>},
|
||||
{sparse_caller_multi<1, 0, 1, 5>, sparse_caller_multi<1, 0, 2, 5>, sparse_caller_multi<1, 0, 3, 5>, sparse_caller_multi<1, 0, 4, 5>, sparse_caller_multi<1, 0, 5, 5>}
|
||||
},
|
||||
{ // index 1
|
||||
{sparse_caller_multi<1, 1, 1, 1>, sparse_caller_multi<1, 1, 2, 1>, sparse_caller_multi<1, 1, 3, 1>, sparse_caller_multi<1, 1, 4, 1>, sparse_caller_multi<1, 1, 5, 1>},
|
||||
{sparse_caller_multi<1, 1, 1, 2>, sparse_caller_multi<1, 1, 2, 2>, sparse_caller_multi<1, 1, 3, 2>, sparse_caller_multi<1, 1, 4, 2>, sparse_caller_multi<1, 1, 5, 2>},
|
||||
{sparse_caller_multi<1, 1, 1, 3>, sparse_caller_multi<1, 1, 2, 3>, sparse_caller_multi<1, 1, 3, 3>, sparse_caller_multi<1, 1, 4, 3>, sparse_caller_multi<1, 1, 5, 3>},
|
||||
{sparse_caller_multi<1, 1, 1, 4>, sparse_caller_multi<1, 1, 2, 4>, sparse_caller_multi<1, 1, 3, 4>, sparse_caller_multi<1, 1, 4, 4>, sparse_caller_multi<1, 1, 5, 4>},
|
||||
{sparse_caller_multi<1, 1, 1, 5>, sparse_caller_multi<1, 1, 2, 5>, sparse_caller_multi<1, 1, 3, 5>, sparse_caller_multi<1, 1, 4, 5>, sparse_caller_multi<1, 1, 5, 5>}
|
||||
},
|
||||
{ // index 2
|
||||
{sparse_caller_multi<1, 2, 1, 1>, sparse_caller_multi<1, 2, 2, 1>, sparse_caller_multi<1, 2, 3, 1>, sparse_caller_multi<1, 2, 4, 1>, sparse_caller_multi<1, 2, 5, 1>},
|
||||
{sparse_caller_multi<1, 2, 1, 2>, sparse_caller_multi<1, 2, 2, 2>, sparse_caller_multi<1, 2, 3, 2>, sparse_caller_multi<1, 2, 4, 2>, sparse_caller_multi<1, 2, 5, 2>},
|
||||
{sparse_caller_multi<1, 2, 1, 3>, sparse_caller_multi<1, 2, 2, 3>, sparse_caller_multi<1, 2, 3, 3>, sparse_caller_multi<1, 2, 4, 3>, sparse_caller_multi<1, 2, 5, 3>},
|
||||
{sparse_caller_multi<1, 2, 1, 4>, sparse_caller_multi<1, 2, 2, 4>, sparse_caller_multi<1, 2, 3, 4>, sparse_caller_multi<1, 2, 4, 4>, sparse_caller_multi<1, 2, 5, 4>},
|
||||
{sparse_caller_multi<1, 2, 1, 5>, sparse_caller_multi<1, 2, 2, 5>, sparse_caller_multi<1, 2, 3, 5>, sparse_caller_multi<1, 2, 4, 5>, sparse_caller_multi<1, 2, 5, 5>}
|
||||
},
|
||||
{ // index 3
|
||||
{sparse_caller_multi<1, 3, 1, 1>, sparse_caller_multi<1, 3, 2, 1>, sparse_caller_multi<1, 3, 3, 1>, sparse_caller_multi<1, 3, 4, 1>, sparse_caller_multi<1, 3, 5, 1>},
|
||||
{sparse_caller_multi<1, 3, 1, 2>, sparse_caller_multi<1, 3, 2, 2>, sparse_caller_multi<1, 3, 3, 2>, sparse_caller_multi<1, 3, 4, 2>, sparse_caller_multi<1, 3, 5, 2>},
|
||||
{sparse_caller_multi<1, 3, 1, 3>, sparse_caller_multi<1, 3, 2, 3>, sparse_caller_multi<1, 3, 3, 3>, sparse_caller_multi<1, 3, 4, 3>, sparse_caller_multi<1, 3, 5, 3>},
|
||||
{sparse_caller_multi<1, 3, 1, 4>, sparse_caller_multi<1, 3, 2, 4>, sparse_caller_multi<1, 3, 3, 4>, sparse_caller_multi<1, 3, 4, 4>, sparse_caller_multi<1, 3, 5, 4>},
|
||||
{sparse_caller_multi<1, 3, 1, 5>, sparse_caller_multi<1, 3, 2, 5>, sparse_caller_multi<1, 3, 3, 5>, sparse_caller_multi<1, 3, 4, 5>, sparse_caller_multi<1, 3, 5, 5>}
|
||||
},
|
||||
{ // index 4
|
||||
{sparse_caller_multi<1, 4, 1, 1>, sparse_caller_multi<1, 4, 2, 1>, sparse_caller_multi<1, 4, 3, 1>, sparse_caller_multi<1, 4, 4, 1>, sparse_caller_multi<1, 4, 5, 1>},
|
||||
{sparse_caller_multi<1, 4, 1, 2>, sparse_caller_multi<1, 4, 2, 2>, sparse_caller_multi<1, 4, 3, 2>, sparse_caller_multi<1, 4, 4, 2>, sparse_caller_multi<1, 4, 5, 2>},
|
||||
{sparse_caller_multi<1, 4, 1, 3>, sparse_caller_multi<1, 4, 2, 3>, sparse_caller_multi<1, 4, 3, 3>, sparse_caller_multi<1, 4, 4, 3>, sparse_caller_multi<1, 4, 5, 3>},
|
||||
{sparse_caller_multi<1, 4, 1, 4>, sparse_caller_multi<1, 4, 2, 4>, sparse_caller_multi<1, 4, 3, 4>, sparse_caller_multi<1, 4, 4, 4>, sparse_caller_multi<1, 4, 5, 4>},
|
||||
{sparse_caller_multi<1, 4, 1, 5>, sparse_caller_multi<1, 4, 2, 5>, sparse_caller_multi<1, 4, 3, 5>, sparse_caller_multi<1, 4, 4, 5>, sparse_caller_multi<1, 4, 5, 5>}
|
||||
}
|
||||
};
|
||||
|
||||
switch(index)
|
||||
{
|
||||
case 0:
|
||||
bindTexture(&tex_If1_multi0, I);
|
||||
bindTexture(&tex_Jf1_multi0, J);
|
||||
break;
|
||||
case 1:
|
||||
bindTexture(&tex_If1_multi1, I);
|
||||
bindTexture(&tex_Jf1_multi1, J);
|
||||
break;
|
||||
case 2:
|
||||
bindTexture(&tex_If1_multi2, I);
|
||||
bindTexture(&tex_Jf1_multi2, J);
|
||||
break;
|
||||
case 3:
|
||||
bindTexture(&tex_If1_multi3, I);
|
||||
bindTexture(&tex_Jf1_multi3, J);
|
||||
break;
|
||||
case 4:
|
||||
bindTexture(&tex_If1_multi4, I);
|
||||
bindTexture(&tex_Jf1_multi4, J);
|
||||
break;
|
||||
default:
|
||||
CV_Error(CV_StsBadArg, "invalid execution line index");
|
||||
break;
|
||||
}
|
||||
|
||||
funcs[index][patch.y - 1][patch.x - 1](I.rows, I.cols, prevPts, nextPts, status, err, ptcount,
|
||||
level, block, stream);
|
||||
}
|
||||
|
||||
void sparse4_multi(PtrStepSz<float4> I, PtrStepSz<float4> J, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, dim3 patch, cudaStream_t stream, int index)
|
||||
{
|
||||
typedef void (*func_t)(int rows, int cols, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, cudaStream_t stream);
|
||||
|
||||
static const func_t funcs[5][5][5] =
|
||||
{
|
||||
{ // index 0
|
||||
{sparse_caller_multi<4, 0, 1, 1>, sparse_caller_multi<4, 0, 2, 1>, sparse_caller_multi<4, 0, 3, 1>, sparse_caller_multi<4, 0, 4, 1>, sparse_caller_multi<4, 0, 5, 1>},
|
||||
{sparse_caller_multi<4, 0, 1, 2>, sparse_caller_multi<4, 0, 2, 2>, sparse_caller_multi<4, 0, 3, 2>, sparse_caller_multi<4, 0, 4, 2>, sparse_caller_multi<4, 0, 5, 2>},
|
||||
{sparse_caller_multi<4, 0, 1, 3>, sparse_caller_multi<4, 0, 2, 3>, sparse_caller_multi<4, 0, 3, 3>, sparse_caller_multi<4, 0, 4, 3>, sparse_caller_multi<4, 0, 5, 3>},
|
||||
{sparse_caller_multi<4, 0, 1, 4>, sparse_caller_multi<4, 0, 2, 4>, sparse_caller_multi<4, 0, 3, 4>, sparse_caller_multi<4, 0, 4, 4>, sparse_caller_multi<4, 0, 5, 4>},
|
||||
{sparse_caller_multi<4, 0, 1, 5>, sparse_caller_multi<4, 0, 2, 5>, sparse_caller_multi<4, 0, 3, 5>, sparse_caller_multi<4, 0, 4, 5>, sparse_caller_multi<4, 0, 5, 5>}
|
||||
},
|
||||
{ // index 1
|
||||
{sparse_caller_multi<4, 1, 1, 1>, sparse_caller_multi<4, 1, 2, 1>, sparse_caller_multi<4, 1, 3, 1>, sparse_caller_multi<4, 1, 4, 1>, sparse_caller_multi<4, 1, 5, 1>},
|
||||
{sparse_caller_multi<4, 1, 1, 2>, sparse_caller_multi<4, 1, 2, 2>, sparse_caller_multi<4, 1, 3, 2>, sparse_caller_multi<4, 1, 4, 2>, sparse_caller_multi<4, 1, 5, 2>},
|
||||
{sparse_caller_multi<4, 1, 1, 3>, sparse_caller_multi<4, 1, 2, 3>, sparse_caller_multi<4, 1, 3, 3>, sparse_caller_multi<4, 1, 4, 3>, sparse_caller_multi<4, 1, 5, 3>},
|
||||
{sparse_caller_multi<4, 1, 1, 4>, sparse_caller_multi<4, 1, 2, 4>, sparse_caller_multi<4, 1, 3, 4>, sparse_caller_multi<4, 1, 4, 4>, sparse_caller_multi<4, 1, 5, 4>},
|
||||
{sparse_caller_multi<4, 1, 1, 5>, sparse_caller_multi<4, 1, 2, 5>, sparse_caller_multi<4, 1, 3, 5>, sparse_caller_multi<4, 1, 4, 5>, sparse_caller_multi<4, 1, 5, 5>}
|
||||
},
|
||||
{ // index 2
|
||||
{sparse_caller_multi<4, 2, 1, 1>, sparse_caller_multi<4, 2, 2, 1>, sparse_caller_multi<4, 2, 3, 1>, sparse_caller_multi<4, 2, 4, 1>, sparse_caller_multi<4, 2, 5, 1>},
|
||||
{sparse_caller_multi<4, 2, 1, 2>, sparse_caller_multi<4, 2, 2, 2>, sparse_caller_multi<4, 2, 3, 2>, sparse_caller_multi<4, 2, 4, 2>, sparse_caller_multi<4, 2, 5, 2>},
|
||||
{sparse_caller_multi<4, 2, 1, 3>, sparse_caller_multi<4, 2, 2, 3>, sparse_caller_multi<4, 2, 3, 3>, sparse_caller_multi<4, 2, 4, 3>, sparse_caller_multi<4, 2, 5, 3>},
|
||||
{sparse_caller_multi<4, 2, 1, 4>, sparse_caller_multi<4, 2, 2, 4>, sparse_caller_multi<4, 2, 3, 4>, sparse_caller_multi<4, 2, 4, 4>, sparse_caller_multi<4, 2, 5, 4>},
|
||||
{sparse_caller_multi<4, 2, 1, 5>, sparse_caller_multi<4, 2, 2, 5>, sparse_caller_multi<4, 2, 3, 5>, sparse_caller_multi<4, 2, 4, 5>, sparse_caller_multi<4, 2, 5, 5>}
|
||||
},
|
||||
{ // index 3
|
||||
{sparse_caller_multi<4, 3, 1, 1>, sparse_caller_multi<4, 3, 2, 1>, sparse_caller_multi<4, 3, 3, 1>, sparse_caller_multi<4, 3, 4, 1>, sparse_caller_multi<4, 3, 5, 1>},
|
||||
{sparse_caller_multi<4, 3, 1, 2>, sparse_caller_multi<4, 3, 2, 2>, sparse_caller_multi<4, 3, 3, 2>, sparse_caller_multi<4, 3, 4, 2>, sparse_caller_multi<4, 3, 5, 2>},
|
||||
{sparse_caller_multi<4, 3, 1, 3>, sparse_caller_multi<4, 3, 2, 3>, sparse_caller_multi<4, 3, 3, 3>, sparse_caller_multi<4, 3, 4, 3>, sparse_caller_multi<4, 3, 5, 3>},
|
||||
{sparse_caller_multi<4, 3, 1, 4>, sparse_caller_multi<4, 3, 2, 4>, sparse_caller_multi<4, 3, 3, 4>, sparse_caller_multi<4, 3, 4, 4>, sparse_caller_multi<4, 3, 5, 4>},
|
||||
{sparse_caller_multi<4, 3, 1, 5>, sparse_caller_multi<4, 3, 2, 5>, sparse_caller_multi<4, 3, 3, 5>, sparse_caller_multi<4, 3, 4, 5>, sparse_caller_multi<4, 3, 5, 5>}
|
||||
},
|
||||
{ // index 4
|
||||
{sparse_caller_multi<4, 4, 1, 1>, sparse_caller_multi<4, 4, 2, 1>, sparse_caller_multi<4, 4, 3, 1>, sparse_caller_multi<4, 4, 4, 1>, sparse_caller_multi<4, 4, 5, 1>},
|
||||
{sparse_caller_multi<4, 4, 1, 2>, sparse_caller_multi<4, 4, 2, 2>, sparse_caller_multi<4, 4, 3, 2>, sparse_caller_multi<4, 4, 4, 2>, sparse_caller_multi<4, 4, 5, 2>},
|
||||
{sparse_caller_multi<4, 4, 1, 3>, sparse_caller_multi<4, 4, 2, 3>, sparse_caller_multi<4, 4, 3, 3>, sparse_caller_multi<4, 4, 4, 3>, sparse_caller_multi<4, 4, 5, 3>},
|
||||
{sparse_caller_multi<4, 4, 1, 4>, sparse_caller_multi<4, 4, 2, 4>, sparse_caller_multi<4, 4, 3, 4>, sparse_caller_multi<4, 4, 4, 4>, sparse_caller_multi<4, 4, 5, 4>},
|
||||
{sparse_caller_multi<4, 4, 1, 5>, sparse_caller_multi<4, 4, 2, 5>, sparse_caller_multi<4, 4, 3, 5>, sparse_caller_multi<4, 4, 4, 5>, sparse_caller_multi<4, 4, 5, 5>}
|
||||
}
|
||||
};
|
||||
|
||||
switch(index)
|
||||
{
|
||||
case 0:
|
||||
bindTexture(&tex_If4_multi0, I);
|
||||
bindTexture(&tex_Jf4_multi0, J);
|
||||
break;
|
||||
case 1:
|
||||
bindTexture(&tex_If4_multi1, I);
|
||||
bindTexture(&tex_Jf4_multi1, J);
|
||||
break;
|
||||
case 2:
|
||||
bindTexture(&tex_If4_multi2, I);
|
||||
bindTexture(&tex_Jf4_multi2, J);
|
||||
break;
|
||||
case 3:
|
||||
bindTexture(&tex_If4_multi3, I);
|
||||
bindTexture(&tex_Jf4_multi3, J);
|
||||
break;
|
||||
case 4:
|
||||
bindTexture(&tex_If4_multi4, I);
|
||||
bindTexture(&tex_Jf4_multi4, J);
|
||||
break;
|
||||
default:
|
||||
CV_Error(CV_StsBadArg, "invalid execution line index");
|
||||
break;
|
||||
}
|
||||
|
||||
funcs[index][patch.y - 1][patch.x - 1](I.rows, I.cols, prevPts, nextPts, status, err, ptcount,
|
||||
level, block, stream);
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_TBB)
|
||||
|
||||
void dense(PtrStepSzb I, PtrStepSzf J, PtrStepSzf u, PtrStepSzf v, PtrStepSzf prevU, PtrStepSzf prevV, PtrStepSzf err, int2 winSize, cudaStream_t stream)
|
||||
{
|
||||
dim3 block(16, 16);
|
||||
|
||||
+157
-1
@@ -42,12 +42,18 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
#include <tbb/compat/condition_variable>
|
||||
#include <tbb/mutex.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::gpu;
|
||||
|
||||
#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
|
||||
|
||||
|
||||
cv::gpu::PyrLKOpticalFlow::PyrLKOpticalFlow() { throw_nogpu(); }
|
||||
void cv::gpu::PyrLKOpticalFlow::sparse(const GpuMat&, const GpuMat&, const GpuMat&, GpuMat&, GpuMat&, GpuMat*) { throw_nogpu(); }
|
||||
void cv::gpu::PyrLKOpticalFlow::dense(const GpuMat&, const GpuMat&, GpuMat&, GpuMat&, GpuMat*) { throw_nogpu(); }
|
||||
@@ -64,6 +70,23 @@ namespace pyrlk
|
||||
void sparse4(PtrStepSz<float4> I, PtrStepSz<float4> J, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, dim3 patch, cudaStream_t stream = 0);
|
||||
|
||||
|
||||
#if !defined(HAVE_TBB)
|
||||
#define throw_notbb() CV_Error(CV_StsNotImplemented, "The library is compiled without TBB support")
|
||||
void loadConstants_multi(int2, int, int, cudaStream_t) { throw_notbb(); }
|
||||
void sparse1_multi(PtrStepSzf, PtrStepSzf, const float2*, float2*, uchar*, float*, int,
|
||||
int, dim3, dim3, cudaStream_t, int) { throw_notbb(); }
|
||||
void sparse4_multi(PtrStepSz<float4>, PtrStepSz<float4>, const float2*, float2*, uchar*, float*, int,
|
||||
int, dim3, dim3, cudaStream_t, int) { throw_notbb(); }
|
||||
#else
|
||||
void loadConstants_multi(int2 winSize, int iters, int index = 0, cudaStream_t stream = 0);
|
||||
|
||||
void sparse1_multi(PtrStepSzf I, PtrStepSzf J, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, dim3 patch, cudaStream_t stream = 0, int index = 0);
|
||||
void sparse4_multi(PtrStepSz<float4> I, PtrStepSz<float4> J, const float2* prevPts, float2* nextPts, uchar* status, float* err, int ptcount,
|
||||
int level, dim3 block, dim3 patch, cudaStream_t stream = 0, int index = 0);
|
||||
#endif
|
||||
|
||||
void dense(PtrStepSzb I, PtrStepSzf J, PtrStepSzf u, PtrStepSzf v, PtrStepSzf prevU, PtrStepSzf prevV,
|
||||
PtrStepSzf err, int2 winSize, cudaStream_t stream = 0);
|
||||
}
|
||||
@@ -98,7 +121,9 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
void cv::gpu::PyrLKOpticalFlow::sparse(const GpuMat& prevImg, const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts, GpuMat& status, GpuMat* err)
|
||||
void cv::gpu::PyrLKOpticalFlow::sparse(const GpuMat& prevImg,
|
||||
const GpuMat& nextImg, const GpuMat& prevPts,
|
||||
GpuMat& nextPts, GpuMat& status, GpuMat* err)
|
||||
{
|
||||
if (prevPts.empty())
|
||||
{
|
||||
@@ -181,6 +206,137 @@ void cv::gpu::PyrLKOpticalFlow::sparse(const GpuMat& prevImg, const GpuMat& next
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
//--------------------------------------------------------------------------
|
||||
// Multi-threading support
|
||||
|
||||
static bool index_vector_use[5] = {true, true, true, true, true}; // all free
|
||||
static tbb::mutex s_PyrLKOpticalFlow_Mutex;
|
||||
static condition_variable s_PyrLKOpticalFlow_ConditionVariable;
|
||||
|
||||
void cv::gpu::PyrLKOpticalFlow::sparse_multi(const GpuMat& prevImg,
|
||||
const GpuMat& nextImg, const GpuMat& prevPts, GpuMat& nextPts,
|
||||
GpuMat& status, Stream& stream, GpuMat* err)
|
||||
{
|
||||
if (prevPts.empty())
|
||||
{
|
||||
nextPts.release();
|
||||
status.release();
|
||||
if (err) err->release();
|
||||
return;
|
||||
}
|
||||
|
||||
dim3 block, patch;
|
||||
calcPatchSize(winSize, block, patch);
|
||||
|
||||
CV_Assert(prevImg.channels() == 1 || prevImg.channels() == 3 || prevImg.channels() == 4);
|
||||
CV_Assert(prevImg.size() == nextImg.size() && prevImg.type() == nextImg.type());
|
||||
CV_Assert(maxLevel >= 0);
|
||||
CV_Assert(winSize.width > 2 && winSize.height > 2);
|
||||
CV_Assert(patch.x > 0 && patch.x < 6 && patch.y > 0 && patch.y < 6);
|
||||
CV_Assert(prevPts.rows == 1 && prevPts.type() == CV_32FC2);
|
||||
|
||||
if (useInitialFlow)
|
||||
CV_Assert(nextPts.size() == prevPts.size() && nextPts.type() == CV_32FC2);
|
||||
else
|
||||
ensureSizeIsEnough(1, prevPts.cols, prevPts.type(), nextPts);
|
||||
|
||||
GpuMat temp1 = (useInitialFlow ? nextPts : prevPts).reshape(1);
|
||||
GpuMat temp2 = nextPts.reshape(1);
|
||||
multiply(temp1, Scalar::all(1.0 / (1 << maxLevel) / 2.0), temp2);
|
||||
|
||||
ensureSizeIsEnough(1, prevPts.cols, CV_8UC1, status);
|
||||
status.setTo(Scalar::all(1));
|
||||
|
||||
if (err)
|
||||
ensureSizeIsEnough(1, prevPts.cols, CV_32FC1, *err);
|
||||
|
||||
// build the image pyramids.
|
||||
|
||||
prevPyr_.resize(maxLevel + 1);
|
||||
nextPyr_.resize(maxLevel + 1);
|
||||
|
||||
int cn = prevImg.channels();
|
||||
|
||||
if (cn == 1 || cn == 4)
|
||||
{
|
||||
prevImg.convertTo(prevPyr_[0], CV_32F);
|
||||
nextImg.convertTo(nextPyr_[0], CV_32F);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_.resize(1);
|
||||
|
||||
cvtColor(prevImg, buf_[0], COLOR_BGR2BGRA);
|
||||
buf_[0].convertTo(prevPyr_[0], CV_32F);
|
||||
|
||||
cvtColor(nextImg, buf_[0], COLOR_BGR2BGRA);
|
||||
buf_[0].convertTo(nextPyr_[0], CV_32F);
|
||||
}
|
||||
|
||||
for (int level = 1; level <= maxLevel; ++level)
|
||||
{
|
||||
pyrDown(prevPyr_[level - 1], prevPyr_[level]);
|
||||
pyrDown(nextPyr_[level - 1], nextPyr_[level]);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Multithreading support
|
||||
int index = -1;
|
||||
|
||||
do
|
||||
{
|
||||
unique_lock<tbb::mutex> ul(s_PyrLKOpticalFlow_Mutex);
|
||||
for (unsigned int uiI = 0; uiI < 5; ++uiI)
|
||||
{
|
||||
if (index_vector_use[uiI])
|
||||
{
|
||||
index = uiI;
|
||||
index_vector_use[uiI] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index < 0)
|
||||
s_PyrLKOpticalFlow_ConditionVariable.wait(ul);
|
||||
|
||||
ul.unlock();
|
||||
}while (index < 0);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
pyrlk::loadConstants_multi(make_int2(winSize.width, winSize.height), iters, index);
|
||||
|
||||
for (int level = maxLevel; level >= 0; level--)
|
||||
{
|
||||
if (cn == 1)
|
||||
{
|
||||
pyrlk::sparse1_multi(prevPyr_[level], nextPyr_[level],
|
||||
prevPts.ptr<float2>(), nextPts.ptr<float2>(), status.ptr(),
|
||||
level == 0 && err ? err->ptr<float>() : 0, prevPts.cols,
|
||||
level, block, patch, StreamAccessor::getStream(stream), index);
|
||||
}
|
||||
else
|
||||
{
|
||||
pyrlk::sparse4_multi(prevPyr_[level], nextPyr_[level],
|
||||
prevPts.ptr<float2>(), nextPts.ptr<float2>(), status.ptr(),
|
||||
level == 0 && err ? err->ptr<float>() : 0, prevPts.cols,
|
||||
level, block, patch, StreamAccessor::getStream(stream), index);
|
||||
}
|
||||
}
|
||||
|
||||
unique_lock<tbb::mutex> ul(s_PyrLKOpticalFlow_Mutex);
|
||||
index_vector_use[index] = true;
|
||||
s_PyrLKOpticalFlow_ConditionVariable.notify_one();
|
||||
}
|
||||
#else
|
||||
void cv::gpu::PyrLKOpticalFlow::sparse_multi(const GpuMat& /*prevImg*/,
|
||||
const GpuMat& /*nextImg*/, const GpuMat& /*prevPts*/, GpuMat& /*nextPts*/,
|
||||
GpuMat& /*status*/, Stream& /*stream*/, GpuMat* /*err*/)
|
||||
{
|
||||
throw_notbb();
|
||||
}
|
||||
#endif
|
||||
|
||||
void cv::gpu::PyrLKOpticalFlow::dense(const GpuMat& prevImg, const GpuMat& nextImg, GpuMat& u, GpuMat& v, GpuMat* err)
|
||||
{
|
||||
CV_Assert(prevImg.type() == CV_8UC1);
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
|
||||
#ifdef HAVE_CUDA
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
#include <tbb/tbb.h>
|
||||
#endif
|
||||
|
||||
using namespace cvtest;
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
@@ -322,6 +326,134 @@ GPU_TEST_P(PyrLKOpticalFlow, Sparse)
|
||||
ASSERT_LE(bad_ratio, 0.01);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
|
||||
struct Sparse_Multi_Functor
|
||||
{
|
||||
explicit Sparse_Multi_Functor(const cv::Mat& in_frame0, const cv::Mat& in_frame1,
|
||||
const cv::Mat& in_pts_mat,
|
||||
cv::gpu::GpuMat* in_d_pts,
|
||||
cv::gpu::GpuMat* in_d_nextPts,
|
||||
cv::gpu::GpuMat* in_d_status,
|
||||
cv::gpu::Stream* in_streams):
|
||||
m_frame0(in_frame0), m_frame1(in_frame1),
|
||||
m_pts_mat(in_pts_mat),
|
||||
m_d_pts(in_d_pts), m_d_nextPts(in_d_nextPts),
|
||||
m_d_status(in_d_status), m_streams(in_streams){}
|
||||
|
||||
void operator()( const tbb::blocked_range<size_t>& r ) const
|
||||
{
|
||||
for( size_t i = r.begin(); i != r.end(); ++i )
|
||||
{
|
||||
m_d_pts[i].upload(m_pts_mat);
|
||||
cv::gpu::PyrLKOpticalFlow pyrLK;
|
||||
pyrLK.sparse_multi(loadMat(m_frame0), loadMat(m_frame1), m_d_pts[i],
|
||||
m_d_nextPts[i], m_d_status[i], m_streams[i]);
|
||||
m_streams[i].waitForCompletion();
|
||||
}
|
||||
}
|
||||
|
||||
const cv::Mat& m_frame0;
|
||||
const cv::Mat& m_frame1;
|
||||
const cv::Mat& m_pts_mat;
|
||||
cv::gpu::GpuMat* m_d_pts;
|
||||
cv::gpu::GpuMat* m_d_nextPts;
|
||||
cv::gpu::GpuMat* m_d_status;
|
||||
cv::gpu::Stream* m_streams;
|
||||
};
|
||||
|
||||
|
||||
GPU_TEST_P(PyrLKOpticalFlow, Sparse_Multi)
|
||||
{
|
||||
cv::Mat frame0 = readImage("opticalflow/frame0.png", useGray ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR);
|
||||
ASSERT_FALSE(frame0.empty());
|
||||
|
||||
cv::Mat frame1 = readImage("opticalflow/frame1.png", useGray ? cv::IMREAD_GRAYSCALE : cv::IMREAD_COLOR);
|
||||
ASSERT_FALSE(frame1.empty());
|
||||
|
||||
cv::Mat gray_frame;
|
||||
if (useGray)
|
||||
gray_frame = frame0;
|
||||
else
|
||||
cv::cvtColor(frame0, gray_frame, cv::COLOR_BGR2GRAY);
|
||||
|
||||
std::vector<cv::Point2f> pts;
|
||||
cv::goodFeaturesToTrack(gray_frame, pts, 1000, 0.01, 0.0);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// GPU
|
||||
const unsigned int NB_EXEC_LINES = 27;
|
||||
|
||||
cv::gpu::GpuMat d_pts[NB_EXEC_LINES];
|
||||
cv::gpu::GpuMat d_nextPts[NB_EXEC_LINES];
|
||||
cv::gpu::GpuMat d_status[NB_EXEC_LINES];
|
||||
cv::gpu::Stream streams[NB_EXEC_LINES];
|
||||
|
||||
cv::Mat pts_mat(1, (int) pts.size(), CV_32FC2, (void*) &pts[0]);
|
||||
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, NB_EXEC_LINES),
|
||||
Sparse_Multi_Functor(frame0, frame1, pts_mat,
|
||||
d_pts, d_nextPts, d_status, streams));
|
||||
|
||||
std::vector<cv::Point2f> nextPts[NB_EXEC_LINES];
|
||||
std::vector<unsigned char> status[NB_EXEC_LINES];
|
||||
|
||||
for (unsigned int i = 0; i < NB_EXEC_LINES; ++i)
|
||||
{
|
||||
nextPts[i].resize(d_nextPts[i].cols);
|
||||
cv::Mat nextPts_mat(1, d_nextPts[i].cols, CV_32FC2, (void*) &(nextPts[i][0]));
|
||||
d_nextPts[i].download(nextPts_mat);
|
||||
|
||||
status[i].resize(d_status[i].cols);
|
||||
cv::Mat status_mat(1, d_status[i].cols, CV_8UC1, (void*) &(status[i][0]));
|
||||
d_status[i].download(status_mat);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// CPU
|
||||
std::vector<cv::Point2f> nextPts_gold;
|
||||
std::vector<unsigned char> status_gold;
|
||||
cv::calcOpticalFlowPyrLK(frame0, frame1, pts, nextPts_gold, status_gold, cv::noArray());
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// CHECKS
|
||||
for (unsigned int uiI = 0; uiI < NB_EXEC_LINES; ++uiI)
|
||||
{
|
||||
ASSERT_EQ(nextPts_gold.size(), nextPts[uiI].size());
|
||||
ASSERT_EQ(status_gold.size(), status[uiI].size());
|
||||
}
|
||||
|
||||
size_t mistmatch = 0;
|
||||
for (unsigned int uiI = 0; uiI < NB_EXEC_LINES; ++uiI)
|
||||
{
|
||||
for (size_t i = 0; i < nextPts[uiI].size(); ++i)
|
||||
{
|
||||
cv::Point2i a = nextPts[uiI][i];
|
||||
cv::Point2i b = nextPts_gold[i];
|
||||
|
||||
if (status[uiI][i] != status_gold[i])
|
||||
{
|
||||
++mistmatch;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status[uiI][i])
|
||||
{
|
||||
bool eq = std::abs(a.x - b.x) <= 1 && std::abs(a.y - b.y) <= 1;
|
||||
|
||||
if (!eq)
|
||||
++mistmatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double bad_ratio = static_cast<double>(mistmatch) / (nextPts[0].size() * NB_EXEC_LINES);
|
||||
|
||||
ASSERT_LE(bad_ratio, 0.01);
|
||||
}
|
||||
|
||||
#endif // HAVE_TBB
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(GPU_Video, PyrLKOpticalFlow, testing::Combine(
|
||||
ALL_DEVICES,
|
||||
testing::Values(UseGray(true), UseGray(false))));
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
#include "precomp.hpp"
|
||||
#include "bitstrm.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
namespace cv
|
||||
{
|
||||
@@ -103,7 +104,6 @@ void RBaseStream::readBlock()
|
||||
fseek( m_file, m_block_pos, SEEK_SET );
|
||||
size_t readed = fread( m_start, 1, m_block_size, m_file );
|
||||
m_end = m_start + readed;
|
||||
m_current = m_start;
|
||||
|
||||
if( readed == 0 || m_current >= m_end )
|
||||
throw RBS_THROW_EOS;
|
||||
@@ -164,7 +164,7 @@ void RBaseStream::release()
|
||||
|
||||
void RBaseStream::setPos( int pos )
|
||||
{
|
||||
assert( isOpened() && pos >= 0 );
|
||||
CV_Assert(isOpened() && pos >= 0);
|
||||
|
||||
if( !m_file )
|
||||
{
|
||||
@@ -181,14 +181,19 @@ void RBaseStream::setPos( int pos )
|
||||
|
||||
int RBaseStream::getPos()
|
||||
{
|
||||
assert( isOpened() );
|
||||
return m_block_pos + (int)(m_current - m_start);
|
||||
CV_Assert(isOpened());
|
||||
int pos = validateToInt((m_current - m_start) + m_block_pos);
|
||||
CV_Assert(pos >= m_block_pos); // overflow check
|
||||
CV_Assert(pos >= 0); // overflow check
|
||||
return pos;
|
||||
}
|
||||
|
||||
void RBaseStream::skip( int bytes )
|
||||
{
|
||||
assert( bytes >= 0 );
|
||||
CV_Assert(bytes >= 0);
|
||||
uchar* old = m_current;
|
||||
m_current += bytes;
|
||||
CV_Assert(m_current >= old); // overflow check
|
||||
}
|
||||
|
||||
///////////////////////// RLByteStream ////////////////////////////
|
||||
@@ -220,7 +225,7 @@ int RLByteStream::getBytes( void* buffer, int count )
|
||||
{
|
||||
uchar* data = (uchar*)buffer;
|
||||
int readed = 0;
|
||||
assert( count >= 0 );
|
||||
CV_Assert(count >= 0);
|
||||
|
||||
while( count > 0 )
|
||||
{
|
||||
@@ -371,7 +376,7 @@ void WBaseStream::writeBlock()
|
||||
{
|
||||
int size = (int)(m_current - m_start);
|
||||
|
||||
assert( isOpened() );
|
||||
CV_Assert(isOpened());
|
||||
if( size == 0 )
|
||||
return;
|
||||
|
||||
@@ -442,7 +447,7 @@ void WBaseStream::release()
|
||||
|
||||
int WBaseStream::getPos()
|
||||
{
|
||||
assert( isOpened() );
|
||||
CV_Assert(isOpened());
|
||||
return m_block_pos + (int)(m_current - m_start);
|
||||
}
|
||||
|
||||
@@ -465,7 +470,7 @@ void WLByteStream::putBytes( const void* buffer, int count )
|
||||
{
|
||||
uchar* data = (uchar*)buffer;
|
||||
|
||||
assert( data && m_current && count >= 0 );
|
||||
CV_Assert(data && m_current && count >= 0);
|
||||
|
||||
while( count )
|
||||
{
|
||||
|
||||
@@ -192,7 +192,11 @@ CvDC1394::~CvDC1394()
|
||||
dc = 0;
|
||||
}
|
||||
|
||||
static CvDC1394 dc1394;
|
||||
static CvDC1394& getDC1394()
|
||||
{
|
||||
static CvDC1394 dc1394;
|
||||
return dc1394;
|
||||
}
|
||||
|
||||
class CvCaptureCAM_DC1394_v2_CPP : public CvCapture
|
||||
{
|
||||
@@ -451,7 +455,7 @@ bool CvCaptureCAM_DC1394_v2_CPP::startCapture()
|
||||
code = dc1394_capture_setup(dcCam, nDMABufs, DC1394_CAPTURE_FLAGS_DEFAULT);
|
||||
if (code >= 0)
|
||||
{
|
||||
FD_SET(dc1394_capture_get_fileno(dcCam), &dc1394.camFds);
|
||||
FD_SET(dc1394_capture_get_fileno(dcCam), &getDC1394().camFds);
|
||||
dc1394_video_set_transmission(dcCam, DC1394_ON);
|
||||
if (cameraId == VIDERE)
|
||||
{
|
||||
@@ -477,15 +481,15 @@ bool CvCaptureCAM_DC1394_v2_CPP::open(int index)
|
||||
|
||||
close();
|
||||
|
||||
if (!dc1394.dc)
|
||||
if (!getDC1394().dc)
|
||||
goto _exit_;
|
||||
|
||||
err = dc1394_camera_enumerate(dc1394.dc, &cameraList);
|
||||
err = dc1394_camera_enumerate(getDC1394().dc, &cameraList);
|
||||
if (err < 0 || !cameraList || (unsigned)index >= (unsigned)cameraList->num)
|
||||
goto _exit_;
|
||||
|
||||
guid = cameraList->ids[index].guid;
|
||||
dcCam = dc1394_camera_new(dc1394.dc, guid);
|
||||
dcCam = dc1394_camera_new(getDC1394().dc, guid);
|
||||
if (!dcCam)
|
||||
goto _exit_;
|
||||
|
||||
@@ -510,8 +514,8 @@ void CvCaptureCAM_DC1394_v2_CPP::close()
|
||||
// check for fileno valid before using
|
||||
int fileno=dc1394_capture_get_fileno(dcCam);
|
||||
|
||||
if (fileno>=0 && FD_ISSET(fileno, &dc1394.camFds))
|
||||
FD_CLR(fileno, &dc1394.camFds);
|
||||
if (fileno>=0 && FD_ISSET(fileno, &getDC1394().camFds))
|
||||
FD_CLR(fileno, &getDC1394().camFds);
|
||||
dc1394_video_set_transmission(dcCam, DC1394_OFF);
|
||||
dc1394_capture_stop(dcCam);
|
||||
dc1394_camera_free(dcCam);
|
||||
|
||||
@@ -173,6 +173,10 @@ extern "C" {
|
||||
#define AV_PIX_FMT_GRAY16BE PIX_FMT_GRAY16BE
|
||||
#endif
|
||||
|
||||
#ifndef PKT_FLAG_KEY
|
||||
#define PKT_FLAG_KEY AV_PKT_FLAG_KEY
|
||||
#endif
|
||||
|
||||
#if LIBAVUTIL_BUILD >= (LIBAVUTIL_VERSION_MICRO >= 100 \
|
||||
? CALC_FFMPEG_VERSION(52, 38, 100) : CALC_FFMPEG_VERSION(52, 13, 0))
|
||||
#define USE_AV_FRAME_GET_BUFFER 1
|
||||
@@ -1481,13 +1485,20 @@ static AVStream *icv_add_video_stream_FFMPEG(AVFormatContext *oc,
|
||||
// some formats want stream headers to be seperate
|
||||
if(oc->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
{
|
||||
#if LIBAVCODEC_BUILD > CALC_FFMPEG_VERSION(56, 35, 0)
|
||||
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
#else
|
||||
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LIBAVCODEC_BUILD >= CALC_FFMPEG_VERSION(52, 42, 0)
|
||||
st->avg_frame_rate = (AVRational){frame_rate, frame_rate_base};
|
||||
#endif
|
||||
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(55, 20, 0)
|
||||
st->time_base = c->time_base;
|
||||
#endif
|
||||
|
||||
return st;
|
||||
}
|
||||
@@ -1509,23 +1520,24 @@ static int icv_av_write_frame_FFMPEG( AVFormatContext * oc, AVStream * video_st,
|
||||
#endif
|
||||
int ret = OPENCV_NO_FRAMES_WRITTEN_CODE;
|
||||
|
||||
if (oc->oformat->flags & AVFMT_RAWPICTURE) {
|
||||
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0)
|
||||
if (oc->oformat->flags & AVFMT_RAWPICTURE)
|
||||
{
|
||||
/* raw video case. The API will change slightly in the near
|
||||
futur for that */
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
|
||||
#ifndef PKT_FLAG_KEY
|
||||
#define PKT_FLAG_KEY AV_PKT_FLAG_KEY
|
||||
#endif
|
||||
|
||||
pkt.flags |= PKT_FLAG_KEY;
|
||||
pkt.stream_index= video_st->index;
|
||||
pkt.data= (uint8_t *)picture;
|
||||
pkt.size= sizeof(AVPicture);
|
||||
|
||||
ret = av_write_frame(oc, &pkt);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* encode the image */
|
||||
AVPacket pkt;
|
||||
av_init_packet(&pkt);
|
||||
@@ -1683,7 +1695,9 @@ void CvVideoWriter_FFMPEG::close()
|
||||
/* write the trailer, if any */
|
||||
if(ok && oc)
|
||||
{
|
||||
if( (oc->oformat->flags & AVFMT_RAWPICTURE) == 0 )
|
||||
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0)
|
||||
if (!(oc->oformat->flags & AVFMT_RAWPICTURE))
|
||||
#endif
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
@@ -1917,7 +1931,10 @@ bool CvVideoWriter_FFMPEG::open( const char * filename, int fourcc,
|
||||
|
||||
outbuf = NULL;
|
||||
|
||||
if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
|
||||
#if LIBAVFORMAT_BUILD < CALC_FFMPEG_VERSION(57, 0, 0)
|
||||
if (!(oc->oformat->flags & AVFMT_RAWPICTURE))
|
||||
#endif
|
||||
{
|
||||
/* allocate output buffer */
|
||||
/* assume we will never get codec output with more than 4 bytes per pixel... */
|
||||
outbuf_size = width*height*4;
|
||||
@@ -2211,7 +2228,11 @@ AVStream* OutputMediaStream_FFMPEG::addVideoStream(AVFormatContext *oc, CV_CODEC
|
||||
// some formats want stream headers to be seperate
|
||||
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
|
||||
{
|
||||
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
#if LIBAVCODEC_BUILD > CALC_FFMPEG_VERSION(56, 35, 0)
|
||||
c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
|
||||
#else
|
||||
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -634,11 +634,11 @@ static int icvOpenCamera_QT (CvCapture_QT_Cam * capture, const int index)
|
||||
OPENCV_ASSERT (capture, "icvOpenCamera_QT", "'capture' is a NULL-pointer");
|
||||
OPENCV_ASSERT (index >=0, "icvOpenCamera_QT", "camera index is negative");
|
||||
|
||||
ComponentDescription component_description;
|
||||
Component component = 0;
|
||||
ComponentDescription component_description;
|
||||
Component component = 0;
|
||||
int number_of_inputs = 0;
|
||||
Rect myRect;
|
||||
ComponentResult result = noErr;
|
||||
ComponentResult result = noErr;
|
||||
|
||||
|
||||
// travers all components and count video digitizer channels
|
||||
|
||||
@@ -92,6 +92,7 @@ bool BmpDecoder::readHeader()
|
||||
m_offset = m_strm.getDWord();
|
||||
|
||||
int size = m_strm.getDWord();
|
||||
CV_Assert(size > 0); // overflow, 2Gb limit
|
||||
|
||||
if( size >= 36 )
|
||||
{
|
||||
|
||||
@@ -77,7 +77,8 @@ static JasperInitializer initialize_jasper;
|
||||
|
||||
Jpeg2KDecoder::Jpeg2KDecoder()
|
||||
{
|
||||
m_signature = '\0' + string() + '\0' + string() + '\0' + string("\x0cjP \r\n\x87\n");
|
||||
static const unsigned char signature_[12] = { 0, 0, 0, 0x0c, 'j', 'P', ' ', ' ', 13, 10, 0x87, 10};
|
||||
m_signature = string((const char*)signature_, (const char*)signature_ + sizeof(signature_));
|
||||
m_stream = 0;
|
||||
m_image = 0;
|
||||
}
|
||||
@@ -121,6 +122,8 @@ bool Jpeg2KDecoder::readHeader()
|
||||
jas_image_t* image = jas_image_decode( stream, -1, 0 );
|
||||
m_image = image;
|
||||
if( image ) {
|
||||
CV_Assert(0 == (jas_image_tlx(image)) && "not supported");
|
||||
CV_Assert(0 == (jas_image_tly(image)) && "not supported");
|
||||
m_width = jas_image_width( image );
|
||||
m_height = jas_image_height( image );
|
||||
|
||||
@@ -130,14 +133,31 @@ bool Jpeg2KDecoder::readHeader()
|
||||
for( int i = 0; i < numcmpts; i++ )
|
||||
{
|
||||
int depth_i = jas_image_cmptprec( image, i );
|
||||
CV_Assert(depth == 0 || depth == depth_i); // component data type mismatch
|
||||
depth = MAX(depth, depth_i);
|
||||
if( jas_image_cmpttype( image, i ) > 2 )
|
||||
continue;
|
||||
int sgnd = jas_image_cmptsgnd(image, i);
|
||||
int xstart = jas_image_cmpttlx(image, i);
|
||||
int xend = jas_image_cmptbrx(image, i);
|
||||
int xstep = jas_image_cmpthstep(image, i);
|
||||
int ystart = jas_image_cmpttly(image, i);
|
||||
int yend = jas_image_cmptbry(image, i);
|
||||
int ystep = jas_image_cmptvstep(image, i);
|
||||
CV_Assert(sgnd == 0 && "not supported");
|
||||
CV_Assert(xstart == 0 && "not supported");
|
||||
CV_Assert(ystart == 0 && "not supported");
|
||||
CV_Assert(xstep == 1 && "not supported");
|
||||
CV_Assert(ystep == 1 && "not supported");
|
||||
CV_Assert(xend == m_width);
|
||||
CV_Assert(yend == m_height);
|
||||
cntcmpts++;
|
||||
}
|
||||
|
||||
if( cntcmpts )
|
||||
{
|
||||
CV_Assert(depth == 8 || depth == 16);
|
||||
CV_Assert(cntcmpts == 1 || cntcmpts == 3);
|
||||
m_type = CV_MAKETYPE(depth <= 8 ? CV_8U : CV_16U, cntcmpts > 1 ? 3 : 1);
|
||||
result = true;
|
||||
}
|
||||
@@ -150,9 +170,15 @@ bool Jpeg2KDecoder::readHeader()
|
||||
return result;
|
||||
}
|
||||
|
||||
static void Jpeg2KDecoder_close(Jpeg2KDecoder* ptr)
|
||||
{
|
||||
ptr->close();
|
||||
}
|
||||
template<> void Ptr<Jpeg2KDecoder>::delete_obj() { Jpeg2KDecoder_close(obj); }
|
||||
|
||||
bool Jpeg2KDecoder::readData( Mat& img )
|
||||
{
|
||||
Ptr<Jpeg2KDecoder> close_this(this); // auto cleanup: Jpeg2KDecoder_close
|
||||
bool result = false;
|
||||
int color = img.channels() > 1;
|
||||
uchar* data = img.data;
|
||||
@@ -204,11 +230,16 @@ bool Jpeg2KDecoder::readData( Mat& img )
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "JPEG 2000 LOADER ERROR: cannot convert colorspace\n");
|
||||
{
|
||||
jas_cmprof_destroy(clrprof);
|
||||
CV_Error(CV_StsError, "JPEG 2000 LOADER ERROR: cannot convert colorspace");
|
||||
}
|
||||
jas_cmprof_destroy( clrprof );
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "JPEG 2000 LOADER ERROR: unable to create colorspace\n");
|
||||
{
|
||||
CV_Error(CV_StsError, "JPEG 2000 LOADER ERROR: unable to create colorspace");
|
||||
}
|
||||
}
|
||||
else
|
||||
result = true;
|
||||
@@ -257,8 +288,8 @@ bool Jpeg2KDecoder::readData( Mat& img )
|
||||
result = readComponent16u( ((unsigned short *)data) + i, buffer, validateToInt(step / 2), cmptlut[i], maxval, offset, ncmpts );
|
||||
if( !result )
|
||||
{
|
||||
i = ncmpts;
|
||||
result = false;
|
||||
jas_matrix_destroy( buffer );
|
||||
CV_Error(CV_StsError, "JPEG2000 LOADER ERROR: failed to read component");
|
||||
}
|
||||
}
|
||||
jas_matrix_destroy( buffer );
|
||||
@@ -267,10 +298,12 @@ bool Jpeg2KDecoder::readData( Mat& img )
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "JPEG2000 LOADER ERROR: colorspace conversion failed\n" );
|
||||
{
|
||||
CV_Error(CV_StsError, "JPEG2000 LOADER ERROR: colorspace conversion failed");
|
||||
}
|
||||
}
|
||||
|
||||
close();
|
||||
CV_Assert(result == true);
|
||||
|
||||
#ifndef WIN32
|
||||
if (!clr.empty())
|
||||
|
||||
@@ -331,7 +331,7 @@ bool PxMDecoder::readData( Mat& img )
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy( data, src, m_width*(bit_depth/8) );
|
||||
memcpy(data, src, img.elemSize1()*m_width);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -120,7 +120,7 @@ bool SunRasterDecoder::readHeader()
|
||||
m_type = IsColorPalette( m_palette, m_bpp ) ? CV_8UC3 : CV_8UC1;
|
||||
m_offset = m_strm.getPos();
|
||||
|
||||
assert( m_offset == 32 + m_maplength );
|
||||
CV_Assert(m_offset == 32 + m_maplength);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,7 @@ bool SunRasterDecoder::readHeader()
|
||||
|
||||
m_offset = m_strm.getPos();
|
||||
|
||||
assert( m_offset == 32 + m_maplength );
|
||||
CV_Assert(m_offset == 32 + m_maplength);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
@@ -226,7 +226,7 @@ bool SunRasterDecoder::readData( Mat& img )
|
||||
code = m_strm.getByte();
|
||||
if( len > line_end - tsrc )
|
||||
{
|
||||
assert(0);
|
||||
CV_Error(CV_StsInternal, "");
|
||||
goto bad_decoding_1bpp;
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ bad_decoding_end:
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
CV_Error(CV_StsInternal, "");
|
||||
}
|
||||
}
|
||||
catch( ... )
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <assert.h> // FIX IT: remove this
|
||||
|
||||
#if defined WIN32 || defined WINCE
|
||||
#if !defined _WIN32_WINNT
|
||||
|
||||
@@ -670,7 +670,7 @@ cvConvertImage( const CvArr* srcarr, CvArr* dstarr, int flags )
|
||||
icvCvt_BGR2Gray_8u_C3C1R( s, s_step, d, d_step, size, swap_rb );
|
||||
break;
|
||||
case 33:
|
||||
assert( swap_rb );
|
||||
CV_Assert(swap_rb);
|
||||
icvCvt_RGB2BGR_8u_C3R( s, s_step, d, d_step, size );
|
||||
break;
|
||||
case 41:
|
||||
|
||||
@@ -320,6 +320,7 @@ public:
|
||||
|
||||
for (unsigned int i = 0; i < frameCount && next; ++i)
|
||||
{
|
||||
SCOPED_TRACE(cv::format("frame=%d", (int)i));
|
||||
Mat actual;
|
||||
(*capture) >> actual;
|
||||
|
||||
|
||||
@@ -543,6 +543,7 @@ void FeaturesMatcher::operator ()(const vector<ImageFeatures> &features, vector<
|
||||
if (features[i].keypoints.size() > 0 && features[j].keypoints.size() > 0 && mask_(i, j))
|
||||
near_pairs.push_back(make_pair(i, j));
|
||||
|
||||
pairwise_matches.clear(); // clear history values
|
||||
pairwise_matches.resize(num_images * num_images);
|
||||
MatchPairsBody body(*this, features, pairwise_matches, near_pairs);
|
||||
|
||||
|
||||
@@ -90,6 +90,12 @@ if(BUILD_EXAMPLES AND OCV_DEPENDENCIES_FOUND)
|
||||
list(REMOVE_ITEM all_samples "driver_api_multi.cpp")
|
||||
list(REMOVE_ITEM all_samples "driver_api_stereo_multi.cpp")
|
||||
endif()
|
||||
if(NOT HAVE_CUDA
|
||||
OR NOT HAVE_TBB
|
||||
OR OpenCV_FOUND # via find_package() there is no access to cvconfig.h
|
||||
)
|
||||
list(REMOVE_ITEM all_samples "pyrlk_optical_flow_multithreading.cpp")
|
||||
endif()
|
||||
|
||||
foreach(sample_filename ${all_samples})
|
||||
get_filename_component(sample ${sample_filename} NAME_WE)
|
||||
@@ -111,6 +117,9 @@ if (OCV_DEPENDENCIES_FOUND AND INSTALL_C_EXAMPLES AND NOT WIN32)
|
||||
list_filterout(install_list ".*driver_api_multi.cpp")
|
||||
list_filterout(install_list ".*driver_api_stereo_multi.cpp")
|
||||
endif()
|
||||
if(NOT HAVE_CUDA OR NOT HAVE_TBB)
|
||||
list(REMOVE_ITEM install_list "pyrlk_optical_flow_multithreading.cpp")
|
||||
endif()
|
||||
install(FILES ${install_list}
|
||||
DESTINATION "${OPENCV_SAMPLES_SRC_INSTALL_PATH}/gpu"
|
||||
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT samples)
|
||||
|
||||
@@ -0,0 +1,272 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
#include "cvconfig.h"
|
||||
|
||||
#ifdef HAVE_TBB
|
||||
#include <tbb/parallel_for_each.h>
|
||||
#include <tbb/task_scheduler_init.h>
|
||||
|
||||
#include "opencv2/imgproc/imgproc.hpp"
|
||||
#include "opencv2/highgui/highgui.hpp"
|
||||
#include "opencv2/video/video.hpp"
|
||||
#include "opencv2/gpu/gpu.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
using namespace cv::gpu;
|
||||
|
||||
static void download(const GpuMat& d_mat, vector<Point2f>& vec)
|
||||
{
|
||||
vec.resize(d_mat.cols);
|
||||
Mat mat(1, d_mat.cols, CV_32FC2, (void*)&vec[0]);
|
||||
d_mat.download(mat);
|
||||
}
|
||||
|
||||
static void download(const GpuMat& d_mat, vector<uchar>& vec)
|
||||
{
|
||||
vec.resize(d_mat.cols);
|
||||
Mat mat(1, d_mat.cols, CV_8UC1, (void*)&vec[0]);
|
||||
d_mat.download(mat);
|
||||
}
|
||||
|
||||
static void drawArrows(Mat& frame, const vector<Point2f>& prevPts, const vector<Point2f>& nextPts, const vector<uchar>& status, Scalar line_color = Scalar(0, 0, 255))
|
||||
{
|
||||
for (size_t i = 0; i < prevPts.size(); ++i)
|
||||
{
|
||||
if (status[i])
|
||||
{
|
||||
int line_thickness = 1;
|
||||
|
||||
Point p = prevPts[i];
|
||||
Point q = nextPts[i];
|
||||
|
||||
double angle = atan2((double) p.y - q.y, (double) p.x - q.x);
|
||||
|
||||
double hypotenuse = sqrt( (double)(p.y - q.y)*(p.y - q.y) + (double)(p.x - q.x)*(p.x - q.x) );
|
||||
|
||||
if (hypotenuse < 1.0)
|
||||
continue;
|
||||
|
||||
// Here we lengthen the arrow by a factor of three.
|
||||
q.x = (int) (p.x - 3 * hypotenuse * cos(angle));
|
||||
q.y = (int) (p.y - 3 * hypotenuse * sin(angle));
|
||||
|
||||
// Now we draw the main line of the arrow.
|
||||
line(frame, p, q, line_color, line_thickness);
|
||||
|
||||
// Now draw the tips of the arrow. I do some scaling so that the
|
||||
// tips look proportional to the main line of the arrow.
|
||||
|
||||
p.x = (int) (q.x + 9 * cos(angle + CV_PI / 4));
|
||||
p.y = (int) (q.y + 9 * sin(angle + CV_PI / 4));
|
||||
line(frame, p, q, line_color, line_thickness);
|
||||
|
||||
p.x = (int) (q.x + 9 * cos(angle - CV_PI / 4));
|
||||
p.y = (int) (q.y + 9 * sin(angle - CV_PI / 4));
|
||||
line(frame, p, q, line_color, line_thickness);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T> inline T clamp (T x, T a, T b)
|
||||
{
|
||||
return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a));
|
||||
}
|
||||
|
||||
template <typename T> inline T mapValue(T x, T a, T b, T c, T d)
|
||||
{
|
||||
x = clamp(x, a, b);
|
||||
return c + (d - c) * (x - a) / (b - a);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct S_Thread_data
|
||||
{
|
||||
Size winSize;
|
||||
int maxLevel;
|
||||
int iters;
|
||||
|
||||
Stream stream;
|
||||
Mat frame0;
|
||||
Mat frame1;
|
||||
Mat frame1Gray;
|
||||
|
||||
GpuMat d_frame0Gray;
|
||||
GpuMat d_prevPts;
|
||||
bool useGray;
|
||||
};
|
||||
|
||||
struct pyrLK_task
|
||||
{
|
||||
pyrLK_task(size_t n):
|
||||
_n(n),
|
||||
_thread_data(NULL){}
|
||||
|
||||
void operator()()
|
||||
{
|
||||
// Sparse
|
||||
|
||||
PyrLKOpticalFlow d_pyrLK;
|
||||
|
||||
d_pyrLK.winSize.width = _thread_data->winSize.width;
|
||||
d_pyrLK.winSize.height = _thread_data->winSize.height;
|
||||
d_pyrLK.maxLevel = _thread_data->maxLevel;
|
||||
d_pyrLK.iters = _thread_data->iters;
|
||||
|
||||
GpuMat d_frame0(_thread_data->frame0);
|
||||
GpuMat d_frame1(_thread_data->frame1);
|
||||
GpuMat d_frame1Gray(_thread_data->frame1Gray);
|
||||
GpuMat d_nextPts;
|
||||
GpuMat d_status;
|
||||
|
||||
bool useGray = _thread_data->useGray;
|
||||
|
||||
d_pyrLK.sparse_multi(useGray ? _thread_data->d_frame0Gray : d_frame0,
|
||||
useGray ? d_frame1Gray : d_frame1,
|
||||
_thread_data->d_prevPts, d_nextPts,
|
||||
d_status, _thread_data->stream, NULL);
|
||||
|
||||
// Draw arrows
|
||||
|
||||
vector<Point2f> prevPts(_thread_data->d_prevPts.cols);
|
||||
download(_thread_data->d_prevPts, prevPts);
|
||||
|
||||
vector<Point2f> nextPts(d_nextPts.cols);
|
||||
download(d_nextPts, nextPts);
|
||||
|
||||
vector<uchar> status(d_status.cols);
|
||||
download(d_status, status);
|
||||
|
||||
drawArrows(_thread_data->frame0, prevPts, nextPts, status, Scalar(255, 0, 0));
|
||||
}
|
||||
|
||||
size_t _n;
|
||||
struct S_Thread_data* _thread_data;
|
||||
};
|
||||
|
||||
template <typename T> struct invoker {
|
||||
void operator()(T& it) const {it();}
|
||||
};
|
||||
|
||||
#define THREADS_NB 12
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
const char* keys =
|
||||
"{ h | help | false | print help message }"
|
||||
"{ l | left | | specify left image }"
|
||||
"{ r | right | | specify right image }"
|
||||
"{ gray | gray | false | use grayscale sources [PyrLK Sparse] }"
|
||||
"{ win_size | win_size | 21 | specify windows size [PyrLK] }"
|
||||
"{ max_level | max_level | 3 | specify max level [PyrLK] }"
|
||||
"{ iters | iters | 30 | specify iterations count [PyrLK] }"
|
||||
"{ points | points | 4000 | specify points count [GoodFeatureToTrack] }"
|
||||
"{ min_dist | min_dist | 0 | specify minimal distance between points [GoodFeatureToTrack] }";
|
||||
|
||||
CommandLineParser cmd(argc, argv, keys);
|
||||
|
||||
if (cmd.get<bool>("help"))
|
||||
{
|
||||
cout << "Usage: pyrlk_optical_flow_multithreading [options]" << endl;
|
||||
cout << "Avaible options:" << endl;
|
||||
cmd.printParams();
|
||||
return 0;
|
||||
}
|
||||
|
||||
string fname0 = cmd.get<string>("left");
|
||||
string fname1 = cmd.get<string>("right");
|
||||
|
||||
if (fname0.empty() || fname1.empty())
|
||||
{
|
||||
cerr << "Missing input file names" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool useGray = cmd.get<bool>("gray");
|
||||
int winSize = cmd.get<int>("win_size");
|
||||
int maxLevel = cmd.get<int>("max_level");
|
||||
int iters = cmd.get<int>("iters");
|
||||
int points = cmd.get<int>("points");
|
||||
double minDist = cmd.get<double>("min_dist");
|
||||
|
||||
Mat frame0 = imread(fname0);
|
||||
Mat frame1 = imread(fname1);
|
||||
|
||||
if (frame0.empty() || frame1.empty())
|
||||
{
|
||||
cout << "Can't load input images" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cout << "Image size : " << frame0.cols << " x " << frame0.rows << endl;
|
||||
cout << "Points count : " << points << endl;
|
||||
|
||||
cout << endl;
|
||||
|
||||
Mat frame0Gray;
|
||||
cvtColor(frame0, frame0Gray, COLOR_BGR2GRAY);
|
||||
Mat frame1Gray;
|
||||
cvtColor(frame1, frame1Gray, COLOR_BGR2GRAY);
|
||||
|
||||
// goodFeaturesToTrack
|
||||
|
||||
GoodFeaturesToTrackDetector_GPU detector(points, 0.01, minDist);
|
||||
|
||||
GpuMat d_frame0Gray(frame0Gray);
|
||||
GpuMat d_prevPts;
|
||||
|
||||
detector(d_frame0Gray, d_prevPts);
|
||||
|
||||
// Sparse
|
||||
|
||||
tbb::task_scheduler_init init(THREADS_NB);
|
||||
|
||||
std::vector<pyrLK_task> tasks;
|
||||
|
||||
S_Thread_data s_thread_data[THREADS_NB];
|
||||
|
||||
for (unsigned int uiI = 0; uiI < THREADS_NB; ++uiI)
|
||||
{
|
||||
s_thread_data[uiI].stream = Stream();
|
||||
s_thread_data[uiI].frame0 = frame0.clone();
|
||||
s_thread_data[uiI].frame1 = frame1.clone();
|
||||
s_thread_data[uiI].frame1Gray = frame0Gray.clone();
|
||||
|
||||
s_thread_data[uiI].iters = iters;
|
||||
s_thread_data[uiI].useGray = useGray;
|
||||
s_thread_data[uiI].maxLevel = maxLevel;
|
||||
s_thread_data[uiI].winSize.height = winSize;
|
||||
s_thread_data[uiI].winSize.width = winSize;
|
||||
s_thread_data[uiI].d_frame0Gray = d_frame0Gray.clone();
|
||||
s_thread_data[uiI].d_prevPts = d_prevPts.clone();
|
||||
|
||||
tasks.push_back(pyrLK_task(uiI));
|
||||
tasks.back()._thread_data = &(s_thread_data[uiI]);
|
||||
}
|
||||
|
||||
tbb::parallel_for_each(tasks.begin(),tasks.end(),invoker<pyrLK_task>());
|
||||
|
||||
for (unsigned int uiI = 0; uiI < THREADS_NB; ++uiI)
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "PyrLK MultiThreading [Sparse] " << uiI;
|
||||
|
||||
imshow(ss.str(), s_thread_data[uiI].frame0);
|
||||
ss.str("");
|
||||
}
|
||||
|
||||
waitKey();
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int main(int , const char* [])
|
||||
{
|
||||
std::cout << "This example pyrlk_optical_flow_multithreading must be compiled with TBB Option" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
#endif // HAVE_TBB
|
||||
Reference in New Issue
Block a user