mirror of
https://github.com/opencv/opencv.git
synced 2026-07-25 13:23:02 +04:00
Compare commits
85 Commits
4.5.3-openvino
...
4.5.3
| Author | SHA1 | Date | |
|---|---|---|---|
| ad6e82942b | |||
| d60bb57d4b | |||
| f9d62fba7a | |||
| 85dde8a800 | |||
| 9d039c206b | |||
| cbff19ff1a | |||
| 4c3f9b2ef4 | |||
| 167bac23aa | |||
| 5d0cfa2527 | |||
| 0e523618a1 | |||
| 821fae0d94 | |||
| 3b26105f68 | |||
| 0f2f966a91 | |||
| d7d491d445 | |||
| 41effbe2da | |||
| 9b0d6862c4 | |||
| 890fcdf842 | |||
| 18dbac203f | |||
| 8d1f254dcc | |||
| e5841d3126 | |||
| 90df3af6cf | |||
| 11cc36d770 | |||
| 05f1939b02 | |||
| 050ea9762f | |||
| 0f24d4d2a1 | |||
| fc799191f4 | |||
| 8fad85edda | |||
| d70053aba5 | |||
| b699fe7a9d | |||
| 94c67faaea | |||
| b2ed5c3070 | |||
| 9fe49497bb | |||
| 5b8c10f2f8 | |||
| 24983f62e2 | |||
| f2057ce1ab | |||
| 6797fd65a5 | |||
| bf489feef1 | |||
| 947e06a860 | |||
| 6a3d925a47 | |||
| 04d5ba266f | |||
| 90be83ae99 | |||
| 5e80bd3cc9 | |||
| fb7ef76e74 | |||
| db4b1e613c | |||
| ee39081b11 | |||
| 7d842f5bcf | |||
| 4eac198270 | |||
| faac32418c | |||
| 42810621df | |||
| 61a5378aeb | |||
| 42d644ef91 | |||
| c95a56450d | |||
| dc5199feea | |||
| f88fdf6a1b | |||
| b68057d927 | |||
| e9a860d9cb | |||
| 8be86cbdfd | |||
| 5091e64a42 | |||
| 828304d587 | |||
| 9d584475f6 | |||
| bb60cb0bf9 | |||
| 25f908b320 | |||
| 9b7dca2fa1 | |||
| 55e1dfb778 | |||
| 735a79ae83 | |||
| ef2b400c61 | |||
| c2263db7bc | |||
| 53eca2ff5b | |||
| 7bbbda71df | |||
| 9557b9f70f | |||
| 464441d8c3 | |||
| f30f1afd47 | |||
| b3db37b99d | |||
| 7a276f39fb | |||
| 415668ecf0 | |||
| 651967b95c | |||
| 8e0baf257c | |||
| c8268e65fd | |||
| 3cf4375387 | |||
| 438e2dc228 | |||
| c1adbe3189 | |||
| 7ee1816612 | |||
| b4084491e5 | |||
| 8f4f834ce6 | |||
| 411fd2b761 |
@@ -1,6 +1,6 @@
|
||||
/*************************************************
|
||||
USAGE:
|
||||
./model_diagnostics -m <onnx file location>
|
||||
./model_diagnostics -m <model file location>
|
||||
**************************************************/
|
||||
#include <opencv2/dnn.hpp>
|
||||
#include <opencv2/core/utils/filesystem.hpp>
|
||||
@@ -32,7 +32,7 @@ static std::string checkFileExists(const std::string& fileName)
|
||||
}
|
||||
|
||||
std::string diagnosticKeys =
|
||||
"{ model m | | Path to the model .onnx file. }"
|
||||
"{ model m | | Path to the model file. }"
|
||||
"{ config c | | Path to the model configuration file. }"
|
||||
"{ framework f | | [Optional] Name of the model framework. }";
|
||||
|
||||
@@ -41,7 +41,7 @@ std::string diagnosticKeys =
|
||||
int main( int argc, const char** argv )
|
||||
{
|
||||
CommandLineParser argParser(argc, argv, diagnosticKeys);
|
||||
argParser.about("Use this tool to run the diagnostics of provided ONNX model"
|
||||
argParser.about("Use this tool to run the diagnostics of provided ONNX/TF model"
|
||||
"to obtain the information about its support (supported layers).");
|
||||
|
||||
if (argc == 1)
|
||||
|
||||
@@ -179,7 +179,13 @@ if(CV_GCC OR CV_CLANG)
|
||||
endif()
|
||||
|
||||
# We need pthread's
|
||||
if(UNIX AND NOT ANDROID AND NOT (APPLE AND CV_CLANG)) # TODO
|
||||
if((UNIX
|
||||
AND NOT ANDROID
|
||||
AND NOT (APPLE AND CV_CLANG)
|
||||
AND NOT EMSCRIPTEN
|
||||
)
|
||||
OR (EMSCRIPTEN AND WITH_PTHREADS_PF) # https://github.com/opencv/opencv/issues/20285
|
||||
)
|
||||
add_extra_compiler_option(-pthread)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -9,9 +9,14 @@ set(HALIDE_ROOT_DIR "${HALIDE_ROOT_DIR}" CACHE PATH "Halide root directory")
|
||||
if(NOT HAVE_HALIDE)
|
||||
find_package(Halide QUIET) # Try CMake-based config files
|
||||
if(Halide_FOUND)
|
||||
set(HALIDE_INCLUDE_DIRS "${Halide_INCLUDE_DIRS}" CACHE PATH "Halide include directories" FORCE)
|
||||
set(HALIDE_LIBRARIES "${Halide_LIBRARIES}" CACHE PATH "Halide libraries" FORCE)
|
||||
set(HAVE_HALIDE TRUE)
|
||||
if(TARGET Halide::Halide) # modern Halide scripts defines imported target
|
||||
set(HALIDE_INCLUDE_DIRS "")
|
||||
set(HALIDE_LIBRARIES "Halide::Halide")
|
||||
set(HAVE_HALIDE TRUE)
|
||||
else()
|
||||
# using HALIDE_INCLUDE_DIRS / Halide_LIBRARIES
|
||||
set(HAVE_HALIDE TRUE)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -28,18 +33,15 @@ if(NOT HAVE_HALIDE AND HALIDE_ROOT_DIR)
|
||||
)
|
||||
if(HALIDE_LIBRARY AND HALIDE_INCLUDE_DIR)
|
||||
# TODO try_compile
|
||||
set(HALIDE_INCLUDE_DIRS "${HALIDE_INCLUDE_DIR}" CACHE PATH "Halide include directories" FORCE)
|
||||
set(HALIDE_LIBRARIES "${HALIDE_LIBRARY}" CACHE PATH "Halide libraries" FORCE)
|
||||
set(HALIDE_INCLUDE_DIRS "${HALIDE_INCLUDE_DIR}")
|
||||
set(HALIDE_LIBRARIES "${HALIDE_LIBRARY}")
|
||||
set(HAVE_HALIDE TRUE)
|
||||
endif()
|
||||
if(NOT HAVE_HALIDE)
|
||||
ocv_clear_vars(HALIDE_LIBRARIES HALIDE_INCLUDE_DIRS CACHE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(HAVE_HALIDE)
|
||||
include_directories(${HALIDE_INCLUDE_DIRS})
|
||||
if(HALIDE_INCLUDE_DIRS)
|
||||
include_directories(${HALIDE_INCLUDE_DIRS})
|
||||
endif()
|
||||
list(APPEND OPENCV_LINKER_LIBS ${HALIDE_LIBRARIES})
|
||||
else()
|
||||
ocv_clear_vars(HALIDE_INCLUDE_DIRS HALIDE_LIBRARIES)
|
||||
endif()
|
||||
|
||||
@@ -134,16 +134,21 @@ endif()
|
||||
# Add more features to the target
|
||||
|
||||
if(INF_ENGINE_TARGET)
|
||||
if(InferenceEngine_VERSION VERSION_GREATER_EQUAL "2021.4")
|
||||
math(EXPR INF_ENGINE_RELEASE "${InferenceEngine_VERSION_MAJOR} * 1000000 + ${InferenceEngine_VERSION_MINOR} * 10000 + ${InferenceEngine_VERSION_PATCH} * 100")
|
||||
if(DEFINED InferenceEngine_VERSION)
|
||||
message(STATUS "InferenceEngine: ${InferenceEngine_VERSION}")
|
||||
if(NOT INF_ENGINE_RELEASE AND NOT (InferenceEngine_VERSION VERSION_LESS "2021.4"))
|
||||
math(EXPR INF_ENGINE_RELEASE_INIT "${InferenceEngine_VERSION_MAJOR} * 1000000 + ${InferenceEngine_VERSION_MINOR} * 10000 + ${InferenceEngine_VERSION_PATCH} * 100")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT INF_ENGINE_RELEASE)
|
||||
message(WARNING "InferenceEngine version has not been set, 2021.3 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
|
||||
set(INF_ENGINE_RELEASE "2021030000")
|
||||
if(NOT INF_ENGINE_RELEASE AND NOT INF_ENGINE_RELEASE_INIT)
|
||||
message(WARNING "InferenceEngine version has not been set, 2021.4 will be used by default. Set INF_ENGINE_RELEASE variable if you experience build errors.")
|
||||
set(INF_ENGINE_RELEASE_INIT "2021040000")
|
||||
elseif(DEFINED INF_ENGINE_RELEASE)
|
||||
set(INF_ENGINE_RELEASE_INIT "${INF_ENGINE_RELEASE}")
|
||||
endif()
|
||||
set(INF_ENGINE_RELEASE "${INF_ENGINE_RELEASE}" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2020.1.0.2 -> 2020010002)")
|
||||
set(INF_ENGINE_RELEASE "${INF_ENGINE_RELEASE_INIT}" CACHE STRING "Force IE version, should be in form YYYYAABBCC (e.g. 2020.1.0.2 -> 2020010002)")
|
||||
set_target_properties(${INF_ENGINE_TARGET} PROPERTIES
|
||||
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
|
||||
INTERFACE_COMPILE_DEFINITIONS "HAVE_INF_ENGINE=1;INF_ENGINE_RELEASE=${INF_ENGINE_RELEASE}"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -2,15 +2,6 @@
|
||||
# Detect 3rd-party GUI libraries
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
#--- Win32 UI ---
|
||||
ocv_clear_vars(HAVE_WIN32UI)
|
||||
if(WITH_WIN32UI)
|
||||
try_compile(HAVE_WIN32UI
|
||||
"${OpenCV_BINARY_DIR}"
|
||||
"${OpenCV_SOURCE_DIR}/cmake/checks/win32uitest.cpp"
|
||||
CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=user32;gdi32")
|
||||
endif()
|
||||
|
||||
# --- QT4/5 ---
|
||||
ocv_clear_vars(HAVE_QT HAVE_QT5)
|
||||
if(WITH_QT)
|
||||
|
||||
@@ -121,9 +121,6 @@
|
||||
/* TIFF codec */
|
||||
#cmakedefine HAVE_TIFF
|
||||
|
||||
/* Win32 UI */
|
||||
#cmakedefine HAVE_WIN32UI
|
||||
|
||||
/* Define if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
#cmakedefine WORDS_BIGENDIAN
|
||||
|
||||
+1
-1
@@ -106,7 +106,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/* */legacy/* *_c.h @DOXYGEN_EXCLUDE_PATTERNS@
|
||||
EXCLUDE_SYMBOLS = cv::DataType<*> cv::traits::* int void CV__* T __CV*
|
||||
EXCLUDE_SYMBOLS = cv::DataType<*> cv::traits::* int void CV__* T __CV* cv::gapi::detail*
|
||||
EXAMPLE_PATH = @CMAKE_DOXYGEN_EXAMPLE_PATH@
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = YES
|
||||
|
||||
@@ -3924,7 +3924,7 @@ bool findChessboardCornersSB(cv::InputArray image_, cv::Size pattern_size,
|
||||
{
|
||||
meta_.create(int(board.rowCount()),int(board.colCount()),CV_8UC1);
|
||||
cv::Mat meta = meta_.getMat();
|
||||
meta = 0;
|
||||
meta.setTo(cv::Scalar::all(0));
|
||||
for(int row =0;row < meta.rows-1;++row)
|
||||
{
|
||||
for(int col=0;col< meta.cols-1;++col)
|
||||
|
||||
@@ -897,7 +897,7 @@ void CV_InitInverseRectificationMapTest::prepare_to_validation(int/* test_case_i
|
||||
Mat _new_cam0 = zero_new_cam ? test_mat[INPUT][0] : test_mat[INPUT][3];
|
||||
Mat _mapx(img_size, CV_32F), _mapy(img_size, CV_32F);
|
||||
|
||||
double a[9], d[5]={0,0,0,0,0}, R[9]={1, 0, 0, 0, 1, 0, 0, 0, 1}, a1[9];
|
||||
double a[9], d[5]={0., 0., 0., 0. , 0.}, R[9]={1., 0., 0., 0., 1., 0., 0., 0., 1.}, a1[9];
|
||||
Mat _a(3, 3, CV_64F, a), _a1(3, 3, CV_64F, a1);
|
||||
Mat _d(_d0.rows,_d0.cols, CV_MAKETYPE(CV_64F,_d0.channels()),d);
|
||||
Mat _R(3, 3, CV_64F, R);
|
||||
@@ -951,9 +951,9 @@ void CV_InitInverseRectificationMapTest::prepare_to_validation(int/* test_case_i
|
||||
// Undistort
|
||||
double x2 = x*x, y2 = y*y;
|
||||
double r2 = x2 + y2;
|
||||
double cdist = 1./(1 + (d[0] + (d[1] + d[4]*r2)*r2)*r2); // (1 + (d[5] + (d[6] + d[7]*r2)*r2)*r2) == 1 as d[5-7]=0;
|
||||
double x_ = x*cdist - d[2]*2*x*y + d[3]*(r2 + 2*x2);
|
||||
double y_ = y*cdist - d[3]*2*x*y + d[2]*(r2 + 2*y2);
|
||||
double cdist = 1./(1. + (d[0] + (d[1] + d[4]*r2)*r2)*r2); // (1. + (d[5] + (d[6] + d[7]*r2)*r2)*r2) == 1 as d[5-7]=0;
|
||||
double x_ = (x - (d[2]*2.*x*y + d[3]*(r2 + 2.*x2)))*cdist;
|
||||
double y_ = (y - (d[3]*2.*x*y + d[2]*(r2 + 2.*y2)))*cdist;
|
||||
|
||||
// Rectify
|
||||
double X = R[0]*x_ + R[1]*y_ + R[2];
|
||||
@@ -1807,4 +1807,78 @@ TEST(Calib3d_initUndistortRectifyMap, regression_14467)
|
||||
EXPECT_LE(cvtest::norm(dst, mesh_uv, NORM_INF), 1e-3);
|
||||
}
|
||||
|
||||
TEST(Calib3d_initInverseRectificationMap, regression_20165)
|
||||
{
|
||||
Size size_w_h(1280, 800);
|
||||
Mat dst(size_w_h, CV_32FC2); // Reference for validation
|
||||
Mat mapxy; // Output of initInverseRectificationMap()
|
||||
|
||||
// Camera Matrix
|
||||
double k[9]={
|
||||
1.5393951443032472e+03, 0., 6.7491727003047140e+02,
|
||||
0., 1.5400748240626747e+03, 5.1226968329123963e+02,
|
||||
0., 0., 1.
|
||||
};
|
||||
Mat _K(3, 3, CV_64F, k);
|
||||
|
||||
// Distortion
|
||||
// double d[5]={0,0,0,0,0}; // Zero Distortion
|
||||
double d[5]={ // Non-zero distortion
|
||||
-3.4134571357400023e-03, 2.9733267766101856e-03, // K1, K2
|
||||
3.6653586399031184e-03, -3.1960714017365702e-03, // P1, P2
|
||||
0. // K3
|
||||
};
|
||||
Mat _d(1, 5, CV_64F, d);
|
||||
|
||||
// Rotation
|
||||
//double R[9]={1., 0., 0., 0., 1., 0., 0., 0., 1.}; // Identity transform (none)
|
||||
double R[9]={ // Random transform
|
||||
9.6625486010428052e-01, 1.6055789378989216e-02, 2.5708706103628531e-01,
|
||||
-8.0300261706161002e-03, 9.9944797497929860e-01, -3.2237617614807819e-02,
|
||||
-2.5746274294459848e-01, 2.9085338870243265e-02, 9.6585039165403186e-01
|
||||
};
|
||||
Mat _R(3, 3, CV_64F, R);
|
||||
|
||||
// --- Validation --- //
|
||||
initInverseRectificationMap(_K, _d, _R, _K, size_w_h, CV_32FC2, mapxy, noArray());
|
||||
|
||||
// Copy camera matrix
|
||||
double fx, fy, cx, cy, ifx, ify, cxn, cyn;
|
||||
fx = k[0]; fy = k[4]; cx = k[2]; cy = k[5];
|
||||
|
||||
// Copy new camera matrix
|
||||
ifx = k[0]; ify = k[4]; cxn = k[2]; cyn = k[5];
|
||||
|
||||
// Distort Points
|
||||
for( int v = 0; v < size_w_h.height; v++ )
|
||||
{
|
||||
for( int u = 0; u < size_w_h.width; u++ )
|
||||
{
|
||||
// Convert from image to pin-hole coordinates
|
||||
double x = (u - cx)/fx;
|
||||
double y = (v - cy)/fy;
|
||||
|
||||
// Undistort
|
||||
double x2 = x*x, y2 = y*y;
|
||||
double r2 = x2 + y2;
|
||||
double cdist = 1./(1. + (d[0] + (d[1] + d[4]*r2)*r2)*r2); // (1. + (d[5] + (d[6] + d[7]*r2)*r2)*r2) == 1 as d[5-7]=0;
|
||||
double x_ = (x - (d[2]*2.*x*y + d[3]*(r2 + 2.*x2)))*cdist;
|
||||
double y_ = (y - (d[3]*2.*x*y + d[2]*(r2 + 2.*y2)))*cdist;
|
||||
|
||||
// Rectify
|
||||
double X = R[0]*x_ + R[1]*y_ + R[2];
|
||||
double Y = R[3]*x_ + R[4]*y_ + R[5];
|
||||
double Z = R[6]*x_ + R[7]*y_ + R[8];
|
||||
double x__ = X/Z;
|
||||
double y__ = Y/Z;
|
||||
|
||||
// Convert from pin-hole to image coordinates
|
||||
dst.at<Vec2f>(v, u) = Vec2f((float)(x__*ifx + cxn), (float)(y__*ify + cyn));
|
||||
}
|
||||
}
|
||||
|
||||
// Check Result
|
||||
EXPECT_LE(cvtest::norm(dst, mapxy, NORM_INF), 2e-1);
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -2451,7 +2451,8 @@ public:
|
||||
//! <0 - a diagonal from the lower half)
|
||||
UMat diag(int d=0) const;
|
||||
//! constructs a square diagonal matrix which main diagonal is vector "d"
|
||||
static UMat diag(const UMat& d);
|
||||
static UMat diag(const UMat& d, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
|
||||
static UMat diag(const UMat& d) { return diag(d, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
|
||||
|
||||
//! returns deep copy of the matrix, i.e. the data is copied
|
||||
UMat clone() const CV_NODISCARD;
|
||||
@@ -2485,14 +2486,22 @@ public:
|
||||
double dot(InputArray m) const;
|
||||
|
||||
//! Matlab-style matrix initialization
|
||||
static UMat zeros(int rows, int cols, int type);
|
||||
static UMat zeros(Size size, int type);
|
||||
static UMat zeros(int ndims, const int* sz, int type);
|
||||
static UMat ones(int rows, int cols, int type);
|
||||
static UMat ones(Size size, int type);
|
||||
static UMat ones(int ndims, const int* sz, int type);
|
||||
static UMat eye(int rows, int cols, int type);
|
||||
static UMat eye(Size size, int type);
|
||||
static UMat zeros(int rows, int cols, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
|
||||
static UMat zeros(Size size, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
|
||||
static UMat zeros(int ndims, const int* sz, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
|
||||
static UMat zeros(int rows, int cols, int type) { return zeros(rows, cols, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
|
||||
static UMat zeros(Size size, int type) { return zeros(size, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
|
||||
static UMat zeros(int ndims, const int* sz, int type) { return zeros(ndims, sz, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
|
||||
static UMat ones(int rows, int cols, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
|
||||
static UMat ones(Size size, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
|
||||
static UMat ones(int ndims, const int* sz, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
|
||||
static UMat ones(int rows, int cols, int type) { return ones(rows, cols, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
|
||||
static UMat ones(Size size, int type) { return ones(size, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
|
||||
static UMat ones(int ndims, const int* sz, int type) { return ones(ndims, sz, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
|
||||
static UMat eye(int rows, int cols, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
|
||||
static UMat eye(Size size, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
|
||||
static UMat eye(int rows, int cols, int type) { return eye(rows, cols, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
|
||||
static UMat eye(Size size, int type) { return eye(size, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
|
||||
|
||||
//! allocates new matrix data unless the matrix already has specified size and type.
|
||||
// previous data is unreferenced if needed.
|
||||
|
||||
@@ -144,6 +144,10 @@ static void dumpOpenCLInformation()
|
||||
DUMP_MESSAGE_STDOUT(" Double support = " << doubleSupportStr);
|
||||
DUMP_CONFIG_PROPERTY("cv_ocl_current_haveDoubleSupport", device.doubleFPConfig() > 0);
|
||||
|
||||
const char* halfSupportStr = device.halfFPConfig() > 0 ? "Yes" : "No";
|
||||
DUMP_MESSAGE_STDOUT(" Half support = " << halfSupportStr);
|
||||
DUMP_CONFIG_PROPERTY("cv_ocl_current_haveHalfSupport", device.halfFPConfig() > 0);
|
||||
|
||||
const char* isUnifiedMemoryStr = device.hostUnifiedMemory() ? "Yes" : "No";
|
||||
DUMP_MESSAGE_STDOUT(" Host unified memory = " << isUnifiedMemoryStr);
|
||||
DUMP_CONFIG_PROPERTY("cv_ocl_current_hostUnifiedMemory", device.hostUnifiedMemory());
|
||||
@@ -191,6 +195,9 @@ static void dumpOpenCLInformation()
|
||||
|
||||
DUMP_MESSAGE_STDOUT(" Preferred vector width double = " << device.preferredVectorWidthDouble());
|
||||
DUMP_CONFIG_PROPERTY("cv_ocl_current_preferredVectorWidthDouble", device.preferredVectorWidthDouble());
|
||||
|
||||
DUMP_MESSAGE_STDOUT(" Preferred vector width half = " << device.preferredVectorWidthHalf());
|
||||
DUMP_CONFIG_PROPERTY("cv_ocl_current_preferredVectorWidthHalf", device.preferredVectorWidthHalf());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1
|
||||
# elif defined(__APPLE__)
|
||||
# include <TargetConditionals.h>
|
||||
# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (!defined(TARGET_OS_OSX) && !TARGET_OS_IPHONE)
|
||||
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1 // OSX only
|
||||
# if (defined(TARGET_OS_OSX) && TARGET_OS_OSX) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
|
||||
# define OPENCV_HAVE_FILESYSTEM_SUPPORT 1 // OSX, iOS only
|
||||
# endif
|
||||
# else
|
||||
/* unknown */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#define CV_VERSION_MAJOR 4
|
||||
#define CV_VERSION_MINOR 5
|
||||
#define CV_VERSION_REVISION 3
|
||||
#define CV_VERSION_STATUS "-pre"
|
||||
#define CV_VERSION_STATUS ""
|
||||
|
||||
#define CVAUX_STR_EXP(__A) #__A
|
||||
#define CVAUX_STR(__A) CVAUX_STR_EXP(__A)
|
||||
|
||||
@@ -3,6 +3,16 @@ package org.opencv.core
|
||||
import org.opencv.core.Mat.*
|
||||
import java.lang.RuntimeException
|
||||
|
||||
fun Mat.get(row: Int, col: Int, data: UByteArray) = this.get(row, col, data.asByteArray())
|
||||
fun Mat.get(indices: IntArray, data: UByteArray) = this.get(indices, data.asByteArray())
|
||||
fun Mat.put(row: Int, col: Int, data: UByteArray) = this.put(row, col, data.asByteArray())
|
||||
fun Mat.put(indices: IntArray, data: UByteArray) = this.put(indices, data.asByteArray())
|
||||
|
||||
fun Mat.get(row: Int, col: Int, data: UShortArray) = this.get(row, col, data.asShortArray())
|
||||
fun Mat.get(indices: IntArray, data: UShortArray) = this.get(indices, data.asShortArray())
|
||||
fun Mat.put(row: Int, col: Int, data: UShortArray) = this.put(row, col, data.asShortArray())
|
||||
fun Mat.put(indices: IntArray, data: UShortArray) = this.put(indices, data.asShortArray())
|
||||
|
||||
/***
|
||||
* Example use:
|
||||
*
|
||||
@@ -19,6 +29,7 @@ inline fun <reified T> Mat.at(row: Int, col: Int) : Atable<T> =
|
||||
col
|
||||
)
|
||||
UByte::class -> AtableUByte(this, row, col) as Atable<T>
|
||||
UShort::class -> AtableUShort(this, row, col) as Atable<T>
|
||||
else -> throw RuntimeException("Unsupported class type")
|
||||
}
|
||||
|
||||
@@ -30,6 +41,7 @@ inline fun <reified T> Mat.at(idx: IntArray) : Atable<T> =
|
||||
idx
|
||||
)
|
||||
UByte::class -> AtableUByte(this, idx) as Atable<T>
|
||||
UShort::class -> AtableUShort(this, idx) as Atable<T>
|
||||
else -> throw RuntimeException("Unsupported class type")
|
||||
}
|
||||
|
||||
@@ -38,46 +50,95 @@ class AtableUByte(val mat: Mat, val indices: IntArray): Atable<UByte> {
|
||||
constructor(mat: Mat, row: Int, col: Int) : this(mat, intArrayOf(row, col))
|
||||
|
||||
override fun getV(): UByte {
|
||||
val data = ByteArray(1)
|
||||
mat[indices, data]
|
||||
return data[0].toUByte()
|
||||
val data = UByteArray(1)
|
||||
mat.get(indices, data)
|
||||
return data[0]
|
||||
}
|
||||
|
||||
override fun setV(v: UByte) {
|
||||
val data = byteArrayOf(v.toByte())
|
||||
val data = ubyteArrayOf(v)
|
||||
mat.put(indices, data)
|
||||
}
|
||||
|
||||
override fun getV2c(): Tuple2<UByte> {
|
||||
val data = ByteArray(2)
|
||||
mat[indices, data]
|
||||
return Tuple2(data[0].toUByte(), data[1].toUByte())
|
||||
val data = UByteArray(2)
|
||||
mat.get(indices, data)
|
||||
return Tuple2(data[0], data[1])
|
||||
}
|
||||
|
||||
override fun setV2c(v: Tuple2<UByte>) {
|
||||
val data = byteArrayOf(v._0.toByte(), v._1.toByte())
|
||||
val data = ubyteArrayOf(v._0, v._1)
|
||||
mat.put(indices, data)
|
||||
}
|
||||
|
||||
override fun getV3c(): Tuple3<UByte> {
|
||||
val data = ByteArray(3)
|
||||
mat[indices, data]
|
||||
return Tuple3(data[0].toUByte(), data[1].toUByte(), data[2].toUByte())
|
||||
val data = UByteArray(3)
|
||||
mat.get(indices, data)
|
||||
return Tuple3(data[0], data[1], data[2])
|
||||
}
|
||||
|
||||
override fun setV3c(v: Tuple3<UByte>) {
|
||||
val data = byteArrayOf(v._0.toByte(), v._1.toByte(), v._2.toByte())
|
||||
val data = ubyteArrayOf(v._0, v._1, v._2)
|
||||
mat.put(indices, data)
|
||||
}
|
||||
|
||||
override fun getV4c(): Tuple4<UByte> {
|
||||
val data = ByteArray(4)
|
||||
mat[indices, data]
|
||||
return Tuple4(data[0].toUByte(), data[1].toUByte(), data[2].toUByte(), data[3].toUByte())
|
||||
val data = UByteArray(4)
|
||||
mat.get(indices, data)
|
||||
return Tuple4(data[0], data[1], data[2], data[3])
|
||||
}
|
||||
|
||||
override fun setV4c(v: Tuple4<UByte>) {
|
||||
val data = byteArrayOf(v._0.toByte(), v._1.toByte(), v._2.toByte(), v._3.toByte())
|
||||
val data = ubyteArrayOf(v._0, v._1, v._2, v._3)
|
||||
mat.put(indices, data)
|
||||
}
|
||||
}
|
||||
|
||||
class AtableUShort(val mat: Mat, val indices: IntArray): Atable<UShort> {
|
||||
|
||||
constructor(mat: Mat, row: Int, col: Int) : this(mat, intArrayOf(row, col))
|
||||
|
||||
override fun getV(): UShort {
|
||||
val data = UShortArray(1)
|
||||
mat.get(indices, data)
|
||||
return data[0]
|
||||
}
|
||||
|
||||
override fun setV(v: UShort) {
|
||||
val data = ushortArrayOf(v)
|
||||
mat.put(indices, data)
|
||||
}
|
||||
|
||||
override fun getV2c(): Tuple2<UShort> {
|
||||
val data = UShortArray(2)
|
||||
mat.get(indices, data)
|
||||
return Tuple2(data[0], data[1])
|
||||
}
|
||||
|
||||
override fun setV2c(v: Tuple2<UShort>) {
|
||||
val data = ushortArrayOf(v._0, v._1)
|
||||
mat.put(indices, data)
|
||||
}
|
||||
|
||||
override fun getV3c(): Tuple3<UShort> {
|
||||
val data = UShortArray(3)
|
||||
mat.get(indices, data)
|
||||
return Tuple3(data[0], data[1], data[2])
|
||||
}
|
||||
|
||||
override fun setV3c(v: Tuple3<UShort>) {
|
||||
val data = ushortArrayOf(v._0, v._1, v._2)
|
||||
mat.put(indices, data)
|
||||
}
|
||||
|
||||
override fun getV4c(): Tuple4<UShort> {
|
||||
val data = UShortArray(4)
|
||||
mat.get(indices, data)
|
||||
return Tuple4(data[0], data[1], data[2], data[3])
|
||||
}
|
||||
|
||||
override fun setV4c(v: Tuple4<UShort>) {
|
||||
val data = ushortArrayOf(v._0, v._1, v._2, v._3)
|
||||
mat.put(indices, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,7 +548,7 @@ template<typename T> void putData(uchar* dataDest, int count, T (^readData)(int)
|
||||
if (depth == CV_8U) {
|
||||
putData(dest, count, ^uchar (int index) { return cv::saturate_cast<uchar>(data[offset + index].doubleValue);} );
|
||||
} else if (depth == CV_8S) {
|
||||
putData(dest, count, ^char (int index) { return cv::saturate_cast<char>(data[offset + index].doubleValue);} );
|
||||
putData(dest, count, ^schar (int index) { return cv::saturate_cast<schar>(data[offset + index].doubleValue);} );
|
||||
} else if (depth == CV_16U) {
|
||||
putData(dest, count, ^ushort (int index) { return cv::saturate_cast<ushort>(data[offset + index].doubleValue);} );
|
||||
} else if (depth == CV_16S) {
|
||||
|
||||
@@ -62,6 +62,21 @@ public extension Mat {
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func get(indices:[Int32], data:inout [UInt8]) throws -> Int32 {
|
||||
let channels = CvType.channels(Int32(type()))
|
||||
if Int32(data.count) % channels != 0 {
|
||||
try throwIncompatibleBufferSize(count: data.count, channels: channels)
|
||||
} else if depth() != CvType.CV_8U {
|
||||
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
|
||||
}
|
||||
let count = Int32(data.count)
|
||||
return data.withUnsafeMutableBufferPointer { body in
|
||||
body.withMemoryRebound(to: Int8.self) { reboundBody in
|
||||
return __get(indices as [NSNumber], count: count, byteBuffer: reboundBody.baseAddress!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func get(indices:[Int32], data:inout [Double]) throws -> Int32 {
|
||||
let channels = CvType.channels(Int32(type()))
|
||||
if Int32(data.count) % channels != 0 {
|
||||
@@ -114,10 +129,29 @@ public extension Mat {
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func get(indices:[Int32], data:inout [UInt16]) throws -> Int32 {
|
||||
let channels = CvType.channels(Int32(type()))
|
||||
if Int32(data.count) % channels != 0 {
|
||||
try throwIncompatibleBufferSize(count: data.count, channels: channels)
|
||||
} else if depth() != CvType.CV_16U {
|
||||
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
|
||||
}
|
||||
let count = Int32(data.count)
|
||||
return data.withUnsafeMutableBufferPointer { body in
|
||||
body.withMemoryRebound(to: Int16.self) { reboundBody in
|
||||
return __get(indices as [NSNumber], count: count, shortBuffer: reboundBody.baseAddress!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func get(row: Int32, col: Int32, data:inout [Int8]) throws -> Int32 {
|
||||
return try get(indices: [row, col], data: &data)
|
||||
}
|
||||
|
||||
@discardableResult func get(row: Int32, col: Int32, data:inout [UInt8]) throws -> Int32 {
|
||||
return try get(indices: [row, col], data: &data)
|
||||
}
|
||||
|
||||
@discardableResult func get(row: Int32, col: Int32, data:inout [Double]) throws -> Int32 {
|
||||
return try get(indices: [row, col], data: &data)
|
||||
}
|
||||
@@ -134,6 +168,10 @@ public extension Mat {
|
||||
return try get(indices: [row, col], data: &data)
|
||||
}
|
||||
|
||||
@discardableResult func get(row: Int32, col: Int32, data:inout [UInt16]) throws -> Int32 {
|
||||
return try get(indices: [row, col], data: &data)
|
||||
}
|
||||
|
||||
@discardableResult func put(indices:[Int32], data:[Int8]) throws -> Int32 {
|
||||
let channels = CvType.channels(Int32(type()))
|
||||
if Int32(data.count) % channels != 0 {
|
||||
@@ -147,6 +185,21 @@ public extension Mat {
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func put(indices:[Int32], data:[UInt8]) throws -> Int32 {
|
||||
let channels = CvType.channels(Int32(type()))
|
||||
if Int32(data.count) % channels != 0 {
|
||||
try throwIncompatibleBufferSize(count: data.count, channels: channels)
|
||||
} else if depth() != CvType.CV_8U {
|
||||
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
|
||||
}
|
||||
let count = Int32(data.count)
|
||||
return data.withUnsafeBufferPointer { body in
|
||||
body.withMemoryRebound(to: Int8.self) { reboundBody in
|
||||
return __put(indices as [NSNumber], count: count, byteBuffer: reboundBody.baseAddress!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func put(indices:[Int32], data:[Int8], offset: Int, length: Int32) throws -> Int32 {
|
||||
let channels = CvType.channels(Int32(type()))
|
||||
if Int32(data.count) % channels != 0 {
|
||||
@@ -214,10 +267,29 @@ public extension Mat {
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func put(indices:[Int32], data:[UInt16]) throws -> Int32 {
|
||||
let channels = CvType.channels(Int32(type()))
|
||||
if Int32(data.count) % channels != 0 {
|
||||
try throwIncompatibleBufferSize(count: data.count, channels: channels)
|
||||
} else if depth() != CvType.CV_16U {
|
||||
try throwIncompatibleDataType(typeName: CvType.type(toString: type()))
|
||||
}
|
||||
let count = Int32(data.count)
|
||||
return data.withUnsafeBufferPointer { body in
|
||||
body.withMemoryRebound(to: Int16.self) { reboundBody in
|
||||
return __put(indices as [NSNumber], count: count, shortBuffer: reboundBody.baseAddress!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@discardableResult func put(row: Int32, col: Int32, data:[Int8]) throws -> Int32 {
|
||||
return try put(indices: [row, col], data: data)
|
||||
}
|
||||
|
||||
@discardableResult func put(row: Int32, col: Int32, data:[UInt8]) throws -> Int32 {
|
||||
return try put(indices: [row, col], data: data)
|
||||
}
|
||||
|
||||
@discardableResult func put(row: Int32, col: Int32, data: [Int8], offset: Int, length: Int32) throws -> Int32 {
|
||||
return try put(indices: [row, col], data: data, offset: offset, length: length)
|
||||
}
|
||||
@@ -238,6 +310,10 @@ public extension Mat {
|
||||
return try put(indices: [row, col], data: data)
|
||||
}
|
||||
|
||||
@discardableResult func put(row: Int32, col: Int32, data: [UInt16]) throws -> Int32 {
|
||||
return try put(indices: [row, col], data: data)
|
||||
}
|
||||
|
||||
@discardableResult func get(row: Int32, col: Int32) -> [Double] {
|
||||
return get(indices: [row, col])
|
||||
}
|
||||
@@ -303,46 +379,46 @@ public class MatAt<N: Atable> {
|
||||
|
||||
extension UInt8: Atable {
|
||||
public static func getAt(m: Mat, indices:[Int32]) -> UInt8 {
|
||||
var tmp = [Int8](repeating: 0, count: 1)
|
||||
var tmp = [UInt8](repeating: 0, count: 1)
|
||||
try! m.get(indices: indices, data: &tmp)
|
||||
return UInt8(bitPattern: tmp[0])
|
||||
return tmp[0]
|
||||
}
|
||||
|
||||
public static func putAt(m: Mat, indices: [Int32], v: UInt8) {
|
||||
let tmp = [Int8(bitPattern: v)]
|
||||
let tmp = [v]
|
||||
try! m.put(indices: indices, data: tmp)
|
||||
}
|
||||
|
||||
public static func getAt2c(m: Mat, indices:[Int32]) -> (UInt8, UInt8) {
|
||||
var tmp = [Int8](repeating: 0, count: 2)
|
||||
var tmp = [UInt8](repeating: 0, count: 2)
|
||||
try! m.get(indices: indices, data: &tmp)
|
||||
return (UInt8(bitPattern: tmp[0]), UInt8(bitPattern: tmp[1]))
|
||||
return (tmp[0], tmp[1])
|
||||
}
|
||||
|
||||
public static func putAt2c(m: Mat, indices: [Int32], v: (UInt8, UInt8)) {
|
||||
let tmp = [Int8(bitPattern: v.0), Int8(bitPattern: v.1)]
|
||||
let tmp = [v.0, v.1]
|
||||
try! m.put(indices: indices, data: tmp)
|
||||
}
|
||||
|
||||
public static func getAt3c(m: Mat, indices:[Int32]) -> (UInt8, UInt8, UInt8) {
|
||||
var tmp = [Int8](repeating: 0, count: 3)
|
||||
var tmp = [UInt8](repeating: 0, count: 3)
|
||||
try! m.get(indices: indices, data: &tmp)
|
||||
return (UInt8(bitPattern: tmp[0]), UInt8(bitPattern: tmp[1]), UInt8(bitPattern: tmp[2]))
|
||||
return (tmp[0], tmp[1], tmp[2])
|
||||
}
|
||||
|
||||
public static func putAt3c(m: Mat, indices: [Int32], v: (UInt8, UInt8, UInt8)) {
|
||||
let tmp = [Int8(bitPattern: v.0), Int8(bitPattern: v.1), Int8(bitPattern: v.2)]
|
||||
let tmp = [v.0, v.1, v.2]
|
||||
try! m.put(indices: indices, data: tmp)
|
||||
}
|
||||
|
||||
public static func getAt4c(m: Mat, indices:[Int32]) -> (UInt8, UInt8, UInt8, UInt8) {
|
||||
var tmp = [Int8](repeating: 0, count: 4)
|
||||
var tmp = [UInt8](repeating: 0, count: 4)
|
||||
try! m.get(indices: indices, data: &tmp)
|
||||
return (UInt8(bitPattern: tmp[0]), UInt8(bitPattern: tmp[1]), UInt8(bitPattern: tmp[2]), UInt8(bitPattern: tmp[3]))
|
||||
return (tmp[0], tmp[1], tmp[2], tmp[3])
|
||||
}
|
||||
|
||||
public static func putAt4c(m: Mat, indices: [Int32], v: (UInt8, UInt8, UInt8, UInt8)) {
|
||||
let tmp = [Int8(bitPattern: v.0), Int8(bitPattern: v.1), Int8(bitPattern: v.2), Int8(bitPattern: v.3)]
|
||||
let tmp = [v.0, v.1, v.2, v.3]
|
||||
try! m.put(indices: indices, data: tmp)
|
||||
}
|
||||
}
|
||||
@@ -531,6 +607,52 @@ extension Int32: Atable {
|
||||
}
|
||||
}
|
||||
|
||||
extension UInt16: Atable {
|
||||
public static func getAt(m: Mat, indices:[Int32]) -> UInt16 {
|
||||
var tmp = [UInt16](repeating: 0, count: 1)
|
||||
try! m.get(indices: indices, data: &tmp)
|
||||
return tmp[0]
|
||||
}
|
||||
|
||||
public static func putAt(m: Mat, indices: [Int32], v: UInt16) {
|
||||
let tmp = [v]
|
||||
try! m.put(indices: indices, data: tmp)
|
||||
}
|
||||
|
||||
public static func getAt2c(m: Mat, indices:[Int32]) -> (UInt16, UInt16) {
|
||||
var tmp = [UInt16](repeating: 0, count: 2)
|
||||
try! m.get(indices: indices, data: &tmp)
|
||||
return (tmp[0], tmp[1])
|
||||
}
|
||||
|
||||
public static func putAt2c(m: Mat, indices: [Int32], v: (UInt16, UInt16)) {
|
||||
let tmp = [v.0, v.1]
|
||||
try! m.put(indices: indices, data: tmp)
|
||||
}
|
||||
|
||||
public static func getAt3c(m: Mat, indices:[Int32]) -> (UInt16, UInt16, UInt16) {
|
||||
var tmp = [UInt16](repeating: 0, count: 3)
|
||||
try! m.get(indices: indices, data: &tmp)
|
||||
return (tmp[0], tmp[1], tmp[2])
|
||||
}
|
||||
|
||||
public static func putAt3c(m: Mat, indices: [Int32], v: (UInt16, UInt16, UInt16)) {
|
||||
let tmp = [v.0, v.1, v.2]
|
||||
try! m.put(indices: indices, data: tmp)
|
||||
}
|
||||
|
||||
public static func getAt4c(m: Mat, indices:[Int32]) -> (UInt16, UInt16, UInt16, UInt16) {
|
||||
var tmp = [UInt16](repeating: 0, count: 4)
|
||||
try! m.get(indices: indices, data: &tmp)
|
||||
return (tmp[0], tmp[1], tmp[2], tmp[3])
|
||||
}
|
||||
|
||||
public static func putAt4c(m: Mat, indices: [Int32], v: (UInt16, UInt16, UInt16, UInt16)) {
|
||||
let tmp = [v.0, v.1, v.2, v.3]
|
||||
try! m.put(indices: indices, data: tmp)
|
||||
}
|
||||
}
|
||||
|
||||
extension Int16: Atable {
|
||||
public static func getAt(m: Mat, indices:[Int32]) -> Int16 {
|
||||
var tmp = [Int16](repeating: 0, count: 1)
|
||||
|
||||
@@ -308,15 +308,15 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssert([340] == sm.get(row: 1, col: 1))
|
||||
}
|
||||
|
||||
func testGetIntIntByteArray() throws {
|
||||
let m = try getTestMat(size: 5, type: CvType.CV_8UC3)
|
||||
func testGetIntIntInt8Array() throws {
|
||||
let m = try getTestMat(size: 5, type: CvType.CV_8SC3)
|
||||
var goodData = [Int8](repeating: 0, count: 9)
|
||||
|
||||
// whole Mat
|
||||
var bytesNum = try m.get(row: 1, col: 1, data: &goodData)
|
||||
|
||||
XCTAssertEqual(9, bytesNum)
|
||||
XCTAssert([110, 111, 112, 120, 121, 122, -126, -125, -124] == goodData)
|
||||
XCTAssert([110, 111, 112, 120, 121, 122, 127, 127, 127] == goodData)
|
||||
|
||||
var badData = [Int8](repeating: 0, count: 7)
|
||||
XCTAssertThrowsError(bytesNum = try m.get(row: 0, col: 0, data: &badData))
|
||||
@@ -326,11 +326,36 @@ class MatTests: OpenCVTestCase {
|
||||
var buff00 = [Int8](repeating: 0, count: 3)
|
||||
bytesNum = try sm.get(row: 0, col: 0, data: &buff00)
|
||||
XCTAssertEqual(3, bytesNum)
|
||||
XCTAssert(buff00 == [-26, -25, -24])
|
||||
XCTAssert(buff00 == [127, 127, 127])
|
||||
var buff11 = [Int8](repeating: 0, count: 3)
|
||||
bytesNum = try sm.get(row: 1, col: 1, data: &buff11)
|
||||
XCTAssertEqual(3, bytesNum)
|
||||
XCTAssert(buff11 == [-1, -1, -1])
|
||||
XCTAssert(buff11 == [127, 127, 127])
|
||||
}
|
||||
|
||||
func testGetIntIntUInt8Array() throws {
|
||||
let m = try getTestMat(size: 5, type: CvType.CV_8UC3)
|
||||
var goodData = [UInt8](repeating: 0, count: 9)
|
||||
|
||||
// whole Mat
|
||||
var bytesNum = try m.get(row: 1, col: 1, data: &goodData)
|
||||
|
||||
XCTAssertEqual(9, bytesNum)
|
||||
XCTAssert([110, 111, 112, 120, 121, 122, 130, 131, 132] == goodData)
|
||||
|
||||
var badData = [UInt8](repeating: 0, count: 7)
|
||||
XCTAssertThrowsError(bytesNum = try m.get(row: 0, col: 0, data: &badData))
|
||||
|
||||
// sub-Mat
|
||||
let sm = m.submat(rowStart: 2, rowEnd: 4, colStart: 3, colEnd: 5)
|
||||
var buff00 = [UInt8](repeating: 0, count: 3)
|
||||
bytesNum = try sm.get(row: 0, col: 0, data: &buff00)
|
||||
XCTAssertEqual(3, bytesNum)
|
||||
XCTAssert(buff00 == [230, 231, 232])
|
||||
var buff11 = [UInt8](repeating: 0, count: 3)
|
||||
bytesNum = try sm.get(row: 1, col: 1, data: &buff11)
|
||||
XCTAssertEqual(3, bytesNum)
|
||||
XCTAssert(buff11 == [255, 255, 255])
|
||||
}
|
||||
|
||||
func testGetIntIntDoubleArray() throws {
|
||||
@@ -399,7 +424,7 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssert(buff11 == [340, 341, 0, 0])
|
||||
}
|
||||
|
||||
func testGetIntIntShortArray() throws {
|
||||
func testGetIntIntInt16Array() throws {
|
||||
let m = try getTestMat(size: 5, type: CvType.CV_16SC2)
|
||||
var buff = [Int16](repeating: 0, count: 6)
|
||||
|
||||
@@ -421,6 +446,28 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssert(buff11 == [340, 341, 0, 0])
|
||||
}
|
||||
|
||||
func testGetIntIntUInt16Array() throws {
|
||||
let m = try getTestMat(size: 5, type: CvType.CV_16UC2)
|
||||
var buff = [UInt16](repeating: 0, count: 6)
|
||||
|
||||
// whole Mat
|
||||
var bytesNum = try m.get(row: 1, col: 1, data: &buff)
|
||||
|
||||
XCTAssertEqual(12, bytesNum);
|
||||
XCTAssert(buff == [110, 111, 120, 121, 130, 131])
|
||||
|
||||
// sub-Mat
|
||||
let sm = m.submat(rowStart: 2, rowEnd: 4, colStart: 3, colEnd: 5)
|
||||
var buff00 = [UInt16](repeating: 0, count: 4)
|
||||
bytesNum = try sm.get(row: 0, col: 0, data: &buff00)
|
||||
XCTAssertEqual(8, bytesNum)
|
||||
XCTAssert(buff00 == [230, 231, 240, 241])
|
||||
var buff11 = [UInt16](repeating: 0, count: 4)
|
||||
bytesNum = try sm.get(row: 1, col: 1, data: &buff11)
|
||||
XCTAssertEqual(4, bytesNum);
|
||||
XCTAssert(buff11 == [340, 341, 0, 0])
|
||||
}
|
||||
|
||||
func testHeight() {
|
||||
XCTAssertEqual(gray0.rows(), gray0.height())
|
||||
XCTAssertEqual(rgbLena.rows(), rgbLena.height())
|
||||
@@ -653,7 +700,7 @@ class MatTests: OpenCVTestCase {
|
||||
try assertMatEqual(truth!, m1, OpenCVTestCase.EPS)
|
||||
}
|
||||
|
||||
func testPutIntIntByteArray() throws {
|
||||
func testPutIntIntInt8Array() throws {
|
||||
let m = Mat(rows: 5, cols: 5, type: CvType.CV_8SC3, scalar: Scalar(1, 2, 3))
|
||||
let sm = m.submat(rowStart: 2, rowEnd: 4, colStart: 3, colEnd: 5)
|
||||
var buff = [Int8](repeating: 0, count: 6)
|
||||
@@ -683,7 +730,37 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssert(buff == buff0)
|
||||
}
|
||||
|
||||
func testPutIntArrayByteArray() throws {
|
||||
func testPutIntIntUInt8Array() throws {
|
||||
let m = Mat(rows: 5, cols: 5, type: CvType.CV_8UC3, scalar: Scalar(1, 2, 3))
|
||||
let sm = m.submat(rowStart: 2, rowEnd: 4, colStart: 3, colEnd: 5)
|
||||
var buff = [UInt8](repeating: 0, count: 6)
|
||||
let buff0:[UInt8] = [10, 20, 30, 40, 50, 60]
|
||||
let buff1:[UInt8] = [255, 254, 253, 252, 251, 250]
|
||||
|
||||
var bytesNum = try m.put(row:1, col:2, data:buff0)
|
||||
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
bytesNum = try m.get(row: 1, col: 2, data: &buff)
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
XCTAssert(buff == buff0)
|
||||
|
||||
bytesNum = try sm.put(row:0, col:0, data:buff1)
|
||||
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
bytesNum = try sm.get(row: 0, col: 0, data: &buff)
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
XCTAssert(buff == buff1)
|
||||
bytesNum = try m.get(row: 2, col: 3, data: &buff)
|
||||
XCTAssertEqual(6, bytesNum);
|
||||
XCTAssert(buff == buff1)
|
||||
|
||||
let m1 = m.row(1)
|
||||
bytesNum = try m1.get(row: 0, col: 2, data: &buff)
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
XCTAssert(buff == buff0)
|
||||
}
|
||||
|
||||
func testPutIntArrayInt8Array() throws {
|
||||
let m = Mat(sizes: [5, 5, 5], type: CvType.CV_8SC3, scalar: Scalar(1, 2, 3))
|
||||
let sm = m.submat(ranges: [Range(start: 0, end: 2), Range(start: 1, end: 3), Range(start: 2, end: 4)])
|
||||
var buff = [Int8](repeating: 0, count: 6)
|
||||
@@ -714,10 +791,41 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssert(buff == buff0)
|
||||
}
|
||||
|
||||
func testPutIntArrayUInt8Array() throws {
|
||||
let m = Mat(sizes: [5, 5, 5], type: CvType.CV_8UC3, scalar: Scalar(1, 2, 3))
|
||||
let sm = m.submat(ranges: [Range(start: 0, end: 2), Range(start: 1, end: 3), Range(start: 2, end: 4)])
|
||||
var buff = [UInt8](repeating: 0, count: 6)
|
||||
let buff0:[UInt8] = [10, 20, 30, 40, 50, 60]
|
||||
let buff1:[UInt8] = [255, 254, 253, 252, 251, 250]
|
||||
|
||||
var bytesNum = try m.put(indices:[1, 2, 0], data:buff0)
|
||||
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
bytesNum = try m.get(indices: [1, 2, 0], data: &buff)
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
XCTAssert(buff == buff0)
|
||||
|
||||
bytesNum = try sm.put(indices: [0, 0, 0], data: buff1)
|
||||
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
bytesNum = try sm.get(indices: [0, 0, 0], data: &buff)
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
XCTAssert(buff == buff1)
|
||||
|
||||
bytesNum = try m.get(indices: [0, 1, 2], data: &buff)
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
XCTAssert(buff == buff1)
|
||||
|
||||
let m1 = m.submat(ranges: [Range(start: 1,end: 2), Range.all(), Range.all()])
|
||||
bytesNum = try m1.get(indices: [0, 2, 0], data: &buff)
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
XCTAssert(buff == buff0)
|
||||
}
|
||||
|
||||
func testPutIntIntDoubleArray() throws {
|
||||
let m = Mat(rows: 5, cols: 5, type: CvType.CV_8SC3, scalar: Scalar(1, 2, 3))
|
||||
let m = Mat(rows: 5, cols: 5, type: CvType.CV_8UC3, scalar: Scalar(1, 2, 3))
|
||||
let sm = m.submat(rowStart: 2, rowEnd: 4, colStart: 3, colEnd: 5)
|
||||
var buff = [Int8](repeating: 0, count: 6)
|
||||
var buff = [UInt8](repeating: 0, count: 6)
|
||||
|
||||
var bytesNum = try m.put(row: 1, col: 2, data: [10, 20, 30, 40, 50, 60] as [Double])
|
||||
|
||||
@@ -731,16 +839,16 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
bytesNum = try sm.get(row: 0, col: 0, data: &buff)
|
||||
XCTAssertEqual(6, bytesNum);
|
||||
XCTAssert(buff == [-1, -2, -3, -4, -5, -6])
|
||||
XCTAssert(buff == [255, 254, 253, 252, 251, 250])
|
||||
bytesNum = try m.get(row: 2, col: 3, data: &buff)
|
||||
XCTAssertEqual(6, bytesNum);
|
||||
XCTAssert(buff == [-1, -2, -3, -4, -5, -6])
|
||||
XCTAssert(buff == [255, 254, 253, 252, 251, 250])
|
||||
}
|
||||
|
||||
func testPutIntArrayDoubleArray() throws {
|
||||
let m = Mat(sizes: [5, 5, 5], type: CvType.CV_8SC3, scalar: Scalar(1, 2, 3))
|
||||
let m = Mat(sizes: [5, 5, 5], type: CvType.CV_8UC3, scalar: Scalar(1, 2, 3))
|
||||
let sm = m.submat(ranges: [Range(start: 0, end: 2), Range(start: 1, end: 3), Range(start: 2, end: 4)])
|
||||
var buff = [Int8](repeating: 0, count: 6)
|
||||
var buff = [UInt8](repeating: 0, count: 6)
|
||||
|
||||
var bytesNum = try m.put(indices: [1, 2, 0], data: [10, 20, 30, 40, 50, 60] as [Double])
|
||||
|
||||
@@ -754,10 +862,10 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssertEqual(6, bytesNum);
|
||||
bytesNum = try sm.get(indices: [0, 0, 0], data: &buff)
|
||||
XCTAssertEqual(6, bytesNum);
|
||||
XCTAssert(buff == [-1, -2, -3, -4, -5, -6])
|
||||
XCTAssert(buff == [255, 254, 253, 252, 251, 250])
|
||||
bytesNum = try m.get(indices: [0, 1, 2], data: &buff)
|
||||
XCTAssertEqual(6, bytesNum)
|
||||
XCTAssert(buff == [-1, -2, -3, -4, -5, -6])
|
||||
XCTAssert(buff == [255, 254, 253, 252, 251, 250])
|
||||
}
|
||||
|
||||
func testPutIntIntFloatArray() throws {
|
||||
@@ -820,7 +928,7 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssert([40, 50, 60] == m.get(indices: [0, 1, 0]))
|
||||
}
|
||||
|
||||
func testPutIntIntShortArray() throws {
|
||||
func testPutIntIntInt16Array() throws {
|
||||
let m = Mat(rows: 5, cols: 5, type: CvType.CV_16SC3, scalar: Scalar(-1, -2, -3))
|
||||
let elements: [Int16] = [ 10, 20, 30, 40, 50, 60]
|
||||
|
||||
@@ -834,7 +942,21 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssert([40, 50, 60] == m.get(row: 2, col: 4))
|
||||
}
|
||||
|
||||
func testPutIntArrayShortArray() throws {
|
||||
func testPutIntIntUInt16Array() throws {
|
||||
let m = Mat(rows: 5, cols: 5, type: CvType.CV_16UC3, scalar: Scalar(-1, -2, -3))
|
||||
let elements: [UInt16] = [ 10, 20, 30, 40, 50, 60]
|
||||
|
||||
var bytesNum = try m.put(row: 2, col: 3, data: elements)
|
||||
|
||||
XCTAssertEqual(Int32(elements.count * 2), bytesNum)
|
||||
let m1 = m.col(3)
|
||||
var buff = [UInt16](repeating: 0, count: 3)
|
||||
bytesNum = try m1.get(row: 2, col: 0, data: &buff)
|
||||
XCTAssert(buff == [10, 20, 30])
|
||||
XCTAssert([40, 50, 60] == m.get(row: 2, col: 4))
|
||||
}
|
||||
|
||||
func testPutIntArrayInt16Array() throws {
|
||||
let m = Mat(sizes: [5, 5, 5], type: CvType.CV_16SC3, scalar: Scalar(-1, -2, -3))
|
||||
let elements: [Int16] = [ 10, 20, 30, 40, 50, 60]
|
||||
|
||||
@@ -848,6 +970,20 @@ class MatTests: OpenCVTestCase {
|
||||
XCTAssert([40, 50, 60] == m.get(indices: [0, 2, 4]))
|
||||
}
|
||||
|
||||
func testPutIntArrayUInt16Array() throws {
|
||||
let m = Mat(sizes: [5, 5, 5], type: CvType.CV_16UC3, scalar: Scalar(-1, -2, -3))
|
||||
let elements: [UInt16] = [ 10, 20, 30, 40, 50, 60]
|
||||
|
||||
var bytesNum = try m.put(indices: [0, 2, 3], data: elements)
|
||||
|
||||
XCTAssertEqual(Int32(elements.count * 2), bytesNum)
|
||||
let m1 = m.submat(ranges: [Range.all(), Range.all(), Range(start: 3, end: 4)])
|
||||
var buff = [UInt16](repeating: 0, count: 3)
|
||||
bytesNum = try m1.get(indices: [0, 2, 0], data: &buff)
|
||||
XCTAssert(buff == [10, 20, 30])
|
||||
XCTAssert([40, 50, 60] == m.get(indices: [0, 2, 4]))
|
||||
}
|
||||
|
||||
func testReshapeInt() throws {
|
||||
let src = Mat(rows: 4, cols: 4, type: CvType.CV_8U, scalar: Scalar(0))
|
||||
dst = src.reshape(channels: 4)
|
||||
|
||||
@@ -80,15 +80,15 @@ int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT)
|
||||
case DXGI_FORMAT_R32G32B32_UINT:
|
||||
case DXGI_FORMAT_R32G32B32_SINT: return CV_32SC3;
|
||||
//case DXGI_FORMAT_R16G16B16A16_TYPELESS:
|
||||
//case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT: return CV_16FC4;
|
||||
case DXGI_FORMAT_R16G16B16A16_UNORM:
|
||||
case DXGI_FORMAT_R16G16B16A16_UINT: return CV_16UC4;
|
||||
case DXGI_FORMAT_R16G16B16A16_SNORM:
|
||||
case DXGI_FORMAT_R16G16B16A16_SINT: return CV_16SC4;
|
||||
//case DXGI_FORMAT_R32G32_TYPELESS:
|
||||
//case DXGI_FORMAT_R32G32_FLOAT:
|
||||
//case DXGI_FORMAT_R32G32_UINT:
|
||||
//case DXGI_FORMAT_R32G32_SINT:
|
||||
case DXGI_FORMAT_R32G32_FLOAT: return CV_32FC2;
|
||||
case DXGI_FORMAT_R32G32_UINT:
|
||||
case DXGI_FORMAT_R32G32_SINT: return CV_32SC2;
|
||||
//case DXGI_FORMAT_R32G8X24_TYPELESS:
|
||||
//case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
|
||||
//case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
|
||||
@@ -104,13 +104,13 @@ int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT)
|
||||
case DXGI_FORMAT_R8G8B8A8_SNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_SINT: return CV_8SC4;
|
||||
//case DXGI_FORMAT_R16G16_TYPELESS:
|
||||
//case DXGI_FORMAT_R16G16_FLOAT:
|
||||
case DXGI_FORMAT_R16G16_FLOAT: return CV_16FC2;
|
||||
case DXGI_FORMAT_R16G16_UNORM:
|
||||
case DXGI_FORMAT_R16G16_UINT: return CV_16UC2;
|
||||
case DXGI_FORMAT_R16G16_SNORM:
|
||||
case DXGI_FORMAT_R16G16_SINT: return CV_16SC2;
|
||||
//case DXGI_FORMAT_R32_TYPELESS:
|
||||
//case DXGI_FORMAT_D32_FLOAT:
|
||||
case DXGI_FORMAT_D32_FLOAT:
|
||||
case DXGI_FORMAT_R32_FLOAT: return CV_32FC1;
|
||||
case DXGI_FORMAT_R32_UINT:
|
||||
case DXGI_FORMAT_R32_SINT: return CV_32SC1;
|
||||
@@ -124,7 +124,7 @@ int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT)
|
||||
case DXGI_FORMAT_R8G8_SNORM:
|
||||
case DXGI_FORMAT_R8G8_SINT: return CV_8SC2;
|
||||
//case DXGI_FORMAT_R16_TYPELESS:
|
||||
//case DXGI_FORMAT_R16_FLOAT:
|
||||
case DXGI_FORMAT_R16_FLOAT: return CV_16FC1;
|
||||
case DXGI_FORMAT_D16_UNORM:
|
||||
case DXGI_FORMAT_R16_UNORM:
|
||||
case DXGI_FORMAT_R16_UINT: return CV_16UC1;
|
||||
@@ -138,8 +138,8 @@ int getTypeFromDXGI_FORMAT(const int iDXGI_FORMAT)
|
||||
case DXGI_FORMAT_A8_UNORM: return CV_8UC1;
|
||||
//case DXGI_FORMAT_R1_UNORM:
|
||||
//case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
|
||||
//case DXGI_FORMAT_R8G8_B8G8_UNORM:
|
||||
//case DXGI_FORMAT_G8R8_G8B8_UNORM:
|
||||
case DXGI_FORMAT_R8G8_B8G8_UNORM:
|
||||
case DXGI_FORMAT_G8R8_G8B8_UNORM: return CV_8UC4;
|
||||
//case DXGI_FORMAT_BC1_TYPELESS:
|
||||
//case DXGI_FORMAT_BC1_UNORM:
|
||||
//case DXGI_FORMAT_BC1_UNORM_SRGB:
|
||||
|
||||
@@ -229,14 +229,14 @@ void cv::setIdentity( InputOutputArray _m, const Scalar& s )
|
||||
|
||||
namespace cv {
|
||||
|
||||
UMat UMat::eye(int rows, int cols, int type)
|
||||
UMat UMat::eye(int rows, int cols, int type, UMatUsageFlags usageFlags)
|
||||
{
|
||||
return UMat::eye(Size(cols, rows), type);
|
||||
return UMat::eye(Size(cols, rows), type, usageFlags);
|
||||
}
|
||||
|
||||
UMat UMat::eye(Size size, int type)
|
||||
UMat UMat::eye(Size size, int type, UMatUsageFlags usageFlags)
|
||||
{
|
||||
UMat m(size, type);
|
||||
UMat m(size, type, usageFlags);
|
||||
setIdentity(m);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -1194,7 +1194,7 @@ double norm( InputArray _src1, InputArray _src2, int normType, InputArray _mask
|
||||
// special case to handle "integer" overflow in accumulator
|
||||
const size_t esz = src1.elemSize();
|
||||
const int total = (int)it.size;
|
||||
const int intSumBlockSize = normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15);
|
||||
const int intSumBlockSize = (normType == NORM_L1 && depth <= CV_8S ? (1 << 23) : (1 << 15))/cn;
|
||||
const int blockSize = std::min(total, intSumBlockSize);
|
||||
int isum = 0;
|
||||
int count = 0;
|
||||
|
||||
+35
-10
@@ -1566,6 +1566,7 @@ struct Device::Impl
|
||||
version_ = getStrProp(CL_DEVICE_VERSION);
|
||||
extensions_ = getStrProp(CL_DEVICE_EXTENSIONS);
|
||||
doubleFPConfig_ = getProp<cl_device_fp_config, int>(CL_DEVICE_DOUBLE_FP_CONFIG);
|
||||
halfFPConfig_ = getProp<cl_device_fp_config, int>(CL_DEVICE_HALF_FP_CONFIG);
|
||||
hostUnifiedMemory_ = getBoolProp(CL_DEVICE_HOST_UNIFIED_MEMORY);
|
||||
maxComputeUnits_ = getProp<cl_uint, int>(CL_DEVICE_MAX_COMPUTE_UNITS);
|
||||
maxWorkGroupSize_ = getProp<size_t, size_t>(CL_DEVICE_MAX_WORK_GROUP_SIZE);
|
||||
@@ -1678,6 +1679,7 @@ struct Device::Impl
|
||||
String version_;
|
||||
std::string extensions_;
|
||||
int doubleFPConfig_;
|
||||
int halfFPConfig_;
|
||||
bool hostUnifiedMemory_;
|
||||
int maxComputeUnits_;
|
||||
size_t maxWorkGroupSize_;
|
||||
@@ -1827,11 +1829,7 @@ int Device::singleFPConfig() const
|
||||
{ return p ? p->getProp<cl_device_fp_config, int>(CL_DEVICE_SINGLE_FP_CONFIG) : 0; }
|
||||
|
||||
int Device::halfFPConfig() const
|
||||
#ifdef CL_VERSION_1_2
|
||||
{ return p ? p->getProp<cl_device_fp_config, int>(CL_DEVICE_HALF_FP_CONFIG) : 0; }
|
||||
#else
|
||||
{ CV_REQUIRE_OPENCL_1_2_ERROR; }
|
||||
#endif
|
||||
{ return p ? p->halfFPConfig_ : 0; }
|
||||
|
||||
bool Device::endianLittle() const
|
||||
{ return p ? p->getBoolProp(CL_DEVICE_ENDIAN_LITTLE) : false; }
|
||||
@@ -6668,6 +6666,10 @@ void convertFromImage(void* cl_mem_image, UMat& dst)
|
||||
depth = CV_32F;
|
||||
break;
|
||||
|
||||
case CL_HALF_FLOAT:
|
||||
depth = CV_16F;
|
||||
break;
|
||||
|
||||
default:
|
||||
CV_Error(cv::Error::OpenCLApiCallError, "Not supported image_channel_data_type");
|
||||
}
|
||||
@@ -6676,9 +6678,23 @@ void convertFromImage(void* cl_mem_image, UMat& dst)
|
||||
switch (fmt.image_channel_order)
|
||||
{
|
||||
case CL_R:
|
||||
case CL_A:
|
||||
case CL_INTENSITY:
|
||||
case CL_LUMINANCE:
|
||||
type = CV_MAKE_TYPE(depth, 1);
|
||||
break;
|
||||
|
||||
case CL_RG:
|
||||
case CL_RA:
|
||||
type = CV_MAKE_TYPE(depth, 2);
|
||||
break;
|
||||
|
||||
// CL_RGB has no mappings to OpenCV types because CL_RGB can only be used with
|
||||
// CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, or CL_UNORM_INT_101010.
|
||||
/*case CL_RGB:
|
||||
type = CV_MAKE_TYPE(depth, 3);
|
||||
break;*/
|
||||
|
||||
case CL_RGBA:
|
||||
case CL_BGRA:
|
||||
case CL_ARGB:
|
||||
@@ -7068,6 +7084,13 @@ static std::string kerToStr(const Mat & k)
|
||||
stream << "DIG(" << data[i] << "f)";
|
||||
stream << "DIG(" << data[width] << "f)";
|
||||
}
|
||||
else if (depth == CV_16F)
|
||||
{
|
||||
stream.setf(std::ios_base::showpoint);
|
||||
for (int i = 0; i < width; ++i)
|
||||
stream << "DIG(" << (float)data[i] << "h)";
|
||||
stream << "DIG(" << (float)data[width] << "h)";
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < width; ++i)
|
||||
@@ -7091,7 +7114,7 @@ String kernelToStr(InputArray _kernel, int ddepth, const char * name)
|
||||
|
||||
typedef std::string (* func_t)(const Mat &);
|
||||
static const func_t funcs[] = { kerToStr<uchar>, kerToStr<char>, kerToStr<ushort>, kerToStr<short>,
|
||||
kerToStr<int>, kerToStr<float>, kerToStr<double>, 0 };
|
||||
kerToStr<int>, kerToStr<float>, kerToStr<double>, kerToStr<float16_t> };
|
||||
const func_t func = funcs[ddepth];
|
||||
CV_Assert(func != 0);
|
||||
|
||||
@@ -7130,14 +7153,14 @@ int predictOptimalVectorWidth(InputArray src1, InputArray src2, InputArray src3,
|
||||
int vectorWidths[] = { d.preferredVectorWidthChar(), d.preferredVectorWidthChar(),
|
||||
d.preferredVectorWidthShort(), d.preferredVectorWidthShort(),
|
||||
d.preferredVectorWidthInt(), d.preferredVectorWidthFloat(),
|
||||
d.preferredVectorWidthDouble(), -1 };
|
||||
d.preferredVectorWidthDouble(), d.preferredVectorWidthHalf() };
|
||||
|
||||
// if the device says don't use vectors
|
||||
if (vectorWidths[0] == 1)
|
||||
{
|
||||
// it's heuristic
|
||||
vectorWidths[CV_8U] = vectorWidths[CV_8S] = 4;
|
||||
vectorWidths[CV_16U] = vectorWidths[CV_16S] = 2;
|
||||
vectorWidths[CV_16U] = vectorWidths[CV_16S] = vectorWidths[CV_16F] = 2;
|
||||
vectorWidths[CV_32S] = vectorWidths[CV_32F] = vectorWidths[CV_64F] = 1;
|
||||
}
|
||||
|
||||
@@ -7225,10 +7248,12 @@ struct Image2D::Impl
|
||||
{
|
||||
cl_image_format format;
|
||||
static const int channelTypes[] = { CL_UNSIGNED_INT8, CL_SIGNED_INT8, CL_UNSIGNED_INT16,
|
||||
CL_SIGNED_INT16, CL_SIGNED_INT32, CL_FLOAT, -1, -1 };
|
||||
CL_SIGNED_INT16, CL_SIGNED_INT32, CL_FLOAT, -1, CL_HALF_FLOAT };
|
||||
static const int channelTypesNorm[] = { CL_UNORM_INT8, CL_SNORM_INT8, CL_UNORM_INT16,
|
||||
CL_SNORM_INT16, -1, -1, -1, -1 };
|
||||
static const int channelOrders[] = { -1, CL_R, CL_RG, -1, CL_RGBA };
|
||||
// CL_RGB has no mappings to OpenCV types because CL_RGB can only be used with
|
||||
// CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, or CL_UNORM_INT_101010.
|
||||
static const int channelOrders[] = { -1, CL_R, CL_RG, /*CL_RGB*/ -1, CL_RGBA };
|
||||
|
||||
int channelType = norm ? channelTypesNorm[depth] : channelTypes[depth];
|
||||
int channelOrder = channelOrders[cn];
|
||||
|
||||
@@ -143,17 +143,17 @@ static const char symbols[9] = "ucwsifdh";
|
||||
static char typeSymbol(int depth)
|
||||
{
|
||||
CV_StaticAssert(CV_64F == 6, "");
|
||||
CV_Assert(depth >=0 && depth <= CV_64F);
|
||||
CV_CheckDepth(depth, depth >=0 && depth <= CV_16F, "");
|
||||
return symbols[depth];
|
||||
}
|
||||
|
||||
static int symbolToType(char c)
|
||||
{
|
||||
if (c == 'r')
|
||||
return CV_SEQ_ELTYPE_PTR;
|
||||
const char* pos = strchr( symbols, c );
|
||||
if( !pos )
|
||||
CV_Error( CV_StsBadArg, "Invalid data type specification" );
|
||||
if (c == 'r')
|
||||
return CV_SEQ_ELTYPE_PTR;
|
||||
return static_cast<int>(pos - symbols);
|
||||
}
|
||||
|
||||
@@ -245,8 +245,12 @@ int calcStructSize( const char* dt, int initial_size )
|
||||
{
|
||||
int size = calcElemSize( dt, initial_size );
|
||||
size_t elem_max_size = 0;
|
||||
for ( const char * type = dt; *type != '\0'; type++ ) {
|
||||
switch ( *type )
|
||||
for ( const char * type = dt; *type != '\0'; type++ )
|
||||
{
|
||||
char v = *type;
|
||||
if (v >= '0' && v <= '9')
|
||||
continue; // skip vector size
|
||||
switch (v)
|
||||
{
|
||||
case 'u': { elem_max_size = std::max( elem_max_size, sizeof(uchar ) ); break; }
|
||||
case 'c': { elem_max_size = std::max( elem_max_size, sizeof(schar ) ); break; }
|
||||
@@ -255,7 +259,9 @@ int calcStructSize( const char* dt, int initial_size )
|
||||
case 'i': { elem_max_size = std::max( elem_max_size, sizeof(int ) ); break; }
|
||||
case 'f': { elem_max_size = std::max( elem_max_size, sizeof(float ) ); break; }
|
||||
case 'd': { elem_max_size = std::max( elem_max_size, sizeof(double) ); break; }
|
||||
default: break;
|
||||
case 'h': { elem_max_size = std::max(elem_max_size, sizeof(float16_t)); break; }
|
||||
default:
|
||||
CV_Error_(Error::StsNotImplemented, ("Unknown type identifier: '%c' in '%s'", (char)(*type), dt));
|
||||
}
|
||||
}
|
||||
size = cvAlign( size, static_cast<int>(elem_max_size) );
|
||||
@@ -1054,6 +1060,7 @@ public:
|
||||
CV_Assert(write_mode);
|
||||
|
||||
size_t elemSize = fs::calcStructSize(dt.c_str(), 0);
|
||||
CV_Assert(elemSize);
|
||||
CV_Assert( len % elemSize == 0 );
|
||||
len /= elemSize;
|
||||
|
||||
|
||||
@@ -1835,7 +1835,15 @@ void* TLSDataContainer::getData() const
|
||||
{
|
||||
// Create new data instance and save it to TLS storage
|
||||
pData = createDataInstance();
|
||||
getTlsStorage().setData(key_, pData);
|
||||
try
|
||||
{
|
||||
getTlsStorage().setData(key_, pData);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
deleteDataInstance(pData);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return pData;
|
||||
}
|
||||
|
||||
@@ -951,11 +951,11 @@ UMat UMat::reshape(int new_cn, int new_rows) const
|
||||
return hdr;
|
||||
}
|
||||
|
||||
UMat UMat::diag(const UMat& d)
|
||||
UMat UMat::diag(const UMat& d, UMatUsageFlags usageFlags)
|
||||
{
|
||||
CV_Assert( d.cols == 1 || d.rows == 1 );
|
||||
int len = d.rows + d.cols - 1;
|
||||
UMat m(len, len, d.type(), Scalar(0));
|
||||
UMat m(len, len, d.type(), Scalar(0), usageFlags);
|
||||
UMat md = m.diag();
|
||||
if( d.cols == 1 )
|
||||
d.copyTo(md);
|
||||
@@ -1323,34 +1323,34 @@ UMat UMat::t() const
|
||||
return m;
|
||||
}
|
||||
|
||||
UMat UMat::zeros(int rows, int cols, int type)
|
||||
UMat UMat::zeros(int rows, int cols, int type, UMatUsageFlags usageFlags)
|
||||
{
|
||||
return UMat(rows, cols, type, Scalar::all(0));
|
||||
return UMat(rows, cols, type, Scalar::all(0), usageFlags);
|
||||
}
|
||||
|
||||
UMat UMat::zeros(Size size, int type)
|
||||
UMat UMat::zeros(Size size, int type, UMatUsageFlags usageFlags)
|
||||
{
|
||||
return UMat(size, type, Scalar::all(0));
|
||||
return UMat(size, type, Scalar::all(0), usageFlags);
|
||||
}
|
||||
|
||||
UMat UMat::zeros(int ndims, const int* sz, int type)
|
||||
UMat UMat::zeros(int ndims, const int* sz, int type, UMatUsageFlags usageFlags)
|
||||
{
|
||||
return UMat(ndims, sz, type, Scalar::all(0));
|
||||
return UMat(ndims, sz, type, Scalar::all(0), usageFlags);
|
||||
}
|
||||
|
||||
UMat UMat::ones(int rows, int cols, int type)
|
||||
UMat UMat::ones(int rows, int cols, int type, UMatUsageFlags usageFlags)
|
||||
{
|
||||
return UMat::ones(Size(cols, rows), type);
|
||||
return UMat(rows, cols, type, Scalar(1), usageFlags);
|
||||
}
|
||||
|
||||
UMat UMat::ones(Size size, int type)
|
||||
UMat UMat::ones(Size size, int type, UMatUsageFlags usageFlags)
|
||||
{
|
||||
return UMat(size, type, Scalar(1));
|
||||
return UMat(size, type, Scalar(1), usageFlags);
|
||||
}
|
||||
|
||||
UMat UMat::ones(int ndims, const int* sz, int type)
|
||||
UMat UMat::ones(int ndims, const int* sz, int type, UMatUsageFlags usageFlags)
|
||||
{
|
||||
return UMat(ndims, sz, type, Scalar(1));
|
||||
return UMat(ndims, sz, type, Scalar(1), usageFlags);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -76,6 +76,24 @@ OCL_TEST_P(UMatExpr, Ones)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////// with usageFlags /////////////////////////////////////////////////
|
||||
|
||||
OCL_TEST_P(UMatExpr, WithUsageFlags)
|
||||
{
|
||||
for (int j = 0; j < test_loop_times; j++)
|
||||
{
|
||||
generateTestData();
|
||||
|
||||
UMat u0 = UMat::zeros(size, type, cv::USAGE_ALLOCATE_HOST_MEMORY);
|
||||
UMat u1 = UMat::ones(size, type, cv::USAGE_ALLOCATE_HOST_MEMORY);
|
||||
UMat u8 = UMat::eye(size, type, cv::USAGE_ALLOCATE_HOST_MEMORY);
|
||||
|
||||
EXPECT_EQ(cv::USAGE_ALLOCATE_HOST_MEMORY, u0.usageFlags);
|
||||
EXPECT_EQ(cv::USAGE_ALLOCATE_HOST_MEMORY, u1.usageFlags);
|
||||
EXPECT_EQ(cv::USAGE_ALLOCATE_HOST_MEMORY, u8.usageFlags);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////// Instantiation /////////////////////////////////////////////////
|
||||
|
||||
OCL_INSTANTIATE_TEST_CASE_P(MatrixOperation, UMatExpr, Combine(OCL_ALL_DEPTHS_16F, OCL_ALL_CHANNELS));
|
||||
|
||||
@@ -2166,6 +2166,15 @@ TEST(Core_Norm, IPP_regression_NORM_L1_16UC3_small)
|
||||
EXPECT_EQ((double)20*cn, cv::norm(a, b, NORM_L1, mask));
|
||||
}
|
||||
|
||||
TEST(Core_Norm, NORM_L2_8UC4)
|
||||
{
|
||||
// Tests there is no integer overflow in norm computation for multiple channels.
|
||||
const int kSide = 100;
|
||||
cv::Mat4b a(kSide, kSide, cv::Scalar(255, 255, 255, 255));
|
||||
cv::Mat4b b = cv::Mat4b::zeros(kSide, kSide);
|
||||
const double kNorm = 2.*kSide*255.;
|
||||
EXPECT_EQ(kNorm, cv::norm(a, b, NORM_L2));
|
||||
}
|
||||
|
||||
TEST(Core_ConvertTo, regression_12121)
|
||||
{
|
||||
|
||||
@@ -1837,4 +1837,69 @@ TEST(Core_InputOutput, FileStorage_copy_constructor_17412_heap)
|
||||
EXPECT_EQ(0, remove(fname.c_str()));
|
||||
}
|
||||
|
||||
|
||||
static void test_20279(FileStorage& fs)
|
||||
{
|
||||
Mat m32fc1(5, 10, CV_32FC1, Scalar::all(0));
|
||||
for (size_t i = 0; i < m32fc1.total(); i++)
|
||||
{
|
||||
float v = (float)i;
|
||||
m32fc1.at<float>((int)i) = v * 0.5f;
|
||||
}
|
||||
Mat m16fc1;
|
||||
// produces CV_16S output: convertFp16(m32fc1, m16fc1);
|
||||
m32fc1.convertTo(m16fc1, CV_16FC1);
|
||||
EXPECT_EQ(CV_16FC1, m16fc1.type()) << typeToString(m16fc1.type());
|
||||
//std::cout << m16fc1 << std::endl;
|
||||
|
||||
Mat m32fc3(4, 3, CV_32FC3, Scalar::all(0));
|
||||
for (size_t i = 0; i < m32fc3.total(); i++)
|
||||
{
|
||||
float v = (float)i;
|
||||
m32fc3.at<Vec3f>((int)i) = Vec3f(v, v * 0.2f, -v);
|
||||
}
|
||||
Mat m16fc3;
|
||||
m32fc3.convertTo(m16fc3, CV_16FC3);
|
||||
EXPECT_EQ(CV_16FC3, m16fc3.type()) << typeToString(m16fc3.type());
|
||||
//std::cout << m16fc3 << std::endl;
|
||||
|
||||
fs << "m16fc1" << m16fc1;
|
||||
fs << "m16fc3" << m16fc3;
|
||||
|
||||
string content = fs.releaseAndGetString();
|
||||
if (cvtest::debugLevel > 0) std::cout << content << std::endl;
|
||||
|
||||
FileStorage fs_read(content, FileStorage::READ + FileStorage::MEMORY);
|
||||
Mat m16fc1_result;
|
||||
Mat m16fc3_result;
|
||||
fs_read["m16fc1"] >> m16fc1_result;
|
||||
ASSERT_FALSE(m16fc1_result.empty());
|
||||
EXPECT_EQ(CV_16FC1, m16fc1_result.type()) << typeToString(m16fc1_result.type());
|
||||
EXPECT_LE(cvtest::norm(m16fc1_result, m16fc1, NORM_INF), 1e-2);
|
||||
|
||||
fs_read["m16fc3"] >> m16fc3_result;
|
||||
ASSERT_FALSE(m16fc3_result.empty());
|
||||
EXPECT_EQ(CV_16FC3, m16fc3_result.type()) << typeToString(m16fc3_result.type());
|
||||
EXPECT_LE(cvtest::norm(m16fc3_result, m16fc3, NORM_INF), 1e-2);
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput, FileStorage_16F_xml)
|
||||
{
|
||||
FileStorage fs("test.xml", cv::FileStorage::WRITE | cv::FileStorage::MEMORY);
|
||||
test_20279(fs);
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput, FileStorage_16F_yml)
|
||||
{
|
||||
FileStorage fs("test.yml", cv::FileStorage::WRITE | cv::FileStorage::MEMORY);
|
||||
test_20279(fs);
|
||||
}
|
||||
|
||||
TEST(Core_InputOutput, FileStorage_16F_json)
|
||||
{
|
||||
FileStorage fs("test.json", cv::FileStorage::WRITE | cv::FileStorage::MEMORY);
|
||||
test_20279(fs);
|
||||
}
|
||||
|
||||
|
||||
}} // namespace
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
]
|
||||
|
||||
],
|
||||
"jni_name": "(*(cv::dnn::DictValue*)%(n)s_nativeObj)",
|
||||
"jni_name": "(*(*(Ptr<cv::dnn::DictValue>*)%(n)s_nativeObj))",
|
||||
"jni_type": "jlong",
|
||||
"suffix": "J",
|
||||
"j_import": "org.opencv.dnn.DictValue"
|
||||
|
||||
@@ -657,7 +657,11 @@ void InfEngineNgraphNet::initPlugin(InferenceEngine::CNNNetwork& net)
|
||||
try
|
||||
{
|
||||
InferenceEngine::IExtensionPtr extension =
|
||||
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4)
|
||||
std::make_shared<InferenceEngine::Extension>(libName);
|
||||
#else
|
||||
InferenceEngine::make_so_pointer<InferenceEngine::IExtension>(libName);
|
||||
#endif
|
||||
|
||||
ie.AddExtension(extension, "CPU");
|
||||
CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << libName);
|
||||
@@ -1005,35 +1009,54 @@ void InfEngineNgraphNet::forward(const std::vector<Ptr<BackendWrapper> >& outBlo
|
||||
reqWrapper->req.SetInput(inpBlobs);
|
||||
reqWrapper->req.SetOutput(outBlobs);
|
||||
|
||||
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4)
|
||||
InferenceEngine::InferRequest infRequest = reqWrapper->req;
|
||||
NgraphReqWrapper* wrapperPtr = reqWrapper.get();
|
||||
CV_Assert(wrapperPtr && "Internal error");
|
||||
#else
|
||||
InferenceEngine::IInferRequest::Ptr infRequestPtr = reqWrapper->req;
|
||||
infRequestPtr->SetUserData(reqWrapper.get(), 0);
|
||||
CV_Assert(infRequestPtr);
|
||||
InferenceEngine::IInferRequest& infRequest = *infRequestPtr.get();
|
||||
infRequest.SetUserData(reqWrapper.get(), 0);
|
||||
#endif
|
||||
|
||||
infRequestPtr->SetCompletionCallback(
|
||||
[](InferenceEngine::IInferRequest::Ptr request, InferenceEngine::StatusCode status)
|
||||
#if INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4)
|
||||
// do NOT capture 'reqWrapper' (smart ptr) in the lambda callback
|
||||
infRequest.SetCompletionCallback<std::function<void(InferenceEngine::InferRequest, InferenceEngine::StatusCode)>>(
|
||||
[wrapperPtr](InferenceEngine::InferRequest /*request*/, InferenceEngine::StatusCode status)
|
||||
#else
|
||||
infRequest.SetCompletionCallback(
|
||||
[](InferenceEngine::IInferRequest::Ptr requestPtr, InferenceEngine::StatusCode status)
|
||||
#endif
|
||||
{
|
||||
CV_LOG_DEBUG(NULL, "DNN(nGraph): completionCallback(" << (int)status << ")");
|
||||
#if !INF_ENGINE_VER_MAJOR_GE(INF_ENGINE_RELEASE_2021_4)
|
||||
CV_Assert(requestPtr);
|
||||
InferenceEngine::IInferRequest& request = *requestPtr.get();
|
||||
|
||||
NgraphReqWrapper* wrapper;
|
||||
request->GetUserData((void**)&wrapper, 0);
|
||||
CV_Assert(wrapper && "Internal error");
|
||||
NgraphReqWrapper* wrapperPtr;
|
||||
request.GetUserData((void**)&wrapperPtr, 0);
|
||||
CV_Assert(wrapperPtr && "Internal error");
|
||||
#endif
|
||||
NgraphReqWrapper& wrapper = *wrapperPtr;
|
||||
|
||||
size_t processedOutputs = 0;
|
||||
try
|
||||
{
|
||||
for (; processedOutputs < wrapper->outProms.size(); ++processedOutputs)
|
||||
for (; processedOutputs < wrapper.outProms.size(); ++processedOutputs)
|
||||
{
|
||||
const std::string& name = wrapper->outsNames[processedOutputs];
|
||||
Mat m = ngraphBlobToMat(wrapper->req.GetBlob(name));
|
||||
const std::string& name = wrapper.outsNames[processedOutputs];
|
||||
Mat m = ngraphBlobToMat(wrapper.req.GetBlob(name));
|
||||
|
||||
try
|
||||
{
|
||||
CV_Assert(status == InferenceEngine::StatusCode::OK);
|
||||
wrapper->outProms[processedOutputs].setValue(m.clone());
|
||||
wrapper.outProms[processedOutputs].setValue(m.clone());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
try {
|
||||
wrapper->outProms[processedOutputs].setException(std::current_exception());
|
||||
wrapper.outProms[processedOutputs].setException(std::current_exception());
|
||||
} catch(...) {
|
||||
CV_LOG_ERROR(NULL, "DNN: Exception occurred during async inference exception propagation");
|
||||
}
|
||||
@@ -1043,16 +1066,16 @@ void InfEngineNgraphNet::forward(const std::vector<Ptr<BackendWrapper> >& outBlo
|
||||
catch (...)
|
||||
{
|
||||
std::exception_ptr e = std::current_exception();
|
||||
for (; processedOutputs < wrapper->outProms.size(); ++processedOutputs)
|
||||
for (; processedOutputs < wrapper.outProms.size(); ++processedOutputs)
|
||||
{
|
||||
try {
|
||||
wrapper->outProms[processedOutputs].setException(e);
|
||||
wrapper.outProms[processedOutputs].setException(e);
|
||||
} catch(...) {
|
||||
CV_LOG_ERROR(NULL, "DNN: Exception occurred during async inference exception propagation");
|
||||
}
|
||||
}
|
||||
}
|
||||
wrapper->isReady = true;
|
||||
wrapper.isReady = true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace dnn
|
||||
class BatchNormLayerImpl CV_FINAL : public BatchNormLayer
|
||||
{
|
||||
public:
|
||||
Mat origin_weights, origin_bias;
|
||||
Mat weights_, bias_;
|
||||
UMat umat_weight, umat_bias;
|
||||
mutable int dims;
|
||||
@@ -88,11 +89,11 @@ public:
|
||||
const float* weightsData = hasWeights ? blobs[weightsBlobIndex].ptr<float>() : 0;
|
||||
const float* biasData = hasBias ? blobs[biasBlobIndex].ptr<float>() : 0;
|
||||
|
||||
weights_.create(1, (int)n, CV_32F);
|
||||
bias_.create(1, (int)n, CV_32F);
|
||||
origin_weights.create(1, (int)n, CV_32F);
|
||||
origin_bias.create(1, (int)n, CV_32F);
|
||||
|
||||
float* dstWeightsData = weights_.ptr<float>();
|
||||
float* dstBiasData = bias_.ptr<float>();
|
||||
float* dstWeightsData = origin_weights.ptr<float>();
|
||||
float* dstBiasData = origin_bias.ptr<float>();
|
||||
|
||||
for (size_t i = 0; i < n; ++i)
|
||||
{
|
||||
@@ -100,15 +101,12 @@ public:
|
||||
dstWeightsData[i] = w;
|
||||
dstBiasData[i] = (hasBias ? biasData[i] : 0.0f) - w * meanData[i] * varMeanScale;
|
||||
}
|
||||
// We will use blobs to store origin weights and bias to restore them in case of reinitialization.
|
||||
weights_.copyTo(blobs[0].reshape(1, 1));
|
||||
bias_.copyTo(blobs[1].reshape(1, 1));
|
||||
}
|
||||
|
||||
virtual void finalize(InputArrayOfArrays, OutputArrayOfArrays) CV_OVERRIDE
|
||||
{
|
||||
blobs[0].reshape(1, 1).copyTo(weights_);
|
||||
blobs[1].reshape(1, 1).copyTo(bias_);
|
||||
origin_weights.reshape(1, 1).copyTo(weights_);
|
||||
origin_bias.reshape(1, 1).copyTo(bias_);
|
||||
}
|
||||
|
||||
void getScaleShift(Mat& scale, Mat& shift) const CV_OVERRIDE
|
||||
|
||||
@@ -338,7 +338,7 @@ public:
|
||||
std::iota(axes_data.begin(), axes_data.end(), 1);
|
||||
}
|
||||
auto axes = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{axes_data.size()}, axes_data);
|
||||
auto norm = std::make_shared<ngraph::op::NormalizeL2>(ieInpNode, axes, epsilon, ngraph::op::EpsMode::ADD);
|
||||
auto norm = std::make_shared<ngraph::op::v0::NormalizeL2>(ieInpNode, axes, epsilon, ngraph::op::EpsMode::ADD);
|
||||
|
||||
CV_Assert(blobs.empty() || numChannels == blobs[0].total());
|
||||
std::vector<size_t> shape(ieInpNode->get_shape().size(), 1);
|
||||
|
||||
@@ -1954,6 +1954,23 @@ void ONNXImporter::handleNode(const opencv_onnx::NodeProto& node_proto_)
|
||||
addConstant(layerParams.name, concatenated[0]);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < node_proto.input_size(); ++i)
|
||||
{
|
||||
if (constBlobs.find(node_proto.input(i)) != constBlobs.end())
|
||||
{
|
||||
LayerParams constParams;
|
||||
constParams.name = node_proto.input(i);
|
||||
constParams.type = "Const";
|
||||
constParams.blobs.push_back(getBlob(node_proto, i));
|
||||
|
||||
opencv_onnx::NodeProto proto;
|
||||
proto.add_output(constParams.name);
|
||||
addLayer(constParams, proto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (layer_type == "Resize")
|
||||
{
|
||||
|
||||
@@ -30,10 +30,11 @@
|
||||
#define INF_ENGINE_RELEASE_2021_1 2021010000
|
||||
#define INF_ENGINE_RELEASE_2021_2 2021020000
|
||||
#define INF_ENGINE_RELEASE_2021_3 2021030000
|
||||
#define INF_ENGINE_RELEASE_2021_4 2021040000
|
||||
|
||||
#ifndef INF_ENGINE_RELEASE
|
||||
#warning("IE version have not been provided via command-line. Using 2021.3 by default")
|
||||
#define INF_ENGINE_RELEASE INF_ENGINE_RELEASE_2021_3
|
||||
#warning("IE version have not been provided via command-line. Using 2021.4 by default")
|
||||
#define INF_ENGINE_RELEASE INF_ENGINE_RELEASE_2021_4
|
||||
#endif
|
||||
|
||||
#define INF_ENGINE_VER_MAJOR_GT(ver) (((INF_ENGINE_RELEASE) / 10000) > ((ver) / 10000))
|
||||
|
||||
+1866
-1610
File diff suppressed because it is too large
Load Diff
@@ -204,7 +204,7 @@ TEST_P(DNNTestNetwork, MobileNet_SSD_Caffe)
|
||||
Mat inp = blobFromImage(sample, 1.0f / 127.5, Size(300, 300), Scalar(127.5, 127.5, 127.5), false);
|
||||
float scoreDiff = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD) ? 1.5e-2 : 0.0;
|
||||
float iouDiff = (target == DNN_TARGET_MYRIAD) ? 0.063 : 0.0;
|
||||
float detectionConfThresh = (target == DNN_TARGET_MYRIAD) ? 0.252 : FLT_MIN;
|
||||
float detectionConfThresh = (target == DNN_TARGET_MYRIAD) ? 0.262 : FLT_MIN;
|
||||
processNet("dnn/MobileNetSSD_deploy.caffemodel", "dnn/MobileNetSSD_deploy.prototxt",
|
||||
inp, "detection_out", "", scoreDiff, iouDiff, detectionConfThresh);
|
||||
expectNoFallbacksFromIE(net);
|
||||
@@ -359,8 +359,8 @@ TEST_P(DNNTestNetwork, OpenPose_pose_coco)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD_X, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.0056 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD) ? 0.072 : 0.0;
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.009 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD) ? 0.09 : 0.0;
|
||||
processNet("dnn/openpose_pose_coco.caffemodel", "dnn/openpose_pose_coco.prototxt",
|
||||
Size(46, 46), "", "", l1, lInf);
|
||||
expectNoFallbacksFromIE(net);
|
||||
@@ -380,8 +380,8 @@ TEST_P(DNNTestNetwork, OpenPose_pose_mpi)
|
||||
#endif
|
||||
|
||||
// output range: [-0.001, 0.97]
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.012 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16) ? 0.16 : 0.0;
|
||||
const float l1 = (target == DNN_TARGET_MYRIAD) ? 0.02 : 0.0;
|
||||
const float lInf = (target == DNN_TARGET_MYRIAD || target == DNN_TARGET_OPENCL_FP16) ? 0.2 : 0.0;
|
||||
processNet("dnn/openpose_pose_mpi.caffemodel", "dnn/openpose_pose_mpi.prototxt",
|
||||
Size(46, 46), "", "", l1, lInf);
|
||||
expectNoFallbacksFromIE(net);
|
||||
|
||||
@@ -307,6 +307,15 @@ TEST_P(DNNTestOpenVINO, models)
|
||||
ASSERT_FALSE(backendId != DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019 && backendId != DNN_BACKEND_INFERENCE_ENGINE_NGRAPH) <<
|
||||
"Inference Engine backend is required";
|
||||
|
||||
#if INF_ENGINE_VER_MAJOR_EQ(2021040000)
|
||||
if (targetId == DNN_TARGET_MYRIAD && (
|
||||
modelName == "person-detection-retail-0013" || // ncDeviceOpen:1013 Failed to find booted device after boot
|
||||
modelName == "age-gender-recognition-retail-0013" // ncDeviceOpen:1013 Failed to find booted device after boot
|
||||
)
|
||||
)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_DNN_BACKEND_INFERENCE_ENGINE_NGRAPH, CV_TEST_TAG_DNN_SKIP_IE_VERSION);
|
||||
#endif
|
||||
|
||||
#if INF_ENGINE_VER_MAJOR_GE(2020020000)
|
||||
if (targetId == DNN_TARGET_MYRIAD && backendId == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
|
||||
{
|
||||
|
||||
@@ -349,6 +349,7 @@ TEST_P(Test_ONNX_layers, Concatenation)
|
||||
if (target == DNN_TARGET_MYRIAD) applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
|
||||
}
|
||||
testONNXModels("concatenation");
|
||||
testONNXModels("concat_const_blobs");
|
||||
}
|
||||
|
||||
TEST_P(Test_ONNX_layers, Eltwise3D)
|
||||
|
||||
@@ -290,9 +290,14 @@ TEST_P(Test_Torch_layers, net_padding)
|
||||
|
||||
TEST_P(Test_Torch_layers, net_non_spatial)
|
||||
{
|
||||
#if defined(INF_ENGINE_RELEASE) && INF_ENGINE_VER_MAJOR_EQ(2021030000)
|
||||
#if defined(INF_ENGINE_RELEASE) && ( \
|
||||
INF_ENGINE_VER_MAJOR_EQ(2021030000) || \
|
||||
INF_ENGINE_VER_MAJOR_EQ(2021040000) \
|
||||
)
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_MYRIAD)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // crash
|
||||
// 2021.3: crash
|
||||
// 2021.4: [ GENERAL_ERROR ] AssertionFailed: !out.networkInputs.empty()
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_MYRIAD, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH);
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL)
|
||||
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_OPENCL, CV_TEST_TAG_DNN_SKIP_IE_NGRAPH); // exception
|
||||
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH && target == DNN_TARGET_OPENCL_FP16)
|
||||
|
||||
@@ -1337,6 +1337,13 @@ CV_EXPORTS_W void drawMatches( InputArray img1, const std::vector<KeyPoint>& key
|
||||
const std::vector<char>& matchesMask=std::vector<char>(), DrawMatchesFlags flags=DrawMatchesFlags::DEFAULT );
|
||||
|
||||
/** @overload */
|
||||
CV_EXPORTS_W void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
InputArray img2, const std::vector<KeyPoint>& keypoints2,
|
||||
const std::vector<DMatch>& matches1to2, InputOutputArray outImg,
|
||||
const int matchesThickness, const Scalar& matchColor=Scalar::all(-1),
|
||||
const Scalar& singlePointColor=Scalar::all(-1), const std::vector<char>& matchesMask=std::vector<char>(),
|
||||
DrawMatchesFlags flags=DrawMatchesFlags::DEFAULT );
|
||||
|
||||
CV_EXPORTS_AS(drawMatchesKnn) void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
InputArray img2, const std::vector<KeyPoint>& keypoints2,
|
||||
const std::vector<std::vector<DMatch> >& matches1to2, InputOutputArray outImg,
|
||||
|
||||
@@ -183,7 +183,8 @@ static void _prepareImgAndDrawKeypoints( InputArray img1, const std::vector<KeyP
|
||||
}
|
||||
|
||||
static inline void _drawMatch( InputOutputArray outImg, InputOutputArray outImg1, InputOutputArray outImg2 ,
|
||||
const KeyPoint& kp1, const KeyPoint& kp2, const Scalar& matchColor, DrawMatchesFlags flags )
|
||||
const KeyPoint& kp1, const KeyPoint& kp2, const Scalar& matchColor, DrawMatchesFlags flags,
|
||||
const int matchesThickness )
|
||||
{
|
||||
RNG& rng = theRNG();
|
||||
bool isRandMatchColor = matchColor == Scalar::all(-1);
|
||||
@@ -199,7 +200,7 @@ static inline void _drawMatch( InputOutputArray outImg, InputOutputArray outImg1
|
||||
line( outImg,
|
||||
Point(cvRound(pt1.x*draw_multiplier), cvRound(pt1.y*draw_multiplier)),
|
||||
Point(cvRound(dpt2.x*draw_multiplier), cvRound(dpt2.y*draw_multiplier)),
|
||||
color, 1, LINE_AA, draw_shift_bits );
|
||||
color, matchesThickness, LINE_AA, draw_shift_bits );
|
||||
}
|
||||
|
||||
void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
@@ -207,6 +208,21 @@ void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
const std::vector<DMatch>& matches1to2, InputOutputArray outImg,
|
||||
const Scalar& matchColor, const Scalar& singlePointColor,
|
||||
const std::vector<char>& matchesMask, DrawMatchesFlags flags )
|
||||
{
|
||||
drawMatches( img1, keypoints1,
|
||||
img2, keypoints2,
|
||||
matches1to2, outImg,
|
||||
1, matchColor,
|
||||
singlePointColor, matchesMask,
|
||||
flags);
|
||||
}
|
||||
|
||||
void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
InputArray img2, const std::vector<KeyPoint>& keypoints2,
|
||||
const std::vector<DMatch>& matches1to2, InputOutputArray outImg,
|
||||
const int matchesThickness, const Scalar& matchColor,
|
||||
const Scalar& singlePointColor, const std::vector<char>& matchesMask,
|
||||
DrawMatchesFlags flags )
|
||||
{
|
||||
if( !matchesMask.empty() && matchesMask.size() != matches1to2.size() )
|
||||
CV_Error( Error::StsBadSize, "matchesMask must have the same size as matches1to2" );
|
||||
@@ -226,11 +242,12 @@ void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
CV_Assert(i2 >= 0 && i2 < static_cast<int>(keypoints2.size()));
|
||||
|
||||
const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2];
|
||||
_drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags );
|
||||
_drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags, matchesThickness );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
InputArray img2, const std::vector<KeyPoint>& keypoints2,
|
||||
const std::vector<std::vector<DMatch> >& matches1to2, InputOutputArray outImg,
|
||||
@@ -254,7 +271,7 @@ void drawMatches( InputArray img1, const std::vector<KeyPoint>& keypoints1,
|
||||
if( matchesMask.empty() || matchesMask[i][j] )
|
||||
{
|
||||
const KeyPoint &kp1 = keypoints1[i1], &kp2 = keypoints2[i2];
|
||||
_drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags );
|
||||
_drawMatch( outImg, outImg1, outImg2, kp1, kp2, matchColor, flags, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,31 +450,184 @@ public:
|
||||
const sift_wt* currptr = img.ptr<sift_wt>(r);
|
||||
const sift_wt* prevptr = prev.ptr<sift_wt>(r);
|
||||
const sift_wt* nextptr = next.ptr<sift_wt>(r);
|
||||
int c = SIFT_IMG_BORDER;
|
||||
|
||||
for( int c = SIFT_IMG_BORDER; c < cols-SIFT_IMG_BORDER; c++)
|
||||
#if CV_SIMD && !(DoG_TYPE_SHORT)
|
||||
const int vecsize = v_float32::nlanes;
|
||||
for( ; c <= cols-SIFT_IMG_BORDER - vecsize; c += vecsize)
|
||||
{
|
||||
v_float32 val = vx_load(&currptr[c]);
|
||||
v_float32 _00,_01,_02;
|
||||
v_float32 _10, _12;
|
||||
v_float32 _20,_21,_22;
|
||||
|
||||
v_float32 vmin,vmax;
|
||||
|
||||
|
||||
v_float32 cond = v_abs(val) > vx_setall_f32((float)threshold);
|
||||
if (!v_check_any(cond))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_00 = vx_load(&currptr[c-step-1]); _01 = vx_load(&currptr[c-step]); _02 = vx_load(&currptr[c-step+1]);
|
||||
_10 = vx_load(&currptr[c -1]); _12 = vx_load(&currptr[c +1]);
|
||||
_20 = vx_load(&currptr[c+step-1]); _21 = vx_load(&currptr[c+step]); _22 = vx_load(&currptr[c+step+1]);
|
||||
|
||||
vmax = v_max(v_max(v_max(_00,_01),v_max(_02,_10)),v_max(v_max(_12,_20),v_max(_21,_22)));
|
||||
vmin = v_min(v_min(v_min(_00,_01),v_min(_02,_10)),v_min(v_min(_12,_20),v_min(_21,_22)));
|
||||
|
||||
v_float32 condp = cond & (val > vx_setall_f32(0)) & (val >= vmax);
|
||||
v_float32 condm = cond & (val < vx_setall_f32(0)) & (val <= vmin);
|
||||
|
||||
cond = condp | condm;
|
||||
if (!v_check_any(cond))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_00 = vx_load(&prevptr[c-step-1]); _01 = vx_load(&prevptr[c-step]); _02 = vx_load(&prevptr[c-step+1]);
|
||||
_10 = vx_load(&prevptr[c -1]); _12 = vx_load(&prevptr[c +1]);
|
||||
_20 = vx_load(&prevptr[c+step-1]); _21 = vx_load(&prevptr[c+step]); _22 = vx_load(&prevptr[c+step+1]);
|
||||
|
||||
vmax = v_max(v_max(v_max(_00,_01),v_max(_02,_10)),v_max(v_max(_12,_20),v_max(_21,_22)));
|
||||
vmin = v_min(v_min(v_min(_00,_01),v_min(_02,_10)),v_min(v_min(_12,_20),v_min(_21,_22)));
|
||||
|
||||
condp &= (val >= vmax);
|
||||
condm &= (val <= vmin);
|
||||
|
||||
cond = condp | condm;
|
||||
if (!v_check_any(cond))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
v_float32 _11p = vx_load(&prevptr[c]);
|
||||
v_float32 _11n = vx_load(&nextptr[c]);
|
||||
|
||||
v_float32 max_middle = v_max(_11n,_11p);
|
||||
v_float32 min_middle = v_min(_11n,_11p);
|
||||
|
||||
_00 = vx_load(&nextptr[c-step-1]); _01 = vx_load(&nextptr[c-step]); _02 = vx_load(&nextptr[c-step+1]);
|
||||
_10 = vx_load(&nextptr[c -1]); _12 = vx_load(&nextptr[c +1]);
|
||||
_20 = vx_load(&nextptr[c+step-1]); _21 = vx_load(&nextptr[c+step]); _22 = vx_load(&nextptr[c+step+1]);
|
||||
|
||||
vmax = v_max(v_max(v_max(_00,_01),v_max(_02,_10)),v_max(v_max(_12,_20),v_max(_21,_22)));
|
||||
vmin = v_min(v_min(v_min(_00,_01),v_min(_02,_10)),v_min(v_min(_12,_20),v_min(_21,_22)));
|
||||
|
||||
condp &= (val >= v_max(vmax,max_middle));
|
||||
condm &= (val <= v_min(vmin,min_middle));
|
||||
|
||||
cond = condp | condm;
|
||||
if (!v_check_any(cond))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int mask = v_signmask(cond);
|
||||
for (int k = 0; k<vecsize;k++)
|
||||
{
|
||||
if ((mask & (1<<k)) == 0)
|
||||
continue;
|
||||
|
||||
CV_TRACE_REGION("pixel_candidate_simd");
|
||||
|
||||
KeyPoint kpt;
|
||||
int r1 = r, c1 = c+k, layer = i;
|
||||
if( !adjustLocalExtrema(dog_pyr, kpt, o, layer, r1, c1,
|
||||
nOctaveLayers, (float)contrastThreshold,
|
||||
(float)edgeThreshold, (float)sigma) )
|
||||
continue;
|
||||
float scl_octv = kpt.size*0.5f/(1 << o);
|
||||
float omax = calcOrientationHist(gauss_pyr[o*(nOctaveLayers+3) + layer],
|
||||
Point(c1, r1),
|
||||
cvRound(SIFT_ORI_RADIUS * scl_octv),
|
||||
SIFT_ORI_SIG_FCTR * scl_octv,
|
||||
hist, n);
|
||||
float mag_thr = (float)(omax * SIFT_ORI_PEAK_RATIO);
|
||||
for( int j = 0; j < n; j++ )
|
||||
{
|
||||
int l = j > 0 ? j - 1 : n - 1;
|
||||
int r2 = j < n-1 ? j + 1 : 0;
|
||||
|
||||
if( hist[j] > hist[l] && hist[j] > hist[r2] && hist[j] >= mag_thr )
|
||||
{
|
||||
float bin = j + 0.5f * (hist[l]-hist[r2]) / (hist[l] - 2*hist[j] + hist[r2]);
|
||||
bin = bin < 0 ? n + bin : bin >= n ? bin - n : bin;
|
||||
kpt.angle = 360.f - (float)((360.f/n) * bin);
|
||||
if(std::abs(kpt.angle - 360.f) < FLT_EPSILON)
|
||||
kpt.angle = 0.f;
|
||||
|
||||
kpts_.push_back(kpt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //CV_SIMD && !(DoG_TYPE_SHORT)
|
||||
|
||||
// vector loop reminder, better predictibility and less branch density
|
||||
for( ; c < cols-SIFT_IMG_BORDER; c++)
|
||||
{
|
||||
sift_wt val = currptr[c];
|
||||
if (std::abs(val) <= threshold)
|
||||
continue;
|
||||
|
||||
// find local extrema with pixel accuracy
|
||||
if( std::abs(val) > threshold &&
|
||||
((val > 0 && val >= currptr[c-1] && val >= currptr[c+1] &&
|
||||
val >= currptr[c-step-1] && val >= currptr[c-step] && val >= currptr[c-step+1] &&
|
||||
val >= currptr[c+step-1] && val >= currptr[c+step] && val >= currptr[c+step+1] &&
|
||||
val >= nextptr[c] && val >= nextptr[c-1] && val >= nextptr[c+1] &&
|
||||
val >= nextptr[c-step-1] && val >= nextptr[c-step] && val >= nextptr[c-step+1] &&
|
||||
val >= nextptr[c+step-1] && val >= nextptr[c+step] && val >= nextptr[c+step+1] &&
|
||||
val >= prevptr[c] && val >= prevptr[c-1] && val >= prevptr[c+1] &&
|
||||
val >= prevptr[c-step-1] && val >= prevptr[c-step] && val >= prevptr[c-step+1] &&
|
||||
val >= prevptr[c+step-1] && val >= prevptr[c+step] && val >= prevptr[c+step+1]) ||
|
||||
(val < 0 && val <= currptr[c-1] && val <= currptr[c+1] &&
|
||||
val <= currptr[c-step-1] && val <= currptr[c-step] && val <= currptr[c-step+1] &&
|
||||
val <= currptr[c+step-1] && val <= currptr[c+step] && val <= currptr[c+step+1] &&
|
||||
val <= nextptr[c] && val <= nextptr[c-1] && val <= nextptr[c+1] &&
|
||||
val <= nextptr[c-step-1] && val <= nextptr[c-step] && val <= nextptr[c-step+1] &&
|
||||
val <= nextptr[c+step-1] && val <= nextptr[c+step] && val <= nextptr[c+step+1] &&
|
||||
val <= prevptr[c] && val <= prevptr[c-1] && val <= prevptr[c+1] &&
|
||||
val <= prevptr[c-step-1] && val <= prevptr[c-step] && val <= prevptr[c-step+1] &&
|
||||
val <= prevptr[c+step-1] && val <= prevptr[c+step] && val <= prevptr[c+step+1])))
|
||||
sift_wt _00,_01,_02;
|
||||
sift_wt _10, _12;
|
||||
sift_wt _20,_21,_22;
|
||||
_00 = currptr[c-step-1]; _01 = currptr[c-step]; _02 = currptr[c-step+1];
|
||||
_10 = currptr[c -1]; _12 = currptr[c +1];
|
||||
_20 = currptr[c+step-1]; _21 = currptr[c+step]; _22 = currptr[c+step+1];
|
||||
|
||||
bool calculate = false;
|
||||
if (val > 0)
|
||||
{
|
||||
sift_wt vmax = std::max(std::max(std::max(_00,_01),std::max(_02,_10)),std::max(std::max(_12,_20),std::max(_21,_22)));
|
||||
if (val >= vmax)
|
||||
{
|
||||
_00 = prevptr[c-step-1]; _01 = prevptr[c-step]; _02 = prevptr[c-step+1];
|
||||
_10 = prevptr[c -1]; _12 = prevptr[c +1];
|
||||
_20 = prevptr[c+step-1]; _21 = prevptr[c+step]; _22 = prevptr[c+step+1];
|
||||
vmax = std::max(std::max(std::max(_00,_01),std::max(_02,_10)),std::max(std::max(_12,_20),std::max(_21,_22)));
|
||||
if (val >= vmax)
|
||||
{
|
||||
_00 = nextptr[c-step-1]; _01 = nextptr[c-step]; _02 = nextptr[c-step+1];
|
||||
_10 = nextptr[c -1]; _12 = nextptr[c +1];
|
||||
_20 = nextptr[c+step-1]; _21 = nextptr[c+step]; _22 = nextptr[c+step+1];
|
||||
vmax = std::max(std::max(std::max(_00,_01),std::max(_02,_10)),std::max(std::max(_12,_20),std::max(_21,_22)));
|
||||
if (val >= vmax)
|
||||
{
|
||||
sift_wt _11p = prevptr[c], _11n = nextptr[c];
|
||||
calculate = (val >= std::max(_11p,_11n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else { // val cant be zero here (first abs took care of zero), must be negative
|
||||
sift_wt vmin = std::min(std::min(std::min(_00,_01),std::min(_02,_10)),std::min(std::min(_12,_20),std::min(_21,_22)));
|
||||
if (val <= vmin)
|
||||
{
|
||||
_00 = prevptr[c-step-1]; _01 = prevptr[c-step]; _02 = prevptr[c-step+1];
|
||||
_10 = prevptr[c -1]; _12 = prevptr[c +1];
|
||||
_20 = prevptr[c+step-1]; _21 = prevptr[c+step]; _22 = prevptr[c+step+1];
|
||||
vmin = std::min(std::min(std::min(_00,_01),std::min(_02,_10)),std::min(std::min(_12,_20),std::min(_21,_22)));
|
||||
if (val <= vmin)
|
||||
{
|
||||
_00 = nextptr[c-step-1]; _01 = nextptr[c-step]; _02 = nextptr[c-step+1];
|
||||
_10 = nextptr[c -1]; _12 = nextptr[c +1];
|
||||
_20 = nextptr[c+step-1]; _21 = nextptr[c+step]; _22 = nextptr[c+step+1];
|
||||
vmin = std::min(std::min(std::min(_00,_01),std::min(_02,_10)),std::min(std::min(_12,_20),std::min(_21,_22)));
|
||||
if (val <= vmin)
|
||||
{
|
||||
sift_wt _11p = prevptr[c], _11n = nextptr[c];
|
||||
calculate = (val <= std::min(_11p,_11n));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (calculate)
|
||||
{
|
||||
CV_TRACE_REGION("pixel_candidate");
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
*/
|
||||
|
||||
namespace cv { namespace gapi {
|
||||
/**
|
||||
* @brief This namespace contains G-API Operation Types for OpenCV
|
||||
* Core module functionality.
|
||||
*/
|
||||
namespace core {
|
||||
using GMat2 = std::tuple<GMat,GMat>;
|
||||
using GMat3 = std::tuple<GMat,GMat,GMat>; // FIXME: how to avoid this?
|
||||
|
||||
@@ -40,6 +40,10 @@ namespace gimpl
|
||||
|
||||
namespace gapi
|
||||
{
|
||||
/**
|
||||
* @brief This namespace contains G-API CPU backend functions,
|
||||
* structures, and symbols.
|
||||
*/
|
||||
namespace cpu
|
||||
{
|
||||
/**
|
||||
@@ -492,7 +496,7 @@ public:
|
||||
#define GAPI_OCV_KERNEL_ST(Name, API, State) \
|
||||
struct Name: public cv::GCPUStKernelImpl<Name, API, State> \
|
||||
|
||||
|
||||
/// @private
|
||||
class gapi::cpu::GOCVFunctor : public gapi::GFunctor
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -25,6 +25,9 @@ namespace cv {
|
||||
|
||||
namespace gapi
|
||||
{
|
||||
/**
|
||||
* @brief This namespace contains G-API Fluid backend functions, structures, and symbols.
|
||||
*/
|
||||
namespace fluid
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -340,21 +340,79 @@ namespace detail
|
||||
/** \addtogroup gapi_data_objects
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief `cv::GArray<T>` template class represents a list of objects
|
||||
* of class `T` in the graph.
|
||||
*
|
||||
* `cv::GArray<T>` describes a functional relationship between
|
||||
* operations consuming and producing arrays of objects of class
|
||||
* `T`. The primary purpose of `cv::GArray<T>` is to represent a
|
||||
* dynamic list of objects -- where the size of the list is not known
|
||||
* at the graph construction or compile time. Examples include: corner
|
||||
* and feature detectors (`cv::GArray<cv::Point>`), object detection
|
||||
* and tracking results (`cv::GArray<cv::Rect>`). Programmers can use
|
||||
* their own types with `cv::GArray<T>` in the custom operations.
|
||||
*
|
||||
* Similar to `cv::GScalar`, `cv::GArray<T>` may be value-initialized
|
||||
* -- in this case a graph-constant value is associated with the object.
|
||||
*
|
||||
* `GArray<T>` is a virtual counterpart of `std::vector<T>`, which is
|
||||
* usually used to represent the `GArray<T>` data in G-API during the
|
||||
* execution.
|
||||
*
|
||||
* @sa `cv::GOpaque<T>`
|
||||
*/
|
||||
template<typename T> class GArray
|
||||
{
|
||||
public:
|
||||
// Host type (or Flat type) - the type this GArray is actually
|
||||
// specified to.
|
||||
/// @private
|
||||
using HT = typename detail::flatten_g<typename std::decay<T>::type>::type;
|
||||
|
||||
/**
|
||||
* @brief Constructs a value-initialized `cv::GArray<T>`
|
||||
*
|
||||
* `cv::GArray<T>` objects may have their values
|
||||
* be associated at graph construction time. It is useful when
|
||||
* some operation has a `cv::GArray<T>` input which doesn't change during
|
||||
* the program execution, and is set only once. In this case,
|
||||
* there is no need to declare such `cv::GArray<T>` as a graph input.
|
||||
*
|
||||
* @note The value of `cv::GArray<T>` may be overwritten by assigning some
|
||||
* other `cv::GArray<T>` to the object using `operator=` -- on the
|
||||
* assigment, the old association or value is discarded.
|
||||
*
|
||||
* @param v a std::vector<T> to associate with this
|
||||
* `cv::GArray<T>` object. Vector data is copied into the
|
||||
* `cv::GArray<T>` (no reference to the passed data is held).
|
||||
*/
|
||||
explicit GArray(const std::vector<HT>& v) // Constant value constructor
|
||||
: m_ref(detail::GArrayU(detail::VectorRef(v))) { putDetails(); }
|
||||
|
||||
/**
|
||||
* @overload
|
||||
* @brief Constructs a value-initialized `cv::GArray<T>`
|
||||
*
|
||||
* @param v a std::vector<T> to associate with this
|
||||
* `cv::GArray<T>` object. Vector data is moved into the `cv::GArray<T>`.
|
||||
*/
|
||||
explicit GArray(std::vector<HT>&& v) // Move-constructor
|
||||
: m_ref(detail::GArrayU(detail::VectorRef(std::move(v)))) { putDetails(); }
|
||||
GArray() { putDetails(); } // Empty constructor
|
||||
explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
|
||||
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
|
||||
|
||||
/**
|
||||
* @brief Constructs an empty `cv::GArray<T>`
|
||||
*
|
||||
* Normally, empty G-API data objects denote a starting point of
|
||||
* the graph. When an empty `cv::GArray<T>` is assigned to a result
|
||||
* of some operation, it obtains a functional link to this
|
||||
* operation (and is not empty anymore).
|
||||
*/
|
||||
GArray() { putDetails(); } // Empty constructor
|
||||
|
||||
/// @private
|
||||
explicit GArray(detail::GArrayU &&ref) // GArrayU-based constructor
|
||||
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
|
||||
|
||||
/// @private
|
||||
detail::GArrayU strip() const {
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
|
||||
namespace cv {
|
||||
namespace gapi{
|
||||
|
||||
/**
|
||||
* @brief This namespace contains experimental G-API functionality,
|
||||
* functions or structures in this namespace are subjects to change or
|
||||
* removal in the future releases. This namespace also contains
|
||||
* functions which API is not stabilized yet.
|
||||
*/
|
||||
namespace wip {
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace detail
|
||||
CV_UNKNOWN, // Unknown, generic, opaque-to-GAPI data type unsupported in graph seriallization
|
||||
CV_BOOL, // bool user G-API data
|
||||
CV_INT, // int user G-API data
|
||||
CV_INT64, // int64_t user G-API data
|
||||
CV_DOUBLE, // double user G-API data
|
||||
CV_FLOAT, // float user G-API data
|
||||
CV_UINT64, // uint64_t user G-API data
|
||||
@@ -61,6 +62,7 @@ namespace detail
|
||||
template<typename T> struct GOpaqueTraits;
|
||||
template<typename T> struct GOpaqueTraits { static constexpr const OpaqueKind kind = OpaqueKind::CV_UNKNOWN; };
|
||||
template<> struct GOpaqueTraits<int> { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT; };
|
||||
template<> struct GOpaqueTraits<int64_t> { static constexpr const OpaqueKind kind = OpaqueKind::CV_INT64; };
|
||||
template<> struct GOpaqueTraits<double> { static constexpr const OpaqueKind kind = OpaqueKind::CV_DOUBLE; };
|
||||
template<> struct GOpaqueTraits<float> { static constexpr const OpaqueKind kind = OpaqueKind::CV_FLOAT; };
|
||||
template<> struct GOpaqueTraits<uint64_t> { static constexpr const OpaqueKind kind = OpaqueKind::CV_UINT64; };
|
||||
|
||||
@@ -28,14 +28,54 @@ struct GOrigin;
|
||||
/** \addtogroup gapi_data_objects
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief GFrame class represents an image or media frame in the graph.
|
||||
*
|
||||
* GFrame doesn't store any data itself, instead it describes a
|
||||
* functional relationship between operations consuming and producing
|
||||
* GFrame objects.
|
||||
*
|
||||
* GFrame is introduced to handle various media formats (e.g., NV12 or
|
||||
* I420) under the same type. Various image formats may differ in the
|
||||
* number of planes (e.g. two for NV12, three for I420) and the pixel
|
||||
* layout inside. GFrame type allows to handle these media formats in
|
||||
* the graph uniformly -- the graph structure will not change if the
|
||||
* media format changes, e.g. a different camera or decoder is used
|
||||
* with the same graph. G-API provides a number of operations which
|
||||
* operate directly on GFrame, like `infer<>()` or
|
||||
* renderFrame(); these operations are expected to handle different
|
||||
* media formats inside. There is also a number of accessor
|
||||
* operations like BGR(), Y(), UV() -- these operations provide
|
||||
* access to frame's data in the familiar cv::GMat form, which can be
|
||||
* used with the majority of the existing G-API operations. These
|
||||
* accessor functions may perform color space converion on the fly if
|
||||
* the image format of the GFrame they are applied to differs from the
|
||||
* operation's semantic (e.g. the BGR() accessor is called on an NV12
|
||||
* image frame).
|
||||
*
|
||||
* GFrame is a virtual counterpart of cv::MediaFrame.
|
||||
*
|
||||
* @sa cv::MediaFrame, cv::GFrameDesc, BGR(), Y(), UV(), infer<>().
|
||||
*/
|
||||
class GAPI_EXPORTS_W_SIMPLE GFrame
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GFrame(); // Empty constructor
|
||||
GFrame(const GNode &n, std::size_t out); // Operation result constructor
|
||||
/**
|
||||
* @brief Constructs an empty GFrame
|
||||
*
|
||||
* Normally, empty G-API data objects denote a starting point of
|
||||
* the graph. When an empty GFrame is assigned to a result of some
|
||||
* operation, it obtains a functional link to this operation (and
|
||||
* is not empty anymore).
|
||||
*/
|
||||
GAPI_WRAP GFrame(); // Empty constructor
|
||||
|
||||
GOrigin& priv(); // Internal use only
|
||||
const GOrigin& priv() const; // Internal use only
|
||||
/// @private
|
||||
GFrame(const GNode &n, std::size_t out); // Operation result constructor
|
||||
/// @private
|
||||
GOrigin& priv(); // Internal use only
|
||||
/// @private
|
||||
const GOrigin& priv() const; // Internal use only
|
||||
|
||||
private:
|
||||
std::shared_ptr<GOrigin> m_priv;
|
||||
|
||||
@@ -372,6 +372,7 @@ namespace gapi
|
||||
{
|
||||
// Prework: model "Device" API before it gets to G-API headers.
|
||||
// FIXME: Don't mix with internal Backends class!
|
||||
/// @private
|
||||
class GAPI_EXPORTS GBackend
|
||||
{
|
||||
public:
|
||||
@@ -412,6 +413,7 @@ namespace std
|
||||
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
/// @private
|
||||
class GFunctor
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -30,29 +30,57 @@ struct GOrigin;
|
||||
* @brief G-API data objects used to build G-API expressions.
|
||||
*
|
||||
* These objects do not own any particular data (except compile-time
|
||||
* associated values like with cv::GScalar) and are used to construct
|
||||
* graphs.
|
||||
* associated values like with cv::GScalar or `cv::GArray<T>`) and are
|
||||
* used only to construct graphs.
|
||||
*
|
||||
* Every graph in G-API starts and ends with data objects.
|
||||
*
|
||||
* Once constructed and compiled, G-API operates with regular host-side
|
||||
* data instead. Refer to the below table to find the mapping between
|
||||
* G-API and regular data types.
|
||||
* G-API and regular data types when passing input and output data
|
||||
* structures to G-API:
|
||||
*
|
||||
* G-API data type | I/O data type
|
||||
* ------------------ | -------------
|
||||
* cv::GMat | cv::Mat
|
||||
* cv::GMat | cv::Mat, cv::UMat, cv::RMat
|
||||
* cv::GScalar | cv::Scalar
|
||||
* `cv::GArray<T>` | std::vector<T>
|
||||
* `cv::GOpaque<T>` | T
|
||||
* cv::GFrame | cv::MediaFrame
|
||||
*/
|
||||
/**
|
||||
* @brief GMat class represents image or tensor data in the
|
||||
* graph.
|
||||
*
|
||||
* GMat doesn't store any data itself, instead it describes a
|
||||
* functional relationship between operations consuming and producing
|
||||
* GMat objects.
|
||||
*
|
||||
* GMat is a virtual counterpart of Mat and UMat, but it
|
||||
* doesn't mean G-API use Mat or UMat objects internally to represent
|
||||
* GMat objects -- the internal data representation may be
|
||||
* backend-specific or optimized out at all.
|
||||
*
|
||||
* @sa Mat, GMatDesc
|
||||
*/
|
||||
class GAPI_EXPORTS_W_SIMPLE GMat
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs an empty GMat
|
||||
*
|
||||
* Normally, empty G-API data objects denote a starting point of
|
||||
* the graph. When an empty GMat is assigned to a result of some
|
||||
* operation, it obtains a functional link to this operation (and
|
||||
* is not empty anymore).
|
||||
*/
|
||||
GAPI_WRAP GMat(); // Empty constructor
|
||||
GMat(const GNode &n, std::size_t out); // Operation result constructor
|
||||
|
||||
/// @private
|
||||
GMat(const GNode &n, std::size_t out); // Operation result constructor
|
||||
/// @private
|
||||
GOrigin& priv(); // Internal use only
|
||||
/// @private
|
||||
const GOrigin& priv() const; // Internal use only
|
||||
|
||||
private:
|
||||
|
||||
@@ -307,15 +307,40 @@ namespace detail
|
||||
/** \addtogroup gapi_data_objects
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief `cv::GOpaque<T>` template class represents an object of
|
||||
* class `T` in the graph.
|
||||
*
|
||||
* `cv::GOpaque<T>` describes a functional relationship between operations
|
||||
* consuming and producing object of class `T`. `cv::GOpaque<T>` is
|
||||
* designed to extend G-API with user-defined data types, which are
|
||||
* often required with user-defined operations. G-API can't apply any
|
||||
* optimizations to user-defined types since these types are opaque to
|
||||
* the framework. However, there is a number of G-API operations
|
||||
* declared with `cv::GOpaque<T>` as a return type,
|
||||
* e.g. cv::gapi::streaming::timestamp() or cv::gapi::streaming::size().
|
||||
*
|
||||
* @sa `cv::GArray<T>`
|
||||
*/
|
||||
template<typename T> class GOpaque
|
||||
{
|
||||
public:
|
||||
// Host type (or Flat type) - the type this GOpaque is actually
|
||||
// specified to.
|
||||
/// @private
|
||||
using HT = typename detail::flatten_g<util::decay_t<T>>::type;
|
||||
|
||||
/**
|
||||
* @brief Constructs an empty `cv::GOpaque<T>`
|
||||
*
|
||||
* Normally, empty G-API data objects denote a starting point of
|
||||
* the graph. When an empty `cv::GOpaque<T>` is assigned to a result
|
||||
* of some operation, it obtains a functional link to this
|
||||
* operation (and is not empty anymore).
|
||||
*/
|
||||
GOpaque() { putDetails(); } // Empty constructor
|
||||
|
||||
/// @private
|
||||
explicit GOpaque(detail::GOpaqueU &&ref) // GOpaqueU-based constructor
|
||||
: m_ref(ref) { putDetails(); } // (used by GCall, not for users)
|
||||
|
||||
|
||||
@@ -25,18 +25,83 @@ struct GOrigin;
|
||||
/** \addtogroup gapi_data_objects
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief GScalar class represents cv::Scalar data in the graph.
|
||||
*
|
||||
* GScalar may be associated with a cv::Scalar value, which becomes
|
||||
* its constant value bound in graph compile time. cv::GScalar describes a
|
||||
* functional relationship between operations consuming and producing
|
||||
* GScalar objects.
|
||||
*
|
||||
* GScalar is a virtual counterpart of cv::Scalar, which is usually used
|
||||
* to represent the GScalar data in G-API during the execution.
|
||||
*
|
||||
* @sa Scalar
|
||||
*/
|
||||
class GAPI_EXPORTS_W_SIMPLE GScalar
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GScalar(); // Empty constructor
|
||||
explicit GScalar(const cv::Scalar& s); // Constant value constructor from cv::Scalar
|
||||
/**
|
||||
* @brief Constructs an empty GScalar
|
||||
*
|
||||
* Normally, empty G-API data objects denote a starting point of
|
||||
* the graph. When an empty GScalar is assigned to a result of some
|
||||
* operation, it obtains a functional link to this operation (and
|
||||
* is not empty anymore).
|
||||
*/
|
||||
GAPI_WRAP GScalar();
|
||||
|
||||
/**
|
||||
* @brief Constructs a value-initialized GScalar
|
||||
*
|
||||
* In contrast with GMat (which can be either an explicit graph input
|
||||
* or a result of some operation), GScalars may have their values
|
||||
* be associated at graph construction time. It is useful when
|
||||
* some operation has a GScalar input which doesn't change during
|
||||
* the program execution, and is set only once. In this case,
|
||||
* there is no need to declare such GScalar as a graph input.
|
||||
*
|
||||
* @note The value of GScalar may be overwritten by assigning some
|
||||
* other GScalar to the object using `operator=` -- on the
|
||||
* assigment, the old GScalar value is discarded.
|
||||
*
|
||||
* @param s a cv::Scalar value to associate with this GScalar object.
|
||||
*/
|
||||
explicit GScalar(const cv::Scalar& s);
|
||||
|
||||
/**
|
||||
* @overload
|
||||
* @brief Constructs a value-initialized GScalar
|
||||
*
|
||||
* @param s a cv::Scalar value to associate with this GScalar object.
|
||||
*/
|
||||
explicit GScalar(cv::Scalar&& s); // Constant value move-constructor from cv::Scalar
|
||||
|
||||
/**
|
||||
* @overload
|
||||
* @brief Constructs a value-initialized GScalar
|
||||
*
|
||||
* @param v0 A `double` value to associate with this GScalar. Note
|
||||
* that only the first component of a four-component cv::Scalar is
|
||||
* set to this value, with others remain zeros.
|
||||
*
|
||||
* This constructor overload is not marked `explicit` and can be
|
||||
* used in G-API expression code like this:
|
||||
*
|
||||
* @snippet modules/gapi/samples/api_ref_snippets.cpp gscalar_implicit
|
||||
*
|
||||
* Here operator+(GMat,GScalar) is used to wrap cv::gapi::addC()
|
||||
* and a value-initialized GScalar is created on the fly.
|
||||
*
|
||||
* @overload
|
||||
*/
|
||||
GScalar(double v0); // Constant value constructor from double
|
||||
GScalar(const GNode &n, std::size_t out); // Operation result constructor
|
||||
|
||||
/// @private
|
||||
GScalar(const GNode &n, std::size_t out); // Operation result constructor
|
||||
/// @private
|
||||
GOrigin& priv(); // Internal use only
|
||||
/// @private
|
||||
const GOrigin& priv() const; // Internal use only
|
||||
|
||||
private:
|
||||
|
||||
@@ -71,6 +71,15 @@ using GOptRunArgP = util::variant<
|
||||
>;
|
||||
using GOptRunArgsP = std::vector<GOptRunArgP>;
|
||||
|
||||
using GOptRunArg = util::variant<
|
||||
optional<cv::Mat>,
|
||||
optional<cv::RMat>,
|
||||
optional<cv::Scalar>,
|
||||
optional<cv::detail::VectorRef>,
|
||||
optional<cv::detail::OpaqueRef>
|
||||
>;
|
||||
using GOptRunArgs = std::vector<GOptRunArg>;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T> inline GOptRunArgP wrap_opt_arg(optional<T>& arg) {
|
||||
@@ -196,7 +205,7 @@ public:
|
||||
* @param s a shared pointer to IStreamSource representing the
|
||||
* input video stream.
|
||||
*/
|
||||
GAPI_WRAP void setSource(const gapi::wip::IStreamSource::Ptr& s);
|
||||
void setSource(const gapi::wip::IStreamSource::Ptr& s);
|
||||
|
||||
/**
|
||||
* @brief Constructs and specifies an input video stream for a
|
||||
@@ -255,7 +264,7 @@ public:
|
||||
|
||||
// NB: Used from python
|
||||
/// @private -- Exclude this function from OpenCV documentation
|
||||
GAPI_WRAP std::tuple<bool, cv::GRunArgs> pull();
|
||||
GAPI_WRAP std::tuple<bool, cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>> pull();
|
||||
|
||||
/**
|
||||
* @brief Get some next available data from the pipeline.
|
||||
@@ -372,6 +381,14 @@ protected:
|
||||
/** @} */
|
||||
|
||||
namespace gapi {
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API functions, structures, and
|
||||
* symbols related to the Streaming execution mode.
|
||||
*
|
||||
* Some of the operations defined in this namespace (e.g. size(),
|
||||
* BGR(), etc.) can be used in the traditional execution mode too.
|
||||
*/
|
||||
namespace streaming {
|
||||
/**
|
||||
* @brief Specify queue capacity for streaming execution.
|
||||
|
||||
@@ -47,6 +47,10 @@ void validateFindingContoursMeta(const int depth, const int chan, const int mode
|
||||
|
||||
namespace cv { namespace gapi {
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API Operation Types for OpenCV
|
||||
* ImgProc module functionality.
|
||||
*/
|
||||
namespace imgproc {
|
||||
using GMat2 = std::tuple<GMat,GMat>;
|
||||
using GMat3 = std::tuple<GMat,GMat,GMat>; // FIXME: how to avoid this?
|
||||
|
||||
@@ -136,11 +136,12 @@ public:
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
void setInput(const std::string& name, U in)
|
||||
GInferInputsTyped<Ts...>& setInput(const std::string& name, U in)
|
||||
{
|
||||
m_priv->blobs.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(name),
|
||||
std::forward_as_tuple(in));
|
||||
return *this;
|
||||
}
|
||||
|
||||
using StorageT = cv::util::variant<Ts...>;
|
||||
@@ -653,7 +654,8 @@ namespace gapi {
|
||||
|
||||
// A type-erased form of network parameters.
|
||||
// Similar to how a type-erased GKernel is represented and used.
|
||||
struct GAPI_EXPORTS GNetParam {
|
||||
/// @private
|
||||
struct GAPI_EXPORTS_W_SIMPLE GNetParam {
|
||||
std::string tag; // FIXME: const?
|
||||
GBackend backend; // Specifies the execution model
|
||||
util::any params; // Backend-interpreted parameter structure
|
||||
@@ -664,12 +666,13 @@ struct GAPI_EXPORTS GNetParam {
|
||||
*/
|
||||
/**
|
||||
* @brief A container class for network configurations. Similar to
|
||||
* GKernelPackage.Use cv::gapi::networks() to construct this object.
|
||||
* GKernelPackage. Use cv::gapi::networks() to construct this object.
|
||||
*
|
||||
* @sa cv::gapi::networks
|
||||
*/
|
||||
struct GAPI_EXPORTS_W_SIMPLE GNetPackage {
|
||||
GAPI_WRAP GNetPackage() = default;
|
||||
GAPI_WRAP explicit GNetPackage(std::vector<GNetParam> nets);
|
||||
explicit GNetPackage(std::initializer_list<GNetParam> ii);
|
||||
std::vector<GBackend> backends() const;
|
||||
std::vector<GNetParam> networks;
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
// FIXME: introduce a new sub-namespace for NN?
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API OpenVINO backend functions,
|
||||
* structures, and symbols.
|
||||
*/
|
||||
namespace ie {
|
||||
|
||||
GAPI_EXPORTS cv::gapi::GBackend backend();
|
||||
@@ -69,7 +74,11 @@ struct ParamDesc {
|
||||
std::map<std::string, std::vector<std::size_t>> reshape_table;
|
||||
std::unordered_set<std::string> layer_names_to_reshape;
|
||||
|
||||
// NB: Number of asyncrhonious infer requests
|
||||
size_t nireq;
|
||||
|
||||
// NB: An optional config to setup RemoteContext for IE
|
||||
cv::util::any context_config;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
@@ -110,7 +119,8 @@ public:
|
||||
, {}
|
||||
, {}
|
||||
, {}
|
||||
, 1u} {
|
||||
, 1u
|
||||
, {}} {
|
||||
};
|
||||
|
||||
/** @overload
|
||||
@@ -130,7 +140,8 @@ public:
|
||||
, {}
|
||||
, {}
|
||||
, {}
|
||||
, 1u} {
|
||||
, 1u
|
||||
, {}} {
|
||||
};
|
||||
|
||||
/** @brief Specifies sequence of network input layers names for inference.
|
||||
@@ -212,6 +223,30 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @brief Specifies configuration for RemoteContext in InferenceEngine.
|
||||
|
||||
When RemoteContext is configured the backend imports the networks using the context.
|
||||
It also expects cv::MediaFrames to be actually remote, to operate with blobs via the context.
|
||||
|
||||
@param ctx_cfg cv::util::any value which holds InferenceEngine::ParamMap.
|
||||
@return reference to this parameter structure.
|
||||
*/
|
||||
Params& cfgContextParams(const cv::util::any& ctx_cfg) {
|
||||
desc.context_config = ctx_cfg;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @overload
|
||||
Function with an rvalue parameter.
|
||||
|
||||
@param ctx_cfg cv::util::any value which holds InferenceEngine::ParamMap.
|
||||
@return reference to this parameter structure.
|
||||
*/
|
||||
Params& cfgContextParams(cv::util::any&& ctx_cfg) {
|
||||
desc.context_config = std::move(ctx_cfg);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** @brief Specifies number of asynchronous inference requests.
|
||||
|
||||
@param nireq Number of inference asynchronous requests.
|
||||
@@ -313,7 +348,10 @@ public:
|
||||
const std::string &model,
|
||||
const std::string &weights,
|
||||
const std::string &device)
|
||||
: desc{ model, weights, device, {}, {}, {}, 0u, 0u, detail::ParamDesc::Kind::Load, true, {}, {}, {}, 1u}, m_tag(tag) {
|
||||
: desc{ model, weights, device, {}, {}, {}, 0u, 0u,
|
||||
detail::ParamDesc::Kind::Load, true, {}, {}, {}, 1u,
|
||||
{}},
|
||||
m_tag(tag) {
|
||||
};
|
||||
|
||||
/** @overload
|
||||
@@ -328,7 +366,10 @@ public:
|
||||
Params(const std::string &tag,
|
||||
const std::string &model,
|
||||
const std::string &device)
|
||||
: desc{ model, {}, device, {}, {}, {}, 0u, 0u, detail::ParamDesc::Kind::Import, true, {}, {}, {}, 1u}, m_tag(tag) {
|
||||
: desc{ model, {}, device, {}, {}, {}, 0u, 0u,
|
||||
detail::ParamDesc::Kind::Import, true, {}, {}, {}, 1u,
|
||||
{}},
|
||||
m_tag(tag) {
|
||||
};
|
||||
|
||||
/** @see ie::Params::pluginConfig. */
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API ONNX Runtime backend functions, structures, and symbols.
|
||||
*/
|
||||
namespace onnx {
|
||||
|
||||
GAPI_EXPORTS cv::gapi::GBackend backend();
|
||||
|
||||
@@ -64,12 +64,13 @@ detection is smaller than confidence threshold, detection is rejected.
|
||||
given label will get to the output.
|
||||
@return a tuple with a vector of detected boxes and a vector of appropriate labels.
|
||||
*/
|
||||
GAPI_EXPORTS std::tuple<GArray<Rect>, GArray<int>> parseSSD(const GMat& in,
|
||||
const GOpaque<Size>& inSz,
|
||||
const float confidenceThreshold = 0.5f,
|
||||
const int filterLabel = -1);
|
||||
GAPI_EXPORTS_W std::tuple<GArray<Rect>, GArray<int>> parseSSD(const GMat& in,
|
||||
const GOpaque<Size>& inSz,
|
||||
const float confidenceThreshold = 0.5f,
|
||||
const int filterLabel = -1);
|
||||
|
||||
/** @brief Parses output of SSD network.
|
||||
|
||||
/** @overload
|
||||
Extracts detection information (box, confidence) from SSD output and
|
||||
filters it by given confidence and by going out of bounds.
|
||||
|
||||
@@ -87,9 +88,9 @@ the larger side of the rectangle.
|
||||
*/
|
||||
GAPI_EXPORTS_W GArray<Rect> parseSSD(const GMat& in,
|
||||
const GOpaque<Size>& inSz,
|
||||
const float confidenceThreshold = 0.5f,
|
||||
const bool alignmentToSquare = false,
|
||||
const bool filterOutOfBounds = false);
|
||||
const float confidenceThreshold,
|
||||
const bool alignmentToSquare,
|
||||
const bool filterOutOfBounds);
|
||||
|
||||
/** @brief Parses output of Yolo network.
|
||||
|
||||
@@ -112,12 +113,12 @@ If 1.f, nms is not performed and no boxes are rejected.
|
||||
<a href="https://github.com/openvinotoolkit/open_model_zoo/blob/master/models/public/yolo-v2-tiny-tf/yolo-v2-tiny-tf.md">documentation</a>.
|
||||
@return a tuple with a vector of detected boxes and a vector of appropriate labels.
|
||||
*/
|
||||
GAPI_EXPORTS std::tuple<GArray<Rect>, GArray<int>> parseYolo(const GMat& in,
|
||||
const GOpaque<Size>& inSz,
|
||||
const float confidenceThreshold = 0.5f,
|
||||
const float nmsThreshold = 0.5f,
|
||||
const std::vector<float>& anchors
|
||||
= nn::parsers::GParseYolo::defaultAnchors());
|
||||
GAPI_EXPORTS_W std::tuple<GArray<Rect>, GArray<int>> parseYolo(const GMat& in,
|
||||
const GOpaque<Size>& inSz,
|
||||
const float confidenceThreshold = 0.5f,
|
||||
const float nmsThreshold = 0.5f,
|
||||
const std::vector<float>& anchors
|
||||
= nn::parsers::GParseYolo::defaultAnchors());
|
||||
|
||||
} // namespace gapi
|
||||
} // namespace cv
|
||||
|
||||
@@ -17,28 +17,107 @@
|
||||
|
||||
namespace cv {
|
||||
|
||||
/** \addtogroup gapi_data_structures
|
||||
* @{
|
||||
*
|
||||
* @brief Extra G-API data structures used to pass input/output data
|
||||
* to the graph for processing.
|
||||
*/
|
||||
/**
|
||||
* @brief cv::MediaFrame class represents an image/media frame
|
||||
* obtained from an external source.
|
||||
*
|
||||
* cv::MediaFrame represents image data as specified in
|
||||
* cv::MediaFormat. cv::MediaFrame is designed to be a thin wrapper over some
|
||||
* external memory of buffer; the class itself provides an uniform
|
||||
* interface over such types of memory. cv::MediaFrame wraps data from
|
||||
* a camera driver or from a media codec and provides an abstraction
|
||||
* layer over this memory to G-API. MediaFrame defines a compact interface
|
||||
* to access and manage the underlying data; the implementation is
|
||||
* fully defined by the associated Adapter (which is usually
|
||||
* user-defined).
|
||||
*
|
||||
* @sa cv::RMat
|
||||
*/
|
||||
class GAPI_EXPORTS MediaFrame {
|
||||
public:
|
||||
enum class Access { R, W };
|
||||
/// This enum defines different types of cv::MediaFrame provided
|
||||
/// access to the underlying data. Note that different flags can't
|
||||
/// be combined in this version.
|
||||
enum class Access {
|
||||
R, ///< Access data for reading
|
||||
W, ///< Access data for writing
|
||||
};
|
||||
class IAdapter;
|
||||
class View;
|
||||
using AdapterPtr = std::unique_ptr<IAdapter>;
|
||||
|
||||
/**
|
||||
* @brief Constructs an empty MediaFrame
|
||||
*
|
||||
* The constructed object has no any data associated with it.
|
||||
*/
|
||||
MediaFrame();
|
||||
explicit MediaFrame(AdapterPtr &&);
|
||||
template<class T, class... Args> static cv::MediaFrame Create(Args&&...);
|
||||
|
||||
View access(Access) const;
|
||||
/**
|
||||
* @brief Constructs a MediaFrame with the given
|
||||
* Adapter. MediaFrame takes ownership over the passed adapter.
|
||||
*
|
||||
* @param p an unique pointer to instance of IAdapter derived class.
|
||||
*/
|
||||
explicit MediaFrame(AdapterPtr &&p);
|
||||
|
||||
/**
|
||||
* @overload
|
||||
* @brief Constructs a MediaFrame with the given parameters for
|
||||
* the Adapter. The adapter of type `T` is costructed on the fly.
|
||||
*
|
||||
* @param args list of arguments to construct an adapter of type
|
||||
* `T`.
|
||||
*/
|
||||
template<class T, class... Args> static cv::MediaFrame Create(Args&&... args);
|
||||
|
||||
/**
|
||||
* @brief Obtain access to the underlying data with the given
|
||||
* mode.
|
||||
*
|
||||
* Depending on the associated Adapter and the data wrapped, this
|
||||
* method may be cheap (e.g., the underlying memory is local) or
|
||||
* costly (if the underlying memory is external or device
|
||||
* memory).
|
||||
*
|
||||
* @param mode an access mode flag
|
||||
* @return a MediaFrame::View object. The views should be handled
|
||||
* carefully, refer to the MediaFrame::View documentation for details.
|
||||
*/
|
||||
View access(Access mode) const;
|
||||
|
||||
/**
|
||||
* @brief Returns a media frame descriptor -- the information
|
||||
* about the media format, dimensions, etc.
|
||||
* @return a cv::GFrameDesc
|
||||
*/
|
||||
cv::GFrameDesc desc() const;
|
||||
|
||||
// FIXME: design a better solution
|
||||
// Should be used only if the actual adapter provides implementation
|
||||
/// @private -- exclude from the OpenCV documentation for now.
|
||||
cv::util::any blobParams() const;
|
||||
|
||||
// Cast underlying MediaFrame adapter to the particular adapter type,
|
||||
// return nullptr if underlying type is different
|
||||
template<typename T> T* get() const
|
||||
{
|
||||
/**
|
||||
* @brief Casts and returns the associated MediaFrame adapter to
|
||||
* the particular adapter type `T`, returns nullptr if the type is
|
||||
* different.
|
||||
*
|
||||
* This method may be useful if the adapter type is known by the
|
||||
* caller, and some lower level access to the memory is required.
|
||||
* Depending on the memory type, it may be more efficient than
|
||||
* access().
|
||||
*
|
||||
* @return a pointer to the adapter object, nullptr if the adapter
|
||||
* type is different.
|
||||
*/
|
||||
template<typename T> T* get() const {
|
||||
static_assert(std::is_base_of<IAdapter, T>::value,
|
||||
"T is not derived from cv::MediaFrame::IAdapter!");
|
||||
auto* adapter = getAdapter();
|
||||
@@ -58,6 +137,43 @@ inline cv::MediaFrame cv::MediaFrame::Create(Args&&... args) {
|
||||
return cv::MediaFrame(std::move(ptr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provides access to the MediaFrame's underlying data.
|
||||
*
|
||||
* This object contains the necessary information to access the pixel
|
||||
* data of the associated MediaFrame: arrays of pointers and strides
|
||||
* (distance between every plane row, in bytes) for every image
|
||||
* plane, as defined in cv::MediaFormat.
|
||||
* There may be up to four image planes in MediaFrame.
|
||||
*
|
||||
* Depending on the MediaFrame::Access flag passed in
|
||||
* MediaFrame::access(), a MediaFrame::View may be read- or
|
||||
* write-only.
|
||||
*
|
||||
* Depending on the MediaFrame::IAdapter implementation associated
|
||||
* with the parent MediaFrame, writing to memory with
|
||||
* MediaFrame::Access::R flag may have no effect or lead to
|
||||
* undefined behavior. Same applies to reading the memory with
|
||||
* MediaFrame::Access::W flag -- again, depending on the IAdapter
|
||||
* implementation, the host-side buffer the view provides access to
|
||||
* may have no current data stored in (so in-place editing of the
|
||||
* buffer contents may not be possible).
|
||||
*
|
||||
* MediaFrame::View objects must be handled carefully, as an external
|
||||
* resource associated with MediaFrame may be locked for the time the
|
||||
* MediaFrame::View object exists. Obtaining MediaFrame::View should
|
||||
* be seen as "map" and destroying it as "unmap" in the "map/unmap"
|
||||
* idiom (applicable to OpenCL, device memory, remote
|
||||
* memory).
|
||||
*
|
||||
* When a MediaFrame buffer is accessed for writing, and the memory
|
||||
* under MediaFrame::View::Ptrs is altered, the data synchronization
|
||||
* of a host-side and device/remote buffer is not guaranteed until the
|
||||
* MediaFrame::View is destroyed. In other words, the real data on the
|
||||
* device or in a remote target may be updated at the MediaFrame::View
|
||||
* destruction only -- but it depends on the associated
|
||||
* MediaFrame::IAdapter implementation.
|
||||
*/
|
||||
class GAPI_EXPORTS MediaFrame::View final {
|
||||
public:
|
||||
static constexpr const size_t MAX_PLANES = 4;
|
||||
@@ -65,19 +181,38 @@ public:
|
||||
using Strides = std::array<std::size_t, MAX_PLANES>; // in bytes
|
||||
using Callback = std::function<void()>;
|
||||
|
||||
/// @private
|
||||
View(Ptrs&& ptrs, Strides&& strs, Callback &&cb = [](){});
|
||||
|
||||
/// @private
|
||||
View(const View&) = delete;
|
||||
|
||||
/// @private
|
||||
View(View&&) = default;
|
||||
|
||||
/// @private
|
||||
View& operator = (const View&) = delete;
|
||||
|
||||
~View();
|
||||
|
||||
Ptrs ptr;
|
||||
Strides stride;
|
||||
Ptrs ptr; ///< Array of image plane pointers
|
||||
Strides stride; ///< Array of image plane strides, in bytes.
|
||||
|
||||
private:
|
||||
Callback m_cb;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An interface class for MediaFrame data adapters.
|
||||
*
|
||||
* Implement this interface to wrap media data in the MediaFrame. It
|
||||
* makes sense to implement this class if there is a custom
|
||||
* cv::gapi::wip::IStreamSource defined -- in this case, a stream
|
||||
* source can produce MediaFrame objects with this adapter and the
|
||||
* media data may be passed to graph without any copy. For example, a
|
||||
* GStreamer-based stream source can implement an adapter over
|
||||
* `GstBuffer` and G-API will transparently use it in the graph.
|
||||
*/
|
||||
class GAPI_EXPORTS MediaFrame::IAdapter {
|
||||
public:
|
||||
virtual ~IAdapter() = 0;
|
||||
@@ -87,6 +222,7 @@ public:
|
||||
// The default implementation does nothing
|
||||
virtual cv::util::any blobParams() const;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
} //namespace cv
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace gimpl
|
||||
|
||||
namespace gapi
|
||||
{
|
||||
/**
|
||||
* @brief This namespace contains G-API OpenCL backend functions, structures, and symbols.
|
||||
*/
|
||||
namespace ocl
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
# define GAPI_EXPORTS CV_EXPORTS
|
||||
/* special informative macros for wrapper generators */
|
||||
# define GAPI_PROP CV_PROP
|
||||
# define GAPI_PROP_RW CV_PROP_RW
|
||||
# define GAPI_WRAP CV_WRAP
|
||||
# define GAPI_EXPORTS_W_SIMPLE CV_EXPORTS_W_SIMPLE
|
||||
# define GAPI_EXPORTS_W CV_EXPORTS_W
|
||||
# else
|
||||
# define GAPI_PROP
|
||||
# define GAPI_PROP_RW
|
||||
# define GAPI_WRAP
|
||||
# define GAPI_EXPORTS
|
||||
# define GAPI_EXPORTS_W_SIMPLE
|
||||
|
||||
@@ -15,6 +15,11 @@ namespace cv
|
||||
{
|
||||
namespace gapi
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API own data structures used in
|
||||
* its standalone mode build.
|
||||
*/
|
||||
namespace own
|
||||
{
|
||||
|
||||
|
||||
@@ -15,6 +15,11 @@ namespace cv
|
||||
{
|
||||
namespace gapi
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API PlaidML backend functions,
|
||||
* structures, and symbols.
|
||||
*/
|
||||
namespace plaidml
|
||||
{
|
||||
|
||||
|
||||
@@ -13,6 +13,15 @@
|
||||
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API Python backend functions,
|
||||
* structures, and symbols.
|
||||
*
|
||||
* This functionality is required to enable G-API custom operations
|
||||
* and kernels when using G-API from Python, no need to use it in the
|
||||
* C++ form.
|
||||
*/
|
||||
namespace python {
|
||||
|
||||
GAPI_EXPORTS cv::gapi::GBackend backend();
|
||||
|
||||
@@ -81,9 +81,9 @@ using GMatDesc2 = std::tuple<cv::GMatDesc,cv::GMatDesc>;
|
||||
@param prims vector of drawing primitivies
|
||||
@param args graph compile time parameters
|
||||
*/
|
||||
void GAPI_EXPORTS render(cv::Mat& bgr,
|
||||
const Prims& prims,
|
||||
cv::GCompileArgs&& args = {});
|
||||
void GAPI_EXPORTS_W render(cv::Mat& bgr,
|
||||
const Prims& prims,
|
||||
cv::GCompileArgs&& args = {});
|
||||
|
||||
/** @brief The function renders on two NV12 planes passed drawing primitivies
|
||||
|
||||
@@ -92,10 +92,10 @@ void GAPI_EXPORTS render(cv::Mat& bgr,
|
||||
@param prims vector of drawing primitivies
|
||||
@param args graph compile time parameters
|
||||
*/
|
||||
void GAPI_EXPORTS render(cv::Mat& y_plane,
|
||||
cv::Mat& uv_plane,
|
||||
const Prims& prims,
|
||||
cv::GCompileArgs&& args = {});
|
||||
void GAPI_EXPORTS_W render(cv::Mat& y_plane,
|
||||
cv::Mat& uv_plane,
|
||||
const Prims& prims,
|
||||
cv::GCompileArgs&& args = {});
|
||||
|
||||
/** @brief The function renders on the input media frame passed drawing primitivies
|
||||
|
||||
@@ -139,7 +139,7 @@ Output image must be 8-bit unsigned planar 3-channel image
|
||||
@param src input image: 8-bit unsigned 3-channel image @ref CV_8UC3
|
||||
@param prims draw primitives
|
||||
*/
|
||||
GAPI_EXPORTS GMat render3ch(const GMat& src, const GArray<Prim>& prims);
|
||||
GAPI_EXPORTS_W GMat render3ch(const GMat& src, const GArray<Prim>& prims);
|
||||
|
||||
/** @brief Renders on two planes
|
||||
|
||||
@@ -150,9 +150,9 @@ uv image must be 8-bit unsigned planar 2-channel image @ref CV_8UC2
|
||||
@param uv input image: 8-bit unsigned 2-channel image @ref CV_8UC2
|
||||
@param prims draw primitives
|
||||
*/
|
||||
GAPI_EXPORTS GMat2 renderNV12(const GMat& y,
|
||||
const GMat& uv,
|
||||
const GArray<Prim>& prims);
|
||||
GAPI_EXPORTS_W GMat2 renderNV12(const GMat& y,
|
||||
const GMat& uv,
|
||||
const GArray<Prim>& prims);
|
||||
|
||||
/** @brief Renders Media Frame
|
||||
|
||||
@@ -169,11 +169,15 @@ GAPI_EXPORTS GFrame renderFrame(const GFrame& m_frame,
|
||||
} // namespace draw
|
||||
} // namespace wip
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API CPU rendering backend functions,
|
||||
* structures, and symbols. See @ref gapi_draw for details.
|
||||
*/
|
||||
namespace render
|
||||
{
|
||||
namespace ocv
|
||||
{
|
||||
GAPI_EXPORTS cv::gapi::GKernelPackage kernels();
|
||||
GAPI_EXPORTS_W cv::gapi::GKernelPackage kernels();
|
||||
|
||||
} // namespace ocv
|
||||
} // namespace render
|
||||
|
||||
@@ -41,7 +41,7 @@ struct freetype_font
|
||||
*
|
||||
* Parameters match cv::putText().
|
||||
*/
|
||||
struct Text
|
||||
struct GAPI_EXPORTS_W_SIMPLE Text
|
||||
{
|
||||
/**
|
||||
* @brief Text constructor
|
||||
@@ -55,6 +55,7 @@ struct Text
|
||||
* @param lt_ The line type. See #LineTypes
|
||||
* @param bottom_left_origin_ When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
|
||||
*/
|
||||
GAPI_WRAP
|
||||
Text(const std::string& text_,
|
||||
const cv::Point& org_,
|
||||
int ff_,
|
||||
@@ -68,17 +69,18 @@ struct Text
|
||||
{
|
||||
}
|
||||
|
||||
GAPI_WRAP
|
||||
Text() = default;
|
||||
|
||||
/*@{*/
|
||||
std::string text; //!< The text string to be drawn
|
||||
cv::Point org; //!< The bottom-left corner of the text string in the image
|
||||
int ff; //!< The font type, see #HersheyFonts
|
||||
double fs; //!< The font scale factor that is multiplied by the font-specific base size
|
||||
cv::Scalar color; //!< The text color
|
||||
int thick; //!< The thickness of the lines used to draw a text
|
||||
int lt; //!< The line type. See #LineTypes
|
||||
bool bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
|
||||
GAPI_PROP_RW std::string text; //!< The text string to be drawn
|
||||
GAPI_PROP_RW cv::Point org; //!< The bottom-left corner of the text string in the image
|
||||
GAPI_PROP_RW int ff; //!< The font type, see #HersheyFonts
|
||||
GAPI_PROP_RW double fs; //!< The font scale factor that is multiplied by the font-specific base size
|
||||
GAPI_PROP_RW cv::Scalar color; //!< The text color
|
||||
GAPI_PROP_RW int thick; //!< The thickness of the lines used to draw a text
|
||||
GAPI_PROP_RW int lt; //!< The line type. See #LineTypes
|
||||
GAPI_PROP_RW bool bottom_left_origin; //!< When true, the image data origin is at the bottom-left corner. Otherwise, it is at the top-left corner
|
||||
/*@{*/
|
||||
};
|
||||
|
||||
@@ -122,7 +124,7 @@ struct FText
|
||||
*
|
||||
* Parameters match cv::rectangle().
|
||||
*/
|
||||
struct Rect
|
||||
struct GAPI_EXPORTS_W_SIMPLE Rect
|
||||
{
|
||||
/**
|
||||
* @brief Rect constructor
|
||||
@@ -142,14 +144,15 @@ struct Rect
|
||||
{
|
||||
}
|
||||
|
||||
GAPI_WRAP
|
||||
Rect() = default;
|
||||
|
||||
/*@{*/
|
||||
cv::Rect rect; //!< Coordinates of the rectangle
|
||||
cv::Scalar color; //!< The rectangle color or brightness (grayscale image)
|
||||
int thick; //!< The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
|
||||
int lt; //!< The type of the line. See #LineTypes
|
||||
int shift; //!< The number of fractional bits in the point coordinates
|
||||
GAPI_PROP_RW cv::Rect rect; //!< Coordinates of the rectangle
|
||||
GAPI_PROP_RW cv::Scalar color; //!< The rectangle color or brightness (grayscale image)
|
||||
GAPI_PROP_RW int thick; //!< The thickness of lines that make up the rectangle. Negative values, like #FILLED, mean that the function has to draw a filled rectangle
|
||||
GAPI_PROP_RW int lt; //!< The type of the line. See #LineTypes
|
||||
GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinates
|
||||
/*@{*/
|
||||
};
|
||||
|
||||
@@ -158,7 +161,7 @@ struct Rect
|
||||
*
|
||||
* Parameters match cv::circle().
|
||||
*/
|
||||
struct Circle
|
||||
struct GAPI_EXPORTS_W_SIMPLE Circle
|
||||
{
|
||||
/**
|
||||
* @brief Circle constructor
|
||||
@@ -170,6 +173,7 @@ struct Circle
|
||||
* @param lt_ The Type of the circle boundary. See #LineTypes
|
||||
* @param shift_ The Number of fractional bits in the coordinates of the center and in the radius value
|
||||
*/
|
||||
GAPI_WRAP
|
||||
Circle(const cv::Point& center_,
|
||||
int radius_,
|
||||
const cv::Scalar& color_,
|
||||
@@ -180,15 +184,16 @@ struct Circle
|
||||
{
|
||||
}
|
||||
|
||||
GAPI_WRAP
|
||||
Circle() = default;
|
||||
|
||||
/*@{*/
|
||||
cv::Point center; //!< The center of the circle
|
||||
int radius; //!< The radius of the circle
|
||||
cv::Scalar color; //!< The color of the circle
|
||||
int thick; //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
|
||||
int lt; //!< The Type of the circle boundary. See #LineTypes
|
||||
int shift; //!< The Number of fractional bits in the coordinates of the center and in the radius value
|
||||
GAPI_PROP_RW cv::Point center; //!< The center of the circle
|
||||
GAPI_PROP_RW int radius; //!< The radius of the circle
|
||||
GAPI_PROP_RW cv::Scalar color; //!< The color of the circle
|
||||
GAPI_PROP_RW int thick; //!< The thickness of the circle outline, if positive. Negative values, like #FILLED, mean that a filled circle is to be drawn
|
||||
GAPI_PROP_RW int lt; //!< The Type of the circle boundary. See #LineTypes
|
||||
GAPI_PROP_RW int shift; //!< The Number of fractional bits in the coordinates of the center and in the radius value
|
||||
/*@{*/
|
||||
};
|
||||
|
||||
@@ -197,7 +202,7 @@ struct Circle
|
||||
*
|
||||
* Parameters match cv::line().
|
||||
*/
|
||||
struct Line
|
||||
struct GAPI_EXPORTS_W_SIMPLE Line
|
||||
{
|
||||
/**
|
||||
* @brief Line constructor
|
||||
@@ -209,6 +214,7 @@ struct Line
|
||||
* @param lt_ The Type of the line. See #LineTypes
|
||||
* @param shift_ The number of fractional bits in the point coordinates
|
||||
*/
|
||||
GAPI_WRAP
|
||||
Line(const cv::Point& pt1_,
|
||||
const cv::Point& pt2_,
|
||||
const cv::Scalar& color_,
|
||||
@@ -219,15 +225,16 @@ struct Line
|
||||
{
|
||||
}
|
||||
|
||||
GAPI_WRAP
|
||||
Line() = default;
|
||||
|
||||
/*@{*/
|
||||
cv::Point pt1; //!< The first point of the line segment
|
||||
cv::Point pt2; //!< The second point of the line segment
|
||||
cv::Scalar color; //!< The line color
|
||||
int thick; //!< The thickness of line
|
||||
int lt; //!< The Type of the line. See #LineTypes
|
||||
int shift; //!< The number of fractional bits in the point coordinates
|
||||
GAPI_PROP_RW cv::Point pt1; //!< The first point of the line segment
|
||||
GAPI_PROP_RW cv::Point pt2; //!< The second point of the line segment
|
||||
GAPI_PROP_RW cv::Scalar color; //!< The line color
|
||||
GAPI_PROP_RW int thick; //!< The thickness of line
|
||||
GAPI_PROP_RW int lt; //!< The Type of the line. See #LineTypes
|
||||
GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinates
|
||||
/*@{*/
|
||||
};
|
||||
|
||||
@@ -236,7 +243,7 @@ struct Line
|
||||
*
|
||||
* Mosaicing is a very basic method to obfuscate regions in the image.
|
||||
*/
|
||||
struct Mosaic
|
||||
struct GAPI_EXPORTS_W_SIMPLE Mosaic
|
||||
{
|
||||
/**
|
||||
* @brief Mosaic constructor
|
||||
@@ -252,12 +259,13 @@ struct Mosaic
|
||||
{
|
||||
}
|
||||
|
||||
GAPI_WRAP
|
||||
Mosaic() : cellSz(0), decim(0) {}
|
||||
|
||||
/*@{*/
|
||||
cv::Rect mos; //!< Coordinates of the mosaic
|
||||
int cellSz; //!< Cell size (same for X, Y)
|
||||
int decim; //!< Decimation (0 stands for no decimation)
|
||||
GAPI_PROP_RW cv::Rect mos; //!< Coordinates of the mosaic
|
||||
GAPI_PROP_RW int cellSz; //!< Cell size (same for X, Y)
|
||||
GAPI_PROP_RW int decim; //!< Decimation (0 stands for no decimation)
|
||||
/*@{*/
|
||||
};
|
||||
|
||||
@@ -266,7 +274,7 @@ struct Mosaic
|
||||
*
|
||||
* Image is blended on a frame using the specified mask.
|
||||
*/
|
||||
struct Image
|
||||
struct GAPI_EXPORTS_W_SIMPLE Image
|
||||
{
|
||||
/**
|
||||
* @brief Mosaic constructor
|
||||
@@ -275,6 +283,7 @@ struct Image
|
||||
* @param img_ Image to draw
|
||||
* @param alpha_ Alpha channel for image to draw (same size and number of channels)
|
||||
*/
|
||||
GAPI_WRAP
|
||||
Image(const cv::Point& org_,
|
||||
const cv::Mat& img_,
|
||||
const cv::Mat& alpha_) :
|
||||
@@ -282,19 +291,20 @@ struct Image
|
||||
{
|
||||
}
|
||||
|
||||
GAPI_WRAP
|
||||
Image() = default;
|
||||
|
||||
/*@{*/
|
||||
cv::Point org; //!< The bottom-left corner of the image
|
||||
cv::Mat img; //!< Image to draw
|
||||
cv::Mat alpha; //!< Alpha channel for image to draw (same size and number of channels)
|
||||
GAPI_PROP_RW cv::Point org; //!< The bottom-left corner of the image
|
||||
GAPI_PROP_RW cv::Mat img; //!< Image to draw
|
||||
GAPI_PROP_RW cv::Mat alpha; //!< Alpha channel for image to draw (same size and number of channels)
|
||||
/*@{*/
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This structure represents a polygon to draw.
|
||||
*/
|
||||
struct Poly
|
||||
struct GAPI_EXPORTS_W_SIMPLE Poly
|
||||
{
|
||||
/**
|
||||
* @brief Mosaic constructor
|
||||
@@ -305,6 +315,7 @@ struct Poly
|
||||
* @param lt_ The Type of the line. See #LineTypes
|
||||
* @param shift_ The number of fractional bits in the point coordinate
|
||||
*/
|
||||
GAPI_WRAP
|
||||
Poly(const std::vector<cv::Point>& points_,
|
||||
const cv::Scalar& color_,
|
||||
int thick_ = 1,
|
||||
@@ -314,14 +325,15 @@ struct Poly
|
||||
{
|
||||
}
|
||||
|
||||
GAPI_WRAP
|
||||
Poly() = default;
|
||||
|
||||
/*@{*/
|
||||
std::vector<cv::Point> points; //!< Points to connect
|
||||
cv::Scalar color; //!< The line color
|
||||
int thick; //!< The thickness of line
|
||||
int lt; //!< The Type of the line. See #LineTypes
|
||||
int shift; //!< The number of fractional bits in the point coordinate
|
||||
GAPI_PROP_RW std::vector<cv::Point> points; //!< Points to connect
|
||||
GAPI_PROP_RW cv::Scalar color; //!< The line color
|
||||
GAPI_PROP_RW int thick; //!< The thickness of line
|
||||
GAPI_PROP_RW int lt; //!< The Type of the line. See #LineTypes
|
||||
GAPI_PROP_RW int shift; //!< The number of fractional bits in the point coordinate
|
||||
/*@{*/
|
||||
};
|
||||
|
||||
@@ -336,7 +348,7 @@ using Prim = util::variant
|
||||
, Poly
|
||||
>;
|
||||
|
||||
using Prims = std::vector<Prim>;
|
||||
using Prims = std::vector<Prim>;
|
||||
//! @} gapi_draw_prims
|
||||
|
||||
} // namespace draw
|
||||
|
||||
@@ -42,6 +42,9 @@ namespace cv {
|
||||
// performCalculations(in_view, out_view);
|
||||
// // data from out_view is transferred to the device when out_view is destroyed
|
||||
// }
|
||||
/** \addtogroup gapi_data_structures
|
||||
* @{
|
||||
*/
|
||||
class GAPI_EXPORTS RMat
|
||||
{
|
||||
public:
|
||||
@@ -146,6 +149,7 @@ private:
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
RMat make_rmat(Ts&&... args) { return { std::make_shared<T>(std::forward<Ts>(args)...) }; }
|
||||
/** @} */
|
||||
|
||||
} //namespace cv
|
||||
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
|
||||
namespace cv {
|
||||
namespace gapi {
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API serialization and
|
||||
* deserialization functions and data structures.
|
||||
*/
|
||||
namespace s11n {
|
||||
struct IOStream;
|
||||
struct IIStream;
|
||||
|
||||
@@ -38,6 +38,11 @@ enum class StereoOutputFormat {
|
||||
DISPARITY_16Q_11_4 = DISPARITY_FIXED16_12_4 ///< Same as DISPARITY_FIXED16_12_4
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API Operation Types for Stereo and
|
||||
* related functionality.
|
||||
*/
|
||||
namespace calib3d {
|
||||
|
||||
G_TYPED_KERNEL(GStereo, <GMat(GMat, GMat, const StereoOutputFormat)>, "org.opencv.stereo") {
|
||||
|
||||
@@ -74,7 +74,7 @@ e.g when graph's input needs to be passed directly to output, like in Streaming
|
||||
@param in Input image
|
||||
@return Copy of the input
|
||||
*/
|
||||
GAPI_EXPORTS GMat copy(const GMat& in);
|
||||
GAPI_EXPORTS_W GMat copy(const GMat& in);
|
||||
|
||||
/** @brief Makes a copy of the input frame. Note that this copy may be not real
|
||||
(no actual data copied). Use this function to maintain graph contracts,
|
||||
|
||||
@@ -42,6 +42,10 @@ struct GAPI_EXPORTS KalmanParams
|
||||
Mat controlMatrix;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This namespace contains G-API Operations and functions for
|
||||
* video-oriented algorithms, like optical flow and background subtraction.
|
||||
*/
|
||||
namespace video
|
||||
{
|
||||
using GBuildPyrOutput = std::tuple<GArray<GMat>, GScalar>;
|
||||
|
||||
@@ -11,6 +11,36 @@ def register(mname):
|
||||
return parameterized
|
||||
|
||||
|
||||
@register('cv2.gapi')
|
||||
def networks(*args):
|
||||
return cv.gapi_GNetPackage(list(map(cv.detail.strip, args)))
|
||||
|
||||
|
||||
@register('cv2.gapi')
|
||||
def compile_args(*args):
|
||||
return list(map(cv.GCompileArg, args))
|
||||
|
||||
|
||||
@register('cv2')
|
||||
def GIn(*args):
|
||||
return [*args]
|
||||
|
||||
|
||||
@register('cv2')
|
||||
def GOut(*args):
|
||||
return [*args]
|
||||
|
||||
|
||||
@register('cv2')
|
||||
def gin(*args):
|
||||
return [*args]
|
||||
|
||||
|
||||
@register('cv2.gapi')
|
||||
def descr_of(*args):
|
||||
return [*args]
|
||||
|
||||
|
||||
@register('cv2')
|
||||
class GOpaque():
|
||||
# NB: Inheritance from c++ class cause segfault.
|
||||
@@ -54,6 +84,10 @@ class GOpaque():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_RECT)
|
||||
|
||||
class Prim():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_DRAW_PRIM)
|
||||
|
||||
class Any():
|
||||
def __new__(self):
|
||||
return cv.GOpaqueT(cv.gapi.CV_ANY)
|
||||
@@ -113,6 +147,10 @@ class GArray():
|
||||
def __new__(self):
|
||||
return cv.GArrayT(cv.gapi.CV_GMAT)
|
||||
|
||||
class Prim():
|
||||
def __new__(self):
|
||||
return cv.GArray(cv.gapi.CV_DRAW_PRIM)
|
||||
|
||||
class Any():
|
||||
def __new__(self):
|
||||
return cv.GArray(cv.gapi.CV_ANY)
|
||||
@@ -134,6 +172,7 @@ def op(op_id, in_types, out_types):
|
||||
cv.GArray.Scalar: cv.gapi.CV_SCALAR,
|
||||
cv.GArray.Mat: cv.gapi.CV_MAT,
|
||||
cv.GArray.GMat: cv.gapi.CV_GMAT,
|
||||
cv.GArray.Prim: cv.gapi.CV_DRAW_PRIM,
|
||||
cv.GArray.Any: cv.gapi.CV_ANY
|
||||
}
|
||||
|
||||
@@ -149,22 +188,24 @@ def op(op_id, in_types, out_types):
|
||||
cv.GOpaque.Point2f: cv.gapi.CV_POINT2F,
|
||||
cv.GOpaque.Size: cv.gapi.CV_SIZE,
|
||||
cv.GOpaque.Rect: cv.gapi.CV_RECT,
|
||||
cv.GOpaque.Prim: cv.gapi.CV_DRAW_PRIM,
|
||||
cv.GOpaque.Any: cv.gapi.CV_ANY
|
||||
}
|
||||
|
||||
type2str = {
|
||||
cv.gapi.CV_BOOL: 'cv.gapi.CV_BOOL' ,
|
||||
cv.gapi.CV_INT: 'cv.gapi.CV_INT' ,
|
||||
cv.gapi.CV_DOUBLE: 'cv.gapi.CV_DOUBLE' ,
|
||||
cv.gapi.CV_FLOAT: 'cv.gapi.CV_FLOAT' ,
|
||||
cv.gapi.CV_STRING: 'cv.gapi.CV_STRING' ,
|
||||
cv.gapi.CV_POINT: 'cv.gapi.CV_POINT' ,
|
||||
cv.gapi.CV_POINT2F: 'cv.gapi.CV_POINT2F' ,
|
||||
cv.gapi.CV_SIZE: 'cv.gapi.CV_SIZE',
|
||||
cv.gapi.CV_RECT: 'cv.gapi.CV_RECT',
|
||||
cv.gapi.CV_SCALAR: 'cv.gapi.CV_SCALAR',
|
||||
cv.gapi.CV_MAT: 'cv.gapi.CV_MAT',
|
||||
cv.gapi.CV_GMAT: 'cv.gapi.CV_GMAT'
|
||||
cv.gapi.CV_BOOL: 'cv.gapi.CV_BOOL' ,
|
||||
cv.gapi.CV_INT: 'cv.gapi.CV_INT' ,
|
||||
cv.gapi.CV_DOUBLE: 'cv.gapi.CV_DOUBLE' ,
|
||||
cv.gapi.CV_FLOAT: 'cv.gapi.CV_FLOAT' ,
|
||||
cv.gapi.CV_STRING: 'cv.gapi.CV_STRING' ,
|
||||
cv.gapi.CV_POINT: 'cv.gapi.CV_POINT' ,
|
||||
cv.gapi.CV_POINT2F: 'cv.gapi.CV_POINT2F' ,
|
||||
cv.gapi.CV_SIZE: 'cv.gapi.CV_SIZE',
|
||||
cv.gapi.CV_RECT: 'cv.gapi.CV_RECT',
|
||||
cv.gapi.CV_SCALAR: 'cv.gapi.CV_SCALAR',
|
||||
cv.gapi.CV_MAT: 'cv.gapi.CV_MAT',
|
||||
cv.gapi.CV_GMAT: 'cv.gapi.CV_GMAT',
|
||||
cv.gapi.CV_DRAW_PRIM: 'cv.gapi.CV_DRAW_PRIM'
|
||||
}
|
||||
|
||||
# NB: Second lvl decorator takes class to decorate
|
||||
@@ -244,3 +285,13 @@ def kernel(op_cls):
|
||||
return cls
|
||||
|
||||
return kernel_with_params
|
||||
|
||||
|
||||
# FIXME: On the c++ side every class is placed in cv2 module.
|
||||
cv.gapi.wip.draw.Rect = cv.gapi_wip_draw_Rect
|
||||
cv.gapi.wip.draw.Text = cv.gapi_wip_draw_Text
|
||||
cv.gapi.wip.draw.Circle = cv.gapi_wip_draw_Circle
|
||||
cv.gapi.wip.draw.Line = cv.gapi_wip_draw_Line
|
||||
cv.gapi.wip.draw.Mosaic = cv.gapi_wip_draw_Mosaic
|
||||
cv.gapi.wip.draw.Image = cv.gapi_wip_draw_Image
|
||||
cv.gapi.wip.draw.Poly = cv.gapi_wip_draw_Poly
|
||||
|
||||
@@ -17,6 +17,7 @@ using gapi_ie_PyParams = cv::gapi::ie::PyParams;
|
||||
using gapi_wip_IStreamSource_Ptr = cv::Ptr<cv::gapi::wip::IStreamSource>;
|
||||
using detail_ExtractArgsCallback = cv::detail::ExtractArgsCallback;
|
||||
using detail_ExtractMetaCallback = cv::detail::ExtractMetaCallback;
|
||||
using vector_GNetParam = std::vector<cv::gapi::GNetParam>;
|
||||
|
||||
// NB: Python wrapper generate T_U for T<U>
|
||||
// This behavior is only observed for inputs
|
||||
@@ -42,6 +43,7 @@ using GArray_Rect = cv::GArray<cv::Rect>;
|
||||
using GArray_Scalar = cv::GArray<cv::Scalar>;
|
||||
using GArray_Mat = cv::GArray<cv::Mat>;
|
||||
using GArray_GMat = cv::GArray<cv::GMat>;
|
||||
using GArray_Prim = cv::GArray<cv::gapi::wip::draw::Prim>;
|
||||
|
||||
// FIXME: Python wrapper generate code without namespace std,
|
||||
// so it cause error: "string wasn't declared"
|
||||
@@ -124,6 +126,66 @@ PyObject* pyopencv_from(const cv::detail::PyObjectHolder& v)
|
||||
return o;
|
||||
}
|
||||
|
||||
// #FIXME: Is it possible to implement pyopencv_from/pyopencv_to for generic
|
||||
// cv::variant<Types...> ?
|
||||
template <>
|
||||
PyObject* pyopencv_from(const cv::gapi::wip::draw::Prim& prim)
|
||||
{
|
||||
switch (prim.index())
|
||||
{
|
||||
case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Rect>():
|
||||
return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Rect>(prim));
|
||||
case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Text>():
|
||||
return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Text>(prim));
|
||||
case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Circle>():
|
||||
return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Circle>(prim));
|
||||
case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Line>():
|
||||
return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Line>(prim));
|
||||
case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Poly>():
|
||||
return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Poly>(prim));
|
||||
case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Mosaic>():
|
||||
return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Mosaic>(prim));
|
||||
case cv::gapi::wip::draw::Prim::index_of<cv::gapi::wip::draw::Image>():
|
||||
return pyopencv_from(cv::util::get<cv::gapi::wip::draw::Image>(prim));
|
||||
}
|
||||
|
||||
util::throw_error(std::logic_error("Unsupported draw primitive type"));
|
||||
}
|
||||
|
||||
template <>
|
||||
PyObject* pyopencv_from(const cv::gapi::wip::draw::Prims& value)
|
||||
{
|
||||
return pyopencv_from_generic_vec(value);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prim& value, const ArgInfo& info)
|
||||
{
|
||||
#define TRY_EXTRACT(Prim) \
|
||||
if (PyObject_TypeCheck(obj, reinterpret_cast<PyTypeObject*>(pyopencv_gapi_wip_draw_##Prim##_TypePtr))) \
|
||||
{ \
|
||||
value = reinterpret_cast<pyopencv_gapi_wip_draw_##Prim##_t*>(obj)->v; \
|
||||
return true; \
|
||||
} \
|
||||
|
||||
TRY_EXTRACT(Rect)
|
||||
TRY_EXTRACT(Text)
|
||||
TRY_EXTRACT(Circle)
|
||||
TRY_EXTRACT(Line)
|
||||
TRY_EXTRACT(Mosaic)
|
||||
TRY_EXTRACT(Image)
|
||||
TRY_EXTRACT(Poly)
|
||||
|
||||
failmsg("Unsupported primitive type");
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool pyopencv_to(PyObject* obj, cv::gapi::wip::draw::Prims& value, const ArgInfo& info)
|
||||
{
|
||||
return pyopencv_to_generic_vec(obj, value, info);
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const cv::GArg& value)
|
||||
{
|
||||
@@ -136,20 +198,21 @@ PyObject* pyopencv_from(const cv::GArg& value)
|
||||
#define UNSUPPORTED(T) case cv::detail::OpaqueKind::CV_##T: break
|
||||
switch (value.opaque_kind)
|
||||
{
|
||||
HANDLE_CASE(BOOL, bool);
|
||||
HANDLE_CASE(INT, int);
|
||||
HANDLE_CASE(DOUBLE, double);
|
||||
HANDLE_CASE(FLOAT, float);
|
||||
HANDLE_CASE(STRING, std::string);
|
||||
HANDLE_CASE(POINT, cv::Point);
|
||||
HANDLE_CASE(POINT2F, cv::Point2f);
|
||||
HANDLE_CASE(SIZE, cv::Size);
|
||||
HANDLE_CASE(RECT, cv::Rect);
|
||||
HANDLE_CASE(SCALAR, cv::Scalar);
|
||||
HANDLE_CASE(MAT, cv::Mat);
|
||||
HANDLE_CASE(UNKNOWN, cv::detail::PyObjectHolder);
|
||||
HANDLE_CASE(BOOL, bool);
|
||||
HANDLE_CASE(INT, int);
|
||||
HANDLE_CASE(INT64, int64_t);
|
||||
HANDLE_CASE(DOUBLE, double);
|
||||
HANDLE_CASE(FLOAT, float);
|
||||
HANDLE_CASE(STRING, std::string);
|
||||
HANDLE_CASE(POINT, cv::Point);
|
||||
HANDLE_CASE(POINT2F, cv::Point2f);
|
||||
HANDLE_CASE(SIZE, cv::Size);
|
||||
HANDLE_CASE(RECT, cv::Rect);
|
||||
HANDLE_CASE(SCALAR, cv::Scalar);
|
||||
HANDLE_CASE(MAT, cv::Mat);
|
||||
HANDLE_CASE(UNKNOWN, cv::detail::PyObjectHolder);
|
||||
HANDLE_CASE(DRAW_PRIM, cv::gapi::wip::draw::Prim);
|
||||
UNSUPPORTED(UINT64);
|
||||
UNSUPPORTED(DRAW_PRIM);
|
||||
#undef HANDLE_CASE
|
||||
#undef UNSUPPORTED
|
||||
}
|
||||
@@ -163,6 +226,18 @@ bool pyopencv_to(PyObject* obj, cv::GArg& value, const ArgInfo& info)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool pyopencv_to(PyObject* obj, std::vector<cv::gapi::GNetParam>& value, const ArgInfo& info)
|
||||
{
|
||||
return pyopencv_to_generic_vec(obj, value, info);
|
||||
}
|
||||
|
||||
template <>
|
||||
PyObject* pyopencv_from(const std::vector<cv::gapi::GNetParam>& value)
|
||||
{
|
||||
return pyopencv_from_generic_vec(value);
|
||||
}
|
||||
|
||||
template <>
|
||||
bool pyopencv_to(PyObject* obj, std::vector<GCompileArg>& value, const ArgInfo& info)
|
||||
{
|
||||
@@ -175,12 +250,6 @@ PyObject* pyopencv_from(const std::vector<GCompileArg>& value)
|
||||
return pyopencv_from_generic_vec(value);
|
||||
}
|
||||
|
||||
template <>
|
||||
bool pyopencv_to(PyObject* obj, GRunArgs& value, const ArgInfo& info)
|
||||
{
|
||||
return pyopencv_to_generic_vec(obj, value, info);
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const cv::detail::OpaqueRef& o)
|
||||
{
|
||||
@@ -188,6 +257,7 @@ PyObject* pyopencv_from(const cv::detail::OpaqueRef& o)
|
||||
{
|
||||
case cv::detail::OpaqueKind::CV_BOOL : return pyopencv_from(o.rref<bool>());
|
||||
case cv::detail::OpaqueKind::CV_INT : return pyopencv_from(o.rref<int>());
|
||||
case cv::detail::OpaqueKind::CV_INT64 : return pyopencv_from(o.rref<int64_t>());
|
||||
case cv::detail::OpaqueKind::CV_DOUBLE : return pyopencv_from(o.rref<double>());
|
||||
case cv::detail::OpaqueKind::CV_FLOAT : return pyopencv_from(o.rref<float>());
|
||||
case cv::detail::OpaqueKind::CV_STRING : return pyopencv_from(o.rref<std::string>());
|
||||
@@ -196,10 +266,10 @@ PyObject* pyopencv_from(const cv::detail::OpaqueRef& o)
|
||||
case cv::detail::OpaqueKind::CV_SIZE : return pyopencv_from(o.rref<cv::Size>());
|
||||
case cv::detail::OpaqueKind::CV_RECT : return pyopencv_from(o.rref<cv::Rect>());
|
||||
case cv::detail::OpaqueKind::CV_UNKNOWN : return pyopencv_from(o.rref<cv::GArg>());
|
||||
case cv::detail::OpaqueKind::CV_DRAW_PRIM : return pyopencv_from(o.rref<cv::gapi::wip::draw::Prim>());
|
||||
case cv::detail::OpaqueKind::CV_UINT64 : break;
|
||||
case cv::detail::OpaqueKind::CV_SCALAR : break;
|
||||
case cv::detail::OpaqueKind::CV_MAT : break;
|
||||
case cv::detail::OpaqueKind::CV_DRAW_PRIM : break;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Unsupported GOpaque type");
|
||||
@@ -213,6 +283,7 @@ PyObject* pyopencv_from(const cv::detail::VectorRef& v)
|
||||
{
|
||||
case cv::detail::OpaqueKind::CV_BOOL : return pyopencv_from_generic_vec(v.rref<bool>());
|
||||
case cv::detail::OpaqueKind::CV_INT : return pyopencv_from_generic_vec(v.rref<int>());
|
||||
case cv::detail::OpaqueKind::CV_INT64 : return pyopencv_from_generic_vec(v.rref<int64_t>());
|
||||
case cv::detail::OpaqueKind::CV_DOUBLE : return pyopencv_from_generic_vec(v.rref<double>());
|
||||
case cv::detail::OpaqueKind::CV_FLOAT : return pyopencv_from_generic_vec(v.rref<float>());
|
||||
case cv::detail::OpaqueKind::CV_STRING : return pyopencv_from_generic_vec(v.rref<std::string>());
|
||||
@@ -223,8 +294,8 @@ PyObject* pyopencv_from(const cv::detail::VectorRef& v)
|
||||
case cv::detail::OpaqueKind::CV_SCALAR : return pyopencv_from_generic_vec(v.rref<cv::Scalar>());
|
||||
case cv::detail::OpaqueKind::CV_MAT : return pyopencv_from_generic_vec(v.rref<cv::Mat>());
|
||||
case cv::detail::OpaqueKind::CV_UNKNOWN : return pyopencv_from_generic_vec(v.rref<cv::GArg>());
|
||||
case cv::detail::OpaqueKind::CV_DRAW_PRIM : return pyopencv_from_generic_vec(v.rref<cv::gapi::wip::draw::Prim>());
|
||||
case cv::detail::OpaqueKind::CV_UINT64 : break;
|
||||
case cv::detail::OpaqueKind::CV_DRAW_PRIM : break;
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Unsupported GArray type");
|
||||
@@ -249,52 +320,69 @@ PyObject* pyopencv_from(const GRunArg& v)
|
||||
return pyopencv_from(util::get<cv::detail::OpaqueRef>(v));
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to unpack GRunArgs");
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to unpack GRunArgs. Index of variant is unknown");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PyObject* pyopencv_from(const cv::optional<T>& opt)
|
||||
{
|
||||
if (!opt.has_value())
|
||||
{
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
return pyopencv_from(*opt);
|
||||
}
|
||||
|
||||
template <>
|
||||
PyObject* pyopencv_from(const GOptRunArg& v)
|
||||
{
|
||||
switch (v.index())
|
||||
{
|
||||
case GOptRunArg::index_of<cv::optional<cv::Mat>>():
|
||||
return pyopencv_from(util::get<cv::optional<cv::Mat>>(v));
|
||||
|
||||
case GOptRunArg::index_of<cv::optional<cv::Scalar>>():
|
||||
return pyopencv_from(util::get<cv::optional<cv::Scalar>>(v));
|
||||
|
||||
case GOptRunArg::index_of<optional<cv::detail::VectorRef>>():
|
||||
return pyopencv_from(util::get<optional<cv::detail::VectorRef>>(v));
|
||||
|
||||
case GOptRunArg::index_of<optional<cv::detail::OpaqueRef>>():
|
||||
return pyopencv_from(util::get<optional<cv::detail::OpaqueRef>>(v));
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to unpack GOptRunArg. Index of variant is unknown");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const GRunArgs& value)
|
||||
{
|
||||
size_t i, n = value.size();
|
||||
|
||||
// NB: It doesn't make sense to return list with a single element
|
||||
if (n == 1)
|
||||
{
|
||||
PyObject* item = pyopencv_from(value[0]);
|
||||
if(!item)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
PyObject* list = PyList_New(n);
|
||||
for(i = 0; i < n; ++i)
|
||||
{
|
||||
PyObject* item = pyopencv_from(value[i]);
|
||||
if(!item)
|
||||
{
|
||||
Py_DECREF(list);
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to unpack GRunArgs");
|
||||
return NULL;
|
||||
}
|
||||
PyList_SetItem(list, i, item);
|
||||
}
|
||||
|
||||
return list;
|
||||
return value.size() == 1 ? pyopencv_from(value[0]) : pyopencv_from_generic_vec(value);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject* obj, GMetaArgs& value, const ArgInfo& info)
|
||||
PyObject* pyopencv_from(const GOptRunArgs& value)
|
||||
{
|
||||
return pyopencv_to_generic_vec(obj, value, info);
|
||||
return value.size() == 1 ? pyopencv_from(value[0]) : pyopencv_from_generic_vec(value);
|
||||
}
|
||||
|
||||
template<>
|
||||
PyObject* pyopencv_from(const GMetaArgs& value)
|
||||
// FIXME: cv::variant should be wrapped once for all types.
|
||||
template <>
|
||||
PyObject* pyopencv_from(const cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>& v)
|
||||
{
|
||||
return pyopencv_from_generic_vec(value);
|
||||
using RunArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
|
||||
switch (v.index())
|
||||
{
|
||||
case RunArgs::index_of<cv::GRunArgs>():
|
||||
return pyopencv_from(util::get<cv::GRunArgs>(v));
|
||||
case RunArgs::index_of<cv::GOptRunArgs>():
|
||||
return pyopencv_from(util::get<cv::GOptRunArgs>(v));
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Failed to recognize kind of RunArgs. Index of variant is unknown");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -318,16 +406,16 @@ void pyopencv_to_generic_vec_with_check(PyObject* from,
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static PyObject* extract_proto_args(PyObject* py_args, PyObject* kw)
|
||||
static T extract_proto_args(PyObject* py_args)
|
||||
{
|
||||
using namespace cv;
|
||||
|
||||
GProtoArgs args;
|
||||
Py_ssize_t size = PyTuple_Size(py_args);
|
||||
Py_ssize_t size = PyList_Size(py_args);
|
||||
args.reserve(size);
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
PyObject* item = PyTuple_GetItem(py_args, i);
|
||||
PyObject* item = PyList_GetItem(py_args, i);
|
||||
if (PyObject_TypeCheck(item, reinterpret_cast<PyTypeObject*>(pyopencv_GScalar_TypePtr)))
|
||||
{
|
||||
args.emplace_back(reinterpret_cast<pyopencv_GScalar_t*>(item)->v);
|
||||
@@ -346,22 +434,11 @@ static PyObject* extract_proto_args(PyObject* py_args, PyObject* kw)
|
||||
}
|
||||
else
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Unsupported type for cv.GIn()/cv.GOut()");
|
||||
return NULL;
|
||||
util::throw_error(std::logic_error("Unsupported type for GProtoArgs"));
|
||||
}
|
||||
}
|
||||
|
||||
return pyopencv_from<T>(T{std::move(args)});
|
||||
}
|
||||
|
||||
static PyObject* pyopencv_cv_GIn(PyObject* , PyObject* py_args, PyObject* kw)
|
||||
{
|
||||
return extract_proto_args<GProtoInputArgs>(py_args, kw);
|
||||
}
|
||||
|
||||
static PyObject* pyopencv_cv_GOut(PyObject* , PyObject* py_args, PyObject* kw)
|
||||
{
|
||||
return extract_proto_args<GProtoOutputArgs>(py_args, kw);
|
||||
return T(std::move(args));
|
||||
}
|
||||
|
||||
static cv::detail::OpaqueRef extract_opaque_ref(PyObject* from, cv::detail::OpaqueKind kind)
|
||||
@@ -386,6 +463,7 @@ static cv::detail::OpaqueRef extract_opaque_ref(PyObject* from, cv::detail::Opaq
|
||||
HANDLE_CASE(RECT, cv::Rect);
|
||||
HANDLE_CASE(UNKNOWN, cv::GArg);
|
||||
UNSUPPORTED(UINT64);
|
||||
UNSUPPORTED(INT64);
|
||||
UNSUPPORTED(SCALAR);
|
||||
UNSUPPORTED(MAT);
|
||||
UNSUPPORTED(DRAW_PRIM);
|
||||
@@ -406,20 +484,21 @@ static cv::detail::VectorRef extract_vector_ref(PyObject* from, cv::detail::Opaq
|
||||
#define UNSUPPORTED(T) case cv::detail::OpaqueKind::CV_##T: break
|
||||
switch (kind)
|
||||
{
|
||||
HANDLE_CASE(BOOL, bool);
|
||||
HANDLE_CASE(INT, int);
|
||||
HANDLE_CASE(DOUBLE, double);
|
||||
HANDLE_CASE(FLOAT, float);
|
||||
HANDLE_CASE(STRING, std::string);
|
||||
HANDLE_CASE(POINT, cv::Point);
|
||||
HANDLE_CASE(POINT2F, cv::Point2f);
|
||||
HANDLE_CASE(SIZE, cv::Size);
|
||||
HANDLE_CASE(RECT, cv::Rect);
|
||||
HANDLE_CASE(SCALAR, cv::Scalar);
|
||||
HANDLE_CASE(MAT, cv::Mat);
|
||||
HANDLE_CASE(UNKNOWN, cv::GArg);
|
||||
HANDLE_CASE(BOOL, bool);
|
||||
HANDLE_CASE(INT, int);
|
||||
HANDLE_CASE(DOUBLE, double);
|
||||
HANDLE_CASE(FLOAT, float);
|
||||
HANDLE_CASE(STRING, std::string);
|
||||
HANDLE_CASE(POINT, cv::Point);
|
||||
HANDLE_CASE(POINT2F, cv::Point2f);
|
||||
HANDLE_CASE(SIZE, cv::Size);
|
||||
HANDLE_CASE(RECT, cv::Rect);
|
||||
HANDLE_CASE(SCALAR, cv::Scalar);
|
||||
HANDLE_CASE(MAT, cv::Mat);
|
||||
HANDLE_CASE(UNKNOWN, cv::GArg);
|
||||
HANDLE_CASE(DRAW_PRIM, cv::gapi::wip::draw::Prim);
|
||||
UNSUPPORTED(UINT64);
|
||||
UNSUPPORTED(DRAW_PRIM);
|
||||
UNSUPPORTED(INT64);
|
||||
#undef HANDLE_CASE
|
||||
#undef UNSUPPORTED
|
||||
}
|
||||
@@ -470,13 +549,15 @@ static cv::GRunArg extract_run_arg(const cv::GTypeInfo& info, PyObject* item)
|
||||
|
||||
static cv::GRunArgs extract_run_args(const cv::GTypesInfo& info, PyObject* py_args)
|
||||
{
|
||||
cv::GRunArgs args;
|
||||
Py_ssize_t tuple_size = PyTuple_Size(py_args);
|
||||
args.reserve(tuple_size);
|
||||
GAPI_Assert(PyList_Check(py_args));
|
||||
|
||||
for (int i = 0; i < tuple_size; ++i)
|
||||
cv::GRunArgs args;
|
||||
Py_ssize_t list_size = PyList_Size(py_args);
|
||||
args.reserve(list_size);
|
||||
|
||||
for (int i = 0; i < list_size; ++i)
|
||||
{
|
||||
args.push_back(extract_run_arg(info[i], PyTuple_GetItem(py_args, i)));
|
||||
args.push_back(extract_run_arg(info[i], PyList_GetItem(py_args, i)));
|
||||
}
|
||||
|
||||
return args;
|
||||
@@ -517,13 +598,15 @@ static cv::GMetaArg extract_meta_arg(const cv::GTypeInfo& info, PyObject* item)
|
||||
|
||||
static cv::GMetaArgs extract_meta_args(const cv::GTypesInfo& info, PyObject* py_args)
|
||||
{
|
||||
cv::GMetaArgs metas;
|
||||
Py_ssize_t tuple_size = PyTuple_Size(py_args);
|
||||
metas.reserve(tuple_size);
|
||||
GAPI_Assert(PyList_Check(py_args));
|
||||
|
||||
for (int i = 0; i < tuple_size; ++i)
|
||||
cv::GMetaArgs metas;
|
||||
Py_ssize_t list_size = PyList_Size(py_args);
|
||||
metas.reserve(list_size);
|
||||
|
||||
for (int i = 0; i < list_size; ++i)
|
||||
{
|
||||
metas.push_back(extract_meta_arg(info[i], PyTuple_GetItem(py_args, i)));
|
||||
metas.push_back(extract_meta_arg(info[i], PyList_GetItem(py_args, i)));
|
||||
}
|
||||
|
||||
return metas;
|
||||
@@ -581,7 +664,8 @@ static cv::GRunArgs run_py_kernel(cv::detail::PyObjectHolder kernel,
|
||||
cv::detail::PyObjectHolder result(
|
||||
PyObject_CallObject(kernel.get(), args.get()), false);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
PyErr_PrintEx(0);
|
||||
PyErr_Clear();
|
||||
throw std::logic_error("Python kernel failed with error!");
|
||||
@@ -589,8 +673,27 @@ static cv::GRunArgs run_py_kernel(cv::detail::PyObjectHolder kernel,
|
||||
// NB: In fact it's impossible situation, becase errors were handled above.
|
||||
GAPI_Assert(result.get() && "Python kernel returned NULL!");
|
||||
|
||||
outs = out_info.size() == 1 ? cv::GRunArgs{extract_run_arg(out_info[0], result.get())}
|
||||
: extract_run_args(out_info, result.get());
|
||||
if (out_info.size() == 1)
|
||||
{
|
||||
outs = cv::GRunArgs{extract_run_arg(out_info[0], result.get())};
|
||||
}
|
||||
else if (out_info.size() > 1)
|
||||
{
|
||||
GAPI_Assert(PyTuple_Check(result.get()));
|
||||
|
||||
Py_ssize_t tuple_size = PyTuple_Size(result.get());
|
||||
outs.reserve(tuple_size);
|
||||
|
||||
for (int i = 0; i < tuple_size; ++i)
|
||||
{
|
||||
outs.push_back(extract_run_arg(out_info[i], PyTuple_GetItem(result.get(), i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Seems to be impossible case.
|
||||
GAPI_Assert(false);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@@ -645,8 +748,9 @@ static cv::GMetaArgs get_meta_args(PyObject* tuple)
|
||||
}
|
||||
|
||||
static GMetaArgs run_py_meta(cv::detail::PyObjectHolder out_meta,
|
||||
const cv::GMetaArgs &meta,
|
||||
const cv::GArgs &gargs) {
|
||||
const cv::GMetaArgs &meta,
|
||||
const cv::GArgs &gargs)
|
||||
{
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
@@ -688,7 +792,8 @@ static GMetaArgs run_py_meta(cv::detail::PyObjectHolder out_meta,
|
||||
cv::detail::PyObjectHolder result(
|
||||
PyObject_CallObject(out_meta.get(), args.get()), false);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
PyErr_PrintEx(0);
|
||||
PyErr_Clear();
|
||||
throw std::logic_error("Python outMeta failed with error!");
|
||||
@@ -720,21 +825,24 @@ static PyObject* pyopencv_cv_gapi_kernels(PyObject* , PyObject* py_args, PyObjec
|
||||
PyObject* user_kernel = PyTuple_GetItem(py_args, i);
|
||||
|
||||
PyObject* id_obj = PyObject_GetAttrString(user_kernel, "id");
|
||||
if (!id_obj) {
|
||||
if (!id_obj)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Python kernel should contain id, please use cv.gapi.kernel to define kernel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* out_meta = PyObject_GetAttrString(user_kernel, "outMeta");
|
||||
if (!out_meta) {
|
||||
if (!out_meta)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Python kernel should contain outMeta, please use cv.gapi.kernel to define kernel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* run = PyObject_GetAttrString(user_kernel, "run");
|
||||
if (!run) {
|
||||
if (!run)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Python kernel should contain run, please use cv.gapi.kernel to define kernel");
|
||||
return NULL;
|
||||
@@ -756,23 +864,6 @@ static PyObject* pyopencv_cv_gapi_kernels(PyObject* , PyObject* py_args, PyObjec
|
||||
return pyopencv_from(pkg);
|
||||
}
|
||||
|
||||
static PyObject* pyopencv_cv_gapi_networks(PyObject*, PyObject* py_args, PyObject*)
|
||||
{
|
||||
using namespace cv;
|
||||
gapi::GNetPackage pkg;
|
||||
Py_ssize_t size = PyTuple_Size(py_args);
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
gapi_ie_PyParams params;
|
||||
PyObject* item = PyTuple_GetItem(py_args, i);
|
||||
if (pyopencv_to(item, params, ArgInfo("PyParams", false)))
|
||||
{
|
||||
pkg += gapi::networks(params);
|
||||
}
|
||||
}
|
||||
return pyopencv_from(pkg);
|
||||
}
|
||||
|
||||
static PyObject* pyopencv_cv_gapi_op(PyObject* , PyObject* py_args, PyObject*)
|
||||
{
|
||||
using namespace cv;
|
||||
@@ -834,53 +925,54 @@ static PyObject* pyopencv_cv_gapi_op(PyObject* , PyObject* py_args, PyObject*)
|
||||
return pyopencv_from(cv::gapi::wip::op(id, outMetaWrapper, std::move(args)));
|
||||
}
|
||||
|
||||
static PyObject* pyopencv_cv_gin(PyObject*, PyObject* py_args, PyObject*)
|
||||
template<>
|
||||
bool pyopencv_to(PyObject* obj, cv::detail::ExtractArgsCallback& value, const ArgInfo&)
|
||||
{
|
||||
cv::detail::PyObjectHolder holder{py_args};
|
||||
auto callback = cv::detail::ExtractArgsCallback{[=](const cv::GTypesInfo& info)
|
||||
cv::detail::PyObjectHolder holder{obj};
|
||||
value = cv::detail::ExtractArgsCallback{[=](const cv::GTypesInfo& info)
|
||||
{
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
cv::GRunArgs args;
|
||||
try
|
||||
{
|
||||
args = extract_run_args(info, holder.get());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
cv::GRunArgs args;
|
||||
try
|
||||
{
|
||||
args = extract_run_args(info, holder.get());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
PyGILState_Release(gstate);
|
||||
throw;
|
||||
}
|
||||
PyGILState_Release(gstate);
|
||||
return args;
|
||||
}};
|
||||
|
||||
return pyopencv_from(callback);
|
||||
throw;
|
||||
}
|
||||
PyGILState_Release(gstate);
|
||||
return args;
|
||||
}};
|
||||
return true;
|
||||
}
|
||||
|
||||
static PyObject* pyopencv_cv_descr_of(PyObject*, PyObject* py_args, PyObject*)
|
||||
template<>
|
||||
bool pyopencv_to(PyObject* obj, cv::detail::ExtractMetaCallback& value, const ArgInfo&)
|
||||
{
|
||||
Py_INCREF(py_args);
|
||||
auto callback = cv::detail::ExtractMetaCallback{[=](const cv::GTypesInfo& info)
|
||||
{
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
cv::detail::PyObjectHolder holder{obj};
|
||||
value = cv::detail::ExtractMetaCallback{[=](const cv::GTypesInfo& info)
|
||||
{
|
||||
PyGILState_STATE gstate;
|
||||
gstate = PyGILState_Ensure();
|
||||
|
||||
cv::GMetaArgs args;
|
||||
try
|
||||
{
|
||||
args = extract_meta_args(info, py_args);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
PyGILState_Release(gstate);
|
||||
throw;
|
||||
}
|
||||
cv::GMetaArgs args;
|
||||
try
|
||||
{
|
||||
args = extract_meta_args(info, holder.get());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
PyGILState_Release(gstate);
|
||||
return args;
|
||||
}};
|
||||
return pyopencv_from(callback);
|
||||
throw;
|
||||
}
|
||||
PyGILState_Release(gstate);
|
||||
return args;
|
||||
}};
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -895,9 +987,12 @@ struct PyOpenCV_Converter<cv::GArray<T>>
|
||||
if (PyObject_TypeCheck(obj, reinterpret_cast<PyTypeObject*>(pyopencv_GArrayT_TypePtr)))
|
||||
{
|
||||
auto& array = reinterpret_cast<pyopencv_GArrayT_t*>(obj)->v;
|
||||
try {
|
||||
try
|
||||
{
|
||||
value = cv::util::get<cv::GArray<T>>(array.arg());
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -918,9 +1013,12 @@ struct PyOpenCV_Converter<cv::GOpaque<T>>
|
||||
if (PyObject_TypeCheck(obj, reinterpret_cast<PyTypeObject*>(pyopencv_GOpaqueT_TypePtr)))
|
||||
{
|
||||
auto& opaque = reinterpret_cast<pyopencv_GOpaqueT_t*>(obj)->v;
|
||||
try {
|
||||
try
|
||||
{
|
||||
value = cv::util::get<cv::GOpaque<T>>(opaque.arg());
|
||||
} catch (...) {
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -929,11 +1027,39 @@ struct PyOpenCV_Converter<cv::GOpaque<T>>
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject* obj, cv::GProtoInputArgs& value, const ArgInfo& info)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = extract_proto_args<cv::GProtoInputArgs>(obj);
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
failmsg("Can't parse cv::GProtoInputArgs");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
bool pyopencv_to(PyObject* obj, cv::GProtoOutputArgs& value, const ArgInfo& info)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = extract_proto_args<cv::GProtoOutputArgs>(obj);
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
failmsg("Can't parse cv::GProtoOutputArgs");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// extend cv.gapi methods
|
||||
#define PYOPENCV_EXTRA_METHODS_GAPI \
|
||||
{"kernels", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_kernels), "kernels(...) -> GKernelPackage"}, \
|
||||
{"networks", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_networks), "networks(...) -> GNetPackage"}, \
|
||||
{"__op", CV_PY_FN_WITH_KW(pyopencv_cv_gapi_op), "__op(...) -> retval\n"},
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <opencv2/gapi.hpp>
|
||||
#include <opencv2/gapi/garg.hpp>
|
||||
#include <opencv2/gapi/gopaque.hpp>
|
||||
#include <opencv2/gapi/render/render_types.hpp> // Prim
|
||||
|
||||
#define ID(T, E) T
|
||||
#define ID_(T, E) ID(T, E),
|
||||
@@ -24,24 +25,29 @@
|
||||
GAPI_Assert(false && "Unsupported type"); \
|
||||
}
|
||||
|
||||
using cv::gapi::wip::draw::Prim;
|
||||
|
||||
#define GARRAY_TYPE_LIST_G(G, G2) \
|
||||
WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \
|
||||
WRAP_ARGS(int , cv::gapi::ArgType::CV_INT, G) \
|
||||
WRAP_ARGS(double , cv::gapi::ArgType::CV_DOUBLE, G) \
|
||||
WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \
|
||||
WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, G) \
|
||||
WRAP_ARGS(cv::Point , cv::gapi::ArgType::CV_POINT, G) \
|
||||
WRAP_ARGS(cv::Point2f , cv::gapi::ArgType::CV_POINT2F, G) \
|
||||
WRAP_ARGS(cv::Size , cv::gapi::ArgType::CV_SIZE, G) \
|
||||
WRAP_ARGS(cv::Rect , cv::gapi::ArgType::CV_RECT, G) \
|
||||
WRAP_ARGS(cv::Scalar , cv::gapi::ArgType::CV_SCALAR, G) \
|
||||
WRAP_ARGS(cv::Mat , cv::gapi::ArgType::CV_MAT, G) \
|
||||
WRAP_ARGS(cv::GArg , cv::gapi::ArgType::CV_ANY, G) \
|
||||
WRAP_ARGS(cv::GMat , cv::gapi::ArgType::CV_GMAT, G2) \
|
||||
WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \
|
||||
WRAP_ARGS(int , cv::gapi::ArgType::CV_INT, G) \
|
||||
WRAP_ARGS(int64_t , cv::gapi::ArgType::CV_INT64, G) \
|
||||
WRAP_ARGS(double , cv::gapi::ArgType::CV_DOUBLE, G) \
|
||||
WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \
|
||||
WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, G) \
|
||||
WRAP_ARGS(cv::Point , cv::gapi::ArgType::CV_POINT, G) \
|
||||
WRAP_ARGS(cv::Point2f , cv::gapi::ArgType::CV_POINT2F, G) \
|
||||
WRAP_ARGS(cv::Size , cv::gapi::ArgType::CV_SIZE, G) \
|
||||
WRAP_ARGS(cv::Rect , cv::gapi::ArgType::CV_RECT, G) \
|
||||
WRAP_ARGS(cv::Scalar , cv::gapi::ArgType::CV_SCALAR, G) \
|
||||
WRAP_ARGS(cv::Mat , cv::gapi::ArgType::CV_MAT, G) \
|
||||
WRAP_ARGS(Prim , cv::gapi::ArgType::CV_DRAW_PRIM, G) \
|
||||
WRAP_ARGS(cv::GArg , cv::gapi::ArgType::CV_ANY, G) \
|
||||
WRAP_ARGS(cv::GMat , cv::gapi::ArgType::CV_GMAT, G2) \
|
||||
|
||||
#define GOPAQUE_TYPE_LIST_G(G, G2) \
|
||||
WRAP_ARGS(bool , cv::gapi::ArgType::CV_BOOL, G) \
|
||||
WRAP_ARGS(int , cv::gapi::ArgType::CV_INT, G) \
|
||||
WRAP_ARGS(int64_t , cv::gapi::ArgType::CV_INT64, G) \
|
||||
WRAP_ARGS(double , cv::gapi::ArgType::CV_DOUBLE, G) \
|
||||
WRAP_ARGS(float , cv::gapi::ArgType::CV_FLOAT, G) \
|
||||
WRAP_ARGS(std::string , cv::gapi::ArgType::CV_STRING, G) \
|
||||
@@ -58,6 +64,7 @@ namespace gapi {
|
||||
enum ArgType {
|
||||
CV_BOOL,
|
||||
CV_INT,
|
||||
CV_INT64,
|
||||
CV_DOUBLE,
|
||||
CV_FLOAT,
|
||||
CV_STRING,
|
||||
@@ -68,6 +75,7 @@ enum ArgType {
|
||||
CV_SCALAR,
|
||||
CV_MAT,
|
||||
CV_GMAT,
|
||||
CV_DRAW_PRIM,
|
||||
CV_ANY,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,467 @@
|
||||
import argparse
|
||||
import time
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
|
||||
# ------------------------Service operations------------------------
|
||||
def weight_path(model_path):
|
||||
""" Get path of weights based on path to IR
|
||||
|
||||
Params:
|
||||
model_path: the string contains path to IR file
|
||||
|
||||
Return:
|
||||
Path to weights file
|
||||
"""
|
||||
assert model_path.endswith('.xml'), "Wrong topology path was provided"
|
||||
return model_path[:-3] + 'bin'
|
||||
|
||||
|
||||
def build_argparser():
|
||||
""" Parse arguments from command line
|
||||
|
||||
Return:
|
||||
Pack of arguments from command line
|
||||
"""
|
||||
parser = argparse.ArgumentParser(description='This is an OpenCV-based version of Gaze Estimation example')
|
||||
|
||||
parser.add_argument('--input',
|
||||
help='Path to the input video file')
|
||||
parser.add_argument('--out',
|
||||
help='Path to the output video file')
|
||||
parser.add_argument('--facem',
|
||||
default='face-detection-retail-0005.xml',
|
||||
help='Path to OpenVINO face detection model (.xml)')
|
||||
parser.add_argument('--faced',
|
||||
default='CPU',
|
||||
help='Target device for the face detection' +
|
||||
'(e.g. CPU, GPU, VPU, ...)')
|
||||
parser.add_argument('--headm',
|
||||
default='head-pose-estimation-adas-0001.xml',
|
||||
help='Path to OpenVINO head pose estimation model (.xml)')
|
||||
parser.add_argument('--headd',
|
||||
default='CPU',
|
||||
help='Target device for the head pose estimation inference ' +
|
||||
'(e.g. CPU, GPU, VPU, ...)')
|
||||
parser.add_argument('--landm',
|
||||
default='facial-landmarks-35-adas-0002.xml',
|
||||
help='Path to OpenVINO landmarks detector model (.xml)')
|
||||
parser.add_argument('--landd',
|
||||
default='CPU',
|
||||
help='Target device for the landmarks detector (e.g. CPU, GPU, VPU, ...)')
|
||||
parser.add_argument('--gazem',
|
||||
default='gaze-estimation-adas-0002.xml',
|
||||
help='Path to OpenVINO gaze vector estimaiton model (.xml)')
|
||||
parser.add_argument('--gazed',
|
||||
default='CPU',
|
||||
help='Target device for the gaze vector estimation inference ' +
|
||||
'(e.g. CPU, GPU, VPU, ...)')
|
||||
parser.add_argument('--eyem',
|
||||
default='open-closed-eye-0001.xml',
|
||||
help='Path to OpenVINO open closed eye model (.xml)')
|
||||
parser.add_argument('--eyed',
|
||||
default='CPU',
|
||||
help='Target device for the eyes state inference (e.g. CPU, GPU, VPU, ...)')
|
||||
return parser
|
||||
|
||||
|
||||
# ------------------------Support functions for custom kernels------------------------
|
||||
def intersection(surface, rect):
|
||||
""" Remove zone of out of bound from ROI
|
||||
|
||||
Params:
|
||||
surface: image bounds is rect representation (top left coordinates and width and height)
|
||||
rect: region of interest is also has rect representation
|
||||
|
||||
Return:
|
||||
Modified ROI with correct bounds
|
||||
"""
|
||||
l_x = max(surface[0], rect[0])
|
||||
l_y = max(surface[1], rect[1])
|
||||
width = min(surface[0] + surface[2], rect[0] + rect[2]) - l_x
|
||||
height = min(surface[1] + surface[3], rect[1] + rect[3]) - l_y
|
||||
if width < 0 or height < 0:
|
||||
return (0, 0, 0, 0)
|
||||
return (l_x, l_y, width, height)
|
||||
|
||||
|
||||
def process_landmarks(r_x, r_y, r_w, r_h, landmarks):
|
||||
""" Create points from result of inference of facial-landmarks network and size of input image
|
||||
|
||||
Params:
|
||||
r_x: x coordinate of top left corner of input image
|
||||
r_y: y coordinate of top left corner of input image
|
||||
r_w: width of input image
|
||||
r_h: height of input image
|
||||
landmarks: result of inference of facial-landmarks network
|
||||
|
||||
Return:
|
||||
Array of landmarks points for one face
|
||||
"""
|
||||
lmrks = landmarks[0]
|
||||
raw_x = lmrks[::2] * r_w + r_x
|
||||
raw_y = lmrks[1::2] * r_h + r_y
|
||||
return np.array([[int(x), int(y)] for x, y in zip(raw_x, raw_y)])
|
||||
|
||||
|
||||
def eye_box(p_1, p_2, scale=1.8):
|
||||
""" Get bounding box of eye
|
||||
|
||||
Params:
|
||||
p_1: point of left edge of eye
|
||||
p_2: point of right edge of eye
|
||||
scale: change size of box with this value
|
||||
|
||||
Return:
|
||||
Bounding box of eye and its midpoint
|
||||
"""
|
||||
|
||||
size = np.linalg.norm(p_1 - p_2)
|
||||
midpoint = (p_1 + p_2) / 2
|
||||
width = scale * size
|
||||
height = width
|
||||
p_x = midpoint[0] - (width / 2)
|
||||
p_y = midpoint[1] - (height / 2)
|
||||
return (int(p_x), int(p_y), int(width), int(height)), list(map(int, midpoint))
|
||||
|
||||
|
||||
# ------------------------Custom graph operations------------------------
|
||||
@cv.gapi.op('custom.GProcessPoses',
|
||||
in_types=[cv.GArray.GMat, cv.GArray.GMat, cv.GArray.GMat],
|
||||
out_types=[cv.GArray.GMat])
|
||||
class GProcessPoses:
|
||||
@staticmethod
|
||||
def outMeta(arr_desc0, arr_desc1, arr_desc2):
|
||||
return cv.empty_array_desc()
|
||||
|
||||
|
||||
@cv.gapi.op('custom.GParseEyes',
|
||||
in_types=[cv.GArray.GMat, cv.GArray.Rect, cv.GOpaque.Size],
|
||||
out_types=[cv.GArray.Rect, cv.GArray.Rect, cv.GArray.Point, cv.GArray.Point])
|
||||
class GParseEyes:
|
||||
@staticmethod
|
||||
def outMeta(arr_desc0, arr_desc1, arr_desc2):
|
||||
return cv.empty_array_desc(), cv.empty_array_desc(), \
|
||||
cv.empty_array_desc(), cv.empty_array_desc()
|
||||
|
||||
|
||||
@cv.gapi.op('custom.GGetStates',
|
||||
in_types=[cv.GArray.GMat, cv.GArray.GMat],
|
||||
out_types=[cv.GArray.Int, cv.GArray.Int])
|
||||
class GGetStates:
|
||||
@staticmethod
|
||||
def outMeta(arr_desc0, arr_desc1):
|
||||
return cv.empty_array_desc(), cv.empty_array_desc()
|
||||
|
||||
|
||||
# ------------------------Custom kernels------------------------
|
||||
@cv.gapi.kernel(GProcessPoses)
|
||||
class GProcessPosesImpl:
|
||||
""" Custom kernel. Processed poses of heads
|
||||
"""
|
||||
@staticmethod
|
||||
def run(in_ys, in_ps, in_rs):
|
||||
""" Сustom kernel executable code
|
||||
|
||||
Params:
|
||||
in_ys: yaw angle of head
|
||||
in_ps: pitch angle of head
|
||||
in_rs: roll angle of head
|
||||
|
||||
Return:
|
||||
Arrays with heads poses
|
||||
"""
|
||||
out_poses = []
|
||||
size = len(in_ys)
|
||||
for i in range(size):
|
||||
out_poses.append(np.array([in_ys[i][0], in_ps[i][0], in_rs[i][0]]).T)
|
||||
return out_poses
|
||||
|
||||
|
||||
@cv.gapi.kernel(GParseEyes)
|
||||
class GParseEyesImpl:
|
||||
""" Custom kernel. Get information about eyes
|
||||
"""
|
||||
@staticmethod
|
||||
def run(in_landm_per_face, in_face_rcs, frame_size):
|
||||
""" Сustom kernel executable code
|
||||
|
||||
Params:
|
||||
in_landm_per_face: landmarks from inference of facial-landmarks network for each face
|
||||
in_face_rcs: bounding boxes for each face
|
||||
frame_size: size of input image
|
||||
|
||||
Return:
|
||||
Arrays of ROI for left and right eyes, array of midpoints and
|
||||
array of landmarks points
|
||||
"""
|
||||
left_eyes = []
|
||||
right_eyes = []
|
||||
midpoints = []
|
||||
lmarks = []
|
||||
num_faces = len(in_landm_per_face)
|
||||
surface = (0, 0, *frame_size)
|
||||
for i in range(num_faces):
|
||||
rect = in_face_rcs[i]
|
||||
points = process_landmarks(*rect, in_landm_per_face[i])
|
||||
for p in points:
|
||||
lmarks.append(p)
|
||||
size = int(len(in_landm_per_face[i][0]) / 2)
|
||||
|
||||
rect, midpoint_l = eye_box(lmarks[0 + i * size], lmarks[1 + i * size])
|
||||
left_eyes.append(intersection(surface, rect))
|
||||
rect, midpoint_r = eye_box(lmarks[2 + i * size], lmarks[3 + i * size])
|
||||
right_eyes.append(intersection(surface, rect))
|
||||
midpoints += [midpoint_l, midpoint_r]
|
||||
return left_eyes, right_eyes, midpoints, lmarks
|
||||
|
||||
|
||||
@cv.gapi.kernel(GGetStates)
|
||||
class GGetStatesImpl:
|
||||
""" Custom kernel. Get state of eye - open or closed
|
||||
"""
|
||||
@staticmethod
|
||||
def run(eyesl, eyesr):
|
||||
""" Сustom kernel executable code
|
||||
|
||||
Params:
|
||||
eyesl: result of inference of open-closed-eye network for left eye
|
||||
eyesr: result of inference of open-closed-eye network for right eye
|
||||
|
||||
Return:
|
||||
States of left eyes and states of right eyes
|
||||
"""
|
||||
size = len(eyesl)
|
||||
out_l_st = []
|
||||
out_r_st = []
|
||||
for i in range(size):
|
||||
for st in eyesl[i]:
|
||||
out_l_st += [1 if st[0] < st[1] else 0]
|
||||
for st in eyesr[i]:
|
||||
out_r_st += [1 if st[0] < st[1] else 0]
|
||||
return out_l_st, out_r_st
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ARGUMENTS = build_argparser().parse_args()
|
||||
|
||||
# ------------------------Demo's graph------------------------
|
||||
g_in = cv.GMat()
|
||||
|
||||
# Detect faces
|
||||
face_inputs = cv.GInferInputs()
|
||||
face_inputs.setInput('data', g_in)
|
||||
face_outputs = cv.gapi.infer('face-detection', face_inputs)
|
||||
faces = face_outputs.at('detection_out')
|
||||
|
||||
# Parse faces
|
||||
sz = cv.gapi.streaming.size(g_in)
|
||||
faces_rc = cv.gapi.parseSSD(faces, sz, 0.5, False, False)
|
||||
|
||||
# Detect poses
|
||||
head_inputs = cv.GInferInputs()
|
||||
head_inputs.setInput('data', g_in)
|
||||
face_outputs = cv.gapi.infer('head-pose', faces_rc, head_inputs)
|
||||
angles_y = face_outputs.at('angle_y_fc')
|
||||
angles_p = face_outputs.at('angle_p_fc')
|
||||
angles_r = face_outputs.at('angle_r_fc')
|
||||
|
||||
# Parse poses
|
||||
heads_pos = GProcessPoses.on(angles_y, angles_p, angles_r)
|
||||
|
||||
# Detect landmarks
|
||||
landmark_inputs = cv.GInferInputs()
|
||||
landmark_inputs.setInput('data', g_in)
|
||||
landmark_outputs = cv.gapi.infer('facial-landmarks', faces_rc,
|
||||
landmark_inputs)
|
||||
landmark = landmark_outputs.at('align_fc3')
|
||||
|
||||
# Parse landmarks
|
||||
left_eyes, right_eyes, mids, lmarks = GParseEyes.on(landmark, faces_rc, sz)
|
||||
|
||||
# Detect eyes
|
||||
eyes_inputs = cv.GInferInputs()
|
||||
eyes_inputs.setInput('input.1', g_in)
|
||||
eyesl_outputs = cv.gapi.infer('open-closed-eye', left_eyes, eyes_inputs)
|
||||
eyesr_outputs = cv.gapi.infer('open-closed-eye', right_eyes, eyes_inputs)
|
||||
eyesl = eyesl_outputs.at('19')
|
||||
eyesr = eyesr_outputs.at('19')
|
||||
|
||||
# Process eyes states
|
||||
l_eye_st, r_eye_st = GGetStates.on(eyesl, eyesr)
|
||||
|
||||
# Gaze estimation
|
||||
gaze_inputs = cv.GInferListInputs()
|
||||
gaze_inputs.setInput('left_eye_image', left_eyes)
|
||||
gaze_inputs.setInput('right_eye_image', right_eyes)
|
||||
gaze_inputs.setInput('head_pose_angles', heads_pos)
|
||||
gaze_outputs = cv.gapi.infer2('gaze-estimation', g_in, gaze_inputs)
|
||||
gaze_vectors = gaze_outputs.at('gaze_vector')
|
||||
|
||||
out = cv.gapi.copy(g_in)
|
||||
# ------------------------End of graph------------------------
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(out,
|
||||
faces_rc,
|
||||
left_eyes,
|
||||
right_eyes,
|
||||
gaze_vectors,
|
||||
angles_y,
|
||||
angles_p,
|
||||
angles_r,
|
||||
l_eye_st,
|
||||
r_eye_st,
|
||||
mids,
|
||||
lmarks))
|
||||
|
||||
# Networks
|
||||
face_net = cv.gapi.ie.params('face-detection', ARGUMENTS.facem,
|
||||
weight_path(ARGUMENTS.facem), ARGUMENTS.faced)
|
||||
head_pose_net = cv.gapi.ie.params('head-pose', ARGUMENTS.headm,
|
||||
weight_path(ARGUMENTS.headm), ARGUMENTS.headd)
|
||||
landmarks_net = cv.gapi.ie.params('facial-landmarks', ARGUMENTS.landm,
|
||||
weight_path(ARGUMENTS.landm), ARGUMENTS.landd)
|
||||
gaze_net = cv.gapi.ie.params('gaze-estimation', ARGUMENTS.gazem,
|
||||
weight_path(ARGUMENTS.gazem), ARGUMENTS.gazed)
|
||||
eye_net = cv.gapi.ie.params('open-closed-eye', ARGUMENTS.eyem,
|
||||
weight_path(ARGUMENTS.eyem), ARGUMENTS.eyed)
|
||||
|
||||
nets = cv.gapi.networks(face_net, head_pose_net, landmarks_net, gaze_net, eye_net)
|
||||
|
||||
# Kernels pack
|
||||
kernels = cv.gapi.kernels(GParseEyesImpl, GProcessPosesImpl, GGetStatesImpl)
|
||||
|
||||
# ------------------------Execution part------------------------
|
||||
ccomp = comp.compileStreaming(args=cv.gapi.compile_args(kernels, nets))
|
||||
source = cv.gapi.wip.make_capture_src(ARGUMENTS.input)
|
||||
ccomp.setSource(cv.gin(source))
|
||||
ccomp.start()
|
||||
|
||||
frames = 0
|
||||
fps = 0
|
||||
print('Processing')
|
||||
START_TIME = time.time()
|
||||
|
||||
while True:
|
||||
start_time_cycle = time.time()
|
||||
has_frame, (oimg,
|
||||
outr,
|
||||
l_eyes,
|
||||
r_eyes,
|
||||
outg,
|
||||
out_y,
|
||||
out_p,
|
||||
out_r,
|
||||
out_st_l,
|
||||
out_st_r,
|
||||
out_mids,
|
||||
outl) = ccomp.pull()
|
||||
|
||||
if not has_frame:
|
||||
break
|
||||
|
||||
# Draw
|
||||
GREEN = (0, 255, 0)
|
||||
RED = (0, 0, 255)
|
||||
WHITE = (255, 255, 255)
|
||||
BLUE = (255, 0, 0)
|
||||
PINK = (255, 0, 255)
|
||||
YELLOW = (0, 255, 255)
|
||||
|
||||
M_PI_180 = np.pi / 180
|
||||
M_PI_2 = np.pi / 2
|
||||
M_PI = np.pi
|
||||
|
||||
FACES_SIZE = len(outr)
|
||||
|
||||
for i, out_rect in enumerate(outr):
|
||||
# Face box
|
||||
cv.rectangle(oimg, out_rect, WHITE, 1)
|
||||
rx, ry, rwidth, rheight = out_rect
|
||||
|
||||
# Landmarks
|
||||
lm_radius = int(0.01 * rwidth + 1)
|
||||
lmsize = int(len(outl) / FACES_SIZE)
|
||||
for j in range(lmsize):
|
||||
cv.circle(oimg, outl[j + i * lmsize], lm_radius, YELLOW, -1)
|
||||
|
||||
# Headposes
|
||||
yaw = out_y[i]
|
||||
pitch = out_p[i]
|
||||
roll = out_r[i]
|
||||
sin_y = np.sin(yaw[:] * M_PI_180)
|
||||
sin_p = np.sin(pitch[:] * M_PI_180)
|
||||
sin_r = np.sin(roll[:] * M_PI_180)
|
||||
|
||||
cos_y = np.cos(yaw[:] * M_PI_180)
|
||||
cos_p = np.cos(pitch[:] * M_PI_180)
|
||||
cos_r = np.cos(roll[:] * M_PI_180)
|
||||
|
||||
axis_length = 0.4 * rwidth
|
||||
x_center = int(rx + rwidth / 2)
|
||||
y_center = int(ry + rheight / 2)
|
||||
|
||||
# center to right
|
||||
cv.line(oimg, [x_center, y_center],
|
||||
[int(x_center + axis_length * (cos_r * cos_y + sin_y * sin_p * sin_r)),
|
||||
int(y_center + axis_length * cos_p * sin_r)],
|
||||
RED, 2)
|
||||
|
||||
# center to top
|
||||
cv.line(oimg, [x_center, y_center],
|
||||
[int(x_center + axis_length * (cos_r * sin_y * sin_p + cos_y * sin_r)),
|
||||
int(y_center - axis_length * cos_p * cos_r)],
|
||||
GREEN, 2)
|
||||
|
||||
# center to forward
|
||||
cv.line(oimg, [x_center, y_center],
|
||||
[int(x_center + axis_length * sin_y * cos_p),
|
||||
int(y_center + axis_length * sin_p)],
|
||||
PINK, 2)
|
||||
|
||||
scale_box = 0.002 * rwidth
|
||||
cv.putText(oimg, "head pose: (y=%0.0f, p=%0.0f, r=%0.0f)" %
|
||||
(np.round(yaw), np.round(pitch), np.round(roll)),
|
||||
[int(rx), int(ry + rheight + 5 * rwidth / 100)],
|
||||
cv.FONT_HERSHEY_PLAIN, scale_box * 2, WHITE, 1)
|
||||
|
||||
# Eyes boxes
|
||||
color_l = GREEN if out_st_l[i] else RED
|
||||
cv.rectangle(oimg, l_eyes[i], color_l, 1)
|
||||
color_r = GREEN if out_st_r[i] else RED
|
||||
cv.rectangle(oimg, r_eyes[i], color_r, 1)
|
||||
|
||||
# Gaze vectors
|
||||
norm_gazes = np.linalg.norm(outg[i][0])
|
||||
gaze_vector = outg[i][0] / norm_gazes
|
||||
|
||||
arrow_length = 0.4 * rwidth
|
||||
gaze_arrow = [arrow_length * gaze_vector[0], -arrow_length * gaze_vector[1]]
|
||||
left_arrow = [int(a+b) for a, b in zip(out_mids[0 + i * 2], gaze_arrow)]
|
||||
right_arrow = [int(a+b) for a, b in zip(out_mids[1 + i * 2], gaze_arrow)]
|
||||
if out_st_l[i]:
|
||||
cv.arrowedLine(oimg, out_mids[0 + i * 2], left_arrow, BLUE, 2)
|
||||
if out_st_r[i]:
|
||||
cv.arrowedLine(oimg, out_mids[1 + i * 2], right_arrow, BLUE, 2)
|
||||
|
||||
v0, v1, v2 = outg[i][0]
|
||||
|
||||
gaze_angles = [180 / M_PI * (M_PI_2 + np.arctan2(v2, v0)),
|
||||
180 / M_PI * (M_PI_2 - np.arccos(v1 / norm_gazes))]
|
||||
cv.putText(oimg, "gaze angles: (h=%0.0f, v=%0.0f)" %
|
||||
(np.round(gaze_angles[0]), np.round(gaze_angles[1])),
|
||||
[int(rx), int(ry + rheight + 12 * rwidth / 100)],
|
||||
cv.FONT_HERSHEY_PLAIN, scale_box * 2, WHITE, 1)
|
||||
|
||||
# Add FPS value to frame
|
||||
cv.putText(oimg, "FPS: %0i" % (fps), [int(20), int(40)],
|
||||
cv.FONT_HERSHEY_PLAIN, 2, RED, 2)
|
||||
|
||||
# Show result
|
||||
cv.imshow('Gaze Estimation', oimg)
|
||||
|
||||
fps = int(1. / (time.time() - start_time_cycle))
|
||||
frames += 1
|
||||
EXECUTION_TIME = time.time() - START_TIME
|
||||
print('Execution successful')
|
||||
print('Mean FPS is ', int(frames / EXECUTION_TIME))
|
||||
@@ -3,64 +3,80 @@
|
||||
|
||||
namespace cv
|
||||
{
|
||||
struct GAPI_EXPORTS_W_SIMPLE GCompileArg { };
|
||||
struct GAPI_EXPORTS_W_SIMPLE GCompileArg
|
||||
{
|
||||
GAPI_WRAP GCompileArg(gapi::GKernelPackage pkg);
|
||||
GAPI_WRAP GCompileArg(gapi::GNetPackage pkg);
|
||||
};
|
||||
|
||||
GAPI_EXPORTS_W GCompileArgs compile_args(gapi::GKernelPackage pkg);
|
||||
GAPI_EXPORTS_W GCompileArgs compile_args(gapi::GNetPackage pkg);
|
||||
GAPI_EXPORTS_W GCompileArgs compile_args(gapi::GKernelPackage kernels, gapi::GNetPackage nets);
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferInputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferInputs();
|
||||
GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GMat& value);
|
||||
GAPI_WRAP GInferInputs& setInput(const std::string& name, const cv::GFrame& value);
|
||||
};
|
||||
|
||||
// NB: This classes doesn't exist in *.so
|
||||
// HACK: Mark them as a class to force python wrapper generate code for this entities
|
||||
class GAPI_EXPORTS_W_SIMPLE GProtoArg { };
|
||||
class GAPI_EXPORTS_W_SIMPLE GProtoInputArgs { };
|
||||
class GAPI_EXPORTS_W_SIMPLE GProtoOutputArgs { };
|
||||
class GAPI_EXPORTS_W_SIMPLE GRunArg { };
|
||||
class GAPI_EXPORTS_W_SIMPLE GMetaArg { GAPI_WRAP GMetaArg(); };
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferListInputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferListInputs();
|
||||
GAPI_WRAP GInferListInputs setInput(const std::string& name, const cv::GArray<cv::GMat>& value);
|
||||
GAPI_WRAP GInferListInputs setInput(const std::string& name, const cv::GArray<cv::Rect>& value);
|
||||
};
|
||||
|
||||
using GProtoInputArgs = GIOProtoArgs<In_Tag>;
|
||||
using GProtoOutputArgs = GIOProtoArgs<Out_Tag>;
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferOutputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferOutputs();
|
||||
GAPI_WRAP cv::GMat at(const std::string& name);
|
||||
};
|
||||
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferInputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferInputs();
|
||||
GAPI_WRAP void setInput(const std::string& name, const cv::GMat& value);
|
||||
GAPI_WRAP void setInput(const std::string& name, const cv::GFrame& value);
|
||||
};
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferListOutputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferListOutputs();
|
||||
GAPI_WRAP cv::GArray<cv::GMat> at(const std::string& name);
|
||||
};
|
||||
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferListInputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferListInputs();
|
||||
GAPI_WRAP void setInput(const std::string& name, const cv::GArray<cv::GMat>& value);
|
||||
GAPI_WRAP void setInput(const std::string& name, const cv::GArray<cv::Rect>& value);
|
||||
};
|
||||
namespace gapi
|
||||
{
|
||||
namespace wip
|
||||
{
|
||||
class GAPI_EXPORTS_W IStreamSource { };
|
||||
namespace draw
|
||||
{
|
||||
// NB: These render primitives are partially wrapped in shadow file
|
||||
// because cv::Rect conflicts with cv::gapi::wip::draw::Rect in python generator
|
||||
// and cv::Rect2i breaks standalone mode.
|
||||
struct Rect
|
||||
{
|
||||
GAPI_WRAP Rect(const cv::Rect2i& rect_,
|
||||
const cv::Scalar& color_,
|
||||
int thick_ = 1,
|
||||
int lt_ = 8,
|
||||
int shift_ = 0);
|
||||
};
|
||||
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferOutputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferOutputs();
|
||||
GAPI_WRAP cv::GMat at(const std::string& name);
|
||||
};
|
||||
struct Mosaic
|
||||
{
|
||||
GAPI_WRAP Mosaic(const cv::Rect2i& mos_, int cellSz_, int decim_);
|
||||
};
|
||||
} // namespace draw
|
||||
} // namespace wip
|
||||
namespace streaming
|
||||
{
|
||||
// FIXME: Extend to work with an arbitrary G-type.
|
||||
cv::GOpaque<int64_t> GAPI_EXPORTS_W timestamp(cv::GMat);
|
||||
cv::GOpaque<int64_t> GAPI_EXPORTS_W seqNo(cv::GMat);
|
||||
cv::GOpaque<int64_t> GAPI_EXPORTS_W seq_id(cv::GMat);
|
||||
|
||||
class GAPI_EXPORTS_W_SIMPLE GInferListOutputs
|
||||
{
|
||||
public:
|
||||
GAPI_WRAP GInferListOutputs();
|
||||
GAPI_WRAP cv::GArray<cv::GMat> at(const std::string& name);
|
||||
};
|
||||
GAPI_EXPORTS_W cv::GMat desync(const cv::GMat &g);
|
||||
} // namespace streaming
|
||||
} // namespace gapi
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct GAPI_EXPORTS_W_SIMPLE ExtractArgsCallback { };
|
||||
struct GAPI_EXPORTS_W_SIMPLE ExtractMetaCallback { };
|
||||
} // namespace detail
|
||||
|
||||
namespace gapi
|
||||
{
|
||||
namespace wip
|
||||
{
|
||||
class GAPI_EXPORTS_W IStreamSource { };
|
||||
} // namespace wip
|
||||
} // namespace gapi
|
||||
namespace detail
|
||||
{
|
||||
gapi::GNetParam GAPI_EXPORTS_W strip(gapi::ie::PyParams params);
|
||||
} // namespace detail
|
||||
} // namespace cv
|
||||
|
||||
@@ -3,187 +3,209 @@
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
|
||||
# Plaidml is an optional backend
|
||||
pkgs = [
|
||||
('ocl' , cv.gapi.core.ocl.kernels()),
|
||||
('cpu' , cv.gapi.core.cpu.kernels()),
|
||||
('fluid' , cv.gapi.core.fluid.kernels())
|
||||
# ('plaidml', cv.gapi.core.plaidml.kernels())
|
||||
]
|
||||
try:
|
||||
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
raise unittest.SkipTest('Python 2.x is not supported')
|
||||
|
||||
# Plaidml is an optional backend
|
||||
pkgs = [
|
||||
('ocl' , cv.gapi.core.ocl.kernels()),
|
||||
('cpu' , cv.gapi.core.cpu.kernels()),
|
||||
('fluid' , cv.gapi.core.fluid.kernels())
|
||||
# ('plaidml', cv.gapi.core.plaidml.kernels())
|
||||
]
|
||||
|
||||
|
||||
class gapi_core_test(NewOpenCVTests):
|
||||
class gapi_core_test(NewOpenCVTests):
|
||||
|
||||
def test_add(self):
|
||||
# TODO: Extend to use any type and size here
|
||||
sz = (720, 1280)
|
||||
in1 = np.full(sz, 100)
|
||||
in2 = np.full(sz, 50)
|
||||
def test_add(self):
|
||||
# TODO: Extend to use any type and size here
|
||||
sz = (720, 1280)
|
||||
in1 = np.full(sz, 100)
|
||||
in2 = np.full(sz, 50)
|
||||
|
||||
# OpenCV
|
||||
expected = cv.add(in1, in2)
|
||||
# OpenCV
|
||||
expected = cv.add(in1, in2)
|
||||
|
||||
# G-API
|
||||
g_in1 = cv.GMat()
|
||||
g_in2 = cv.GMat()
|
||||
g_out = cv.gapi.add(g_in1, g_in2)
|
||||
comp = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
|
||||
# G-API
|
||||
g_in1 = cv.GMat()
|
||||
g_in2 = cv.GMat()
|
||||
g_out = cv.gapi.add(g_in1, g_in2)
|
||||
comp = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in1, in2), args=cv.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(expected.dtype, actual.dtype, 'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
def test_add_uint8(self):
|
||||
sz = (720, 1280)
|
||||
in1 = np.full(sz, 100, dtype=np.uint8)
|
||||
in2 = np.full(sz, 50 , dtype=np.uint8)
|
||||
|
||||
# OpenCV
|
||||
expected = cv.add(in1, in2)
|
||||
|
||||
# G-API
|
||||
g_in1 = cv.GMat()
|
||||
g_in2 = cv.GMat()
|
||||
g_out = cv.gapi.add(g_in1, g_in2)
|
||||
comp = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in1, in2), args=cv.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(expected.dtype, actual.dtype, 'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
def test_mean(self):
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in_mat = cv.imread(img_path)
|
||||
|
||||
# OpenCV
|
||||
expected = cv.mean(in_mat)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.mean(g_in)
|
||||
comp = cv.GComputation(g_in, g_out)
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
def test_split3(self):
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in_mat = cv.imread(img_path)
|
||||
|
||||
# OpenCV
|
||||
expected = cv.split(in_mat)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
b, g, r = cv.gapi.split3(g_in)
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(b, g, r))
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.compile_args(pkg))
|
||||
# Comparison
|
||||
for e, a in zip(expected, actual):
|
||||
self.assertEqual(0.0, cv.norm(e, a, cv.NORM_INF),
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in1, in2), args=cv.gapi.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(e.dtype, a.dtype, 'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(expected.dtype, actual.dtype, 'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
def test_threshold(self):
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in_mat = cv.cvtColor(cv.imread(img_path), cv.COLOR_RGB2GRAY)
|
||||
maxv = (30, 30)
|
||||
def test_add_uint8(self):
|
||||
sz = (720, 1280)
|
||||
in1 = np.full(sz, 100, dtype=np.uint8)
|
||||
in2 = np.full(sz, 50 , dtype=np.uint8)
|
||||
|
||||
# OpenCV
|
||||
expected_thresh, expected_mat = cv.threshold(in_mat, maxv[0], maxv[0], cv.THRESH_TRIANGLE)
|
||||
# OpenCV
|
||||
expected = cv.add(in1, in2)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_sc = cv.GScalar()
|
||||
mat, threshold = cv.gapi.threshold(g_in, g_sc, cv.THRESH_TRIANGLE)
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_sc), cv.GOut(mat, threshold))
|
||||
# G-API
|
||||
g_in1 = cv.GMat()
|
||||
g_in2 = cv.GMat()
|
||||
g_out = cv.gapi.add(g_in1, g_in2)
|
||||
comp = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual_mat, actual_thresh = comp.apply(cv.gin(in_mat, maxv), args=cv.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected_mat, actual_mat, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(expected_mat.dtype, actual_mat.dtype,
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(expected_thresh, actual_thresh[0],
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
def test_kmeans(self):
|
||||
# K-means params
|
||||
count = 100
|
||||
sz = (count, 2)
|
||||
in_mat = np.random.random(sz).astype(np.float32)
|
||||
K = 5
|
||||
flags = cv.KMEANS_RANDOM_CENTERS
|
||||
attempts = 1;
|
||||
criteria = (cv.TERM_CRITERIA_MAX_ITER + cv.TERM_CRITERIA_EPS, 30, 0)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
compactness, out_labels, centers = cv.gapi.kmeans(g_in, K, criteria, attempts, flags)
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(compactness, out_labels, centers))
|
||||
|
||||
compact, labels, centers = comp.apply(cv.gin(in_mat))
|
||||
|
||||
# Assert
|
||||
self.assertTrue(compact >= 0)
|
||||
self.assertEqual(sz[0], labels.shape[0])
|
||||
self.assertEqual(1, labels.shape[1])
|
||||
self.assertTrue(labels.size != 0)
|
||||
self.assertEqual(centers.shape[1], sz[1]);
|
||||
self.assertEqual(centers.shape[0], K);
|
||||
self.assertTrue(centers.size != 0);
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in1, in2), args=cv.gapi.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(expected.dtype, actual.dtype, 'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
def generate_random_points(self, sz):
|
||||
arr = np.random.random(sz).astype(np.float32).T
|
||||
return list(zip(arr[0], arr[1]))
|
||||
def test_mean(self):
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in_mat = cv.imread(img_path)
|
||||
|
||||
# OpenCV
|
||||
expected = cv.mean(in_mat)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.mean(g_in)
|
||||
comp = cv.GComputation(g_in, g_out)
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.gapi.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
def test_kmeans_2d(self):
|
||||
# K-means 2D params
|
||||
count = 100
|
||||
sz = (count, 2)
|
||||
amount = sz[0]
|
||||
K = 5
|
||||
flags = cv.KMEANS_RANDOM_CENTERS
|
||||
attempts = 1;
|
||||
criteria = (cv.TERM_CRITERIA_MAX_ITER + cv.TERM_CRITERIA_EPS, 30, 0);
|
||||
in_vector = self.generate_random_points(sz)
|
||||
in_labels = []
|
||||
def test_split3(self):
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in_mat = cv.imread(img_path)
|
||||
|
||||
# G-API
|
||||
data = cv.GArrayT(cv.gapi.CV_POINT2F)
|
||||
best_labels = cv.GArrayT(cv.gapi.CV_INT)
|
||||
# OpenCV
|
||||
expected = cv.split(in_mat)
|
||||
|
||||
compactness, out_labels, centers = cv.gapi.kmeans(data, K, best_labels, criteria, attempts, flags);
|
||||
comp = cv.GComputation(cv.GIn(data, best_labels), cv.GOut(compactness, out_labels, centers));
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
b, g, r = cv.gapi.split3(g_in)
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(b, g, r))
|
||||
|
||||
compact, labels, centers = comp.apply(cv.gin(in_vector, in_labels));
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.gapi.compile_args(pkg))
|
||||
# Comparison
|
||||
for e, a in zip(expected, actual):
|
||||
self.assertEqual(0.0, cv.norm(e, a, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(e.dtype, a.dtype, 'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
# Assert
|
||||
self.assertTrue(compact >= 0)
|
||||
self.assertEqual(amount, len(labels))
|
||||
self.assertEqual(K, len(centers))
|
||||
|
||||
def test_threshold(self):
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in_mat = cv.cvtColor(cv.imread(img_path), cv.COLOR_RGB2GRAY)
|
||||
maxv = (30, 30)
|
||||
|
||||
# OpenCV
|
||||
expected_thresh, expected_mat = cv.threshold(in_mat, maxv[0], maxv[0], cv.THRESH_TRIANGLE)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_sc = cv.GScalar()
|
||||
mat, threshold = cv.gapi.threshold(g_in, g_sc, cv.THRESH_TRIANGLE)
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_sc), cv.GOut(mat, threshold))
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual_mat, actual_thresh = comp.apply(cv.gin(in_mat, maxv), args=cv.gapi.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected_mat, actual_mat, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(expected_mat.dtype, actual_mat.dtype,
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
self.assertEqual(expected_thresh, actual_thresh[0],
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
def test_kmeans(self):
|
||||
# K-means params
|
||||
count = 100
|
||||
sz = (count, 2)
|
||||
in_mat = np.random.random(sz).astype(np.float32)
|
||||
K = 5
|
||||
flags = cv.KMEANS_RANDOM_CENTERS
|
||||
attempts = 1
|
||||
criteria = (cv.TERM_CRITERIA_MAX_ITER + cv.TERM_CRITERIA_EPS, 30, 0)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
compactness, out_labels, centers = cv.gapi.kmeans(g_in, K, criteria, attempts, flags)
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(compactness, out_labels, centers))
|
||||
|
||||
compact, labels, centers = comp.apply(cv.gin(in_mat))
|
||||
|
||||
# Assert
|
||||
self.assertTrue(compact >= 0)
|
||||
self.assertEqual(sz[0], labels.shape[0])
|
||||
self.assertEqual(1, labels.shape[1])
|
||||
self.assertTrue(labels.size != 0)
|
||||
self.assertEqual(centers.shape[1], sz[1])
|
||||
self.assertEqual(centers.shape[0], K)
|
||||
self.assertTrue(centers.size != 0)
|
||||
|
||||
|
||||
def generate_random_points(self, sz):
|
||||
arr = np.random.random(sz).astype(np.float32).T
|
||||
return list(zip(arr[0], arr[1]))
|
||||
|
||||
|
||||
def test_kmeans_2d(self):
|
||||
# K-means 2D params
|
||||
count = 100
|
||||
sz = (count, 2)
|
||||
amount = sz[0]
|
||||
K = 5
|
||||
flags = cv.KMEANS_RANDOM_CENTERS
|
||||
attempts = 1
|
||||
criteria = (cv.TERM_CRITERIA_MAX_ITER + cv.TERM_CRITERIA_EPS, 30, 0)
|
||||
in_vector = self.generate_random_points(sz)
|
||||
in_labels = []
|
||||
|
||||
# G-API
|
||||
data = cv.GArrayT(cv.gapi.CV_POINT2F)
|
||||
best_labels = cv.GArrayT(cv.gapi.CV_INT)
|
||||
|
||||
compactness, out_labels, centers = cv.gapi.kmeans(data, K, best_labels, criteria, attempts, flags)
|
||||
comp = cv.GComputation(cv.GIn(data, best_labels), cv.GOut(compactness, out_labels, centers))
|
||||
|
||||
compact, labels, centers = comp.apply(cv.gin(in_vector, in_labels))
|
||||
|
||||
# Assert
|
||||
self.assertTrue(compact >= 0)
|
||||
self.assertEqual(amount, len(labels))
|
||||
self.assertEqual(K, len(centers))
|
||||
|
||||
|
||||
except unittest.SkipTest as e:
|
||||
|
||||
message = str(e)
|
||||
|
||||
class TestSkip(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.skipTest('Skip tests: ' + message)
|
||||
|
||||
def test_skip():
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -3,103 +3,124 @@
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
|
||||
# Plaidml is an optional backend
|
||||
pkgs = [
|
||||
('ocl' , cv.gapi.core.ocl.kernels()),
|
||||
('cpu' , cv.gapi.core.cpu.kernels()),
|
||||
('fluid' , cv.gapi.core.fluid.kernels())
|
||||
# ('plaidml', cv.gapi.core.plaidml.kernels())
|
||||
]
|
||||
try:
|
||||
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
raise unittest.SkipTest('Python 2.x is not supported')
|
||||
|
||||
# Plaidml is an optional backend
|
||||
pkgs = [
|
||||
('ocl' , cv.gapi.core.ocl.kernels()),
|
||||
('cpu' , cv.gapi.core.cpu.kernels()),
|
||||
('fluid' , cv.gapi.core.fluid.kernels())
|
||||
# ('plaidml', cv.gapi.core.plaidml.kernels())
|
||||
]
|
||||
|
||||
|
||||
class gapi_imgproc_test(NewOpenCVTests):
|
||||
class gapi_imgproc_test(NewOpenCVTests):
|
||||
|
||||
def test_good_features_to_track(self):
|
||||
# TODO: Extend to use any type and size here
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in1 = cv.cvtColor(cv.imread(img_path), cv.COLOR_RGB2GRAY)
|
||||
def test_good_features_to_track(self):
|
||||
# TODO: Extend to use any type and size here
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in1 = cv.cvtColor(cv.imread(img_path), cv.COLOR_RGB2GRAY)
|
||||
|
||||
# NB: goodFeaturesToTrack configuration
|
||||
max_corners = 50
|
||||
quality_lvl = 0.01
|
||||
min_distance = 10
|
||||
block_sz = 3
|
||||
use_harris_detector = True
|
||||
k = 0.04
|
||||
mask = None
|
||||
# NB: goodFeaturesToTrack configuration
|
||||
max_corners = 50
|
||||
quality_lvl = 0.01
|
||||
min_distance = 10
|
||||
block_sz = 3
|
||||
use_harris_detector = True
|
||||
k = 0.04
|
||||
mask = None
|
||||
|
||||
# OpenCV
|
||||
expected = cv.goodFeaturesToTrack(in1, max_corners, quality_lvl,
|
||||
min_distance, mask=mask,
|
||||
blockSize=block_sz, useHarrisDetector=use_harris_detector, k=k)
|
||||
# OpenCV
|
||||
expected = cv.goodFeaturesToTrack(in1, max_corners, quality_lvl,
|
||||
min_distance, mask=mask,
|
||||
blockSize=block_sz, useHarrisDetector=use_harris_detector, k=k)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.goodFeaturesToTrack(g_in, max_corners, quality_lvl,
|
||||
min_distance, mask, block_sz, use_harris_detector, k)
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.goodFeaturesToTrack(g_in, max_corners, quality_lvl,
|
||||
min_distance, mask, block_sz, use_harris_detector, k)
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in1), args=cv.compile_args(pkg))
|
||||
# NB: OpenCV & G-API have different output shapes:
|
||||
# OpenCV - (num_points, 1, 2)
|
||||
# G-API - (num_points, 2)
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected.flatten(),
|
||||
np.array(actual, dtype=np.float32).flatten(),
|
||||
cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in1), args=cv.gapi.compile_args(pkg))
|
||||
# NB: OpenCV & G-API have different output shapes:
|
||||
# OpenCV - (num_points, 1, 2)
|
||||
# G-API - (num_points, 2)
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected.flatten(),
|
||||
np.array(actual, dtype=np.float32).flatten(),
|
||||
cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
def test_rgb2gray(self):
|
||||
# TODO: Extend to use any type and size here
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in1 = cv.imread(img_path)
|
||||
def test_rgb2gray(self):
|
||||
# TODO: Extend to use any type and size here
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
in1 = cv.imread(img_path)
|
||||
|
||||
# OpenCV
|
||||
expected = cv.cvtColor(in1, cv.COLOR_RGB2GRAY)
|
||||
# OpenCV
|
||||
expected = cv.cvtColor(in1, cv.COLOR_RGB2GRAY)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.RGB2Gray(g_in)
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.RGB2Gray(g_in)
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in1), args=cv.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(in1), args=cv.gapi.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
def test_bounding_rect(self):
|
||||
sz = 1280
|
||||
fscale = 256
|
||||
def test_bounding_rect(self):
|
||||
sz = 1280
|
||||
fscale = 256
|
||||
|
||||
def sample_value(fscale):
|
||||
return np.random.uniform(0, 255 * fscale) / fscale
|
||||
def sample_value(fscale):
|
||||
return np.random.uniform(0, 255 * fscale) / fscale
|
||||
|
||||
points = np.array([(sample_value(fscale), sample_value(fscale)) for _ in range(1280)], np.float32)
|
||||
points = np.array([(sample_value(fscale), sample_value(fscale)) for _ in range(1280)], np.float32)
|
||||
|
||||
# OpenCV
|
||||
expected = cv.boundingRect(points)
|
||||
# OpenCV
|
||||
expected = cv.boundingRect(points)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.boundingRect(g_in)
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.boundingRect(g_in)
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(points), args=cv.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
for pkg_name, pkg in pkgs:
|
||||
actual = comp.apply(cv.gin(points), args=cv.gapi.compile_args(pkg))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF),
|
||||
'Failed on ' + pkg_name + ' backend')
|
||||
|
||||
|
||||
except unittest.SkipTest as e:
|
||||
|
||||
message = str(e)
|
||||
|
||||
class TestSkip(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.skipTest('Skip tests: ' + message)
|
||||
|
||||
def test_skip():
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -3,318 +3,338 @@
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
|
||||
class test_gapi_infer(NewOpenCVTests):
|
||||
try:
|
||||
|
||||
def infer_reference_network(self, model_path, weights_path, img):
|
||||
net = cv.dnn.readNetFromModelOptimizer(model_path, weights_path)
|
||||
net.setPreferableBackend(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE)
|
||||
net.setPreferableTarget(cv.dnn.DNN_TARGET_CPU)
|
||||
|
||||
blob = cv.dnn.blobFromImage(img)
|
||||
|
||||
net.setInput(blob)
|
||||
return net.forward(net.getUnconnectedOutLayersNames())
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
raise unittest.SkipTest('Python 2.x is not supported')
|
||||
|
||||
|
||||
def make_roi(self, img, roi):
|
||||
return img[roi[1]:roi[1] + roi[3], roi[0]:roi[0] + roi[2], ...]
|
||||
class test_gapi_infer(NewOpenCVTests):
|
||||
|
||||
def infer_reference_network(self, model_path, weights_path, img):
|
||||
net = cv.dnn.readNetFromModelOptimizer(model_path, weights_path)
|
||||
net.setPreferableBackend(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE)
|
||||
net.setPreferableTarget(cv.dnn.DNN_TARGET_CPU)
|
||||
|
||||
blob = cv.dnn.blobFromImage(img)
|
||||
|
||||
net.setInput(blob)
|
||||
return net.forward(net.getUnconnectedOutLayersNames())
|
||||
|
||||
|
||||
def test_age_gender_infer(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
|
||||
root_path = '/omz_intel_models/intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
img = cv.resize(cv.imread(img_path), (62,62))
|
||||
|
||||
# OpenCV DNN
|
||||
dnn_age, dnn_gender = self.infer_reference_network(model_path, weights_path, img)
|
||||
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
|
||||
outputs = cv.gapi.infer("net", inputs)
|
||||
age_g = outputs.at("age_conv3")
|
||||
gender_g = outputs.at("prob")
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(age_g, gender_g))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
|
||||
gapi_age, gapi_gender = comp.apply(cv.gin(img), args=cv.compile_args(cv.gapi.networks(pp)))
|
||||
|
||||
# Check
|
||||
self.assertEqual(0.0, cv.norm(dnn_gender, gapi_gender, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(dnn_age, gapi_age, cv.NORM_INF))
|
||||
def make_roi(self, img, roi):
|
||||
return img[roi[1]:roi[1] + roi[3], roi[0]:roi[0] + roi[2], ...]
|
||||
|
||||
|
||||
def test_age_gender_infer_roi(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
def test_age_gender_infer(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
|
||||
root_path = '/omz_intel_models/intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
root_path = '/omz_intel_models/intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
img = cv.imread(img_path)
|
||||
roi = (10, 10, 62, 62)
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
img = cv.resize(cv.imread(img_path), (62,62))
|
||||
|
||||
# OpenCV DNN
|
||||
dnn_age, dnn_gender = self.infer_reference_network(model_path,
|
||||
# OpenCV DNN
|
||||
dnn_age, dnn_gender = self.infer_reference_network(model_path, weights_path, img)
|
||||
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
|
||||
outputs = cv.gapi.infer("net", inputs)
|
||||
age_g = outputs.at("age_conv3")
|
||||
gender_g = outputs.at("prob")
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(age_g, gender_g))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
|
||||
gapi_age, gapi_gender = comp.apply(cv.gin(img), args=cv.gapi.compile_args(cv.gapi.networks(pp)))
|
||||
|
||||
# Check
|
||||
self.assertEqual(0.0, cv.norm(dnn_gender, gapi_gender, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(dnn_age, gapi_age, cv.NORM_INF))
|
||||
|
||||
|
||||
def test_age_gender_infer_roi(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
|
||||
root_path = '/omz_intel_models/intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
img = cv.imread(img_path)
|
||||
roi = (10, 10, 62, 62)
|
||||
|
||||
# OpenCV DNN
|
||||
dnn_age, dnn_gender = self.infer_reference_network(model_path,
|
||||
weights_path,
|
||||
self.make_roi(img, roi))
|
||||
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
g_roi = cv.GOpaqueT(cv.gapi.CV_RECT)
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
|
||||
outputs = cv.gapi.infer("net", g_roi, inputs)
|
||||
age_g = outputs.at("age_conv3")
|
||||
gender_g = outputs.at("prob")
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_roi), cv.GOut(age_g, gender_g))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
|
||||
gapi_age, gapi_gender = comp.apply(cv.gin(img, roi), args=cv.gapi.compile_args(cv.gapi.networks(pp)))
|
||||
|
||||
# Check
|
||||
self.assertEqual(0.0, cv.norm(dnn_gender, gapi_gender, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(dnn_age, gapi_age, cv.NORM_INF))
|
||||
|
||||
|
||||
def test_age_gender_infer_roi_list(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
|
||||
root_path = '/omz_intel_models/intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
|
||||
rois = [(10, 15, 62, 62), (23, 50, 62, 62), (14, 100, 62, 62), (80, 50, 62, 62)]
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
img = cv.imread(img_path)
|
||||
|
||||
# OpenCV DNN
|
||||
dnn_age_list = []
|
||||
dnn_gender_list = []
|
||||
for roi in rois:
|
||||
age, gender = self.infer_reference_network(model_path,
|
||||
weights_path,
|
||||
self.make_roi(img, roi))
|
||||
dnn_age_list.append(age)
|
||||
dnn_gender_list.append(gender)
|
||||
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
g_roi = cv.GOpaqueT(cv.gapi.CV_RECT)
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
g_rois = cv.GArrayT(cv.gapi.CV_RECT)
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
|
||||
outputs = cv.gapi.infer("net", g_roi, inputs)
|
||||
age_g = outputs.at("age_conv3")
|
||||
gender_g = outputs.at("prob")
|
||||
outputs = cv.gapi.infer("net", g_rois, inputs)
|
||||
age_g = outputs.at("age_conv3")
|
||||
gender_g = outputs.at("prob")
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_roi), cv.GOut(age_g, gender_g))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_rois), cv.GOut(age_g, gender_g))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
|
||||
gapi_age, gapi_gender = comp.apply(cv.gin(img, roi), args=cv.compile_args(cv.gapi.networks(pp)))
|
||||
gapi_age_list, gapi_gender_list = comp.apply(cv.gin(img, rois),
|
||||
args=cv.gapi.compile_args(cv.gapi.networks(pp)))
|
||||
|
||||
# Check
|
||||
self.assertEqual(0.0, cv.norm(dnn_gender, gapi_gender, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(dnn_age, gapi_age, cv.NORM_INF))
|
||||
# Check
|
||||
for gapi_age, gapi_gender, dnn_age, dnn_gender in zip(gapi_age_list,
|
||||
gapi_gender_list,
|
||||
dnn_age_list,
|
||||
dnn_gender_list):
|
||||
self.assertEqual(0.0, cv.norm(dnn_gender, gapi_gender, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(dnn_age, gapi_age, cv.NORM_INF))
|
||||
|
||||
|
||||
def test_age_gender_infer_roi_list(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
def test_age_gender_infer2_roi(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
|
||||
root_path = '/omz_intel_models/intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
root_path = '/omz_intel_models/intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
|
||||
rois = [(10, 15, 62, 62), (23, 50, 62, 62), (14, 100, 62, 62), (80, 50, 62, 62)]
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
img = cv.imread(img_path)
|
||||
rois = [(10, 15, 62, 62), (23, 50, 62, 62), (14, 100, 62, 62), (80, 50, 62, 62)]
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
img = cv.imread(img_path)
|
||||
|
||||
# OpenCV DNN
|
||||
dnn_age_list = []
|
||||
dnn_gender_list = []
|
||||
for roi in rois:
|
||||
age, gender = self.infer_reference_network(model_path,
|
||||
weights_path,
|
||||
self.make_roi(img, roi))
|
||||
dnn_age_list.append(age)
|
||||
dnn_gender_list.append(gender)
|
||||
# OpenCV DNN
|
||||
dnn_age_list = []
|
||||
dnn_gender_list = []
|
||||
for roi in rois:
|
||||
age, gender = self.infer_reference_network(model_path,
|
||||
weights_path,
|
||||
self.make_roi(img, roi))
|
||||
dnn_age_list.append(age)
|
||||
dnn_gender_list.append(gender)
|
||||
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
g_rois = cv.GArrayT(cv.gapi.CV_RECT)
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
g_rois = cv.GArrayT(cv.gapi.CV_RECT)
|
||||
inputs = cv.GInferListInputs()
|
||||
inputs.setInput('data', g_rois)
|
||||
|
||||
outputs = cv.gapi.infer("net", g_rois, inputs)
|
||||
age_g = outputs.at("age_conv3")
|
||||
gender_g = outputs.at("prob")
|
||||
outputs = cv.gapi.infer2("net", g_in, inputs)
|
||||
age_g = outputs.at("age_conv3")
|
||||
gender_g = outputs.at("prob")
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_rois), cv.GOut(age_g, gender_g))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_rois), cv.GOut(age_g, gender_g))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
|
||||
gapi_age_list, gapi_gender_list = comp.apply(cv.gin(img, rois),
|
||||
args=cv.compile_args(cv.gapi.networks(pp)))
|
||||
gapi_age_list, gapi_gender_list = comp.apply(cv.gin(img, rois),
|
||||
args=cv.gapi.compile_args(cv.gapi.networks(pp)))
|
||||
|
||||
# Check
|
||||
for gapi_age, gapi_gender, dnn_age, dnn_gender in zip(gapi_age_list,
|
||||
gapi_gender_list,
|
||||
dnn_age_list,
|
||||
dnn_gender_list):
|
||||
self.assertEqual(0.0, cv.norm(dnn_gender, gapi_gender, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(dnn_age, gapi_age, cv.NORM_INF))
|
||||
|
||||
|
||||
def test_age_gender_infer2_roi(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
|
||||
root_path = '/omz_intel_models/intel/age-gender-recognition-retail-0013/FP32/age-gender-recognition-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
|
||||
rois = [(10, 15, 62, 62), (23, 50, 62, 62), (14, 100, 62, 62), (80, 50, 62, 62)]
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
img = cv.imread(img_path)
|
||||
|
||||
# OpenCV DNN
|
||||
dnn_age_list = []
|
||||
dnn_gender_list = []
|
||||
for roi in rois:
|
||||
age, gender = self.infer_reference_network(model_path,
|
||||
weights_path,
|
||||
self.make_roi(img, roi))
|
||||
dnn_age_list.append(age)
|
||||
dnn_gender_list.append(gender)
|
||||
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
g_rois = cv.GArrayT(cv.gapi.CV_RECT)
|
||||
inputs = cv.GInferListInputs()
|
||||
inputs.setInput('data', g_rois)
|
||||
|
||||
outputs = cv.gapi.infer2("net", g_in, inputs)
|
||||
age_g = outputs.at("age_conv3")
|
||||
gender_g = outputs.at("prob")
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_rois), cv.GOut(age_g, gender_g))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
|
||||
gapi_age_list, gapi_gender_list = comp.apply(cv.gin(img, rois),
|
||||
args=cv.compile_args(cv.gapi.networks(pp)))
|
||||
|
||||
# Check
|
||||
for gapi_age, gapi_gender, dnn_age, dnn_gender in zip(gapi_age_list,
|
||||
gapi_gender_list,
|
||||
dnn_age_list,
|
||||
dnn_gender_list):
|
||||
self.assertEqual(0.0, cv.norm(dnn_gender, gapi_gender, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(dnn_age, gapi_age, cv.NORM_INF))
|
||||
# Check
|
||||
for gapi_age, gapi_gender, dnn_age, dnn_gender in zip(gapi_age_list,
|
||||
gapi_gender_list,
|
||||
dnn_age_list,
|
||||
dnn_gender_list):
|
||||
self.assertEqual(0.0, cv.norm(dnn_gender, gapi_gender, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(dnn_age, gapi_age, cv.NORM_INF))
|
||||
|
||||
|
||||
|
||||
def test_person_detection_retail_0013(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
def test_person_detection_retail_0013(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
|
||||
root_path = '/omz_intel_models/intel/person-detection-retail-0013/FP32/person-detection-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
img_path = self.find_file('gpu/lbpcascade/er.png', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
img = cv.resize(cv.imread(img_path), (544, 320))
|
||||
root_path = '/omz_intel_models/intel/person-detection-retail-0013/FP32/person-detection-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
img_path = self.find_file('gpu/lbpcascade/er.png', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
img = cv.resize(cv.imread(img_path), (544, 320))
|
||||
|
||||
# OpenCV DNN
|
||||
net = cv.dnn.readNetFromModelOptimizer(model_path, weights_path)
|
||||
net.setPreferableBackend(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE)
|
||||
net.setPreferableTarget(cv.dnn.DNN_TARGET_CPU)
|
||||
# OpenCV DNN
|
||||
net = cv.dnn.readNetFromModelOptimizer(model_path, weights_path)
|
||||
net.setPreferableBackend(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE)
|
||||
net.setPreferableTarget(cv.dnn.DNN_TARGET_CPU)
|
||||
|
||||
blob = cv.dnn.blobFromImage(img)
|
||||
blob = cv.dnn.blobFromImage(img)
|
||||
|
||||
def parseSSD(detections, size):
|
||||
h, w = size
|
||||
bboxes = []
|
||||
detections = detections.reshape(-1, 7)
|
||||
for sample_id, class_id, confidence, xmin, ymin, xmax, ymax in detections:
|
||||
if confidence >= 0.5:
|
||||
x = int(xmin * w)
|
||||
y = int(ymin * h)
|
||||
width = int(xmax * w - x)
|
||||
height = int(ymax * h - y)
|
||||
bboxes.append((x, y, width, height))
|
||||
def parseSSD(detections, size):
|
||||
h, w = size
|
||||
bboxes = []
|
||||
detections = detections.reshape(-1, 7)
|
||||
for sample_id, class_id, confidence, xmin, ymin, xmax, ymax in detections:
|
||||
if confidence >= 0.5:
|
||||
x = int(xmin * w)
|
||||
y = int(ymin * h)
|
||||
width = int(xmax * w - x)
|
||||
height = int(ymax * h - y)
|
||||
bboxes.append((x, y, width, height))
|
||||
|
||||
return bboxes
|
||||
return bboxes
|
||||
|
||||
net.setInput(blob)
|
||||
dnn_detections = net.forward()
|
||||
dnn_boxes = parseSSD(np.array(dnn_detections), img.shape[:2])
|
||||
net.setInput(blob)
|
||||
dnn_detections = net.forward()
|
||||
dnn_boxes = parseSSD(np.array(dnn_detections), img.shape[:2])
|
||||
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
|
||||
g_sz = cv.gapi.streaming.size(g_in)
|
||||
outputs = cv.gapi.infer("net", inputs)
|
||||
detections = outputs.at("detection_out")
|
||||
bboxes = cv.gapi.parseSSD(detections, g_sz, 0.5, False, False)
|
||||
g_sz = cv.gapi.streaming.size(g_in)
|
||||
outputs = cv.gapi.infer("net", inputs)
|
||||
detections = outputs.at("detection_out")
|
||||
bboxes = cv.gapi.parseSSD(detections, g_sz, 0.5, False, False)
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(bboxes))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(bboxes))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
|
||||
gapi_age, gapi_gender = comp.apply(cv.gin(img), args=cv.compile_args(cv.gapi.networks(pp)))
|
||||
gapi_boxes = comp.apply(cv.gin(img.astype(np.float32)),
|
||||
args=cv.gapi.compile_args(cv.gapi.networks(pp)))
|
||||
|
||||
gapi_boxes = comp.apply(cv.gin(img.astype(np.float32)),
|
||||
args=cv.compile_args(cv.gapi.networks(pp)))
|
||||
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(np.array(dnn_boxes).flatten(),
|
||||
np.array(gapi_boxes).flatten(),
|
||||
cv.NORM_INF))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(np.array(dnn_boxes).flatten(),
|
||||
np.array(gapi_boxes).flatten(),
|
||||
cv.NORM_INF))
|
||||
|
||||
|
||||
def test_person_detection_retail_0013(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
def test_person_detection_retail_0013(self):
|
||||
# NB: Check IE
|
||||
if not cv.dnn.DNN_TARGET_CPU in cv.dnn.getAvailableTargets(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE):
|
||||
return
|
||||
|
||||
root_path = '/omz_intel_models/intel/person-detection-retail-0013/FP32/person-detection-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
img_path = self.find_file('gpu/lbpcascade/er.png', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
img = cv.resize(cv.imread(img_path), (544, 320))
|
||||
root_path = '/omz_intel_models/intel/person-detection-retail-0013/FP32/person-detection-retail-0013'
|
||||
model_path = self.find_file(root_path + '.xml', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
weights_path = self.find_file(root_path + '.bin', [os.environ.get('OPENCV_DNN_TEST_DATA_PATH')])
|
||||
img_path = self.find_file('gpu/lbpcascade/er.png', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
device_id = 'CPU'
|
||||
img = cv.resize(cv.imread(img_path), (544, 320))
|
||||
|
||||
# OpenCV DNN
|
||||
net = cv.dnn.readNetFromModelOptimizer(model_path, weights_path)
|
||||
net.setPreferableBackend(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE)
|
||||
net.setPreferableTarget(cv.dnn.DNN_TARGET_CPU)
|
||||
# OpenCV DNN
|
||||
net = cv.dnn.readNetFromModelOptimizer(model_path, weights_path)
|
||||
net.setPreferableBackend(cv.dnn.DNN_BACKEND_INFERENCE_ENGINE)
|
||||
net.setPreferableTarget(cv.dnn.DNN_TARGET_CPU)
|
||||
|
||||
blob = cv.dnn.blobFromImage(img)
|
||||
blob = cv.dnn.blobFromImage(img)
|
||||
|
||||
def parseSSD(detections, size):
|
||||
h, w = size
|
||||
bboxes = []
|
||||
detections = detections.reshape(-1, 7)
|
||||
for sample_id, class_id, confidence, xmin, ymin, xmax, ymax in detections:
|
||||
if confidence >= 0.5:
|
||||
x = int(xmin * w)
|
||||
y = int(ymin * h)
|
||||
width = int(xmax * w - x)
|
||||
height = int(ymax * h - y)
|
||||
bboxes.append((x, y, width, height))
|
||||
def parseSSD(detections, size):
|
||||
h, w = size
|
||||
bboxes = []
|
||||
detections = detections.reshape(-1, 7)
|
||||
for sample_id, class_id, confidence, xmin, ymin, xmax, ymax in detections:
|
||||
if confidence >= 0.5:
|
||||
x = int(xmin * w)
|
||||
y = int(ymin * h)
|
||||
width = int(xmax * w - x)
|
||||
height = int(ymax * h - y)
|
||||
bboxes.append((x, y, width, height))
|
||||
|
||||
return bboxes
|
||||
return bboxes
|
||||
|
||||
net.setInput(blob)
|
||||
dnn_detections = net.forward()
|
||||
dnn_boxes = parseSSD(np.array(dnn_detections), img.shape[:2])
|
||||
net.setInput(blob)
|
||||
dnn_detections = net.forward()
|
||||
dnn_boxes = parseSSD(np.array(dnn_detections), img.shape[:2])
|
||||
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
# OpenCV G-API
|
||||
g_in = cv.GMat()
|
||||
inputs = cv.GInferInputs()
|
||||
inputs.setInput('data', g_in)
|
||||
|
||||
g_sz = cv.gapi.streaming.size(g_in)
|
||||
outputs = cv.gapi.infer("net", inputs)
|
||||
detections = outputs.at("detection_out")
|
||||
bboxes = cv.gapi.parseSSD(detections, g_sz, 0.5, False, False)
|
||||
g_sz = cv.gapi.streaming.size(g_in)
|
||||
outputs = cv.gapi.infer("net", inputs)
|
||||
detections = outputs.at("detection_out")
|
||||
bboxes = cv.gapi.parseSSD(detections, g_sz, 0.5, False, False)
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(bboxes))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(bboxes))
|
||||
pp = cv.gapi.ie.params("net", model_path, weights_path, device_id)
|
||||
|
||||
gapi_boxes = comp.apply(cv.gin(img.astype(np.float32)),
|
||||
args=cv.compile_args(cv.gapi.networks(pp)))
|
||||
gapi_boxes = comp.apply(cv.gin(img.astype(np.float32)),
|
||||
args=cv.gapi.compile_args(cv.gapi.networks(pp)))
|
||||
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(np.array(dnn_boxes).flatten(),
|
||||
np.array(gapi_boxes).flatten(),
|
||||
cv.NORM_INF))
|
||||
# Comparison
|
||||
self.assertEqual(0.0, cv.norm(np.array(dnn_boxes).flatten(),
|
||||
np.array(gapi_boxes).flatten(),
|
||||
cv.NORM_INF))
|
||||
|
||||
|
||||
except unittest.SkipTest as e:
|
||||
|
||||
message = str(e)
|
||||
|
||||
class TestSkip(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.skipTest('Skip tests: ' + message)
|
||||
|
||||
def test_skip():
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
try:
|
||||
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
raise unittest.SkipTest('Python 2.x is not supported')
|
||||
|
||||
# FIXME: FText isn't supported yet.
|
||||
class gapi_render_test(NewOpenCVTests):
|
||||
def __init__(self, *args):
|
||||
super().__init__(*args)
|
||||
|
||||
self.size = (300, 300, 3)
|
||||
|
||||
# Rect
|
||||
self.rect = (30, 30, 50, 50)
|
||||
self.rcolor = (0, 255, 0)
|
||||
self.rlt = cv.LINE_4
|
||||
self.rthick = 2
|
||||
self.rshift = 3
|
||||
|
||||
# Text
|
||||
self.text = 'Hello, world!'
|
||||
self.org = (100, 100)
|
||||
self.ff = cv.FONT_HERSHEY_SIMPLEX
|
||||
self.fs = 1.0
|
||||
self.tthick = 2
|
||||
self.tlt = cv.LINE_8
|
||||
self.tcolor = (255, 255, 255)
|
||||
self.blo = False
|
||||
|
||||
# Circle
|
||||
self.center = (200, 200)
|
||||
self.radius = 200
|
||||
self.ccolor = (255, 255, 0)
|
||||
self.cthick = 2
|
||||
self.clt = cv.LINE_4
|
||||
self.cshift = 1
|
||||
|
||||
# Line
|
||||
self.pt1 = (50, 50)
|
||||
self.pt2 = (200, 200)
|
||||
self.lcolor = (0, 255, 128)
|
||||
self.lthick = 5
|
||||
self.llt = cv.LINE_8
|
||||
self.lshift = 2
|
||||
|
||||
# Poly
|
||||
self.pts = [(50, 100), (100, 200), (25, 250)]
|
||||
self.pcolor = (0, 0, 255)
|
||||
self.pthick = 3
|
||||
self.plt = cv.LINE_4
|
||||
self.pshift = 1
|
||||
|
||||
# Image
|
||||
self.iorg = (150, 150)
|
||||
img_path = self.find_file('cv/face/david2.jpg', [os.environ.get('OPENCV_TEST_DATA_PATH')])
|
||||
self.img = cv.resize(cv.imread(img_path), (50, 50))
|
||||
self.alpha = np.full(self.img.shape[:2], 0.8, dtype=np.float32)
|
||||
|
||||
# Mosaic
|
||||
self.mos = (100, 100, 100, 100)
|
||||
self.cell_sz = 25
|
||||
self.decim = 0
|
||||
|
||||
# Render primitives
|
||||
self.prims = [cv.gapi.wip.draw.Rect(self.rect, self.rcolor, self.rthick, self.rlt, self.rshift),
|
||||
cv.gapi.wip.draw.Text(self.text, self.org, self.ff, self.fs, self.tcolor, self.tthick, self.tlt, self.blo),
|
||||
cv.gapi.wip.draw.Circle(self.center, self.radius, self.ccolor, self.cthick, self.clt, self.cshift),
|
||||
cv.gapi.wip.draw.Line(self.pt1, self.pt2, self.lcolor, self.lthick, self.llt, self.lshift),
|
||||
cv.gapi.wip.draw.Mosaic(self.mos, self.cell_sz, self.decim),
|
||||
cv.gapi.wip.draw.Image(self.iorg, self.img, self.alpha),
|
||||
cv.gapi.wip.draw.Poly(self.pts, self.pcolor, self.pthick, self.plt, self.pshift)]
|
||||
|
||||
def cvt_nv12_to_yuv(self, y, uv):
|
||||
h,w,_ = uv.shape
|
||||
upsample_uv = cv.resize(uv, (h * 2, w * 2))
|
||||
return cv.merge([y, upsample_uv])
|
||||
|
||||
def cvt_yuv_to_nv12(self, yuv, y_out, uv_out):
|
||||
chs = cv.split(yuv, [y_out, None, None])
|
||||
uv = cv.merge([chs[1], chs[2]])
|
||||
uv_out = cv.resize(uv, (uv.shape[0] // 2, uv.shape[1] // 2), dst=uv_out)
|
||||
return y_out, uv_out
|
||||
|
||||
def cvt_bgr_to_yuv_color(self, bgr):
|
||||
y = bgr[2] * 0.299000 + bgr[1] * 0.587000 + bgr[0] * 0.114000;
|
||||
u = bgr[2] * -0.168736 + bgr[1] * -0.331264 + bgr[0] * 0.500000 + 128;
|
||||
v = bgr[2] * 0.500000 + bgr[1] * -0.418688 + bgr[0] * -0.081312 + 128;
|
||||
return (y, u, v)
|
||||
|
||||
def blend_img(self, background, org, img, alpha):
|
||||
x, y = org
|
||||
h, w, _ = img.shape
|
||||
roi_img = background[x:x+w, y:y+h, :]
|
||||
img32f_w = cv.merge([alpha] * 3).astype(np.float32)
|
||||
roi32f_w = np.full(roi_img.shape, 1.0, dtype=np.float32)
|
||||
roi32f_w -= img32f_w
|
||||
img32f = (img / 255).astype(np.float32)
|
||||
roi32f = (roi_img / 255).astype(np.float32)
|
||||
cv.multiply(img32f, img32f_w, dst=img32f)
|
||||
cv.multiply(roi32f, roi32f_w, dst=roi32f)
|
||||
roi32f += img32f
|
||||
roi_img[...] = np.round(roi32f * 255)
|
||||
|
||||
# This is quite naive implementations used as a simple reference
|
||||
# doesn't consider corner cases.
|
||||
def draw_mosaic(self, img, mos, cell_sz, decim):
|
||||
x,y,w,h = mos
|
||||
mosaic_area = img[x:x+w, y:y+h, :]
|
||||
for i in range(0, mosaic_area.shape[0], cell_sz):
|
||||
for j in range(0, mosaic_area.shape[1], cell_sz):
|
||||
cell_roi = mosaic_area[j:j+cell_sz, i:i+cell_sz, :]
|
||||
s0, s1, s2 = cv.mean(cell_roi)[:3]
|
||||
mosaic_area[j:j+cell_sz, i:i+cell_sz] = (round(s0), round(s1), round(s2))
|
||||
|
||||
def render_primitives_bgr_ref(self, img):
|
||||
cv.rectangle(img, self.rect, self.rcolor, self.rthick, self.rlt, self.rshift)
|
||||
cv.putText(img, self.text, self.org, self.ff, self.fs, self.tcolor, self.tthick, self.tlt, self.blo)
|
||||
cv.circle(img, self.center, self.radius, self.ccolor, self.cthick, self.clt, self.cshift)
|
||||
cv.line(img, self.pt1, self.pt2, self.lcolor, self.lthick, self.llt, self.lshift)
|
||||
cv.fillPoly(img, np.expand_dims(np.array([self.pts]), axis=0), self.pcolor, self.plt, self.pshift)
|
||||
self.draw_mosaic(img, self.mos, self.cell_sz, self.decim)
|
||||
self.blend_img(img, self.iorg, self.img, self.alpha)
|
||||
|
||||
def render_primitives_nv12_ref(self, y_plane, uv_plane):
|
||||
yuv = self.cvt_nv12_to_yuv(y_plane, uv_plane)
|
||||
cv.rectangle(yuv, self.rect, self.cvt_bgr_to_yuv_color(self.rcolor), self.rthick, self.rlt, self.rshift)
|
||||
cv.putText(yuv, self.text, self.org, self.ff, self.fs, self.cvt_bgr_to_yuv_color(self.tcolor), self.tthick, self.tlt, self.blo)
|
||||
cv.circle(yuv, self.center, self.radius, self.cvt_bgr_to_yuv_color(self.ccolor), self.cthick, self.clt, self.cshift)
|
||||
cv.line(yuv, self.pt1, self.pt2, self.cvt_bgr_to_yuv_color(self.lcolor), self.lthick, self.llt, self.lshift)
|
||||
cv.fillPoly(yuv, np.expand_dims(np.array([self.pts]), axis=0), self.cvt_bgr_to_yuv_color(self.pcolor), self.plt, self.pshift)
|
||||
self.draw_mosaic(yuv, self.mos, self.cell_sz, self.decim)
|
||||
self.blend_img(yuv, self.iorg, cv.cvtColor(self.img, cv.COLOR_BGR2YUV), self.alpha)
|
||||
self.cvt_yuv_to_nv12(yuv, y_plane, uv_plane)
|
||||
|
||||
def test_render_primitives_on_bgr_graph(self):
|
||||
expected = np.zeros(self.size, dtype=np.uint8)
|
||||
actual = np.array(expected, copy=True)
|
||||
|
||||
# OpenCV
|
||||
self.render_primitives_bgr_ref(expected)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_prims = cv.GArray.Prim()
|
||||
g_out = cv.gapi.wip.draw.render3ch(g_in, g_prims)
|
||||
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_prims), cv.GOut(g_out))
|
||||
actual = comp.apply(cv.gin(actual, self.prims))
|
||||
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
|
||||
def test_render_primitives_on_bgr_function(self):
|
||||
expected = np.zeros(self.size, dtype=np.uint8)
|
||||
actual = np.array(expected, copy=True)
|
||||
|
||||
# OpenCV
|
||||
self.render_primitives_bgr_ref(expected)
|
||||
|
||||
# G-API
|
||||
cv.gapi.wip.draw.render(actual, self.prims)
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
|
||||
def test_render_primitives_on_nv12_graph(self):
|
||||
y_expected = np.zeros((self.size[0], self.size[1], 1), dtype=np.uint8)
|
||||
uv_expected = np.zeros((self.size[0] // 2, self.size[1] // 2, 2), dtype=np.uint8)
|
||||
|
||||
y_actual = np.array(y_expected, copy=True)
|
||||
uv_actual = np.array(uv_expected, copy=True)
|
||||
|
||||
# OpenCV
|
||||
self.render_primitives_nv12_ref(y_expected, uv_expected)
|
||||
|
||||
# G-API
|
||||
g_y = cv.GMat()
|
||||
g_uv = cv.GMat()
|
||||
g_prims = cv.GArray.Prim()
|
||||
g_out_y, g_out_uv = cv.gapi.wip.draw.renderNV12(g_y, g_uv, g_prims)
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_y, g_uv, g_prims), cv.GOut(g_out_y, g_out_uv))
|
||||
y_actual, uv_actual = comp.apply(cv.gin(y_actual, uv_actual, self.prims))
|
||||
|
||||
self.assertEqual(0.0, cv.norm(y_expected, y_actual, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(uv_expected, uv_actual, cv.NORM_INF))
|
||||
|
||||
def test_render_primitives_on_nv12_function(self):
|
||||
y_expected = np.zeros((self.size[0], self.size[1], 1), dtype=np.uint8)
|
||||
uv_expected = np.zeros((self.size[0] // 2, self.size[1] // 2, 2), dtype=np.uint8)
|
||||
|
||||
y_actual = np.array(y_expected, copy=True)
|
||||
uv_actual = np.array(uv_expected, copy=True)
|
||||
|
||||
# OpenCV
|
||||
self.render_primitives_nv12_ref(y_expected, uv_expected)
|
||||
|
||||
# G-API
|
||||
cv.gapi.wip.draw.render(y_actual, uv_actual, self.prims)
|
||||
|
||||
self.assertEqual(0.0, cv.norm(y_expected, y_actual, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(uv_expected, uv_actual, cv.NORM_INF))
|
||||
|
||||
|
||||
except unittest.SkipTest as e:
|
||||
|
||||
message = str(e)
|
||||
|
||||
class TestSkip(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.skipTest('Skip tests: ' + message)
|
||||
|
||||
def test_skip():
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
@@ -225,7 +225,7 @@ try:
|
||||
comp = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(g_out))
|
||||
|
||||
pkg = cv.gapi.kernels(GAddImpl)
|
||||
actual = comp.apply(cv.gin(in_mat1, in_mat2), args=cv.compile_args(pkg))
|
||||
actual = comp.apply(cv.gin(in_mat1, in_mat2), args=cv.gapi.compile_args(pkg))
|
||||
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
|
||||
@@ -245,7 +245,7 @@ try:
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_ch1, g_ch2, g_ch3))
|
||||
|
||||
pkg = cv.gapi.kernels(GSplit3Impl)
|
||||
ch1, ch2, ch3 = comp.apply(cv.gin(in_mat), args=cv.compile_args(pkg))
|
||||
ch1, ch2, ch3 = comp.apply(cv.gin(in_mat), args=cv.gapi.compile_args(pkg))
|
||||
|
||||
self.assertEqual(0.0, cv.norm(in_ch1, ch1, cv.NORM_INF))
|
||||
self.assertEqual(0.0, cv.norm(in_ch2, ch2, cv.NORM_INF))
|
||||
@@ -266,7 +266,7 @@ try:
|
||||
comp = cv.GComputation(g_in, g_out)
|
||||
|
||||
pkg = cv.gapi.kernels(GMeanImpl)
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.compile_args(pkg))
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.gapi.compile_args(pkg))
|
||||
|
||||
# Comparison
|
||||
self.assertEqual(expected, actual)
|
||||
@@ -287,7 +287,7 @@ try:
|
||||
comp = cv.GComputation(cv.GIn(g_in, g_sc), cv.GOut(g_out))
|
||||
|
||||
pkg = cv.gapi.kernels(GAddCImpl)
|
||||
actual = comp.apply(cv.gin(in_mat, sc), args=cv.compile_args(pkg))
|
||||
actual = comp.apply(cv.gin(in_mat, sc), args=cv.gapi.compile_args(pkg))
|
||||
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
|
||||
@@ -305,7 +305,7 @@ try:
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_sz))
|
||||
|
||||
pkg = cv.gapi.kernels(GSizeImpl)
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.compile_args(pkg))
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.gapi.compile_args(pkg))
|
||||
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
|
||||
@@ -322,7 +322,7 @@ try:
|
||||
comp = cv.GComputation(cv.GIn(g_r), cv.GOut(g_sz))
|
||||
|
||||
pkg = cv.gapi.kernels(GSizeRImpl)
|
||||
actual = comp.apply(cv.gin(roi), args=cv.compile_args(pkg))
|
||||
actual = comp.apply(cv.gin(roi), args=cv.gapi.compile_args(pkg))
|
||||
|
||||
# cv.norm works with tuples ?
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
@@ -340,7 +340,7 @@ try:
|
||||
comp = cv.GComputation(cv.GIn(g_pts), cv.GOut(g_br))
|
||||
|
||||
pkg = cv.gapi.kernels(GBoundingRectImpl)
|
||||
actual = comp.apply(cv.gin(points), args=cv.compile_args(pkg))
|
||||
actual = comp.apply(cv.gin(points), args=cv.gapi.compile_args(pkg))
|
||||
|
||||
# cv.norm works with tuples ?
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
@@ -371,7 +371,7 @@ try:
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
pkg = cv.gapi.kernels(GGoodFeaturesImpl)
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.compile_args(pkg))
|
||||
actual = comp.apply(cv.gin(in_mat), args=cv.gapi.compile_args(pkg))
|
||||
|
||||
# NB: OpenCV & G-API have different output types.
|
||||
# OpenCV - numpy array with shape (num_points, 1, 2)
|
||||
@@ -453,10 +453,10 @@ try:
|
||||
g_in = cv.GArray.Int()
|
||||
comp = cv.GComputation(cv.GIn(g_in), cv.GOut(GSum.on(g_in)))
|
||||
|
||||
s = comp.apply(cv.gin([1, 2, 3, 4]), args=cv.compile_args(cv.gapi.kernels(GSumImpl)))
|
||||
s = comp.apply(cv.gin([1, 2, 3, 4]), args=cv.gapi.compile_args(cv.gapi.kernels(GSumImpl)))
|
||||
self.assertEqual(10, s)
|
||||
|
||||
s = comp.apply(cv.gin([1, 2, 8, 7]), args=cv.compile_args(cv.gapi.kernels(GSumImpl)))
|
||||
s = comp.apply(cv.gin([1, 2, 8, 7]), args=cv.gapi.compile_args(cv.gapi.kernels(GSumImpl)))
|
||||
self.assertEqual(18, s)
|
||||
|
||||
self.assertEqual(18, GSumImpl.last_result)
|
||||
@@ -488,13 +488,13 @@ try:
|
||||
'tuple': (42, 42)
|
||||
}
|
||||
|
||||
out = comp.apply(cv.gin(table, 'int'), args=cv.compile_args(cv.gapi.kernels(GLookUpImpl)))
|
||||
out = comp.apply(cv.gin(table, 'int'), args=cv.gapi.compile_args(cv.gapi.kernels(GLookUpImpl)))
|
||||
self.assertEqual(42, out)
|
||||
|
||||
out = comp.apply(cv.gin(table, 'str'), args=cv.compile_args(cv.gapi.kernels(GLookUpImpl)))
|
||||
out = comp.apply(cv.gin(table, 'str'), args=cv.gapi.compile_args(cv.gapi.kernels(GLookUpImpl)))
|
||||
self.assertEqual('hello, world!', out)
|
||||
|
||||
out = comp.apply(cv.gin(table, 'tuple'), args=cv.compile_args(cv.gapi.kernels(GLookUpImpl)))
|
||||
out = comp.apply(cv.gin(table, 'tuple'), args=cv.gapi.compile_args(cv.gapi.kernels(GLookUpImpl)))
|
||||
self.assertEqual((42, 42), out)
|
||||
|
||||
|
||||
@@ -521,7 +521,7 @@ try:
|
||||
arr1 = [3, 'str']
|
||||
|
||||
out = comp.apply(cv.gin(arr0, arr1),
|
||||
args=cv.compile_args(cv.gapi.kernels(GConcatImpl)))
|
||||
args=cv.gapi.compile_args(cv.gapi.kernels(GConcatImpl)))
|
||||
|
||||
self.assertEqual(arr0 + arr1, out)
|
||||
|
||||
@@ -550,7 +550,7 @@ try:
|
||||
img1 = np.array([1, 2, 3])
|
||||
|
||||
with self.assertRaises(Exception): comp.apply(cv.gin(img0, img1),
|
||||
args=cv.compile_args(
|
||||
args=cv.gapi.compile_args(
|
||||
cv.gapi.kernels(GAddImpl)))
|
||||
|
||||
|
||||
@@ -577,7 +577,7 @@ try:
|
||||
img1 = np.array([1, 2, 3])
|
||||
|
||||
with self.assertRaises(Exception): comp.apply(cv.gin(img0, img1),
|
||||
args=cv.compile_args(
|
||||
args=cv.gapi.compile_args(
|
||||
cv.gapi.kernels(GAddImpl)))
|
||||
|
||||
|
||||
@@ -607,7 +607,7 @@ try:
|
||||
# FIXME: Cause Bad variant access.
|
||||
# Need to provide more descriptive error messsage.
|
||||
with self.assertRaises(Exception): comp.apply(cv.gin(img0, img1),
|
||||
args=cv.compile_args(
|
||||
args=cv.gapi.compile_args(
|
||||
cv.gapi.kernels(GAddImpl)))
|
||||
|
||||
def test_pipeline_with_custom_kernels(self):
|
||||
@@ -657,7 +657,7 @@ try:
|
||||
g_mean = cv.gapi.mean(g_transposed)
|
||||
|
||||
comp = cv.GComputation(cv.GIn(g_bgr), cv.GOut(g_mean))
|
||||
actual = comp.apply(cv.gin(img), args=cv.compile_args(
|
||||
actual = comp.apply(cv.gin(img), args=cv.gapi.compile_args(
|
||||
cv.gapi.kernels(GResizeImpl, GTransposeImpl)))
|
||||
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
|
||||
@@ -3,201 +3,323 @@
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
import time
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class test_gapi_streaming(NewOpenCVTests):
|
||||
|
||||
def test_image_input(self):
|
||||
sz = (1280, 720)
|
||||
in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
|
||||
|
||||
# OpenCV
|
||||
expected = cv.medianBlur(in_mat, 3)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.medianBlur(g_in, 3)
|
||||
c = cv.GComputation(g_in, g_out)
|
||||
ccomp = c.compileStreaming(cv.descr_of(in_mat))
|
||||
ccomp.setSource(cv.gin(in_mat))
|
||||
ccomp.start()
|
||||
|
||||
_, actual = ccomp.pull()
|
||||
|
||||
# Assert
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
try:
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
raise unittest.SkipTest('Python 2.x is not supported')
|
||||
|
||||
|
||||
def test_video_input(self):
|
||||
ksize = 3
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
@cv.gapi.op('custom.delay', in_types=[cv.GMat], out_types=[cv.GMat])
|
||||
class GDelay:
|
||||
"""Delay for 10 ms."""
|
||||
|
||||
# OpenCV
|
||||
cap = cv.VideoCapture(path)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.medianBlur(g_in, ksize)
|
||||
c = cv.GComputation(g_in, g_out)
|
||||
|
||||
ccomp = c.compileStreaming()
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(source)
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
while cap.isOpened():
|
||||
has_expected, expected = cap.read()
|
||||
has_actual, actual = ccomp.pull()
|
||||
|
||||
self.assertEqual(has_expected, has_actual)
|
||||
|
||||
if not has_actual:
|
||||
break
|
||||
|
||||
self.assertEqual(0.0, cv.norm(cv.medianBlur(expected, ksize), actual, cv.NORM_INF))
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
break;
|
||||
@staticmethod
|
||||
def outMeta(desc):
|
||||
return desc
|
||||
|
||||
|
||||
def test_video_split3(self):
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
@cv.gapi.kernel(GDelay)
|
||||
class GDelayImpl:
|
||||
"""Implementation for GDelay operation."""
|
||||
|
||||
# OpenCV
|
||||
cap = cv.VideoCapture(path)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
b, g, r = cv.gapi.split3(g_in)
|
||||
c = cv.GComputation(cv.GIn(g_in), cv.GOut(b, g, r))
|
||||
|
||||
ccomp = c.compileStreaming()
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(source)
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
while cap.isOpened():
|
||||
has_expected, frame = cap.read()
|
||||
has_actual, actual = ccomp.pull()
|
||||
|
||||
self.assertEqual(has_expected, has_actual)
|
||||
|
||||
if not has_actual:
|
||||
break
|
||||
|
||||
expected = cv.split(frame)
|
||||
for e, a in zip(expected, actual):
|
||||
self.assertEqual(0.0, cv.norm(e, a, cv.NORM_INF))
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
break;
|
||||
@staticmethod
|
||||
def run(img):
|
||||
time.sleep(0.01)
|
||||
return img
|
||||
|
||||
|
||||
def test_video_add(self):
|
||||
sz = (576, 768, 3)
|
||||
in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
|
||||
class test_gapi_streaming(NewOpenCVTests):
|
||||
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
|
||||
# OpenCV
|
||||
cap = cv.VideoCapture(path)
|
||||
|
||||
# G-API
|
||||
g_in1 = cv.GMat()
|
||||
g_in2 = cv.GMat()
|
||||
out = cv.gapi.add(g_in1, g_in2)
|
||||
c = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(out))
|
||||
|
||||
ccomp = c.compileStreaming()
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(cv.gin(source, in_mat))
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
while cap.isOpened():
|
||||
has_expected, frame = cap.read()
|
||||
has_actual, actual = ccomp.pull()
|
||||
|
||||
self.assertEqual(has_expected, has_actual)
|
||||
|
||||
if not has_actual:
|
||||
break
|
||||
|
||||
expected = cv.add(frame, in_mat)
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
break;
|
||||
|
||||
|
||||
def test_video_good_features_to_track(self):
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
|
||||
# NB: goodFeaturesToTrack configuration
|
||||
max_corners = 50
|
||||
quality_lvl = 0.01
|
||||
min_distance = 10
|
||||
block_sz = 3
|
||||
use_harris_detector = True
|
||||
k = 0.04
|
||||
mask = None
|
||||
|
||||
# OpenCV
|
||||
cap = cv.VideoCapture(path)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_gray = cv.gapi.RGB2Gray(g_in)
|
||||
g_out = cv.gapi.goodFeaturesToTrack(g_gray, max_corners, quality_lvl,
|
||||
min_distance, mask, block_sz, use_harris_detector, k)
|
||||
|
||||
c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
|
||||
ccomp = c.compileStreaming()
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(source)
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
while cap.isOpened():
|
||||
has_expected, frame = cap.read()
|
||||
has_actual, actual = ccomp.pull()
|
||||
|
||||
self.assertEqual(has_expected, has_actual)
|
||||
|
||||
if not has_actual:
|
||||
break
|
||||
def test_image_input(self):
|
||||
sz = (1280, 720)
|
||||
in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
|
||||
|
||||
# OpenCV
|
||||
frame = cv.cvtColor(frame, cv.COLOR_RGB2GRAY)
|
||||
expected = cv.goodFeaturesToTrack(frame, max_corners, quality_lvl,
|
||||
min_distance, mask=mask,
|
||||
blockSize=block_sz, useHarrisDetector=use_harris_detector, k=k)
|
||||
for e, a in zip(expected, actual):
|
||||
# NB: OpenCV & G-API have different output shapes:
|
||||
# OpenCV - (num_points, 1, 2)
|
||||
# G-API - (num_points, 2)
|
||||
self.assertEqual(0.0, cv.norm(e.flatten(),
|
||||
np.array(a, np.float32).flatten(),
|
||||
cv.NORM_INF))
|
||||
expected = cv.medianBlur(in_mat, 3)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.medianBlur(g_in, 3)
|
||||
c = cv.GComputation(g_in, g_out)
|
||||
ccomp = c.compileStreaming(cv.gapi.descr_of(in_mat))
|
||||
ccomp.setSource(cv.gin(in_mat))
|
||||
ccomp.start()
|
||||
|
||||
_, actual = ccomp.pull()
|
||||
|
||||
# Assert
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
|
||||
|
||||
def test_video_input(self):
|
||||
ksize = 3
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
|
||||
# OpenCV
|
||||
cap = cv.VideoCapture(path)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out = cv.gapi.medianBlur(g_in, ksize)
|
||||
c = cv.GComputation(g_in, g_out)
|
||||
|
||||
ccomp = c.compileStreaming()
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(cv.gin(source))
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
while cap.isOpened():
|
||||
has_expected, expected = cap.read()
|
||||
has_actual, actual = ccomp.pull()
|
||||
|
||||
self.assertEqual(has_expected, has_actual)
|
||||
|
||||
if not has_actual:
|
||||
break
|
||||
|
||||
self.assertEqual(0.0, cv.norm(cv.medianBlur(expected, ksize), actual, cv.NORM_INF))
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
break
|
||||
|
||||
|
||||
def test_video_split3(self):
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
|
||||
# OpenCV
|
||||
cap = cv.VideoCapture(path)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
b, g, r = cv.gapi.split3(g_in)
|
||||
c = cv.GComputation(cv.GIn(g_in), cv.GOut(b, g, r))
|
||||
|
||||
ccomp = c.compileStreaming()
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(cv.gin(source))
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
while cap.isOpened():
|
||||
has_expected, frame = cap.read()
|
||||
has_actual, actual = ccomp.pull()
|
||||
|
||||
self.assertEqual(has_expected, has_actual)
|
||||
|
||||
if not has_actual:
|
||||
break
|
||||
|
||||
expected = cv.split(frame)
|
||||
for e, a in zip(expected, actual):
|
||||
self.assertEqual(0.0, cv.norm(e, a, cv.NORM_INF))
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
break
|
||||
|
||||
|
||||
def test_video_add(self):
|
||||
sz = (576, 768, 3)
|
||||
in_mat = np.random.randint(0, 100, sz).astype(np.uint8)
|
||||
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
|
||||
# OpenCV
|
||||
cap = cv.VideoCapture(path)
|
||||
|
||||
# G-API
|
||||
g_in1 = cv.GMat()
|
||||
g_in2 = cv.GMat()
|
||||
out = cv.gapi.add(g_in1, g_in2)
|
||||
c = cv.GComputation(cv.GIn(g_in1, g_in2), cv.GOut(out))
|
||||
|
||||
ccomp = c.compileStreaming()
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(cv.gin(source, in_mat))
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
while cap.isOpened():
|
||||
has_expected, frame = cap.read()
|
||||
has_actual, actual = ccomp.pull()
|
||||
|
||||
self.assertEqual(has_expected, has_actual)
|
||||
|
||||
if not has_actual:
|
||||
break
|
||||
|
||||
expected = cv.add(frame, in_mat)
|
||||
self.assertEqual(0.0, cv.norm(expected, actual, cv.NORM_INF))
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
break
|
||||
|
||||
|
||||
def test_video_good_features_to_track(self):
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
|
||||
# NB: goodFeaturesToTrack configuration
|
||||
max_corners = 50
|
||||
quality_lvl = 0.01
|
||||
min_distance = 10
|
||||
block_sz = 3
|
||||
use_harris_detector = True
|
||||
k = 0.04
|
||||
mask = None
|
||||
|
||||
# OpenCV
|
||||
cap = cv.VideoCapture(path)
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_gray = cv.gapi.RGB2Gray(g_in)
|
||||
g_out = cv.gapi.goodFeaturesToTrack(g_gray, max_corners, quality_lvl,
|
||||
min_distance, mask, block_sz, use_harris_detector, k)
|
||||
|
||||
c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out))
|
||||
|
||||
ccomp = c.compileStreaming()
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(cv.gin(source))
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
while cap.isOpened():
|
||||
has_expected, frame = cap.read()
|
||||
has_actual, actual = ccomp.pull()
|
||||
|
||||
self.assertEqual(has_expected, has_actual)
|
||||
|
||||
if not has_actual:
|
||||
break
|
||||
|
||||
# OpenCV
|
||||
frame = cv.cvtColor(frame, cv.COLOR_RGB2GRAY)
|
||||
expected = cv.goodFeaturesToTrack(frame, max_corners, quality_lvl,
|
||||
min_distance, mask=mask,
|
||||
blockSize=block_sz, useHarrisDetector=use_harris_detector, k=k)
|
||||
for e, a in zip(expected, actual):
|
||||
# NB: OpenCV & G-API have different output shapes:
|
||||
# OpenCV - (num_points, 1, 2)
|
||||
# G-API - (num_points, 2)
|
||||
self.assertEqual(0.0, cv.norm(e.flatten(),
|
||||
np.array(a, np.float32).flatten(),
|
||||
cv.NORM_INF))
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
break
|
||||
|
||||
|
||||
def test_gapi_streaming_meta(self):
|
||||
ksize = 3
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_ts = cv.gapi.streaming.timestamp(g_in)
|
||||
g_seqno = cv.gapi.streaming.seqNo(g_in)
|
||||
g_seqid = cv.gapi.streaming.seq_id(g_in)
|
||||
|
||||
c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_ts, g_seqno, g_seqid))
|
||||
|
||||
ccomp = c.compileStreaming()
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(cv.gin(source))
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
curr_frame_number = 0
|
||||
while True:
|
||||
has_frame, (ts, seqno, seqid) = ccomp.pull()
|
||||
|
||||
if not has_frame:
|
||||
break
|
||||
|
||||
self.assertEqual(curr_frame_number, seqno)
|
||||
self.assertEqual(curr_frame_number, seqid)
|
||||
|
||||
curr_frame_number += 1
|
||||
if curr_frame_number == max_num_frames:
|
||||
break
|
||||
|
||||
def test_desync(self):
|
||||
path = self.find_file('cv/video/768x576.avi', [os.environ['OPENCV_TEST_DATA_PATH']])
|
||||
|
||||
# G-API
|
||||
g_in = cv.GMat()
|
||||
g_out1 = cv.gapi.copy(g_in)
|
||||
des = cv.gapi.streaming.desync(g_in)
|
||||
g_out2 = GDelay.on(des)
|
||||
|
||||
c = cv.GComputation(cv.GIn(g_in), cv.GOut(g_out1, g_out2))
|
||||
|
||||
kernels = cv.gapi.kernels(GDelayImpl)
|
||||
ccomp = c.compileStreaming(args=cv.gapi.compile_args(kernels))
|
||||
source = cv.gapi.wip.make_capture_src(path)
|
||||
ccomp.setSource(cv.gin(source))
|
||||
ccomp.start()
|
||||
|
||||
# Assert
|
||||
max_num_frames = 10
|
||||
proc_num_frames = 0
|
||||
|
||||
out_counter = 0
|
||||
desync_out_counter = 0
|
||||
none_counter = 0
|
||||
while True:
|
||||
has_frame, (out1, out2) = ccomp.pull()
|
||||
if not has_frame:
|
||||
break
|
||||
|
||||
if not out1 is None:
|
||||
out_counter += 1
|
||||
if not out2 is None:
|
||||
desync_out_counter += 1
|
||||
else:
|
||||
none_counter += 1
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
ccomp.stop()
|
||||
break
|
||||
|
||||
self.assertLess(0, proc_num_frames)
|
||||
self.assertLess(desync_out_counter, out_counter)
|
||||
self.assertLess(0, none_counter)
|
||||
|
||||
|
||||
except unittest.SkipTest as e:
|
||||
|
||||
message = str(e)
|
||||
|
||||
class TestSkip(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.skipTest('Skip tests: ' + message)
|
||||
|
||||
def test_skip():
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
proc_num_frames += 1
|
||||
if proc_num_frames == max_num_frames:
|
||||
break;
|
||||
|
||||
if __name__ == '__main__':
|
||||
NewOpenCVTests.bootstrap()
|
||||
|
||||
@@ -3,29 +3,51 @@
|
||||
import numpy as np
|
||||
import cv2 as cv
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
from tests_common import NewOpenCVTests
|
||||
|
||||
class gapi_types_test(NewOpenCVTests):
|
||||
|
||||
def test_garray_type(self):
|
||||
types = [cv.gapi.CV_BOOL , cv.gapi.CV_INT , cv.gapi.CV_DOUBLE , cv.gapi.CV_FLOAT,
|
||||
cv.gapi.CV_STRING, cv.gapi.CV_POINT , cv.gapi.CV_POINT2F, cv.gapi.CV_SIZE ,
|
||||
cv.gapi.CV_RECT , cv.gapi.CV_SCALAR, cv.gapi.CV_MAT , cv.gapi.CV_GMAT]
|
||||
try:
|
||||
|
||||
for t in types:
|
||||
g_array = cv.GArrayT(t)
|
||||
self.assertEqual(t, g_array.type())
|
||||
if sys.version_info[:2] < (3, 0):
|
||||
raise unittest.SkipTest('Python 2.x is not supported')
|
||||
|
||||
class gapi_types_test(NewOpenCVTests):
|
||||
|
||||
def test_garray_type(self):
|
||||
types = [cv.gapi.CV_BOOL , cv.gapi.CV_INT , cv.gapi.CV_DOUBLE , cv.gapi.CV_FLOAT,
|
||||
cv.gapi.CV_STRING, cv.gapi.CV_POINT , cv.gapi.CV_POINT2F, cv.gapi.CV_SIZE ,
|
||||
cv.gapi.CV_RECT , cv.gapi.CV_SCALAR, cv.gapi.CV_MAT , cv.gapi.CV_GMAT]
|
||||
|
||||
for t in types:
|
||||
g_array = cv.GArrayT(t)
|
||||
self.assertEqual(t, g_array.type())
|
||||
|
||||
|
||||
def test_gopaque_type(self):
|
||||
types = [cv.gapi.CV_BOOL , cv.gapi.CV_INT , cv.gapi.CV_DOUBLE , cv.gapi.CV_FLOAT,
|
||||
cv.gapi.CV_STRING, cv.gapi.CV_POINT , cv.gapi.CV_POINT2F, cv.gapi.CV_SIZE ,
|
||||
cv.gapi.CV_RECT]
|
||||
def test_gopaque_type(self):
|
||||
types = [cv.gapi.CV_BOOL , cv.gapi.CV_INT , cv.gapi.CV_DOUBLE , cv.gapi.CV_FLOAT,
|
||||
cv.gapi.CV_STRING, cv.gapi.CV_POINT , cv.gapi.CV_POINT2F, cv.gapi.CV_SIZE ,
|
||||
cv.gapi.CV_RECT]
|
||||
|
||||
for t in types:
|
||||
g_opaque = cv.GOpaqueT(t)
|
||||
self.assertEqual(t, g_opaque.type())
|
||||
for t in types:
|
||||
g_opaque = cv.GOpaqueT(t)
|
||||
self.assertEqual(t, g_opaque.type())
|
||||
|
||||
|
||||
except unittest.SkipTest as e:
|
||||
|
||||
message = str(e)
|
||||
|
||||
class TestSkip(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.skipTest('Skip tests: ' + message)
|
||||
|
||||
def test_skip():
|
||||
pass
|
||||
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
#include <opencv2/gapi/fluid/core.hpp>
|
||||
#include <opencv2/gapi/fluid/imgproc.hpp>
|
||||
|
||||
static void gscalar_example()
|
||||
{
|
||||
//! [gscalar_implicit]
|
||||
cv::GMat a;
|
||||
cv::GMat b = a + 1;
|
||||
//! [gscalar_implicit]
|
||||
}
|
||||
|
||||
static void typed_example()
|
||||
{
|
||||
const cv::Size sz(32, 32);
|
||||
@@ -116,7 +124,9 @@ int main(int argc, char *argv[])
|
||||
>();
|
||||
//! [kernels_snippet]
|
||||
|
||||
// Just call typed example with no input/output
|
||||
// Just call typed example with no input/output - avoid warnings about
|
||||
// unused functions
|
||||
typed_example();
|
||||
gscalar_example();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,13 +16,13 @@ const std::string keys =
|
||||
"{ h help | | Print this help message }"
|
||||
"{ input | | Path to the input video file }"
|
||||
"{ facem | face-detection-retail-0005.xml | Path to OpenVINO face detection model (.xml) }"
|
||||
"{ faced | CPU | Target device for the face detection (e.g. CPU, GPU, VPU, ...) }"
|
||||
"{ faced | CPU | Target device for the face detection (e.g. CPU, GPU, ...) }"
|
||||
"{ landm | facial-landmarks-35-adas-0002.xml | Path to OpenVINO landmarks detector model (.xml) }"
|
||||
"{ landd | CPU | Target device for the landmarks detector (e.g. CPU, GPU, VPU, ...) }"
|
||||
"{ landd | CPU | Target device for the landmarks detector (e.g. CPU, GPU, ...) }"
|
||||
"{ headm | head-pose-estimation-adas-0001.xml | Path to OpenVINO head pose estimation model (.xml) }"
|
||||
"{ headd | CPU | Target device for the head pose estimation inference (e.g. CPU, GPU, VPU, ...) }"
|
||||
"{ headd | CPU | Target device for the head pose estimation inference (e.g. CPU, GPU, ...) }"
|
||||
"{ gazem | gaze-estimation-adas-0002.xml | Path to OpenVINO gaze vector estimaiton model (.xml) }"
|
||||
"{ gazed | CPU | Target device for the gaze vector estimation inference (e.g. CPU, GPU, VPU, ...) }"
|
||||
"{ gazed | CPU | Target device for the gaze vector estimation inference (e.g. CPU, GPU, ...) }"
|
||||
;
|
||||
|
||||
namespace {
|
||||
@@ -338,7 +338,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
cv::GMat in;
|
||||
cv::GMat faces = cv::gapi::infer<custom::Faces>(in);
|
||||
cv::GOpaque<cv::Size> sz = custom::Size::on(in); // FIXME
|
||||
cv::GOpaque<cv::Size> sz = cv::gapi::streaming::size(in);
|
||||
cv::GArray<cv::Rect> faces_rc = custom::ParseSSD::on(faces, sz, true);
|
||||
cv::GArray<cv::GMat> angles_y, angles_p, angles_r;
|
||||
std::tie(angles_y, angles_p, angles_r) = cv::gapi::infer<custom::HeadPose>(faces_rc, in);
|
||||
|
||||
@@ -15,6 +15,10 @@ cv::gapi::GNetPackage::GNetPackage(std::initializer_list<GNetParam> ii)
|
||||
: networks(ii) {
|
||||
}
|
||||
|
||||
cv::gapi::GNetPackage::GNetPackage(std::vector<GNetParam> nets)
|
||||
: networks(nets) {
|
||||
}
|
||||
|
||||
std::vector<cv::gapi::GBackend> cv::gapi::GNetPackage::backends() const {
|
||||
std::unordered_set<cv::gapi::GBackend> unique_set;
|
||||
for (const auto &nn : networks) unique_set.insert(nn.backend);
|
||||
|
||||
@@ -159,7 +159,7 @@ void drawPrimitivesOCV(cv::Mat& in,
|
||||
{
|
||||
const auto& rp = cv::util::get<Rect>(p);
|
||||
const auto color = converter.cvtColor(rp.color);
|
||||
cv::rectangle(in, rp.rect, color , rp.thick);
|
||||
cv::rectangle(in, rp.rect, color, rp.thick, rp.lt, rp.shift);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ void drawPrimitivesOCV(cv::Mat& in,
|
||||
{
|
||||
const auto& cp = cv::util::get<Circle>(p);
|
||||
const auto color = converter.cvtColor(cp.color);
|
||||
cv::circle(in, cp.center, cp.radius, color, cp.thick);
|
||||
cv::circle(in, cp.center, cp.radius, color, cp.thick, cp.lt, cp.shift);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ void drawPrimitivesOCV(cv::Mat& in,
|
||||
{
|
||||
const auto& lp = cv::util::get<Line>(p);
|
||||
const auto color = converter.cvtColor(lp.color);
|
||||
cv::line(in, lp.pt1, lp.pt2, color, lp.thick);
|
||||
cv::line(in, lp.pt1, lp.pt2, color, lp.thick, lp.lt, lp.shift);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,19 @@ class GGraphMetaBackendImpl final: public cv::gapi::GBackend::Priv {
|
||||
const std::vector<cv::gimpl::Data>&) const override {
|
||||
return EPtr{new GraphMetaExecutable(graph, nodes)};
|
||||
}
|
||||
|
||||
virtual bool controlsMerge() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool allowsMerge(const cv::gimpl::GIslandModel::Graph &,
|
||||
const ade::NodeHandle &,
|
||||
const ade::NodeHandle &,
|
||||
const ade::NodeHandle &) const override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
cv::gapi::GBackend graph_meta_backend() {
|
||||
|
||||
@@ -652,7 +652,12 @@ GAPI_OCV_KERNEL(GCPUParseSSDBL, cv::gapi::nn::parsers::GParseSSDBL)
|
||||
std::vector<cv::Rect>& out_boxes,
|
||||
std::vector<int>& out_labels)
|
||||
{
|
||||
cv::parseSSDBL(in_ssd_result, in_size, confidence_threshold, filter_label, out_boxes, out_labels);
|
||||
cv::ParseSSD(in_ssd_result, in_size,
|
||||
confidence_threshold,
|
||||
filter_label,
|
||||
false,
|
||||
false,
|
||||
out_boxes, out_labels);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -665,7 +670,13 @@ GAPI_OCV_KERNEL(GOCVParseSSD, cv::gapi::nn::parsers::GParseSSD)
|
||||
const bool filter_out_of_bounds,
|
||||
std::vector<cv::Rect>& out_boxes)
|
||||
{
|
||||
cv::parseSSD(in_ssd_result, in_size, confidence_threshold, alignment_to_square, filter_out_of_bounds, out_boxes);
|
||||
std::vector<int> unused_labels;
|
||||
cv::ParseSSD(in_ssd_result, in_size,
|
||||
confidence_threshold,
|
||||
-1,
|
||||
alignment_to_square,
|
||||
filter_out_of_bounds,
|
||||
out_boxes, unused_labels);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -170,12 +170,14 @@ private:
|
||||
} // namespace nn
|
||||
} // namespace gapi
|
||||
|
||||
void parseSSDBL(const cv::Mat& in_ssd_result,
|
||||
const cv::Size& in_size,
|
||||
const float confidence_threshold,
|
||||
const int filter_label,
|
||||
std::vector<cv::Rect>& out_boxes,
|
||||
std::vector<int>& out_labels)
|
||||
void ParseSSD(const cv::Mat& in_ssd_result,
|
||||
const cv::Size& in_size,
|
||||
const float confidence_threshold,
|
||||
const int filter_label,
|
||||
const bool alignment_to_square,
|
||||
const bool filter_out_of_bounds,
|
||||
std::vector<cv::Rect>& out_boxes,
|
||||
std::vector<int>& out_labels)
|
||||
{
|
||||
cv::gapi::nn::SSDParser parser(in_ssd_result.size, in_size, in_ssd_result.ptr<float>());
|
||||
out_boxes.clear();
|
||||
@@ -188,38 +190,6 @@ void parseSSDBL(const cv::Mat& in_ssd_result,
|
||||
{
|
||||
std::tie(rc, image_id, confidence, label) = parser.extract(i);
|
||||
|
||||
if (image_id < 0.f)
|
||||
{
|
||||
break; // marks end-of-detections
|
||||
}
|
||||
|
||||
if (confidence < confidence_threshold ||
|
||||
(filter_label != -1 && label != filter_label))
|
||||
{
|
||||
continue; // filter out object classes if filter is specified
|
||||
} // and skip objects with low confidence
|
||||
out_boxes.emplace_back(rc & parser.getSurface());
|
||||
out_labels.emplace_back(label);
|
||||
}
|
||||
}
|
||||
|
||||
void parseSSD(const cv::Mat& in_ssd_result,
|
||||
const cv::Size& in_size,
|
||||
const float confidence_threshold,
|
||||
const bool alignment_to_square,
|
||||
const bool filter_out_of_bounds,
|
||||
std::vector<cv::Rect>& out_boxes)
|
||||
{
|
||||
cv::gapi::nn::SSDParser parser(in_ssd_result.size, in_size, in_ssd_result.ptr<float>());
|
||||
out_boxes.clear();
|
||||
cv::Rect rc;
|
||||
float image_id, confidence;
|
||||
int label;
|
||||
const size_t range = parser.getMaxProposals();
|
||||
for (size_t i = 0; i < range; ++i)
|
||||
{
|
||||
std::tie(rc, image_id, confidence, label) = parser.extract(i);
|
||||
|
||||
if (image_id < 0.f)
|
||||
{
|
||||
break; // marks end-of-detections
|
||||
@@ -228,12 +198,14 @@ void parseSSD(const cv::Mat& in_ssd_result,
|
||||
{
|
||||
continue; // skip objects with low confidence
|
||||
}
|
||||
|
||||
if((filter_label != -1) && (label != filter_label))
|
||||
{
|
||||
continue; // filter out object classes if filter is specified
|
||||
}
|
||||
if (alignment_to_square)
|
||||
{
|
||||
parser.adjustBoundingBox(rc);
|
||||
}
|
||||
|
||||
const auto clipped_rc = rc & parser.getSurface();
|
||||
if (filter_out_of_bounds)
|
||||
{
|
||||
@@ -243,6 +215,7 @@ void parseSSD(const cv::Mat& in_ssd_result,
|
||||
}
|
||||
}
|
||||
out_boxes.emplace_back(clipped_rc);
|
||||
out_labels.emplace_back(label);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,19 +11,14 @@
|
||||
|
||||
namespace cv
|
||||
{
|
||||
void parseSSDBL(const cv::Mat& in_ssd_result,
|
||||
const cv::Size& in_size,
|
||||
const float confidence_threshold,
|
||||
const int filter_label,
|
||||
std::vector<cv::Rect>& out_boxes,
|
||||
std::vector<int>& out_labels);
|
||||
|
||||
void parseSSD(const cv::Mat& in_ssd_result,
|
||||
void ParseSSD(const cv::Mat& in_ssd_result,
|
||||
const cv::Size& in_size,
|
||||
const float confidence_threshold,
|
||||
const int filter_label,
|
||||
const bool alignment_to_square,
|
||||
const bool filter_out_of_bounds,
|
||||
std::vector<cv::Rect>& out_boxes);
|
||||
std::vector<cv::Rect>& out_boxes,
|
||||
std::vector<int>& out_labels);
|
||||
|
||||
void parseYolo(const cv::Mat& in_yolo_result,
|
||||
const cv::Size& in_size,
|
||||
|
||||
@@ -222,8 +222,17 @@ struct IEUnit {
|
||||
IE::ExecutableNetwork this_network;
|
||||
cv::gimpl::ie::wrap::Plugin this_plugin;
|
||||
|
||||
InferenceEngine::RemoteContext::Ptr rctx = nullptr;
|
||||
|
||||
explicit IEUnit(const cv::gapi::ie::detail::ParamDesc &pp)
|
||||
: params(pp) {
|
||||
InferenceEngine::ParamMap* ctx_params =
|
||||
cv::util::any_cast<InferenceEngine::ParamMap>(¶ms.context_config);
|
||||
if (ctx_params != nullptr) {
|
||||
auto ie_core = cv::gimpl::ie::wrap::getCore();
|
||||
rctx = ie_core.CreateContext(params.device_id, *ctx_params);
|
||||
}
|
||||
|
||||
if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Load) {
|
||||
net = cv::gimpl::ie::wrap::readNetwork(params);
|
||||
inputs = net.getInputsInfo();
|
||||
@@ -231,7 +240,7 @@ struct IEUnit {
|
||||
} else if (params.kind == cv::gapi::ie::detail::ParamDesc::Kind::Import) {
|
||||
this_plugin = cv::gimpl::ie::wrap::getPlugin(params);
|
||||
this_plugin.SetConfig(params.config);
|
||||
this_network = cv::gimpl::ie::wrap::importNetwork(this_plugin, params);
|
||||
this_network = cv::gimpl::ie::wrap::importNetwork(this_plugin, params, rctx);
|
||||
// FIXME: ICNNetwork returns InputsDataMap/OutputsDataMap,
|
||||
// but ExecutableNetwork returns ConstInputsDataMap/ConstOutputsDataMap
|
||||
inputs = cv::gimpl::ie::wrap::toInputsDataMap(this_network.GetInputsInfo());
|
||||
@@ -279,7 +288,8 @@ struct IEUnit {
|
||||
// for loadNetwork they can be obtained by using readNetwork
|
||||
non_const_this->this_plugin = cv::gimpl::ie::wrap::getPlugin(params);
|
||||
non_const_this->this_plugin.SetConfig(params.config);
|
||||
non_const_this->this_network = cv::gimpl::ie::wrap::loadNetwork(non_const_this->this_plugin, net, params);
|
||||
non_const_this->this_network = cv::gimpl::ie::wrap::loadNetwork(non_const_this->this_plugin,
|
||||
net, params, rctx);
|
||||
}
|
||||
|
||||
return {params, this_plugin, this_network};
|
||||
@@ -481,7 +491,32 @@ using GConstGIEModel = ade::ConstTypedGraph
|
||||
, IECallable
|
||||
>;
|
||||
|
||||
inline IE::Blob::Ptr extractRemoteBlob(IECallContext& ctx, std::size_t i) {
|
||||
GAPI_Assert(ctx.inShape(i) == cv::GShape::GFRAME &&
|
||||
"Remote blob is supported for MediaFrame only");
|
||||
|
||||
cv::util::any any_blob_params = ctx.inFrame(i).blobParams();
|
||||
auto ie_core = cv::gimpl::ie::wrap::getCore();
|
||||
|
||||
using ParamType = std::pair<InferenceEngine::TensorDesc,
|
||||
InferenceEngine::ParamMap>;
|
||||
|
||||
ParamType* blob_params = cv::util::any_cast<ParamType>(&any_blob_params);
|
||||
if (blob_params == nullptr) {
|
||||
GAPI_Assert(false && "Incorrect type of blobParams: "
|
||||
"expected std::pair<InferenceEngine::TensorDesc,"
|
||||
"InferenceEngine::ParamMap>");
|
||||
}
|
||||
|
||||
return ctx.uu.rctx->CreateBlob(blob_params->first,
|
||||
blob_params->second);
|
||||
}
|
||||
|
||||
inline IE::Blob::Ptr extractBlob(IECallContext& ctx, std::size_t i) {
|
||||
if (ctx.uu.rctx != nullptr) {
|
||||
return extractRemoteBlob(ctx, i);
|
||||
}
|
||||
|
||||
switch (ctx.inShape(i)) {
|
||||
case cv::GShape::GFRAME: {
|
||||
const auto& frame = ctx.inFrame(i);
|
||||
@@ -1060,6 +1095,7 @@ struct InferList: public cv::detail::KernelTag {
|
||||
}
|
||||
|
||||
IE::Blob::Ptr this_blob = extractBlob(*ctx, 1);
|
||||
|
||||
std::vector<std::vector<int>> cached_dims(ctx->uu.params.num_out);
|
||||
for (auto i : ade::util::iota(ctx->uu.params.num_out)) {
|
||||
const IE::DataPtr& ie_out = ctx->uu.outputs.at(ctx->uu.params.output_names[i]);
|
||||
|
||||
@@ -124,7 +124,11 @@ IE::Core giewrap::getPlugin(const GIEParam& params) {
|
||||
{
|
||||
try
|
||||
{
|
||||
#if INF_ENGINE_RELEASE >= 2021040000
|
||||
plugin.AddExtension(std::make_shared<IE::Extension>(extlib), params.device_id);
|
||||
#else
|
||||
plugin.AddExtension(IE::make_so_pointer<IE::IExtension>(extlib), params.device_id);
|
||||
#endif
|
||||
CV_LOG_INFO(NULL, "DNN-IE: Loaded extension plugin: " << extlib);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
#include "opencv2/gapi/infer/ie.hpp"
|
||||
|
||||
@@ -50,12 +51,29 @@ GAPI_EXPORTS IE::Core getCore();
|
||||
GAPI_EXPORTS IE::Core getPlugin(const GIEParam& params);
|
||||
GAPI_EXPORTS inline IE::ExecutableNetwork loadNetwork( IE::Core& core,
|
||||
const IE::CNNNetwork& net,
|
||||
const GIEParam& params) {
|
||||
return core.LoadNetwork(net, params.device_id);
|
||||
const GIEParam& params,
|
||||
IE::RemoteContext::Ptr rctx = nullptr) {
|
||||
if (rctx != nullptr) {
|
||||
return core.LoadNetwork(net, rctx);
|
||||
} else {
|
||||
return core.LoadNetwork(net, params.device_id);
|
||||
}
|
||||
}
|
||||
GAPI_EXPORTS inline IE::ExecutableNetwork importNetwork( IE::Core& core,
|
||||
const GIEParam& param) {
|
||||
return core.ImportNetwork(param.model_path, param.device_id, {});
|
||||
const GIEParam& params,
|
||||
IE::RemoteContext::Ptr rctx = nullptr) {
|
||||
if (rctx != nullptr) {
|
||||
std::filebuf blobFile;
|
||||
if (!blobFile.open(params.model_path, std::ios::in | std::ios::binary))
|
||||
{
|
||||
blobFile.close();
|
||||
throw std::runtime_error("Could not open file");
|
||||
}
|
||||
std::istream graphBlob(&blobFile);
|
||||
return core.ImportNetwork(graphBlob, rctx);
|
||||
} else {
|
||||
return core.ImportNetwork(params.model_path, params.device_id, {});
|
||||
}
|
||||
}
|
||||
#endif // INF_ENGINE_RELEASE < 2019020000
|
||||
}}}}
|
||||
|
||||
@@ -75,6 +75,11 @@ bool cv::GStreamingCompiled::Priv::pull(cv::GOptRunArgsP &&outs)
|
||||
return m_exec->pull(std::move(outs));
|
||||
}
|
||||
|
||||
std::tuple<bool, cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>> cv::GStreamingCompiled::Priv::pull()
|
||||
{
|
||||
return m_exec->pull();
|
||||
}
|
||||
|
||||
bool cv::GStreamingCompiled::Priv::try_pull(cv::GRunArgsP &&outs)
|
||||
{
|
||||
return m_exec->try_pull(std::move(outs));
|
||||
@@ -123,18 +128,9 @@ bool cv::GStreamingCompiled::pull(cv::GRunArgsP &&outs)
|
||||
return m_priv->pull(std::move(outs));
|
||||
}
|
||||
|
||||
std::tuple<bool, cv::GRunArgs> cv::GStreamingCompiled::pull()
|
||||
std::tuple<bool, cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>> cv::GStreamingCompiled::pull()
|
||||
{
|
||||
GRunArgs run_args;
|
||||
GRunArgsP outs;
|
||||
const auto& out_info = m_priv->outInfo();
|
||||
run_args.reserve(out_info.size());
|
||||
outs.reserve(out_info.size());
|
||||
|
||||
cv::detail::constructGraphOutputs(m_priv->outInfo(), run_args, outs);
|
||||
|
||||
bool is_over = m_priv->pull(std::move(outs));
|
||||
return std::make_tuple(is_over, run_args);
|
||||
return m_priv->pull();
|
||||
}
|
||||
|
||||
bool cv::GStreamingCompiled::pull(cv::GOptRunArgsP &&outs)
|
||||
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
void start();
|
||||
bool pull(cv::GRunArgsP &&outs);
|
||||
bool pull(cv::GOptRunArgsP &&outs);
|
||||
std::tuple<bool, cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>> pull();
|
||||
bool try_pull(cv::GRunArgsP &&outs);
|
||||
void stop();
|
||||
|
||||
|
||||
@@ -1017,6 +1017,49 @@ void check_DesyncObjectConsumedByMultipleIslands(const cv::gimpl::GIslandModel::
|
||||
} // for(nodes)
|
||||
}
|
||||
|
||||
// NB: Construct GRunArgsP based on passed info and store the memory in passed cv::GRunArgs.
|
||||
// Needed for python bridge, because in case python user doesn't pass output arguments to apply.
|
||||
void constructOptGraphOutputs(const cv::GTypesInfo &out_info,
|
||||
cv::GOptRunArgs &args,
|
||||
cv::GOptRunArgsP &outs)
|
||||
{
|
||||
for (auto&& info : out_info)
|
||||
{
|
||||
switch (info.shape)
|
||||
{
|
||||
case cv::GShape::GMAT:
|
||||
{
|
||||
args.emplace_back(cv::optional<cv::Mat>{});
|
||||
outs.emplace_back(&cv::util::get<cv::optional<cv::Mat>>(args.back()));
|
||||
break;
|
||||
}
|
||||
case cv::GShape::GSCALAR:
|
||||
{
|
||||
args.emplace_back(cv::optional<cv::Scalar>{});
|
||||
outs.emplace_back(&cv::util::get<cv::optional<cv::Scalar>>(args.back()));
|
||||
break;
|
||||
}
|
||||
case cv::GShape::GARRAY:
|
||||
{
|
||||
cv::detail::VectorRef ref;
|
||||
cv::util::get<cv::detail::ConstructVec>(info.ctor)(ref);
|
||||
args.emplace_back(cv::util::make_optional(std::move(ref)));
|
||||
outs.emplace_back(wrap_opt_arg(cv::util::get<cv::optional<cv::detail::VectorRef>>(args.back())));
|
||||
break;
|
||||
}
|
||||
case cv::GShape::GOPAQUE:
|
||||
{
|
||||
cv::detail::OpaqueRef ref;
|
||||
cv::util::get<cv::detail::ConstructOpaque>(info.ctor)(ref);
|
||||
args.emplace_back(cv::util::make_optional(std::move(ref)));
|
||||
outs.emplace_back(wrap_opt_arg(cv::util::get<cv::optional<cv::detail::OpaqueRef>>(args.back())));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cv::util::throw_error(std::logic_error("Unsupported optional output shape for Python"));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
class cv::gimpl::GStreamingExecutor::Synchronizer final {
|
||||
@@ -1320,6 +1363,16 @@ cv::gimpl::GStreamingExecutor::GStreamingExecutor(std::unique_ptr<ade::Graph> &&
|
||||
// per the same input frame, so the output traffic multiplies)
|
||||
GAPI_Assert(m_collector_map.size() > 0u);
|
||||
m_out_queue.set_capacity(queue_capacity * m_collector_map.size());
|
||||
|
||||
// FIXME: The code duplicates logic of collectGraphInfo()
|
||||
cv::gimpl::GModel::ConstGraph cgr(*m_orig_graph);
|
||||
auto meta = cgr.metadata().get<cv::gimpl::Protocol>().out_nhs;
|
||||
out_info.reserve(meta.size());
|
||||
|
||||
ade::util::transform(meta, std::back_inserter(out_info), [&cgr](const ade::NodeHandle& nh) {
|
||||
const auto& data = cgr.metadata(nh).get<cv::gimpl::Data>();
|
||||
return cv::GTypeInfo{data.shape, data.kind, data.ctor};
|
||||
});
|
||||
}
|
||||
|
||||
cv::gimpl::GStreamingExecutor::~GStreamingExecutor()
|
||||
@@ -1653,6 +1706,31 @@ bool cv::gimpl::GStreamingExecutor::pull(cv::GOptRunArgsP &&outs)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::tuple<bool, cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>> cv::gimpl::GStreamingExecutor::pull()
|
||||
{
|
||||
using RunArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
|
||||
bool is_over = false;
|
||||
|
||||
if (m_desync) {
|
||||
GOptRunArgs opt_run_args;
|
||||
GOptRunArgsP opt_outs;
|
||||
opt_outs.reserve(out_info.size());
|
||||
opt_run_args.reserve(out_info.size());
|
||||
|
||||
constructOptGraphOutputs(out_info, opt_run_args, opt_outs);
|
||||
is_over = pull(std::move(opt_outs));
|
||||
return std::make_tuple(is_over, RunArgs(opt_run_args));
|
||||
}
|
||||
|
||||
GRunArgs run_args;
|
||||
GRunArgsP outs;
|
||||
run_args.reserve(out_info.size());
|
||||
outs.reserve(out_info.size());
|
||||
|
||||
constructGraphOutputs(out_info, run_args, outs);
|
||||
is_over = pull(std::move(outs));
|
||||
return std::make_tuple(is_over, RunArgs(run_args));
|
||||
}
|
||||
|
||||
bool cv::gimpl::GStreamingExecutor::try_pull(cv::GRunArgsP &&outs)
|
||||
{
|
||||
|
||||
@@ -195,6 +195,8 @@ protected:
|
||||
|
||||
void wait_shutdown();
|
||||
|
||||
cv::GTypesInfo out_info;
|
||||
|
||||
public:
|
||||
explicit GStreamingExecutor(std::unique_ptr<ade::Graph> &&g_model,
|
||||
const cv::GCompileArgs &comp_args);
|
||||
@@ -203,6 +205,7 @@ public:
|
||||
void start();
|
||||
bool pull(cv::GRunArgsP &&outs);
|
||||
bool pull(cv::GOptRunArgsP &&outs);
|
||||
std::tuple<bool, cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>> pull();
|
||||
bool try_pull(cv::GRunArgsP &&outs);
|
||||
void stop();
|
||||
bool running() const;
|
||||
|
||||
@@ -639,8 +639,8 @@ INSTANTIATE_TEST_CASE_P(RenderBGROCVTestRectsImpl, RenderBGROCVTestRects,
|
||||
Values(cv::Rect(100, 100, 200, 200)),
|
||||
Values(cv::Scalar(100, 50, 150)),
|
||||
Values(2),
|
||||
Values(LINE_8),
|
||||
Values(0)));
|
||||
Values(LINE_8, LINE_4),
|
||||
Values(0, 1)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestRectsImpl, RenderNV12OCVTestRects,
|
||||
Combine(Values(cv::Size(1280, 720)),
|
||||
@@ -673,8 +673,8 @@ INSTANTIATE_TEST_CASE_P(RenderNV12OCVTestCirclesImpl, RenderNV12OCVTestCircles,
|
||||
Values(10),
|
||||
Values(cv::Scalar(100, 50, 150)),
|
||||
Values(2),
|
||||
Values(LINE_8),
|
||||
Values(0)));
|
||||
Values(LINE_8, LINE_4),
|
||||
Values(0, 1)));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(RenderMFrameOCVTestCirclesImpl, RenderMFrameOCVTestCircles,
|
||||
Combine(Values(cv::Size(1280, 720)),
|
||||
|
||||
@@ -244,6 +244,35 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void checkPullOverload(const cv::Mat& ref,
|
||||
const bool has_output,
|
||||
cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>& args) {
|
||||
EXPECT_TRUE(has_output);
|
||||
using runArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
|
||||
cv::Mat out_mat;
|
||||
switch (args.index()) {
|
||||
case runArgs::index_of<cv::GRunArgs>():
|
||||
{
|
||||
auto outputs = util::get<cv::GRunArgs>(args);
|
||||
EXPECT_EQ(1u, outputs.size());
|
||||
out_mat = cv::util::get<cv::Mat>(outputs[0]);
|
||||
break;
|
||||
}
|
||||
case runArgs::index_of<cv::GOptRunArgs>():
|
||||
{
|
||||
auto outputs = util::get<cv::GOptRunArgs>(args);
|
||||
EXPECT_EQ(1u, outputs.size());
|
||||
auto opt_mat = cv::util::get<cv::optional<cv::Mat>>(outputs[0]);
|
||||
ASSERT_TRUE(opt_mat.has_value());
|
||||
out_mat = *opt_mat;
|
||||
break;
|
||||
}
|
||||
default: GAPI_Assert(false && "Incorrect type of Args");
|
||||
}
|
||||
|
||||
EXPECT_EQ(0., cv::norm(ref, out_mat, cv::NORM_INF));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
TEST_P(GAPI_Streaming, SmokeTest_ConstInput_GMat)
|
||||
@@ -1336,13 +1365,45 @@ TEST(Streaming, Python_Pull_Overload)
|
||||
|
||||
bool has_output;
|
||||
cv::GRunArgs outputs;
|
||||
std::tie(has_output, outputs) = ccomp.pull();
|
||||
using RunArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
|
||||
RunArgs args;
|
||||
|
||||
EXPECT_TRUE(has_output);
|
||||
EXPECT_EQ(1u, outputs.size());
|
||||
std::tie(has_output, args) = ccomp.pull();
|
||||
|
||||
auto out_mat = cv::util::get<cv::Mat>(outputs[0]);
|
||||
EXPECT_EQ(0., cv::norm(in_mat, out_mat, cv::NORM_INF));
|
||||
checkPullOverload(in_mat, has_output, args);
|
||||
|
||||
ccomp.stop();
|
||||
EXPECT_FALSE(ccomp.running());
|
||||
}
|
||||
|
||||
TEST(GAPI_Streaming_Desync, Python_Pull_Overload)
|
||||
{
|
||||
cv::GMat in;
|
||||
cv::GMat out = cv::gapi::streaming::desync(in);
|
||||
cv::GComputation c(in, out);
|
||||
|
||||
cv::Size sz(3,3);
|
||||
cv::Mat in_mat(sz, CV_8UC3);
|
||||
cv::randu(in_mat, cv::Scalar::all(0), cv::Scalar(255));
|
||||
|
||||
auto ccomp = c.compileStreaming();
|
||||
|
||||
EXPECT_TRUE(ccomp);
|
||||
EXPECT_FALSE(ccomp.running());
|
||||
|
||||
ccomp.setSource(cv::gin(in_mat));
|
||||
|
||||
ccomp.start();
|
||||
EXPECT_TRUE(ccomp.running());
|
||||
|
||||
bool has_output;
|
||||
cv::GRunArgs outputs;
|
||||
using RunArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
|
||||
RunArgs args;
|
||||
|
||||
std::tie(has_output, args) = ccomp.pull();
|
||||
|
||||
checkPullOverload(in_mat, has_output, args);
|
||||
|
||||
ccomp.stop();
|
||||
EXPECT_FALSE(ccomp.running());
|
||||
@@ -2132,9 +2193,17 @@ TEST(GAPI_Streaming, TestPythonAPI)
|
||||
|
||||
bool is_over = false;
|
||||
cv::GRunArgs out_args;
|
||||
using RunArgs = cv::util::variant<cv::GRunArgs, cv::GOptRunArgs>;
|
||||
RunArgs args;
|
||||
|
||||
// NB: Used by python bridge
|
||||
std::tie(is_over, out_args) = cc.pull();
|
||||
std::tie(is_over, args) = cc.pull();
|
||||
|
||||
switch (args.index()) {
|
||||
case RunArgs::index_of<cv::GRunArgs>():
|
||||
out_args = util::get<cv::GRunArgs>(args); break;
|
||||
default: GAPI_Assert(false && "Incorrect type of return value");
|
||||
}
|
||||
|
||||
ASSERT_EQ(1u, out_args.size());
|
||||
ASSERT_TRUE(cv::util::holds_alternative<cv::Mat>(out_args[0]));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user