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

pull/13059/head
Alexander Alekhin 6 years ago
commit 2c6f1ab57d
  1. 5
      CMakeLists.txt
  2. 51
      cmake/OpenCVGenSetupVars.cmake
  3. 4
      cmake/OpenCVUtils.cmake
  4. 20
      cmake/templates/setup_vars_linux.sh.in
  5. 20
      cmake/templates/setup_vars_macosx.sh.in
  6. 18
      cmake/templates/setup_vars_win32.cmd.in
  7. 4
      doc/Doxyfile.in
  8. 37
      modules/calib3d/src/circlesgrid.cpp
  9. 2
      modules/calib3d/src/circlesgrid.hpp
  10. 19
      modules/calib3d/test/test_chesscorners.cpp
  11. 133
      modules/core/doc/intro.markdown
  12. 2
      modules/core/include/opencv2/core.hpp
  13. 2
      modules/core/include/opencv2/core/base.hpp
  14. 2
      modules/core/include/opencv2/core/utility.hpp
  15. 9
      modules/core/misc/java/gen_dict.json
  16. 2
      modules/highgui/src/window_w32.cpp
  17. 1235
      modules/imgproc/src/median_blur.cpp
  18. 1073
      modules/imgproc/src/smooth.cpp
  19. 7
      modules/imgproc/src/templmatch.cpp
  20. 14
      modules/java/generator/src/cpp/converters.cpp
  21. 2
      modules/java/generator/src/cpp/converters.h
  22. 39
      modules/java/generator/src/java/org/opencv/utils/Converters.java
  23. 19
      modules/java/test/android_test/src/org/opencv/test/OpenCVTestCase.java
  24. 29
      modules/java/test/common_test/src/org/opencv/test/utils/ConvertersTest.java
  25. 19
      modules/java/test/pure_test/src/org/opencv/test/OpenCVTestCase.java
  26. 7
      modules/videoio/src/cap_ffmpeg_impl.hpp
  27. 1
      samples/gpu/CMakeLists.txt
  28. 37
      samples/gpu/bgfg_segm.cpp
  29. 388
      samples/gpu/cascadeclassifier_nvidia_api.cpp
  30. 651
      samples/gpu/opticalflow_nvidia_api.cpp

@ -347,6 +347,7 @@ OCV_OPTION(GENERATE_ABI_DESCRIPTOR "Generate XML file for abi_compliance_chec
OCV_OPTION(CV_ENABLE_INTRINSICS "Use intrinsic-based optimized code" ON )
OCV_OPTION(CV_DISABLE_OPTIMIZATION "Disable explicit optimized code (dispatched code/intrinsics/loop unrolling/etc)" OFF )
OCV_OPTION(CV_TRACE "Enable OpenCV code trace" ON)
OCV_OPTION(OPENCV_GENERATE_SETUPVARS "Generate setup_vars* scripts" ON IF (NOT ANDROID AND NOT APPLE_FRAMEWORK) )
OCV_OPTION(ENABLE_PYLINT "Add target with Pylint checks" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )
OCV_OPTION(ENABLE_FLAKE8 "Add target with Python flake8 checker" (BUILD_DOCS OR BUILD_EXAMPLES) IF (NOT CMAKE_CROSSCOMPILING AND NOT APPLE_FRAMEWORK) )
@ -929,6 +930,10 @@ if(COMMAND ocv_pylint_finalize)
ocv_pylint_finalize()
endif()
if(OPENCV_GENERATE_SETUPVARS)
include(cmake/OpenCVGenSetupVars.cmake)
endif()
# ----------------------------------------------------------------------------
# Summary:
# ----------------------------------------------------------------------------

@ -0,0 +1,51 @@
if(WIN32)
ocv_update(OPENCV_SETUPVARS_INSTALL_PATH ".")
ocv_update(OPENCV_SCRIPT_EXTENSION ".cmd")
ocv_update(OPENCV_SETUPVARS_TEMPLATE "setup_vars_win32.cmd.in")
else()
ocv_update(OPENCV_SETUPVARS_INSTALL_PATH "bin")
ocv_update(OPENCV_SCRIPT_EXTENSION ".sh")
if(APPLE)
ocv_update(OPENCV_SETUPVARS_TEMPLATE "setup_vars_macosx.sh.in")
else()
ocv_update(OPENCV_SETUPVARS_TEMPLATE "setup_vars_linux.sh.in")
endif()
endif()
if(INSTALL_TO_MANGLED_PATHS)
ocv_update(OPENCV_SETUPVARS_FILENAME "setup_vars_opencv-${OPENCV_VERSION}${OPENCV_SCRIPT_EXTENSION}")
else()
ocv_update(OPENCV_SETUPVARS_FILENAME setup_vars_opencv3${OPENCV_SCRIPT_EXTENSION})
endif()
##### build directory
if(WIN32)
set(__build_type "${CMAKE_BUILD_TYPE}")
if(NOT __build_type)
set(__build_type "Release") # default
endif()
file(RELATIVE_PATH OPENCV_LIB_RUNTIME_DIR_RELATIVE_CMAKECONFIG "${OpenCV_BINARY_DIR}/" "${EXECUTABLE_OUTPUT_PATH}/${__build_type}/")
else()
file(RELATIVE_PATH OPENCV_LIB_RUNTIME_DIR_RELATIVE_CMAKECONFIG "${OpenCV_BINARY_DIR}/" "${LIBRARY_OUTPUT_PATH}/")
endif()
set(OPENCV_PYTHON_DIR_RELATIVE_CMAKECONFIG "python_loader") # https://github.com/opencv/opencv/pull/12977
configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/${OPENCV_SETUPVARS_TEMPLATE}" "${CMAKE_BINARY_DIR}/tmp/setup_vars${OPENCV_SCRIPT_EXTENSION}" @ONLY)
file(COPY "${CMAKE_BINARY_DIR}/tmp/setup_vars${OPENCV_SCRIPT_EXTENSION}" DESTINATION "${CMAKE_BINARY_DIR}"
FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
##### install directory
if(WIN32)
file(RELATIVE_PATH OPENCV_LIB_RUNTIME_DIR_RELATIVE_CMAKECONFIG
"${CMAKE_INSTALL_PREFIX}/${OPENCV_SETUPVARS_INSTALL_PATH}/" "${CMAKE_INSTALL_PREFIX}/${OPENCV_BIN_INSTALL_PATH}/")
else()
file(RELATIVE_PATH OPENCV_LIB_RUNTIME_DIR_RELATIVE_CMAKECONFIG
"${CMAKE_INSTALL_PREFIX}/${OPENCV_SETUPVARS_INSTALL_PATH}/" "${CMAKE_INSTALL_PREFIX}/${OPENCV_LIB_INSTALL_PATH}/")
endif()
file(RELATIVE_PATH OPENCV_PYTHON_DIR_RELATIVE_CMAKECONFIG
"${CMAKE_INSTALL_PREFIX}/${OPENCV_SETUPVARS_INSTALL_PATH}/" "${CMAKE_INSTALL_PREFIX}/")
ocv_path_join(OPENCV_PYTHON_DIR_RELATIVE_CMAKECONFIG "${OPENCV_PYTHON_DIR_RELATIVE_CMAKECONFIG}" "python_loader") # https://github.com/opencv/opencv/pull/12977
configure_file("${OpenCV_SOURCE_DIR}/cmake/templates/${OPENCV_SETUPVARS_TEMPLATE}" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/install/${OPENCV_SETUPVARS_FILENAME}" @ONLY)
install(FILES "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/install/${OPENCV_SETUPVARS_FILENAME}"
DESTINATION "${OPENCV_SETUPVARS_INSTALL_PATH}"
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
COMPONENT scripts)

@ -149,7 +149,9 @@ macro(ocv_path_join result_var P1 P2_)
else()
set(${result_var} "${P1}/${P2}")
endif()
string(REGEX REPLACE "([/\\]?)[\\.][/\\]" "\\1" ${result_var} "${${result_var}}")
string(REPLACE "\\\\" "\\" ${result_var} "${${result_var}}")
string(REPLACE "//" "/" ${result_var} "${${result_var}}")
string(REGEX REPLACE "(^|[/\\])[\\.][/\\]" "\\1" ${result_var} "${${result_var}}")
if("${${result_var}}" STREQUAL "")
set(${result_var} ".")
endif()

@ -0,0 +1,20 @@
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
[[ ! "${OPENCV_QUIET}" ]] && ( echo "Setting vars for OpenCV @OPENCV_VERSION@" )
export LD_LIBRARY_PATH="$SCRIPT_DIR/@OPENCV_LIB_RUNTIME_DIR_RELATIVE_CMAKECONFIG@:$LD_LIBRARY_PATH"
if [[ ! "$OPENCV_SKIP_PYTHON" ]]; then
PYTHONPATH_OPENCV="$SCRIPT_DIR/@OPENCV_PYTHON_DIR_RELATIVE_CMAKECONFIG@"
[[ ! "${OPENCV_QUIET}" ]] && ( echo "Append PYTHONPATH: ${PYTHONPATH_OPENCV}" )
export PYTHONPATH="${PYTHONPATH_OPENCV}:$PYTHONPATH"
fi
# Don't exec in "sourced" mode
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
if [[ $# -ne 0 ]]; then
[[ ! "${OPENCV_QUIET}" && "${OPENCV_VERBOSE}" ]] && ( echo "Executing: $*" )
exec "$@"
fi
fi

@ -0,0 +1,20 @@
#!/bin/bash
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
[[ ! "${OPENCV_QUIET}" ]] && ( echo "Setting vars for OpenCV @OPENCV_VERSION@" )
export DYLD_LIBRARY_PATH="$SCRIPT_DIR/@OPENCV_LIB_RUNTIME_DIR_RELATIVE_CMAKECONFIG@:$DYLD_LIBRARY_PATH"
if [[ ! "$OPENCV_SKIP_PYTHON" ]]; then
PYTHONPATH_OPENCV="$SCRIPT_DIR/@OPENCV_PYTHON_DIR_RELATIVE_CMAKECONFIG@"
[[ ! "${OPENCV_QUIET}" ]] && ( echo "Append PYTHONPATH: ${PYTHONPATH_OPENCV}" )
export PYTHONPATH="${PYTHONPATH_OPENCV}:$PYTHONPATH"
fi
# Don't exec in "sourced" mode
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
if [[ $# -ne 0 ]]; then
[[ ! "${OPENCV_QUIET}" && "${OPENCV_VERBOSE}" ]] && ( echo "Executing: $*" )
exec "$@"
fi
fi

@ -0,0 +1,18 @@
@ECHO OFF
SETLOCAL EnableDelayedExpansion
SET "SCRIPT_DIR=%~dp0"
IF NOT DEFINED OPENCV_QUIET ( ECHO Setting vars for OpenCV @OPENCV_VERSION@ )
SET "PATH=!SCRIPT_DIR!\@OPENCV_LIB_RUNTIME_DIR_RELATIVE_CMAKECONFIG@;%PATH%"
IF NOT DEFINED OPENCV_SKIP_PYTHON (
SET "PYTHONPATH_OPENCV=!SCRIPT_DIR!\@OPENCV_PYTHON_DIR_RELATIVE_CMAKECONFIG@"
IF NOT DEFINED OPENCV_QUIET ( ECHO Append PYTHONPATH: !PYTHONPATH_OPENCV! )
SET "PYTHONPATH=!PYTHONPATH_OPENCV!;%PYTHONPATH%"
)
IF NOT [%1] == [] (
%*
EXIT /B !errorlevel!
)

@ -107,7 +107,7 @@ RECURSIVE = YES
EXCLUDE = @CMAKE_DOXYGEN_EXCLUDE_LIST@
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = *.inl.hpp *.impl.hpp *_detail.hpp */cudev/**/detail/*.hpp *.m */opencl/runtime/*
EXCLUDE_SYMBOLS = cv::DataType<*> cv::traits::* int void CV__*
EXCLUDE_SYMBOLS = cv::DataType<*> cv::traits::* int void CV__* T __CV*
EXAMPLE_PATH = @CMAKE_DOXYGEN_EXAMPLE_PATH@
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = YES
@ -255,6 +255,8 @@ PREDEFINED = __cplusplus=1 \
CV_DEFAULT(x)=" = x" \
CV_NEON=1 \
CV_SSE2=1 \
CV__DEBUG_NS_BEGIN= \
CV__DEBUG_NS_END= \
CV_DEPRECATED=
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES

@ -174,7 +174,7 @@ void CirclesGridClusterFinder::findGrid(const std::vector<cv::Point2f> &points,
if(outsideCorners.size() != outsideCornersCount)
return;
}
getSortedCorners(hull2f, corners, outsideCorners, sortedCorners);
getSortedCorners(hull2f, patternPoints, corners, outsideCorners, sortedCorners);
if(sortedCorners.size() != cornersCount)
return;
@ -291,7 +291,18 @@ void CirclesGridClusterFinder::findOutsideCorners(const std::vector<cv::Point2f>
#endif
}
void CirclesGridClusterFinder::getSortedCorners(const std::vector<cv::Point2f> &hull2f, const std::vector<cv::Point2f> &corners, const std::vector<cv::Point2f> &outsideCorners, std::vector<cv::Point2f> &sortedCorners)
namespace {
double pointLineDistance(const cv::Point2f &p, const cv::Vec4f &line)
{
Vec3f pa( line[0], line[1], 1 );
Vec3f pb( line[2], line[3], 1 );
Vec3f l = pa.cross(pb);
return std::abs((p.x * l[0] + p.y * l[1] + l[2])) * 1.0 /
std::sqrt(double(l[0] * l[0] + l[1] * l[1]));
}
}
void CirclesGridClusterFinder::getSortedCorners(const std::vector<cv::Point2f> &hull2f, const std::vector<cv::Point2f> &patternPoints, const std::vector<cv::Point2f> &corners, const std::vector<cv::Point2f> &outsideCorners, std::vector<cv::Point2f> &sortedCorners)
{
Point2f firstCorner;
if(isAsymmetricGrid)
@ -337,10 +348,26 @@ void CirclesGridClusterFinder::getSortedCorners(const std::vector<cv::Point2f> &
if(!isAsymmetricGrid)
{
double dist1 = norm(sortedCorners[0] - sortedCorners[1]);
double dist2 = norm(sortedCorners[1] - sortedCorners[2]);
double dist01 = norm(sortedCorners[0] - sortedCorners[1]);
double dist12 = norm(sortedCorners[1] - sortedCorners[2]);
// Use half the average distance between circles on the shorter side as threshold for determining whether a point lies on an edge.
double thresh = min(dist01, dist12) / min(patternSize.width, patternSize.height) / 2;
size_t circleCount01 = 0;
size_t circleCount12 = 0;
Vec4f line01( sortedCorners[0].x, sortedCorners[0].y, sortedCorners[1].x, sortedCorners[1].y );
Vec4f line12( sortedCorners[1].x, sortedCorners[1].y, sortedCorners[2].x, sortedCorners[2].y );
// Count the circles along both edges.
for (size_t i = 0; i < patternPoints.size(); i++)
{
if (pointLineDistance(patternPoints[i], line01) < thresh)
circleCount01++;
if (pointLineDistance(patternPoints[i], line12) < thresh)
circleCount12++;
}
if((dist1 > dist2 && patternSize.height > patternSize.width) || (dist1 < dist2 && patternSize.height < patternSize.width))
// Ensure that the edge from sortedCorners[0] to sortedCorners[1] is the one with more circles (i.e. it is interpreted as the pattern's width).
if ((circleCount01 > circleCount12 && patternSize.height > patternSize.width) || (circleCount01 < circleCount12 && patternSize.height < patternSize.width))
{
for(size_t i=0; i<sortedCorners.size()-1; i++)
{

@ -67,7 +67,7 @@ public:
private:
void findCorners(const std::vector<cv::Point2f> &hull2f, std::vector<cv::Point2f> &corners);
void findOutsideCorners(const std::vector<cv::Point2f> &corners, std::vector<cv::Point2f> &outsideCorners);
void getSortedCorners(const std::vector<cv::Point2f> &hull2f, const std::vector<cv::Point2f> &corners, const std::vector<cv::Point2f> &outsideCorners, std::vector<cv::Point2f> &sortedCorners);
void getSortedCorners(const std::vector<cv::Point2f> &hull2f, const std::vector<cv::Point2f> &patternPoints, const std::vector<cv::Point2f> &corners, const std::vector<cv::Point2f> &outsideCorners, std::vector<cv::Point2f> &sortedCorners);
void rectifyPatternPoints(const std::vector<cv::Point2f> &patternPoints, const std::vector<cv::Point2f> &sortedCorners, std::vector<cv::Point2f> &rectifiedPatternPoints);
void parsePatternPoints(const std::vector<cv::Point2f> &patternPoints, const std::vector<cv::Point2f> &rectifiedPatternPoints, std::vector<cv::Point2f> &centers);

@ -624,5 +624,24 @@ TEST(Calib3d_AsymmetricCirclesPatternDetector, accuracy) { CV_ChessboardDetector
TEST(Calib3d_AsymmetricCirclesPatternDetectorWithClustering, accuracy) { CV_ChessboardDetectorTest test( ASYMMETRIC_CIRCLES_GRID, CALIB_CB_CLUSTERING ); test.safe_run(); }
#endif
TEST(Calib3d_CirclesPatternDetectorWithClustering, accuracy)
{
cv::String dataDir = string(TS::ptr()->get_data_path()) + "cv/cameracalibration/circles/";
cv::Mat expected;
FileStorage fs(dataDir + "circles_corners15.dat", FileStorage::READ);
fs["corners"] >> expected;
fs.release();
cv::Mat image = cv::imread(dataDir + "circles15.png");
std::vector<Point2f> centers;
cv::findCirclesGrid(image, Size(10, 8), centers, CALIB_CB_SYMMETRIC_GRID | CALIB_CB_CLUSTERING);
ASSERT_EQ(expected.total(), centers.size());
double error = calcError(centers, expected);
ASSERT_LE(error, precise_success_error_level);
}
}} // namespace
/* End of file. */

@ -3,27 +3,26 @@ Introduction {#intro}
OpenCV (Open Source Computer Vision Library: <http://opencv.org>) is an open-source BSD-licensed
library that includes several hundreds of computer vision algorithms. The document describes the
so-called OpenCV 2.x API, which is essentially a C++ API, as opposed to the C-based OpenCV 1.x API.
The latter is described in opencv1x.pdf.
so-called OpenCV 2.x API, which is essentially a C++ API, as opposed to the C-based OpenCV 1.x API
(C API is deprecated and not tested with "C" compiler since OpenCV 2.4 releases)
OpenCV has a modular structure, which means that the package includes several shared or static
libraries. The following modules are available:
- @ref core - a compact module defining basic data structures, including the dense
- @ref core (**core**) - a compact module defining basic data structures, including the dense
multi-dimensional array Mat and basic functions used by all other modules.
- @ref imgproc - an image processing module that includes linear and non-linear image filtering,
- @ref imgproc (**imgproc**) - an image processing module that includes linear and non-linear image filtering,
geometrical image transformations (resize, affine and perspective warping, generic table-based
remapping), color space conversion, histograms, and so on.
- **video** - a video analysis module that includes motion estimation, background subtraction,
- @ref video (**video**) - a video analysis module that includes motion estimation, background subtraction,
and object tracking algorithms.
- **calib3d** - basic multiple-view geometry algorithms, single and stereo camera calibration,
- @ref calib3d (**calib3d**) - basic multiple-view geometry algorithms, single and stereo camera calibration,
object pose estimation, stereo correspondence algorithms, and elements of 3D reconstruction.
- **features2d** - salient feature detectors, descriptors, and descriptor matchers.
- **objdetect** - detection of objects and instances of the predefined classes (for example,
- @ref features2d (**features2d**) - salient feature detectors, descriptors, and descriptor matchers.
- @ref objdetect (**objdetect**) - detection of objects and instances of the predefined classes (for example,
faces, eyes, mugs, people, cars, and so on).
- **highgui** - an easy-to-use interface to simple UI capabilities.
- @ref videoio - an easy-to-use interface to video capturing and video codecs.
- **gpu** - GPU-accelerated algorithms from different OpenCV modules.
- @ref highgui (**highgui**) - an easy-to-use interface to simple UI capabilities.
- @ref videoio (**videoio**) - an easy-to-use interface to video capturing and video codecs.
- ... some other helper modules, such as FLANN and Google test wrappers, Python bindings, and
others.
@ -35,36 +34,37 @@ API Concepts
### cv Namespace
All the OpenCV classes and functions are placed into the cv namespace. Therefore, to access this
functionality from your code, use the cv:: specifier or using namespace cv; directive:
@code
All the OpenCV classes and functions are placed into the `cv` namespace. Therefore, to access this
functionality from your code, use the `cv::` specifier or `using namespace cv;` directive:
```.cpp
#include "opencv2/core.hpp"
...
cv::Mat H = cv::findHomography(points1, points2, CV_RANSAC, 5);
cv::Mat H = cv::findHomography(points1, points2, cv::RANSAC, 5);
...
@endcode
```
or :
~~~
```.cpp
#include "opencv2/core.hpp"
using namespace cv;
...
Mat H = findHomography(points1, points2, CV_RANSAC, 5 );
Mat H = findHomography(points1, points2, RANSAC, 5 );
...
~~~
```
Some of the current or future OpenCV external names may conflict with STL or other libraries. In
this case, use explicit namespace specifiers to resolve the name conflicts:
@code
```.cpp
Mat a(100, 100, CV_32F);
randu(a, Scalar::all(1), Scalar::all(std::rand()));
cv::log(a, a);
a /= std::log(2.);
@endcode
```
### Automatic Memory Management
OpenCV handles all the memory automatically.
First of all, std::vector, Mat, and other data structures used by the functions and methods have
First of all, std::vector, cv::Mat, and other data structures used by the functions and methods have
destructors that deallocate the underlying memory buffers when needed. This means that the
destructors do not always deallocate the buffers as in case of Mat. They take into account possible
data sharing. A destructor decrements the reference counter associated with the matrix data buffer.
@ -73,7 +73,7 @@ structures refer to the same buffer. Similarly, when a Mat instance is copied, n
really copied. Instead, the reference counter is incremented to memorize that there is another owner
of the same data. There is also the Mat::clone method that creates a full copy of the matrix data.
See the example below:
@code
```.cpp
// create a big 8Mb matrix
Mat A(1000, 1000, CV_64F);
@ -98,24 +98,24 @@ See the example below:
// finally, make a full copy of C. As a result, the big modified
// matrix will be deallocated, since it is not referenced by anyone
C = C.clone();
@endcode
```
You see that the use of Mat and other basic structures is simple. But what about high-level classes
or even user data types created without taking automatic memory management into account? For them,
OpenCV offers the Ptr template class that is similar to std::shared\_ptr from C++11. So, instead of
OpenCV offers the cv::Ptr template class that is similar to std::shared_ptr from C++11. So, instead of
using plain pointers:
@code
```.cpp
T* ptr = new T(...);
@endcode
```
you can use:
@code
```.cpp
Ptr<T> ptr(new T(...));
@endcode
```
or:
@code
```.cpp
Ptr<T> ptr = makePtr<T>(...);
@endcode
Ptr\<T\> encapsulates a pointer to a T instance and a reference counter associated with the pointer.
See the Ptr description for details.
```
`Ptr<T>` encapsulates a pointer to a T instance and a reference counter associated with the pointer.
See the cv::Ptr description for details.
### Automatic Allocation of the Output Data
@ -126,7 +126,7 @@ size and type of the output arrays are determined from the size and type of inpu
the functions take extra parameters that help to figure out the output array properties.
Example:
@code
```.cpp
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
@ -138,7 +138,7 @@ Example:
if(!cap.isOpened()) return -1;
Mat frame, edges;
namedWindow("edges",1);
namedWindow("edges", WINDOW_AUTOSIZE);
for(;;)
{
cap >> frame;
@ -150,11 +150,11 @@ Example:
}
return 0;
}
@endcode
The array frame is automatically allocated by the \>\> operator since the video frame resolution and
```
The array frame is automatically allocated by the `>>` operator since the video frame resolution and
the bit-depth is known to the video capturing module. The array edges is automatically allocated by
the cvtColor function. It has the same size and the bit-depth as the input array. The number of
channels is 1 because the color conversion code COLOR\_BGR2GRAY is passed, which means a color to
channels is 1 because the color conversion code cv::COLOR_BGR2GRAY is passed, which means a color to
grayscale conversion. Note that frame and edges are allocated only once during the first execution
of the loop body since all the next video frames have the same resolution. If you somehow change the
video resolution, the arrays are automatically reallocated.
@ -184,11 +184,11 @@ within the 0..255 range:
\f[I(x,y)= \min ( \max (\textrm{round}(r), 0), 255)\f]
Similar rules are applied to 8-bit signed, 16-bit signed and unsigned types. This semantics is used
everywhere in the library. In C++ code, it is done using the saturate\_cast\<\> functions that
everywhere in the library. In C++ code, it is done using the `cv::saturate_cast<>` functions that
resemble standard C++ cast operations. See below the implementation of the formula provided above:
@code
```.cpp
I.at<uchar>(y, x) = saturate_cast<uchar>(r);
@endcode
```
where cv::uchar is an OpenCV 8-bit unsigned integer type. In the optimized SIMD code, such SSE2
instructions as paddusb, packuswb, and so on are used. They help achieve exactly the same behavior
as in C++ code.
@ -206,7 +206,7 @@ Because of this and also to simplify development of bindings for other languages
Matlab that do not have templates at all or have limited template capabilities, the current OpenCV
implementation is based on polymorphism and runtime dispatching over templates. In those places
where runtime dispatching would be too slow (like pixel access operators), impossible (generic
Ptr\<\> implementation), or just very inconvenient (saturate\_cast\<\>()) the current implementation
`cv::Ptr<>` implementation), or just very inconvenient (`cv::saturate_cast<>()`) the current implementation
introduces small template classes, methods, and functions. Anywhere else in the current OpenCV
version the use of templates is limited.
@ -223,25 +223,25 @@ is, array elements should have one of the following types:
- a tuple of several elements where all elements have the same type (one of the above). An array
whose elements are such tuples, are called multi-channel arrays, as opposite to the
single-channel arrays, whose elements are scalar values. The maximum possible number of
channels is defined by the CV\_CN\_MAX constant, which is currently set to 512.
channels is defined by the #CV_CN_MAX constant, which is currently set to 512.
For these basic types, the following enumeration is applied:
@code
```.cpp
enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 };
@endcode
```
Multi-channel (n-channel) types can be specified using the following options:
- CV_8UC1 ... CV_64FC4 constants (for a number of channels from 1 to 4)
- #CV_8UC1 ... #CV_64FC4 constants (for a number of channels from 1 to 4)
- CV_8UC(n) ... CV_64FC(n) or CV_MAKETYPE(CV_8U, n) ... CV_MAKETYPE(CV_64F, n) macros when
the number of channels is more than 4 or unknown at the compilation time.
@note `CV_32FC1 == CV_32F, CV_32FC2 == CV_32FC(2) == CV_MAKETYPE(CV_32F, 2)`, and
`CV_MAKETYPE(depth, n) == ((depth&7) + ((n-1)<<3)``. This means that the constant type is formed from the
@note `#CV_32FC1 == #CV_32F, #CV_32FC2 == #CV_32FC(2) == #CV_MAKETYPE(CV_32F, 2)`, and
`#CV_MAKETYPE(depth, n) == ((depth&7) + ((n-1)<<3)`. This means that the constant type is formed from the
depth, taking the lowest 3 bits, and the number of channels minus 1, taking the next
`log2(CV_CN_MAX)`` bits.
`log2(CV_CN_MAX)` bits.
Examples:
@code
```.cpp
Mat mtx(3, 3, CV_32F); // make a 3x3 floating-point matrix
Mat cmtx(10, 1, CV_64FC2); // make a 10x1 2-channel floating-point
// matrix (10-element complex vector)
@ -250,7 +250,7 @@ Examples:
Mat grayscale(image.size(), CV_MAKETYPE(image.depth(), 1)); // make a 1-channel image of
// the same size and same
// channel type as img
@endcode
```
Arrays with more complex elements cannot be constructed or processed using OpenCV. Furthermore, each
function or method can handle only a subset of all possible array types. Usually, the more complex
the algorithm is, the smaller the supported subset of formats is. See below typical examples of such
@ -270,13 +270,13 @@ extended in future based on user requests.
Many OpenCV functions process dense 2-dimensional or multi-dimensional numerical arrays. Usually,
such functions take cppMat as parameters, but in some cases it's more convenient to use
std::vector\<\> (for a point set, for example) or Matx\<\> (for 3x3 homography matrix and such). To
`std::vector<>` (for a point set, for example) or `cv::Matx<>` (for 3x3 homography matrix and such). To
avoid many duplicates in the API, special "proxy" classes have been introduced. The base "proxy"
class is InputArray. It is used for passing read-only arrays on a function input. The derived from
InputArray class OutputArray is used to specify an output array for a function. Normally, you should
class is cv::InputArray. It is used for passing read-only arrays on a function input. The derived from
InputArray class cv::OutputArray is used to specify an output array for a function. Normally, you should
not care of those intermediate types (and you should not declare variables of those types
explicitly) - it will all just work automatically. You can assume that instead of
InputArray/OutputArray you can always use Mat, std::vector\<\>, Matx\<\>, Vec\<\> or Scalar. When a
InputArray/OutputArray you can always use `Mat`, `std::vector<>`, `cv::Matx<>`, `cv::Vec<>` or `cv::Scalar`. When a
function has an optional input or output array, and you do not have or do not want one, pass
cv::noArray().
@ -291,28 +291,29 @@ The exceptions can be instances of the cv::Exception class or its derivatives. I
cv::Exception is a derivative of std::exception. So it can be gracefully handled in the code using
other standard C++ library components.
The exception is typically thrown either using the CV\_Error(errcode, description) macro, or its
printf-like CV\_Error\_(errcode, printf-spec, (printf-args)) variant, or using the
CV\_Assert(condition) macro that checks the condition and throws an exception when it is not
satisfied. For performance-critical code, there is CV\_DbgAssert(condition) that is only retained in
The exception is typically thrown either using the `#CV_Error(errcode, description)` macro, or its
printf-like `#CV_Error_(errcode, (printf-spec, printf-args))` variant, or using the
#CV_Assert(condition) macro that checks the condition and throws an exception when it is not
satisfied. For performance-critical code, there is #CV_DbgAssert(condition) that is only retained in
the Debug configuration. Due to the automatic memory management, all the intermediate buffers are
automatically deallocated in case of a sudden error. You only need to add a try statement to catch
exceptions, if needed: :
@code
```.cpp
try
{
... // call OpenCV
}
catch( cv::Exception& e )
catch (const cv::Exception& e)
{
const char* err_msg = e.what();
std::cout << "exception caught: " << err_msg << std::endl;
}
@endcode
```
### Multi-threading and Re-enterability
The current OpenCV implementation is fully re-enterable. That is, the same function, the same
*constant* method of a class instance, or the same *non-constant* method of different class
instances can be called from different threads. Also, the same cv::Mat can be used in different
threads because the reference-counting operations use the architecture-specific atomic instructions.
The current OpenCV implementation is fully re-enterable.
That is, the same function or the same methods of different class instances
can be called from different threads.
Also, the same Mat can be used in different threads
because the reference-counting operations use the architecture-specific atomic instructions.

@ -2959,7 +2959,7 @@ An example on K-means clustering
/** @brief Finds centers of clusters and groups input samples around the clusters.
The function kmeans implements a k-means algorithm that finds the centers of cluster_count clusters
and groups the input samples around the clusters. As an output, \f$\texttt{labels}_i\f$ contains a
and groups the input samples around the clusters. As an output, \f$\texttt{bestLabels}_i\f$ contains a
0-based cluster index for the sample stored in the \f$i^{th}\f$ row of the samples matrix.
@note

@ -325,7 +325,7 @@ This macro can be used to construct an error message on-fly to include some dyna
for example:
@code
// note the extra parentheses around the formatted text message
CV_Error_( CV_StsOutOfRange,
CV_Error_(Error::StsOutOfRange,
("the value at (%d, %d)=%g is out of range", badPt.x, badPt.y, badValue));
@endcode
@param code one of Error::Code

@ -521,7 +521,7 @@ static inline size_t divUp(size_t a, unsigned int b)
/** @brief Enables or disables the optimized code.
The function can be used to dynamically turn on and off optimized code (code that uses SSE2, AVX,
The function can be used to dynamically turn on and off optimized dispatched code (code that uses SSE4.2, AVX/AVX2,
and other instructions on the platforms that support it). It sets a global flag that is further
checked by OpenCV functions. Since the flag is not checked in the inner OpenCV loops, it is only
safe to call the function on the very top level in your application where you can be sure that no

@ -765,6 +765,15 @@
"v_type": "Mat",
"j_import": "org.opencv.core.MatOfRect2d"
},
"vector_RotatedRect": {
"j_type": "MatOfRotatedRect",
"jn_type": "long",
"jni_type": "jlong",
"jni_var": "std::vector< RotatedRect > %(n)s",
"suffix": "J",
"v_type": "Mat",
"j_import": "org.opencv.core.MatOfRotatedRect"
},
"vector_String": {
"j_type": "List<String>",
"jn_type": "List<String>",

@ -1989,7 +1989,7 @@ cvWaitKey( int delay )
MSG message;
int is_processed = 0;
if( delay <= 0 )
if( (delay <= 0) && hg_windows)
GetMessage(&message, 0, 0, 0);
else if( PeekMessage(&message, 0, 0, 0, PM_REMOVE) == FALSE )
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -947,7 +947,12 @@ static void common_matchTemplate( Mat& img, Mat& templ, Mat& result, int method,
if( isNormed )
{
t = std::sqrt(MAX(wndSum2 - wndMean2,0))*templNorm;
double diff2 = MAX(wndSum2 - wndMean2, 0);
if (diff2 <= std::min(0.5, 10 * FLT_EPSILON * wndSum2))
t = 0; // avoid rounding errors
else
t = std::sqrt(diff2)*templNorm;
if( fabs(num) < t )
num /= t;
else if( fabs(num) < t*1.125 )

@ -107,6 +107,20 @@ void vector_Rect2d_to_Mat(std::vector<Rect2d>& v_rect, Mat& mat)
mat = Mat(v_rect, true);
}
//vector_RotatedRect
void Mat_to_vector_RotatedRect(Mat& mat, std::vector<RotatedRect>& v_rect)
{
v_rect.clear();
CHECK_MAT(mat.type()==CV_32FC(5) && mat.cols==1);
v_rect = (std::vector<RotatedRect>) mat;
}
void vector_RotatedRect_to_Mat(std::vector<RotatedRect>& v_rect, Mat& mat)
{
mat = Mat(v_rect, true);
}
//vector_Point
void Mat_to_vector_Point(Mat& mat, std::vector<Point>& v_point)
{

@ -26,6 +26,8 @@ void vector_Rect_to_Mat(std::vector<cv::Rect>& v_rect, cv::Mat& mat);
void Mat_to_vector_Rect2d(cv::Mat& mat, std::vector<cv::Rect2d>& v_rect);
void vector_Rect2d_to_Mat(std::vector<cv::Rect2d>& v_rect, cv::Mat& mat);
void Mat_to_vector_RotatedRect(cv::Mat& mat, std::vector<cv::RotatedRect>& v_rect);
void vector_RotatedRect_to_Mat(std::vector<cv::RotatedRect>& v_rect, cv::Mat& mat);
void Mat_to_vector_Point(cv::Mat& mat, std::vector<cv::Point>& v_point);
void Mat_to_vector_Point2f(cv::Mat& mat, std::vector<cv::Point2f>& v_point);

@ -13,7 +13,9 @@ import org.opencv.core.MatOfPoint2f;
import org.opencv.core.MatOfPoint3f;
import org.opencv.core.Point;
import org.opencv.core.Point3;
import org.opencv.core.Size;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Rect2d;
import org.opencv.core.DMatch;
import org.opencv.core.KeyPoint;
@ -770,4 +772,41 @@ public class Converters {
}
mats.clear();
}
public static Mat vector_RotatedRect_to_Mat(List<RotatedRect> rs) {
Mat res;
int count = (rs != null) ? rs.size() : 0;
if (count > 0) {
res = new Mat(count, 1, CvType.CV_32FC(5));
float[] buff = new float[5 * count];
for (int i = 0; i < count; i++) {
RotatedRect r = rs.get(i);
buff[5 * i] = (float)r.center.x;
buff[5 * i + 1] = (float)r.center.y;
buff[5 * i + 2] = (float)r.size.width;
buff[5 * i + 3] = (float)r.size.height;
buff[5 * i + 4] = (float)r.angle;
}
res.put(0, 0, buff);
} else {
res = new Mat();
}
return res;
}
public static void Mat_to_vector_RotatedRect(Mat m, List<RotatedRect> rs) {
if (rs == null)
throw new java.lang.IllegalArgumentException("rs == null");
int count = m.rows();
if (CvType.CV_32FC(5) != m.type() || m.cols() != 1)
throw new java.lang.IllegalArgumentException(
"CvType.CV_32FC5 != m.type() || m.rows()!=1\n" + m);
rs.clear();
float[] buff = new float[5 * count];
m.get(0, 0, buff);
for (int i = 0; i < count; i++) {
rs.add(new RotatedRect(new Point(buff[5 * i], buff[5 * i + 1]), new Size(buff[5 * i + 2], buff[5 * i + 3]), buff[5 * i + 4]));
}
}
}

@ -17,6 +17,7 @@ import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Point3;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.core.DMatch;
@ -336,6 +337,15 @@ public class OpenCVTestCase extends TestCase {
assertRectEquals(list1.get(i), list2.get(i));
}
public static void assertListRotatedRectEquals(List<RotatedRect> list1, List<RotatedRect> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertRotatedRectEquals(list1.get(i), list2.get(i));
}
public static void assertRectEquals(Rect expected, Rect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x);
@ -344,6 +354,15 @@ public class OpenCVTestCase extends TestCase {
assertEquals(msg, expected.height, actual.height);
}
public static void assertRotatedRectEquals(RotatedRect expected, RotatedRect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.center.x, actual.center.x);
assertEquals(msg, expected.center.y, actual.center.y);
assertEquals(msg, expected.size.width, actual.size.width);
assertEquals(msg, expected.size.height, actual.size.height);
assertEquals(msg, expected.angle, actual.angle);
}
public static void assertMatEqual(Mat m1, Mat m2) {
compareMats(m1, m2, true);
}

@ -4,7 +4,9 @@ import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Point3;
import org.opencv.core.Size;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.DMatch;
import org.opencv.core.KeyPoint;
import org.opencv.test.OpenCVTestCase;
@ -222,6 +224,19 @@ public class ConvertersTest extends OpenCVTestCase {
assertListRectEquals(truth, rectangles);
}
public void testMat_to_vector_RotatedRect() {
Mat src = new Mat(2, 1, CvType.CV_32FC(5));
src.put(0, 0, 2, 2, 5, 2, 7,
0, 6, 4, 1, 3);
List<RotatedRect> rectangles = new ArrayList<RotatedRect>();
Converters.Mat_to_vector_RotatedRect(src, rectangles);
List<RotatedRect> truth = new ArrayList<RotatedRect>();
truth.add(new RotatedRect(new Point(2, 2), new Size(5, 2), 7));
truth.add(new RotatedRect(new Point(0, 6), new Size(4, 1), 3));
assertListRotatedRectEquals(truth, rectangles);
}
public void testMat_to_vector_uchar() {
Mat src = new Mat(3, 1, CvType.CV_8UC1);
src.put(0, 0, 2, 4, 3);
@ -465,6 +480,19 @@ public class ConvertersTest extends OpenCVTestCase {
assertMatEqual(truth, dst);
}
public void testVector_RotatedRect_to_Mat() {
List<RotatedRect> rectangles = new ArrayList<RotatedRect>();
rectangles.add(new RotatedRect(new Point(2, 2), new Size(5, 2), 7));
rectangles.add(new RotatedRect(new Point(0, 0), new Size(6, 4), 3));
Mat dst = Converters.vector_RotatedRect_to_Mat(rectangles);
Mat truth = new Mat(2, 1, CvType.CV_32FC(5));
truth.put(0, 0, 2, 2, 5, 2, 7,
0, 0, 6, 4, 3);
assertMatEqual(truth, dst, EPS);
}
public void testVector_uchar_to_Mat() {
List<Byte> bytes = new ArrayList<Byte>();
byte value1 = 1;
@ -498,5 +526,4 @@ public class ConvertersTest extends OpenCVTestCase {
fail("Not yet implemented");
}
}

@ -20,6 +20,7 @@ import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Point3;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.core.DMatch;
@ -362,6 +363,15 @@ public class OpenCVTestCase extends TestCase {
assertRectEquals(list1.get(i), list2.get(i));
}
public static void assertListRotatedRectEquals(List<RotatedRect> list1, List<RotatedRect> list2) {
if (list1.size() != list2.size()) {
throw new UnsupportedOperationException();
}
for (int i = 0; i < list1.size(); i++)
assertRotatedRectEquals(list1.get(i), list2.get(i));
}
public static void assertRectEquals(Rect expected, Rect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.x, actual.x);
@ -370,6 +380,15 @@ public class OpenCVTestCase extends TestCase {
assertEquals(msg, expected.height, actual.height);
}
public static void assertRotatedRectEquals(RotatedRect expected, RotatedRect actual) {
String msg = "expected:<" + expected + "> but was:<" + actual + ">";
assertEquals(msg, expected.center.x, actual.center.x);
assertEquals(msg, expected.center.y, actual.center.y);
assertEquals(msg, expected.size.width, actual.size.width);
assertEquals(msg, expected.size.height, actual.size.height);
assertEquals(msg, expected.angle, actual.angle);
}
public static void assertMatEqual(Mat m1, Mat m2) {
compareMats(m1, m2, true);
}

@ -48,7 +48,10 @@
#include <algorithm>
#include <limits>
#define OPENCV_FOURCC(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24))
#ifndef __OPENCV_BUILD
#define CV_FOURCC(c1, c2, c3, c4) (((c1) & 255) + (((c2) & 255) << 8) + (((c3) & 255) << 16) + (((c4) & 255) << 24))
#endif
#define CALC_FFMPEG_VERSION(a,b,c) ( a<<16 | b<<8 | c )
#if defined _MSC_VER && _MSC_VER >= 1200
@ -1197,7 +1200,7 @@ double CvCapture_FFMPEG::getProperty( int property_id ) const
return codec_tag;
}
return (double) OPENCV_FOURCC(codec_fourcc[0], codec_fourcc[1], codec_fourcc[2], codec_fourcc[3]);
return (double) CV_FOURCC(codec_fourcc[0], codec_fourcc[1], codec_fourcc[2], codec_fourcc[3]);
case CV_FFMPEG_CAP_PROP_SAR_NUM:
return _opencv_ffmpeg_get_sample_aspect_ratio(ic->streams[video_stream]).num;
case CV_FFMPEG_CAP_PROP_SAR_DEN:

@ -21,7 +21,6 @@ set(OPENCV_CUDA_SAMPLES_REQUIRED_DEPS
opencv_cudaoptflow
opencv_cudabgsegm
opencv_cudastereo
opencv_cudalegacy
opencv_cudaobjdetect)
ocv_check_dependencies(${OPENCV_CUDA_SAMPLES_REQUIRED_DEPS})

@ -4,7 +4,6 @@
#include "opencv2/core.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/cudabgsegm.hpp"
#include "opencv2/cudalegacy.hpp"
#include "opencv2/video.hpp"
#include "opencv2/highgui.hpp"
@ -16,8 +15,6 @@ enum Method
{
MOG,
MOG2,
GMG,
FGD_STAT
};
int main(int argc, const char** argv)
@ -25,7 +22,7 @@ int main(int argc, const char** argv)
cv::CommandLineParser cmd(argc, argv,
"{ c camera | | use camera }"
"{ f file | ../data/vtest.avi | input video file }"
"{ m method | mog | method (mog, mog2, gmg, fgd) }"
"{ m method | mog | method (mog, mog2) }"
"{ h help | | print help message }");
if (cmd.has("help") || !cmd.check())
@ -40,9 +37,7 @@ int main(int argc, const char** argv)
string method = cmd.get<string>("method");
if (method != "mog"
&& method != "mog2"
&& method != "gmg"
&& method != "fgd")
&& method != "mog2")
{
cerr << "Incorrect method" << endl;
return -1;
@ -50,8 +45,8 @@ int main(int argc, const char** argv)
Method m = method == "mog" ? MOG :
method == "mog2" ? MOG2 :
method == "fgd" ? FGD_STAT :
GMG;
(Method)-1;
CV_Assert(m != (Method)-1);
VideoCapture cap;
@ -73,8 +68,6 @@ int main(int argc, const char** argv)
Ptr<BackgroundSubtractor> mog = cuda::createBackgroundSubtractorMOG();
Ptr<BackgroundSubtractor> mog2 = cuda::createBackgroundSubtractorMOG2();
Ptr<BackgroundSubtractor> gmg = cuda::createBackgroundSubtractorGMG(40);
Ptr<BackgroundSubtractor> fgd = cuda::createBackgroundSubtractorFGD();
GpuMat d_fgmask;
GpuMat d_fgimg;
@ -93,23 +86,12 @@ int main(int argc, const char** argv)
case MOG2:
mog2->apply(d_frame, d_fgmask);
break;
case GMG:
gmg->apply(d_frame, d_fgmask);
break;
case FGD_STAT:
fgd->apply(d_frame, d_fgmask);
break;
}
namedWindow("image", WINDOW_NORMAL);
namedWindow("foreground mask", WINDOW_NORMAL);
namedWindow("foreground image", WINDOW_NORMAL);
if (m != GMG)
{
namedWindow("mean background image", WINDOW_NORMAL);
}
namedWindow("mean background image", WINDOW_NORMAL);
for(;;)
{
@ -132,15 +114,6 @@ int main(int argc, const char** argv)
mog2->apply(d_frame, d_fgmask);
mog2->getBackgroundImage(d_bgimg);
break;
case GMG:
gmg->apply(d_frame, d_fgmask);
break;
case FGD_STAT:
fgd->apply(d_frame, d_fgmask);
fgd->getBackgroundImage(d_bgimg);
break;
}
double fps = cv::getTickFrequency() / (cv::getTickCount() - start);

@ -1,388 +0,0 @@
#if defined _MSC_VER && _MSC_VER >= 1400
#pragma warning( disable : 4201 4408 4127 4100)
#endif
#include <iostream>
#include <iomanip>
#include <cstdio>
#include "opencv2/core/cuda.hpp"
#include "opencv2/cudalegacy.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/objdetect.hpp"
#include "opencv2/objdetect/objdetect_c.h"
using namespace std;
using namespace cv;
#if !defined(HAVE_CUDA) || defined(__arm__)
int main( int, const char** )
{
#if !defined(HAVE_CUDA)
std::cout << "CUDA support is required (CMake key 'WITH_CUDA' must be true)." << std::endl;
#endif
#if defined(__arm__)
std::cout << "Unsupported for ARM CUDA library." << std::endl;
#endif
return 0;
}
#else
const Size2i preferredVideoFrameSize(640, 480);
const cv::String wndTitle = "NVIDIA Computer Vision :: Haar Classifiers Cascade";
static void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const string &ss)
{
int fontFace = FONT_HERSHEY_DUPLEX;
double fontScale = 0.8;
int fontThickness = 2;
Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0);
Point org;
org.x = 1;
org.y = 3 * fontSize.height * (lineOffsY + 1) / 2;
putText(img, ss, org, fontFace, fontScale, Scalar(0,0,0), 5*fontThickness/2, 16);
putText(img, ss, org, fontFace, fontScale, fontColor, fontThickness, 16);
}
static void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps)
{
Scalar fontColorRed(0,0,255);
Scalar fontColorNV(0,185,118);
ostringstream ss;
ss << "FPS = " << setprecision(1) << fixed << fps;
matPrint(canvas, 0, fontColorRed, ss.str());
ss.str("");
ss << "[" << canvas.cols << "x" << canvas.rows << "], " <<
(bGpu ? "GPU, " : "CPU, ") <<
(bLargestFace ? "OneFace, " : "MultiFace, ") <<
(bFilter ? "Filter:ON" : "Filter:OFF");
matPrint(canvas, 1, fontColorRed, ss.str());
if (bHelp)
{
matPrint(canvas, 2, fontColorNV, "Space - switch GPU / CPU");
matPrint(canvas, 3, fontColorNV, "M - switch OneFace / MultiFace");
matPrint(canvas, 4, fontColorNV, "F - toggle rectangles Filter");
matPrint(canvas, 5, fontColorNV, "H - toggle hotkeys help");
}
else
{
matPrint(canvas, 2, fontColorNV, "H - toggle hotkeys help");
}
}
static NCVStatus process(Mat *srcdst,
Ncv32u width, Ncv32u height,
NcvBool bFilterRects, NcvBool bLargestFace,
HaarClassifierCascadeDescriptor &haar,
NCVVector<HaarStage64> &d_haarStages, NCVVector<HaarClassifierNode128> &d_haarNodes,
NCVVector<HaarFeature64> &d_haarFeatures, NCVVector<HaarStage64> &h_haarStages,
INCVMemAllocator &gpuAllocator,
INCVMemAllocator &cpuAllocator,
cudaDeviceProp &devProp)
{
ncvAssertReturn(!((srcdst == NULL) ^ gpuAllocator.isCounting()), NCV_NULL_PTR);
NCVStatus ncvStat;
NCV_SET_SKIP_COND(gpuAllocator.isCounting());
NCVMatrixAlloc<Ncv8u> d_src(gpuAllocator, width, height);
ncvAssertReturn(d_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);
NCVMatrixAlloc<Ncv8u> h_src(cpuAllocator, width, height);
ncvAssertReturn(h_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);
NCVVectorAlloc<NcvRect32u> d_rects(gpuAllocator, 100);
ncvAssertReturn(d_rects.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);
NCV_SKIP_COND_BEGIN
for (Ncv32u i=0; i<(Ncv32u)srcdst->rows; i++)
{
memcpy(h_src.ptr() + i * h_src.stride(), srcdst->ptr(i), srcdst->cols);
}
ncvStat = h_src.copySolid(d_src, 0);
ncvAssertReturnNcvStat(ncvStat);
ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);
NCV_SKIP_COND_END
NcvSize32u roi;
roi.width = d_src.width();
roi.height = d_src.height();
Ncv32u numDetections;
ncvStat = ncvDetectObjectsMultiScale_device(
d_src, roi, d_rects, numDetections, haar, h_haarStages,
d_haarStages, d_haarNodes, d_haarFeatures,
haar.ClassifierSize,
(bFilterRects || bLargestFace) ? 4 : 0,
1.2f, 1,
(bLargestFace ? NCVPipeObjDet_FindLargestObject : 0)
| NCVPipeObjDet_VisualizeInPlace,
gpuAllocator, cpuAllocator, devProp, 0);
ncvAssertReturnNcvStat(ncvStat);
ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);
NCV_SKIP_COND_BEGIN
ncvStat = d_src.copySolid(h_src, 0);
ncvAssertReturnNcvStat(ncvStat);
ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);
for (Ncv32u i=0; i<(Ncv32u)srcdst->rows; i++)
{
memcpy(srcdst->ptr(i), h_src.ptr() + i * h_src.stride(), srcdst->cols);
}
NCV_SKIP_COND_END
return NCV_SUCCESS;
}
int main(int argc, const char** argv)
{
cout << "OpenCV / NVIDIA Computer Vision" << endl;
cout << "Face Detection in video and live feed" << endl;
cout << "Syntax: exename <cascade_file> <image_or_video_or_cameraid>" << endl;
cout << "=========================================" << endl;
ncvAssertPrintReturn(cv::cuda::getCudaEnabledDeviceCount() != 0, "No GPU found or the library is compiled without CUDA support", -1);
ncvAssertPrintReturn(argc == 3, "Invalid number of arguments", -1);
cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());
string cascadeName = argv[1];
string inputName = argv[2];
NCVStatus ncvStat;
NcvBool bQuit = false;
VideoCapture capture;
Size2i frameSize;
//open content source
Mat image = imread(inputName);
Mat frame;
if (!image.empty())
{
frameSize.width = image.cols;
frameSize.height = image.rows;
}
else
{
if (!capture.open(inputName))
{
int camid = -1;
istringstream ss(inputName);
int x = 0;
ss >> x;
ncvAssertPrintReturn(capture.open(camid) != 0, "Can't open source", -1);
}
capture >> frame;
ncvAssertPrintReturn(!frame.empty(), "Empty video source", -1);
frameSize.width = frame.cols;
frameSize.height = frame.rows;
}
NcvBool bUseGPU = true;
NcvBool bLargestObject = false;
NcvBool bFilterRects = true;
NcvBool bHelpScreen = false;
CascadeClassifier classifierOpenCV;
ncvAssertPrintReturn(classifierOpenCV.load(cascadeName) != 0, "Error (in OpenCV) opening classifier", -1);
int devId;
ncvAssertCUDAReturn(cudaGetDevice(&devId), -1);
cudaDeviceProp devProp;
ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), -1);
cout << "Using GPU: " << devId << "(" << devProp.name <<
"), arch=" << devProp.major << "." << devProp.minor << endl;
//==============================================================================
//
// Load the classifier from file (assuming its size is about 1 mb)
// using a simple allocator
//
//==============================================================================
NCVMemNativeAllocator gpuCascadeAllocator(NCVMemoryTypeDevice, static_cast<Ncv32u>(devProp.textureAlignment));
ncvAssertPrintReturn(gpuCascadeAllocator.isInitialized(), "Error creating cascade GPU allocator", -1);
NCVMemNativeAllocator cpuCascadeAllocator(NCVMemoryTypeHostPinned, static_cast<Ncv32u>(devProp.textureAlignment));
ncvAssertPrintReturn(cpuCascadeAllocator.isInitialized(), "Error creating cascade CPU allocator", -1);
Ncv32u haarNumStages, haarNumNodes, haarNumFeatures;
ncvStat = ncvHaarGetClassifierSize(cascadeName, haarNumStages, haarNumNodes, haarNumFeatures);
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error reading classifier size (check the file)", -1);
NCVVectorAlloc<HaarStage64> h_haarStages(cpuCascadeAllocator, haarNumStages);
ncvAssertPrintReturn(h_haarStages.isMemAllocated(), "Error in cascade CPU allocator", -1);
NCVVectorAlloc<HaarClassifierNode128> h_haarNodes(cpuCascadeAllocator, haarNumNodes);
ncvAssertPrintReturn(h_haarNodes.isMemAllocated(), "Error in cascade CPU allocator", -1);
NCVVectorAlloc<HaarFeature64> h_haarFeatures(cpuCascadeAllocator, haarNumFeatures);
ncvAssertPrintReturn(h_haarFeatures.isMemAllocated(), "Error in cascade CPU allocator", -1);
HaarClassifierCascadeDescriptor haar;
ncvStat = ncvHaarLoadFromFile_host(cascadeName, haar, h_haarStages, h_haarNodes, h_haarFeatures);
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error loading classifier", -1);
NCVVectorAlloc<HaarStage64> d_haarStages(gpuCascadeAllocator, haarNumStages);
ncvAssertPrintReturn(d_haarStages.isMemAllocated(), "Error in cascade GPU allocator", -1);
NCVVectorAlloc<HaarClassifierNode128> d_haarNodes(gpuCascadeAllocator, haarNumNodes);
ncvAssertPrintReturn(d_haarNodes.isMemAllocated(), "Error in cascade GPU allocator", -1);
NCVVectorAlloc<HaarFeature64> d_haarFeatures(gpuCascadeAllocator, haarNumFeatures);
ncvAssertPrintReturn(d_haarFeatures.isMemAllocated(), "Error in cascade GPU allocator", -1);
ncvStat = h_haarStages.copySolid(d_haarStages, 0);
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1);
ncvStat = h_haarNodes.copySolid(d_haarNodes, 0);
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1);
ncvStat = h_haarFeatures.copySolid(d_haarFeatures, 0);
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1);
//==============================================================================
//
// Calculate memory requirements and create real allocators
//
//==============================================================================
NCVMemStackAllocator gpuCounter(static_cast<Ncv32u>(devProp.textureAlignment));
ncvAssertPrintReturn(gpuCounter.isInitialized(), "Error creating GPU memory counter", -1);
NCVMemStackAllocator cpuCounter(static_cast<Ncv32u>(devProp.textureAlignment));
ncvAssertPrintReturn(cpuCounter.isInitialized(), "Error creating CPU memory counter", -1);
ncvStat = process(NULL, frameSize.width, frameSize.height,
false, false, haar,
d_haarStages, d_haarNodes,
d_haarFeatures, h_haarStages,
gpuCounter, cpuCounter, devProp);
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error in memory counting pass", -1);
NCVMemStackAllocator gpuAllocator(NCVMemoryTypeDevice, gpuCounter.maxSize(), static_cast<Ncv32u>(devProp.textureAlignment));
ncvAssertPrintReturn(gpuAllocator.isInitialized(), "Error creating GPU memory allocator", -1);
NCVMemStackAllocator cpuAllocator(NCVMemoryTypeHostPinned, cpuCounter.maxSize(), static_cast<Ncv32u>(devProp.textureAlignment));
ncvAssertPrintReturn(cpuAllocator.isInitialized(), "Error creating CPU memory allocator", -1);
printf("Initialized for frame size [%dx%d]\n", frameSize.width, frameSize.height);
//==============================================================================
//
// Main processing loop
//
//==============================================================================
namedWindow(wndTitle, 1);
Mat frameDisp;
do
{
Mat gray;
cvtColor((image.empty() ? frame : image), gray, cv::COLOR_BGR2GRAY);
//
// process
//
NcvSize32u minSize = haar.ClassifierSize;
if (bLargestObject)
{
Ncv32u ratioX = preferredVideoFrameSize.width / minSize.width;
Ncv32u ratioY = preferredVideoFrameSize.height / minSize.height;
Ncv32u ratioSmallest = min(ratioX, ratioY);
ratioSmallest = max((Ncv32u)(ratioSmallest / 2.5f), (Ncv32u)1);
minSize.width *= ratioSmallest;
minSize.height *= ratioSmallest;
}
Ncv32f avgTime;
NcvTimer timer = ncvStartTimer();
if (bUseGPU)
{
ncvStat = process(&gray, frameSize.width, frameSize.height,
bFilterRects, bLargestObject, haar,
d_haarStages, d_haarNodes,
d_haarFeatures, h_haarStages,
gpuAllocator, cpuAllocator, devProp);
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error in memory counting pass", -1);
}
else
{
vector<Rect> rectsOpenCV;
classifierOpenCV.detectMultiScale(
gray,
rectsOpenCV,
1.2f,
bFilterRects ? 4 : 0,
(bLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0)
| CV_HAAR_SCALE_IMAGE,
Size(minSize.width, minSize.height));
for (size_t rt = 0; rt < rectsOpenCV.size(); ++rt)
rectangle(gray, rectsOpenCV[rt], Scalar(255));
}
avgTime = (Ncv32f)ncvEndQueryTimerMs(timer);
cvtColor(gray, frameDisp, cv::COLOR_GRAY2BGR);
displayState(frameDisp, bHelpScreen, bUseGPU, bLargestObject, bFilterRects, 1000.0f / avgTime);
imshow(wndTitle, frameDisp);
//handle input
switch (cv::waitKey(3))
{
case ' ':
bUseGPU = !bUseGPU;
break;
case 'm':
case 'M':
bLargestObject = !bLargestObject;
break;
case 'f':
case 'F':
bFilterRects = !bFilterRects;
break;
case 'h':
case 'H':
bHelpScreen = !bHelpScreen;
break;
case 27:
bQuit = true;
break;
}
// For camera and video file, capture the next image
if (capture.isOpened())
{
capture >> frame;
if (frame.empty())
{
break;
}
}
} while (!bQuit);
cv::destroyWindow(wndTitle);
return 0;
}
#endif //!defined(HAVE_CUDA)

@ -1,651 +0,0 @@
#if defined _MSC_VER && _MSC_VER >= 1400
#pragma warning( disable : 4201 4408 4127 4100)
#endif
#include <iostream>
#include <iomanip>
#include <memory>
#include <exception>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <iomanip>
#include "opencv2/core/cuda.hpp"
#include "opencv2/cudalegacy.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/core_c.h" // FIXIT legacy API
#include "opencv2/highgui/highgui_c.h" // FIXIT legacy API
#if !defined(HAVE_CUDA)
int main( int, const char** )
{
std::cout << "Please compile the library with CUDA support" << std::endl;
return -1;
}
#else
//using std::shared_ptr;
using cv::Ptr;
#define PARAM_LEFT "--left"
#define PARAM_RIGHT "--right"
#define PARAM_SCALE "--scale"
#define PARAM_ALPHA "--alpha"
#define PARAM_GAMMA "--gamma"
#define PARAM_INNER "--inner"
#define PARAM_OUTER "--outer"
#define PARAM_SOLVER "--solver"
#define PARAM_TIME_STEP "--time-step"
#define PARAM_HELP "--help"
Ptr<INCVMemAllocator> g_pGPUMemAllocator;
Ptr<INCVMemAllocator> g_pHostMemAllocator;
class RgbToMonochrome
{
public:
float operator ()(unsigned char b, unsigned char g, unsigned char r)
{
float _r = static_cast<float>(r)/255.0f;
float _g = static_cast<float>(g)/255.0f;
float _b = static_cast<float>(b)/255.0f;
return (_r + _g + _b)/3.0f;
}
};
class RgbToR
{
public:
float operator ()(unsigned char /*b*/, unsigned char /*g*/, unsigned char r)
{
return static_cast<float>(r)/255.0f;
}
};
class RgbToG
{
public:
float operator ()(unsigned char /*b*/, unsigned char g, unsigned char /*r*/)
{
return static_cast<float>(g)/255.0f;
}
};
class RgbToB
{
public:
float operator ()(unsigned char b, unsigned char /*g*/, unsigned char /*r*/)
{
return static_cast<float>(b)/255.0f;
}
};
template<class T>
NCVStatus CopyData(IplImage *image, Ptr<NCVMatrixAlloc<Ncv32f> >& dst)
{
dst = Ptr<NCVMatrixAlloc<Ncv32f> > (new NCVMatrixAlloc<Ncv32f> (*g_pHostMemAllocator, image->width, image->height));
ncvAssertReturn (dst->isMemAllocated (), NCV_ALLOCATOR_BAD_ALLOC);
unsigned char *row = reinterpret_cast<unsigned char*> (image->imageData);
T convert;
for (int i = 0; i < image->height; ++i)
{
for (int j = 0; j < image->width; ++j)
{
if (image->nChannels < 3)
{
dst->ptr ()[j + i*dst->stride ()] = static_cast<float> (*(row + j*image->nChannels))/255.0f;
}
else
{
unsigned char *color = row + j * image->nChannels;
dst->ptr ()[j +i*dst->stride ()] = convert (color[0], color[1], color[2]);
}
}
row += image->widthStep;
}
return NCV_SUCCESS;
}
template<class T>
NCVStatus CopyData(const IplImage *image, const NCVMatrixAlloc<Ncv32f> &dst)
{
unsigned char *row = reinterpret_cast<unsigned char*> (image->imageData);
T convert;
for (int i = 0; i < image->height; ++i)
{
for (int j = 0; j < image->width; ++j)
{
if (image->nChannels < 3)
{
dst.ptr ()[j + i*dst.stride ()] = static_cast<float>(*(row + j*image->nChannels))/255.0f;
}
else
{
unsigned char *color = row + j * image->nChannels;
dst.ptr ()[j +i*dst.stride()] = convert (color[0], color[1], color[2]);
}
}
row += image->widthStep;
}
return NCV_SUCCESS;
}
static NCVStatus LoadImages (const char *frame0Name,
const char *frame1Name,
int &width,
int &height,
Ptr<NCVMatrixAlloc<Ncv32f> > &src,
Ptr<NCVMatrixAlloc<Ncv32f> > &dst,
IplImage *&firstFrame,
IplImage *&lastFrame)
{
IplImage *image;
image = cvLoadImage (frame0Name);
if (image == 0)
{
std::cout << "Could not open '" << frame0Name << "'\n";
return NCV_FILE_ERROR;
}
firstFrame = image;
// copy data to src
ncvAssertReturnNcvStat (CopyData<RgbToMonochrome> (image, src));
IplImage *image2;
image2 = cvLoadImage (frame1Name);
if (image2 == 0)
{
std::cout << "Could not open '" << frame1Name << "'\n";
return NCV_FILE_ERROR;
}
lastFrame = image2;
ncvAssertReturnNcvStat (CopyData<RgbToMonochrome> (image2, dst));
width = image->width;
height = image->height;
return NCV_SUCCESS;
}
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);
}
static NCVStatus ShowFlow (NCVMatrixAlloc<Ncv32f> &u, NCVMatrixAlloc<Ncv32f> &v, const char *name)
{
IplImage *flowField;
NCVMatrixAlloc<Ncv32f> host_u(*g_pHostMemAllocator, u.width(), u.height());
ncvAssertReturn(host_u.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);
NCVMatrixAlloc<Ncv32f> host_v (*g_pHostMemAllocator, u.width (), u.height ());
ncvAssertReturn (host_v.isMemAllocated (), NCV_ALLOCATOR_BAD_ALLOC);
ncvAssertReturnNcvStat (u.copySolid (host_u, 0));
ncvAssertReturnNcvStat (v.copySolid (host_v, 0));
float *ptr_u = host_u.ptr ();
float *ptr_v = host_v.ptr ();
float maxDisplacement = 1.0f;
for (Ncv32u i = 0; i < u.height (); ++i)
{
for (Ncv32u j = 0; j < u.width (); ++j)
{
float d = std::max ( fabsf(*ptr_u), fabsf(*ptr_v) );
if (d > maxDisplacement) maxDisplacement = d;
++ptr_u;
++ptr_v;
}
ptr_u += u.stride () - u.width ();
ptr_v += v.stride () - v.width ();
}
CvSize image_size = cvSize (u.width (), u.height ());
flowField = cvCreateImage (image_size, IPL_DEPTH_8U, 4);
if (flowField == 0) return NCV_NULL_PTR;
unsigned char *row = reinterpret_cast<unsigned char *> (flowField->imageData);
ptr_u = host_u.ptr();
ptr_v = host_v.ptr();
for (int i = 0; i < flowField->height; ++i)
{
for (int j = 0; j < flowField->width; ++j)
{
(row + j * flowField->nChannels)[0] = 0;
(row + j * flowField->nChannels)[1] = static_cast<unsigned char> (MapValue (-(*ptr_v), -maxDisplacement, maxDisplacement, 0.0f, 255.0f));
(row + j * flowField->nChannels)[2] = static_cast<unsigned char> (MapValue (*ptr_u , -maxDisplacement, maxDisplacement, 0.0f, 255.0f));
(row + j * flowField->nChannels)[3] = 255;
++ptr_u;
++ptr_v;
}
row += flowField->widthStep;
ptr_u += u.stride () - u.width ();
ptr_v += v.stride () - v.width ();
}
cvShowImage (name, flowField);
return NCV_SUCCESS;
}
static IplImage *CreateImage (NCVMatrixAlloc<Ncv32f> &h_r, NCVMatrixAlloc<Ncv32f> &h_g, NCVMatrixAlloc<Ncv32f> &h_b)
{
CvSize imageSize = cvSize (h_r.width (), h_r.height ());
IplImage *image = cvCreateImage (imageSize, IPL_DEPTH_8U, 4);
if (image == 0) return 0;
unsigned char *row = reinterpret_cast<unsigned char*> (image->imageData);
for (int i = 0; i < image->height; ++i)
{
for (int j = 0; j < image->width; ++j)
{
int offset = j * image->nChannels;
int pos = i * h_r.stride () + j;
row[offset + 0] = static_cast<unsigned char> (h_b.ptr ()[pos] * 255.0f);
row[offset + 1] = static_cast<unsigned char> (h_g.ptr ()[pos] * 255.0f);
row[offset + 2] = static_cast<unsigned char> (h_r.ptr ()[pos] * 255.0f);
row[offset + 3] = 255;
}
row += image->widthStep;
}
return image;
}
static void PrintHelp ()
{
std::cout << "Usage help:\n";
std::cout << std::setiosflags(std::ios::left);
std::cout << "\t" << std::setw(15) << PARAM_ALPHA << " - set alpha\n";
std::cout << "\t" << std::setw(15) << PARAM_GAMMA << " - set gamma\n";
std::cout << "\t" << std::setw(15) << PARAM_INNER << " - set number of inner iterations\n";
std::cout << "\t" << std::setw(15) << PARAM_LEFT << " - specify left image\n";
std::cout << "\t" << std::setw(15) << PARAM_RIGHT << " - specify right image\n";
std::cout << "\t" << std::setw(15) << PARAM_OUTER << " - set number of outer iterations\n";
std::cout << "\t" << std::setw(15) << PARAM_SCALE << " - set pyramid scale factor\n";
std::cout << "\t" << std::setw(15) << PARAM_SOLVER << " - set number of basic solver iterations\n";
std::cout << "\t" << std::setw(15) << PARAM_TIME_STEP << " - set frame interpolation time step\n";
std::cout << "\t" << std::setw(15) << PARAM_HELP << " - display this help message\n";
}
static int ProcessCommandLine(int argc, char **argv,
Ncv32f &timeStep,
char *&frame0Name,
char *&frame1Name,
NCVBroxOpticalFlowDescriptor &desc)
{
timeStep = 0.25f;
for (int iarg = 1; iarg < argc; ++iarg)
{
if (strcmp(argv[iarg], PARAM_LEFT) == 0)
{
if (iarg + 1 < argc)
{
frame0Name = argv[++iarg];
}
else
return -1;
}
if (strcmp(argv[iarg], PARAM_RIGHT) == 0)
{
if (iarg + 1 < argc)
{
frame1Name = argv[++iarg];
}
else
return -1;
}
else if(strcmp(argv[iarg], PARAM_SCALE) == 0)
{
if (iarg + 1 < argc)
desc.scale_factor = static_cast<Ncv32f>(atof(argv[++iarg]));
else
return -1;
}
else if(strcmp(argv[iarg], PARAM_ALPHA) == 0)
{
if (iarg + 1 < argc)
desc.alpha = static_cast<Ncv32f>(atof(argv[++iarg]));
else
return -1;
}
else if(strcmp(argv[iarg], PARAM_GAMMA) == 0)
{
if (iarg + 1 < argc)
desc.gamma = static_cast<Ncv32f>(atof(argv[++iarg]));
else
return -1;
}
else if(strcmp(argv[iarg], PARAM_INNER) == 0)
{
if (iarg + 1 < argc)
desc.number_of_inner_iterations = static_cast<Ncv32u>(atoi(argv[++iarg]));
else
return -1;
}
else if(strcmp(argv[iarg], PARAM_OUTER) == 0)
{
if (iarg + 1 < argc)
desc.number_of_outer_iterations = static_cast<Ncv32u>(atoi(argv[++iarg]));
else
return -1;
}
else if(strcmp(argv[iarg], PARAM_SOLVER) == 0)
{
if (iarg + 1 < argc)
desc.number_of_solver_iterations = static_cast<Ncv32u>(atoi(argv[++iarg]));
else
return -1;
}
else if(strcmp(argv[iarg], PARAM_TIME_STEP) == 0)
{
if (iarg + 1 < argc)
timeStep = static_cast<Ncv32f>(atof(argv[++iarg]));
else
return -1;
}
else if(strcmp(argv[iarg], PARAM_HELP) == 0)
{
PrintHelp ();
return 0;
}
}
return 0;
}
int main(int argc, char **argv)
{
char *frame0Name = 0, *frame1Name = 0;
Ncv32f timeStep = 0.01f;
NCVBroxOpticalFlowDescriptor desc;
desc.alpha = 0.197f;
desc.gamma = 50.0f;
desc.number_of_inner_iterations = 10;
desc.number_of_outer_iterations = 77;
desc.number_of_solver_iterations = 10;
desc.scale_factor = 0.8f;
int result = ProcessCommandLine (argc, argv, timeStep, frame0Name, frame1Name, desc);
if (argc == 1 || result)
{
PrintHelp();
return result;
}
cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());
std::cout << "OpenCV / NVIDIA Computer Vision\n";
std::cout << "Optical Flow Demo: Frame Interpolation\n";
std::cout << "=========================================\n";
std::cout << "Press:\n ESC to quit\n 'a' to move to the previous frame\n 's' to move to the next frame\n";
int devId;
ncvAssertCUDAReturn(cudaGetDevice(&devId), -1);
cudaDeviceProp devProp;
ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), -1);
std::cout << "Using GPU: " << devId << "(" << devProp.name <<
"), arch=" << devProp.major << "." << devProp.minor << std::endl;
g_pGPUMemAllocator = Ptr<INCVMemAllocator> (new NCVMemNativeAllocator (NCVMemoryTypeDevice, static_cast<Ncv32u>(devProp.textureAlignment)));
ncvAssertPrintReturn (g_pGPUMemAllocator->isInitialized (), "Device memory allocator isn't initialized", -1);
g_pHostMemAllocator = Ptr<INCVMemAllocator> (new NCVMemNativeAllocator (NCVMemoryTypeHostPageable, static_cast<Ncv32u>(devProp.textureAlignment)));
ncvAssertPrintReturn (g_pHostMemAllocator->isInitialized (), "Host memory allocator isn't initialized", -1);
int width, height;
Ptr<NCVMatrixAlloc<Ncv32f> > src_host;
Ptr<NCVMatrixAlloc<Ncv32f> > dst_host;
IplImage *firstFrame, *lastFrame;
if (frame0Name != 0 && frame1Name != 0)
{
ncvAssertReturnNcvStat (LoadImages (frame0Name, frame1Name, width, height, src_host, dst_host, firstFrame, lastFrame));
}
else
{
ncvAssertReturnNcvStat (LoadImages ("frame10.bmp", "frame11.bmp", width, height, src_host, dst_host, firstFrame, lastFrame));
}
Ptr<NCVMatrixAlloc<Ncv32f> > src (new NCVMatrixAlloc<Ncv32f> (*g_pGPUMemAllocator, src_host->width (), src_host->height ()));
ncvAssertReturn(src->isMemAllocated(), -1);
Ptr<NCVMatrixAlloc<Ncv32f> > dst (new NCVMatrixAlloc<Ncv32f> (*g_pGPUMemAllocator, src_host->width (), src_host->height ()));
ncvAssertReturn (dst->isMemAllocated (), -1);
ncvAssertReturnNcvStat (src_host->copySolid ( *src, 0 ));
ncvAssertReturnNcvStat (dst_host->copySolid ( *dst, 0 ));
#if defined SAFE_MAT_DECL
#undef SAFE_MAT_DECL
#endif
#define SAFE_MAT_DECL(name, allocator, sx, sy) \
NCVMatrixAlloc<Ncv32f> name(*allocator, sx, sy);\
ncvAssertReturn(name.isMemAllocated(), -1);
SAFE_MAT_DECL (u, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (v, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (uBck, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (vBck, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (h_r, g_pHostMemAllocator, width, height);
SAFE_MAT_DECL (h_g, g_pHostMemAllocator, width, height);
SAFE_MAT_DECL (h_b, g_pHostMemAllocator, width, height);
std::cout << "Estimating optical flow\nForward...\n";
if (NCV_SUCCESS != NCVBroxOpticalFlow (desc, *g_pGPUMemAllocator, *src, *dst, u, v, 0))
{
std::cout << "Failed\n";
return -1;
}
std::cout << "Backward...\n";
if (NCV_SUCCESS != NCVBroxOpticalFlow (desc, *g_pGPUMemAllocator, *dst, *src, uBck, vBck, 0))
{
std::cout << "Failed\n";
return -1;
}
// matrix for temporary data
SAFE_MAT_DECL (d_temp, g_pGPUMemAllocator, width, height);
// first frame color components (GPU memory)
SAFE_MAT_DECL (d_r, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (d_g, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (d_b, g_pGPUMemAllocator, width, height);
// second frame color components (GPU memory)
SAFE_MAT_DECL (d_rt, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (d_gt, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (d_bt, g_pGPUMemAllocator, width, height);
// intermediate frame color components (GPU memory)
SAFE_MAT_DECL (d_rNew, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (d_gNew, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (d_bNew, g_pGPUMemAllocator, width, height);
// interpolated forward flow
SAFE_MAT_DECL (ui, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (vi, g_pGPUMemAllocator, width, height);
// interpolated backward flow
SAFE_MAT_DECL (ubi, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (vbi, g_pGPUMemAllocator, width, height);
// occlusion masks
SAFE_MAT_DECL (occ0, g_pGPUMemAllocator, width, height);
SAFE_MAT_DECL (occ1, g_pGPUMemAllocator, width, height);
// prepare color components on host and copy them to device memory
ncvAssertReturnNcvStat (CopyData<RgbToR> (firstFrame, h_r));
ncvAssertReturnNcvStat (CopyData<RgbToG> (firstFrame, h_g));
ncvAssertReturnNcvStat (CopyData<RgbToB> (firstFrame, h_b));
ncvAssertReturnNcvStat (h_r.copySolid ( d_r, 0 ));
ncvAssertReturnNcvStat (h_g.copySolid ( d_g, 0 ));
ncvAssertReturnNcvStat (h_b.copySolid ( d_b, 0 ));
ncvAssertReturnNcvStat (CopyData<RgbToR> (lastFrame, h_r));
ncvAssertReturnNcvStat (CopyData<RgbToG> (lastFrame, h_g));
ncvAssertReturnNcvStat (CopyData<RgbToB> (lastFrame, h_b));
ncvAssertReturnNcvStat (h_r.copySolid ( d_rt, 0 ));
ncvAssertReturnNcvStat (h_g.copySolid ( d_gt, 0 ));
ncvAssertReturnNcvStat (h_b.copySolid ( d_bt, 0 ));
std::cout << "Interpolating...\n";
std::cout.precision (4);
std::vector<IplImage*> frames;
frames.push_back (firstFrame);
// compute interpolated frames
for (Ncv32f timePos = timeStep; timePos < 1.0f; timePos += timeStep)
{
ncvAssertCUDAReturn (cudaMemset (ui.ptr (), 0, ui.pitch () * ui.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (vi.ptr (), 0, vi.pitch () * vi.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (ubi.ptr (), 0, ubi.pitch () * ubi.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (vbi.ptr (), 0, vbi.pitch () * vbi.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (occ0.ptr (), 0, occ0.pitch () * occ0.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (occ1.ptr (), 0, occ1.pitch () * occ1.height ()), NCV_CUDA_ERROR);
NppStInterpolationState state;
// interpolation state should be filled once except pSrcFrame0, pSrcFrame1, and pNewFrame
// we will only need to reset buffers content to 0 since interpolator doesn't do this itself
state.size = NcvSize32u (width, height);
state.nStep = d_r.pitch ();
state.pSrcFrame0 = d_r.ptr ();
state.pSrcFrame1 = d_rt.ptr ();
state.pFU = u.ptr ();
state.pFV = v.ptr ();
state.pBU = uBck.ptr ();
state.pBV = vBck.ptr ();
state.pos = timePos;
state.pNewFrame = d_rNew.ptr ();
state.ppBuffers[0] = occ0.ptr ();
state.ppBuffers[1] = occ1.ptr ();
state.ppBuffers[2] = ui.ptr ();
state.ppBuffers[3] = vi.ptr ();
state.ppBuffers[4] = ubi.ptr ();
state.ppBuffers[5] = vbi.ptr ();
// interpolate red channel
nppiStInterpolateFrames (&state);
// reset buffers
ncvAssertCUDAReturn (cudaMemset (ui.ptr (), 0, ui.pitch () * ui.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (vi.ptr (), 0, vi.pitch () * vi.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (ubi.ptr (), 0, ubi.pitch () * ubi.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (vbi.ptr (), 0, vbi.pitch () * vbi.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (occ0.ptr (), 0, occ0.pitch () * occ0.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (occ1.ptr (), 0, occ1.pitch () * occ1.height ()), NCV_CUDA_ERROR);
// interpolate green channel
state.pSrcFrame0 = d_g.ptr ();
state.pSrcFrame1 = d_gt.ptr ();
state.pNewFrame = d_gNew.ptr ();
nppiStInterpolateFrames (&state);
// reset buffers
ncvAssertCUDAReturn (cudaMemset (ui.ptr (), 0, ui.pitch () * ui.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (vi.ptr (), 0, vi.pitch () * vi.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (ubi.ptr (), 0, ubi.pitch () * ubi.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (vbi.ptr (), 0, vbi.pitch () * vbi.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (occ0.ptr (), 0, occ0.pitch () * occ0.height ()), NCV_CUDA_ERROR);
ncvAssertCUDAReturn (cudaMemset (occ1.ptr (), 0, occ1.pitch () * occ1.height ()), NCV_CUDA_ERROR);
// interpolate blue channel
state.pSrcFrame0 = d_b.ptr ();
state.pSrcFrame1 = d_bt.ptr ();
state.pNewFrame = d_bNew.ptr ();
nppiStInterpolateFrames (&state);
// copy to host memory
ncvAssertReturnNcvStat (d_rNew.copySolid (h_r, 0));
ncvAssertReturnNcvStat (d_gNew.copySolid (h_g, 0));
ncvAssertReturnNcvStat (d_bNew.copySolid (h_b, 0));
// convert to IplImage
IplImage *newFrame = CreateImage (h_r, h_g, h_b);
if (newFrame == 0)
{
std::cout << "Could not create new frame in host memory\n";
break;
}
frames.push_back (newFrame);
std::cout << timePos * 100.0f << "%\r";
}
std::cout << std::setw (5) << "100%\n";
frames.push_back (lastFrame);
Ncv32u currentFrame;
currentFrame = 0;
ShowFlow (u, v, "Forward flow");
ShowFlow (uBck, vBck, "Backward flow");
cvShowImage ("Interpolated frame", frames[currentFrame]);
bool qPressed = false;
while ( !qPressed )
{
int key = toupper (cvWaitKey (10));
switch (key)
{
case 27:
qPressed = true;
break;
case 'A':
if (currentFrame > 0) --currentFrame;
cvShowImage ("Interpolated frame", frames[currentFrame]);
break;
case 'S':
if (currentFrame < frames.size()-1) ++currentFrame;
cvShowImage ("Interpolated frame", frames[currentFrame]);
break;
}
}
cvDestroyAllWindows ();
std::vector<IplImage*>::iterator iter;
for (iter = frames.begin (); iter != frames.end (); ++iter)
{
cvReleaseImage (&(*iter));
}
return 0;
}
#endif
Loading…
Cancel
Save