Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
5c459aa8
Commit
5c459aa8
authored
Feb 16, 2012
by
Alexey Spizhevoy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added the GPU version of the Farneback's optical flow
parent
59ff1a4c
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
196 additions
and
13 deletions
+196
-13
gpumat.hpp
modules/core/include/opencv2/core/gpumat.hpp
+9
-0
gpu.hpp
modules/gpu/include/opencv2/gpu/gpu.hpp
+64
-0
cudastream.cpp
modules/gpu/src/cudastream.cpp
+17
-13
precomp.hpp
modules/gpu/src/precomp.hpp
+1
-0
test_precomp.hpp
modules/gpu/test/test_precomp.hpp
+1
-0
test_video.cpp
modules/gpu/test/test_video.cpp
+71
-0
basketball1.png
samples/gpu/basketball1.png
+0
-0
basketball2.png
samples/gpu/basketball2.png
+0
-0
tests.cpp
samples/gpu/performance/tests.cpp
+33
-0
No files found.
modules/core/include/opencv2/core/gpumat.hpp
View file @
5c459aa8
...
...
@@ -214,6 +214,8 @@ namespace cv { namespace gpu
CV_EXPORTS
void
ensureSizeIsEnough
(
int
rows
,
int
cols
,
int
type
,
GpuMat
&
m
);
CV_EXPORTS
void
ensureSizeIsEnough
(
Size
size
,
int
type
,
GpuMat
&
m
);
CV_EXPORTS
GpuMat
allocMatFromBuf
(
int
rows
,
int
cols
,
int
type
,
GpuMat
&
mat
);
////////////////////////////////////////////////////////////////////////
// Error handling
...
...
@@ -459,6 +461,13 @@ namespace cv { namespace gpu
else
m
.
create
(
rows
,
cols
,
type
);
}
inline
GpuMat
allocMatFromBuf
(
int
rows
,
int
cols
,
int
type
,
GpuMat
&
mat
)
{
if
(
!
mat
.
empty
()
&&
mat
.
type
()
==
type
&&
mat
.
rows
>=
rows
&&
mat
.
cols
>=
cols
)
return
mat
(
Rect
(
0
,
0
,
cols
,
rows
));
return
mat
=
GpuMat
(
rows
,
cols
,
type
);
}
}}
#endif // __cplusplus
...
...
modules/gpu/include/opencv2/gpu/gpu.hpp
View file @
5c459aa8
...
...
@@ -1819,6 +1819,70 @@ private:
vector
<
GpuMat
>
vPyr_
;
};
class
CV_EXPORTS
FarnebackOpticalFlow
{
public
:
FarnebackOpticalFlow
()
{
numLevels
=
5
;
pyrScale
=
0.5
;
fastPyramids
=
false
;
winSize
=
13
;
numIters
=
10
;
polyN
=
5
;
polySigma
=
1.1
;
flags
=
0
;
}
int
numLevels
;
double
pyrScale
;
bool
fastPyramids
;
int
winSize
;
int
numIters
;
int
polyN
;
double
polySigma
;
int
flags
;
void
operator
()(
const
GpuMat
&
frame0
,
const
GpuMat
&
frame1
,
GpuMat
&
flowx
,
GpuMat
&
flowy
,
Stream
&
s
=
Stream
::
Null
());
void
releaseMemory
()
{
frames_
[
0
].
release
();
frames_
[
1
].
release
();
I_
[
0
].
release
();
I_
[
1
].
release
();
M_
.
release
();
bufM_
.
release
();
R_
[
0
].
release
();
R_
[
1
].
release
();
tmp_
[
0
].
release
();
tmp_
[
1
].
release
();
pyramid0_
.
clear
();
pyramid1_
.
clear
();
}
private
:
void
prepareGaussian
(
int
n
,
double
sigma
,
float
*
g
,
float
*
xg
,
float
*
xxg
,
double
&
ig11
,
double
&
ig03
,
double
&
ig33
,
double
&
ig55
);
void
setPolynomialExpansionConsts
(
int
n
,
double
sigma
);
void
updateFlow_boxFilter
(
const
GpuMat
&
R0
,
const
GpuMat
&
R1
,
GpuMat
&
flowx
,
GpuMat
&
flowy
,
GpuMat
&
M
,
GpuMat
&
bufM
,
int
blockSize
,
bool
updateMatrices
,
Stream
streams
[]);
void
updateFlow_gaussianBlur
(
const
GpuMat
&
R0
,
const
GpuMat
&
R1
,
GpuMat
&
flowx
,
GpuMat
&
flowy
,
GpuMat
&
M
,
GpuMat
&
bufM
,
int
blockSize
,
bool
updateMatrices
,
Stream
streams
[]);
GpuMat
frames_
[
2
];
GpuMat
I_
[
2
],
M_
,
bufM_
,
R_
[
2
],
tmp_
[
2
];
std
::
vector
<
GpuMat
>
pyramid0_
,
pyramid1_
;
};
//! Interpolate frames (images) using provided optical flow (displacement field).
//! frame0 - frame 0 (32-bit floating point images, single channel)
//! frame1 - frame 1 (the same type and size)
...
...
modules/gpu/src/cudastream.cpp
View file @
5c459aa8
...
...
@@ -81,6 +81,7 @@ namespace cv { namespace gpu
struct
Stream
::
Impl
{
static
cudaStream_t
getStream
(
const
Impl
*
impl
)
{
return
impl
?
impl
->
stream
:
0
;
}
cudaStream_t
stream
;
int
ref_counter
;
};
...
...
@@ -95,7 +96,10 @@ namespace
};
}
CV_EXPORTS
cudaStream_t
cv
::
gpu
::
StreamAccessor
::
getStream
(
const
Stream
&
stream
)
{
return
stream
.
impl
?
stream
.
impl
->
stream
:
0
;
};
CV_EXPORTS
cudaStream_t
cv
::
gpu
::
StreamAccessor
::
getStream
(
const
Stream
&
stream
)
{
return
Stream
::
Impl
::
getStream
(
stream
.
impl
);
};
void
cv
::
gpu
::
Stream
::
create
()
{
...
...
@@ -143,7 +147,7 @@ Stream& cv::gpu::Stream::operator=(const Stream& stream)
bool
cv
::
gpu
::
Stream
::
queryIfComplete
()
{
cudaError_t
err
=
cudaStreamQuery
(
impl
->
stream
);
cudaError_t
err
=
cudaStreamQuery
(
Impl
::
getStream
(
impl
)
);
if
(
err
==
cudaErrorNotReady
||
err
==
cudaSuccess
)
return
err
==
cudaSuccess
;
...
...
@@ -152,19 +156,19 @@ bool cv::gpu::Stream::queryIfComplete()
return
false
;
}
void
cv
::
gpu
::
Stream
::
waitForCompletion
()
{
cudaSafeCall
(
cudaStreamSynchronize
(
impl
->
stream
)
);
}
void
cv
::
gpu
::
Stream
::
waitForCompletion
()
{
cudaSafeCall
(
cudaStreamSynchronize
(
Impl
::
getStream
(
impl
)
)
);
}
void
cv
::
gpu
::
Stream
::
enqueueDownload
(
const
GpuMat
&
src
,
Mat
&
dst
)
{
// if not -> allocation will be done, but after that dst will not point to page locked memory
CV_Assert
(
src
.
cols
==
dst
.
cols
&&
src
.
rows
==
dst
.
rows
&&
src
.
type
()
==
dst
.
type
()
);
devcopy
(
src
,
dst
,
impl
->
stream
,
cudaMemcpyDeviceToHost
);
devcopy
(
src
,
dst
,
Impl
::
getStream
(
impl
)
,
cudaMemcpyDeviceToHost
);
}
void
cv
::
gpu
::
Stream
::
enqueueDownload
(
const
GpuMat
&
src
,
CudaMem
&
dst
)
{
devcopy
(
src
,
dst
,
impl
->
stream
,
cudaMemcpyDeviceToHost
);
}
void
cv
::
gpu
::
Stream
::
enqueueDownload
(
const
GpuMat
&
src
,
CudaMem
&
dst
)
{
devcopy
(
src
,
dst
,
Impl
::
getStream
(
impl
)
,
cudaMemcpyDeviceToHost
);
}
void
cv
::
gpu
::
Stream
::
enqueueUpload
(
const
CudaMem
&
src
,
GpuMat
&
dst
){
devcopy
(
src
,
dst
,
impl
->
stream
,
cudaMemcpyHostToDevice
);
}
void
cv
::
gpu
::
Stream
::
enqueueUpload
(
const
Mat
&
src
,
GpuMat
&
dst
)
{
devcopy
(
src
,
dst
,
impl
->
stream
,
cudaMemcpyHostToDevice
);
}
void
cv
::
gpu
::
Stream
::
enqueueCopy
(
const
GpuMat
&
src
,
GpuMat
&
dst
)
{
devcopy
(
src
,
dst
,
impl
->
stream
,
cudaMemcpyDeviceToDevice
);
}
void
cv
::
gpu
::
Stream
::
enqueueUpload
(
const
CudaMem
&
src
,
GpuMat
&
dst
){
devcopy
(
src
,
dst
,
Impl
::
getStream
(
impl
)
,
cudaMemcpyHostToDevice
);
}
void
cv
::
gpu
::
Stream
::
enqueueUpload
(
const
Mat
&
src
,
GpuMat
&
dst
)
{
devcopy
(
src
,
dst
,
Impl
::
getStream
(
impl
)
,
cudaMemcpyHostToDevice
);
}
void
cv
::
gpu
::
Stream
::
enqueueCopy
(
const
GpuMat
&
src
,
GpuMat
&
dst
)
{
devcopy
(
src
,
dst
,
Impl
::
getStream
(
impl
)
,
cudaMemcpyDeviceToDevice
);
}
void
cv
::
gpu
::
Stream
::
enqueueMemSet
(
GpuMat
&
src
,
Scalar
s
)
{
...
...
@@ -173,7 +177,7 @@ void cv::gpu::Stream::enqueueMemSet(GpuMat& src, Scalar s)
if
(
s
[
0
]
==
0.0
&&
s
[
1
]
==
0.0
&&
s
[
2
]
==
0.0
&&
s
[
3
]
==
0.0
)
{
cudaSafeCall
(
cudaMemset2DAsync
(
src
.
data
,
src
.
step
,
0
,
src
.
cols
*
src
.
elemSize
(),
src
.
rows
,
impl
->
stream
)
);
cudaSafeCall
(
cudaMemset2DAsync
(
src
.
data
,
src
.
step
,
0
,
src
.
cols
*
src
.
elemSize
(),
src
.
rows
,
Impl
::
getStream
(
impl
)
)
);
return
;
}
if
(
src
.
depth
()
==
CV_8U
)
...
...
@@ -183,12 +187,12 @@ void cv::gpu::Stream::enqueueMemSet(GpuMat& src, Scalar s)
if
(
cn
==
1
||
(
cn
==
2
&&
s
[
0
]
==
s
[
1
])
||
(
cn
==
3
&&
s
[
0
]
==
s
[
1
]
&&
s
[
0
]
==
s
[
2
])
||
(
cn
==
4
&&
s
[
0
]
==
s
[
1
]
&&
s
[
0
]
==
s
[
2
]
&&
s
[
0
]
==
s
[
3
]))
{
int
val
=
saturate_cast
<
uchar
>
(
s
[
0
]);
cudaSafeCall
(
cudaMemset2DAsync
(
src
.
data
,
src
.
step
,
val
,
src
.
cols
*
src
.
elemSize
(),
src
.
rows
,
impl
->
stream
)
);
cudaSafeCall
(
cudaMemset2DAsync
(
src
.
data
,
src
.
step
,
val
,
src
.
cols
*
src
.
elemSize
(),
src
.
rows
,
Impl
::
getStream
(
impl
)
)
);
return
;
}
}
setTo
(
src
,
s
,
impl
->
stream
);
setTo
(
src
,
s
,
Impl
::
getStream
(
impl
)
);
}
void
cv
::
gpu
::
Stream
::
enqueueMemSet
(
GpuMat
&
src
,
Scalar
val
,
const
GpuMat
&
mask
)
...
...
@@ -198,7 +202,7 @@ void cv::gpu::Stream::enqueueMemSet(GpuMat& src, Scalar val, const GpuMat& mask)
CV_Assert
(
mask
.
type
()
==
CV_8UC1
);
setTo
(
src
,
val
,
mask
,
impl
->
stream
);
setTo
(
src
,
val
,
mask
,
Impl
::
getStream
(
impl
)
);
}
void
cv
::
gpu
::
Stream
::
enqueueConvert
(
const
GpuMat
&
src
,
GpuMat
&
dst
,
int
rtype
,
double
alpha
,
double
beta
)
...
...
@@ -226,7 +230,7 @@ void cv::gpu::Stream::enqueueConvert(const GpuMat& src, GpuMat& dst, int rtype,
psrc
=
&
(
temp
=
src
);
dst
.
create
(
src
.
size
(),
rtype
);
convertTo
(
src
,
dst
,
alpha
,
beta
,
impl
->
stream
);
convertTo
(
src
,
dst
,
alpha
,
beta
,
Impl
::
getStream
(
impl
)
);
}
cv
::
gpu
::
Stream
::
operator
bool
()
const
...
...
modules/gpu/src/precomp.hpp
View file @
5c459aa8
...
...
@@ -65,6 +65,7 @@
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/core/internal.hpp"
#include "opencv2/video/video.hpp"
#define OPENCV_GPU_UNUSED(x) (void)x
...
...
modules/gpu/test/test_precomp.hpp
View file @
5c459aa8
...
...
@@ -44,6 +44,7 @@
#include <cmath>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <sstream>
#include <limits>
...
...
modules/gpu/test/test_video.cpp
View file @
5c459aa8
...
...
@@ -423,3 +423,74 @@ TEST_P(PyrLKOpticalFlowSparse, Accuracy)
INSTANTIATE_TEST_CASE_P
(
Video
,
PyrLKOpticalFlowSparse
,
Combine
(
ALL_DEVICES
,
Bool
()));
#endif // HAVE_CUDA
PARAM_TEST_CASE
(
FarnebackOpticalFlowTest
,
cv
::
gpu
::
DeviceInfo
,
double
,
int
,
int
,
bool
)
{
Mat
frame0
,
frame1
;
double
pyrScale
;
int
polyN
;
double
polySigma
;
int
flags
;
bool
useInitFlow
;
virtual
void
SetUp
()
{
frame0
=
readImage
(
"opticalflow/rubberwhale1.png"
,
cv
::
IMREAD_GRAYSCALE
);
frame1
=
readImage
(
"opticalflow/rubberwhale2.png"
,
cv
::
IMREAD_GRAYSCALE
);
ASSERT_FALSE
(
frame0
.
empty
());
ASSERT_FALSE
(
frame1
.
empty
());
cv
::
gpu
::
setDevice
(
GET_PARAM
(
0
).
deviceID
());
pyrScale
=
GET_PARAM
(
1
);
polyN
=
GET_PARAM
(
2
);
polySigma
=
polyN
<=
5
?
1.1
:
1.5
;
flags
=
GET_PARAM
(
3
);
useInitFlow
=
GET_PARAM
(
4
);
}
};
TEST_P
(
FarnebackOpticalFlowTest
,
Accuracy
)
{
using
namespace
cv
;
gpu
::
FarnebackOpticalFlow
calc
;
calc
.
pyrScale
=
pyrScale
;
calc
.
polyN
=
polyN
;
calc
.
polySigma
=
polySigma
;
calc
.
flags
=
flags
;
gpu
::
GpuMat
d_flowx
,
d_flowy
;
calc
(
gpu
::
GpuMat
(
frame0
),
gpu
::
GpuMat
(
frame1
),
d_flowx
,
d_flowy
);
Mat
flow
;
if
(
useInitFlow
)
{
Mat
flowxy
[]
=
{(
Mat
)
d_flowx
,
(
Mat
)
d_flowy
};
merge
(
flowxy
,
2
,
flow
);
}
if
(
useInitFlow
)
{
calc
.
flags
|=
OPTFLOW_USE_INITIAL_FLOW
;
calc
(
gpu
::
GpuMat
(
frame0
),
gpu
::
GpuMat
(
frame1
),
d_flowx
,
d_flowy
);
}
calcOpticalFlowFarneback
(
frame0
,
frame1
,
flow
,
calc
.
pyrScale
,
calc
.
numLevels
,
calc
.
winSize
,
calc
.
numIters
,
calc
.
polyN
,
calc
.
polySigma
,
calc
.
flags
);
std
::
vector
<
Mat
>
flowxy
;
split
(
flow
,
flowxy
);
/*std::cout << checkSimilarity(flowxy[0], (Mat)d_flowx) << " "
<< checkSimilarity(flowxy[1], (Mat)d_flowy) << std::endl;*/
EXPECT_LT
(
checkSimilarity
(
flowxy
[
0
],
(
Mat
)
d_flowx
),
0.1
);
EXPECT_LT
(
checkSimilarity
(
flowxy
[
1
],
(
Mat
)
d_flowy
),
0.1
);
}
INSTANTIATE_TEST_CASE_P
(
Video
,
FarnebackOpticalFlowTest
,
Combine
(
ALL_DEVICES
,
Values
(
0.3
,
0.5
,
0.8
),
Values
(
5
,
7
),
Values
(
0
,
(
int
)
cv
::
OPTFLOW_FARNEBACK_GAUSSIAN
),
Values
(
false
,
true
)));
samples/gpu/basketball1.png
0 → 100644
View file @
5c459aa8
130 KB
samples/gpu/basketball2.png
0 → 100644
View file @
5c459aa8
130 KB
samples/gpu/performance/tests.cpp
View file @
5c459aa8
...
...
@@ -1183,3 +1183,36 @@ TEST(PyrLKOpticalFlow)
GPU_OFF
;
}
}
TEST
(
FarnebackOpticalFlow
)
{
const
string
names
[]
=
{
"rubberwhale"
,
"basketball"
};
for
(
size_t
i
=
0
;
i
<
sizeof
(
names
)
/
sizeof
(
*
names
);
++
i
)
{
for
(
int
fastPyramids
=
0
;
fastPyramids
<
2
;
++
fastPyramids
)
{
for
(
int
useGaussianBlur
=
0
;
useGaussianBlur
<
2
;
++
useGaussianBlur
)
{
SUBTEST
<<
"dataset="
<<
names
[
i
]
<<
", fastPyramids="
<<
fastPyramids
<<
", useGaussianBlur="
<<
useGaussianBlur
;
Mat
frame0
=
imread
(
abspath
(
names
[
i
]
+
"1.png"
),
IMREAD_GRAYSCALE
);
Mat
frame1
=
imread
(
abspath
(
names
[
i
]
+
"2.png"
),
IMREAD_GRAYSCALE
);
if
(
frame0
.
empty
())
throw
runtime_error
(
"can't open "
+
names
[
i
]
+
"1.png"
);
if
(
frame1
.
empty
())
throw
runtime_error
(
"can't open "
+
names
[
i
]
+
"2.png"
);
gpu
::
FarnebackOpticalFlow
calc
;
calc
.
fastPyramids
=
fastPyramids
;
calc
.
flags
|=
useGaussianBlur
?
OPTFLOW_FARNEBACK_GAUSSIAN
:
0
;
gpu
::
GpuMat
d_frame0
(
frame0
),
d_frame1
(
frame1
),
d_flowx
,
d_flowy
;
calc
(
d_frame0
,
d_frame1
,
d_flowx
,
d_flowy
);
GPU_ON
;
calc
(
d_frame0
,
d_frame1
,
d_flowx
,
d_flowy
);
GPU_OFF
;
Mat
flow
;
calcOpticalFlowFarneback
(
frame0
,
frame1
,
flow
,
calc
.
pyrScale
,
calc
.
numLevels
,
calc
.
winSize
,
calc
.
numIters
,
calc
.
polyN
,
calc
.
polySigma
,
calc
.
flags
);
CPU_ON
;
calcOpticalFlowFarneback
(
frame0
,
frame1
,
flow
,
calc
.
pyrScale
,
calc
.
numLevels
,
calc
.
winSize
,
calc
.
numIters
,
calc
.
polyN
,
calc
.
polySigma
,
calc
.
flags
);
CPU_OFF
;
}}}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment