mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
commit
2c6f1ab57d
@ -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:
|
||||
# ----------------------------------------------------------------------------
|
||||
|
51
cmake/OpenCVGenSetupVars.cmake
Normal file
51
cmake/OpenCVGenSetupVars.cmake
Normal file
@ -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()
|
||||
|
20
cmake/templates/setup_vars_linux.sh.in
Normal file
20
cmake/templates/setup_vars_linux.sh.in
Normal file
@ -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
|
20
cmake/templates/setup_vars_macosx.sh.in
Normal file
20
cmake/templates/setup_vars_macosx.sh.in
Normal file
@ -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
|
18
cmake/templates/setup_vars_win32.cmd.in
Normal file
18
cmake/templates/setup_vars_win32.cmd.in
Normal file
@ -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;
|
||||
|
||||
if((dist1 > dist2 && patternSize.height > patternSize.width) || (dist1 < dist2 && patternSize.height < patternSize.width))
|
||||
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++;
|
||||
}
|
||||
|
||||
// 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> ¢ers);
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
|
1235
modules/imgproc/src/median_blur.cpp
Normal file
1235
modules/imgproc/src/median_blur.cpp
Normal file
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…
Reference in New Issue
Block a user