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

This commit is contained in:
Alexander Alekhin 2021-09-02 15:24:04 +00:00
commit 5aa7435d25
15 changed files with 633 additions and 434 deletions

View File

@ -407,6 +407,9 @@ if(MSVC)
endif()
endif()
# Enable [[attribute]] syntax checking to prevent silent failure: "attribute is ignored in this syntactic position"
add_extra_compiler_option("/w15240")
if(NOT ENABLE_NOISY_WARNINGS)
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4127) # conditional expression is constant
ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4251) # class 'std::XXX' needs to have dll-interface to be used by clients of YYY

View File

@ -122,6 +122,53 @@ String testReservedKeywordConversion(int positional_argument, int lambda = 2, in
return format("arg=%d, lambda=%d, from=%d", positional_argument, lambda, from);
}
CV_EXPORTS_W String dumpVectorOfInt(const std::vector<int>& vec);
CV_EXPORTS_W String dumpVectorOfDouble(const std::vector<double>& vec);
CV_EXPORTS_W String dumpVectorOfRect(const std::vector<Rect>& vec);
CV_WRAP static inline
void generateVectorOfRect(size_t len, CV_OUT std::vector<Rect>& vec)
{
vec.resize(len);
if (len > 0)
{
RNG rng(12345);
Mat tmp(static_cast<int>(len), 1, CV_32SC4);
rng.fill(tmp, RNG::UNIFORM, 10, 20);
tmp.copyTo(vec);
}
}
CV_WRAP static inline
void generateVectorOfInt(size_t len, CV_OUT std::vector<int>& vec)
{
vec.resize(len);
if (len > 0)
{
RNG rng(554433);
Mat tmp(static_cast<int>(len), 1, CV_32SC1);
rng.fill(tmp, RNG::UNIFORM, -10, 10);
tmp.copyTo(vec);
}
}
CV_WRAP static inline
void generateVectorOfMat(size_t len, int rows, int cols, int dtype, CV_OUT std::vector<Mat>& vec)
{
vec.resize(len);
if (len > 0)
{
RNG rng(65431);
for (size_t i = 0; i < len; ++i)
{
vec[i].create(rows, cols, dtype);
rng.fill(vec[i], RNG::UNIFORM, 0, 10);
}
}
}
CV_WRAP static inline
void testRaiseGeneralException()
{

View File

@ -705,14 +705,47 @@ __CV_ENUM_FLAGS_BITWISE_XOR_EQ (EnumType, EnumType)
# endif
#endif
/****************************************************************************************\
* CV_NODISCARD_STD attribute (C++17) *
* encourages the compiler to issue a warning if the return value is discarded *
\****************************************************************************************/
#ifndef CV_NODISCARD_STD
# ifndef __has_cpp_attribute
// workaround preprocessor non-compliance https://reviews.llvm.org/D57851
# define __has_cpp_attribute(__x) 0
# endif
# if __has_cpp_attribute(nodiscard)
# define CV_NODISCARD_STD [[nodiscard]]
# elif __cplusplus >= 201703L
// available when compiler is C++17 compliant
# define CV_NODISCARD_STD [[nodiscard]]
# elif defined(_MSC_VER) && _MSC_VER >= 1911 && _MSVC_LANG >= 201703L
// available with VS2017 v15.3+ with /std:c++17 or higher; works on functions and classes
# define CV_NODISCARD_STD [[nodiscard]]
# elif defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 700) && (__cplusplus >= 201103L)
// available with GCC 7.0+; works on functions, works or silently fails on classes
# define CV_NODISCARD_STD [[nodiscard]]
# elif defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) && (__cplusplus >= 201103L)
// available with GCC 4.8+ but it usually does nothing and can fail noisily -- therefore not used
// define CV_NODISCARD_STD [[gnu::warn_unused_result]]
# endif
#endif
#ifndef CV_NODISCARD_STD
# define CV_NODISCARD_STD /* nothing by default */
#endif
/****************************************************************************************\
* CV_NODISCARD attribute *
* encourages the compiler to issue a warning if the return value is discarded (C++17) *
* CV_NODISCARD attribute (deprecated, GCC only) *
* DONT USE: use instead the standard CV_NODISCARD_STD macro above *
* this legacy method silently fails to issue warning until some version *
* after gcc 6.3.0. Yet with gcc 7+ you can use the above standard method *
* which makes this method useless. Don't use it. *
* @deprecated use instead CV_NODISCARD_STD *
\****************************************************************************************/
#ifndef CV_NODISCARD
# if defined(__GNUC__)
# define CV_NODISCARD __attribute__((__warn_unused_result__)) // at least available with GCC 3.4
# define CV_NODISCARD __attribute__((__warn_unused_result__))
# elif defined(__clang__) && defined(__has_attribute)
# if __has_attribute(__warn_unused_result__)
# define CV_NODISCARD __attribute__((__warn_unused_result__))

View File

@ -1188,14 +1188,14 @@ public:
The method creates a square diagonal matrix from specified main diagonal.
@param d One-dimensional matrix that represents the main diagonal.
*/
static Mat diag(const Mat& d);
CV_NODISCARD_STD static Mat diag(const Mat& d);
/** @brief Creates a full copy of the array and the underlying data.
The method creates a full copy of the array. The original step[] is not taken into account. So, the
array copy is a continuous array occupying total()*elemSize() bytes.
*/
Mat clone() const CV_NODISCARD;
CV_NODISCARD_STD Mat clone() const;
/** @brief Copies the matrix to another one.
@ -1359,20 +1359,20 @@ public:
@param cols Number of columns.
@param type Created matrix type.
*/
static MatExpr zeros(int rows, int cols, int type);
CV_NODISCARD_STD static MatExpr zeros(int rows, int cols, int type);
/** @overload
@param size Alternative to the matrix size specification Size(cols, rows) .
@param type Created matrix type.
*/
static MatExpr zeros(Size size, int type);
CV_NODISCARD_STD static MatExpr zeros(Size size, int type);
/** @overload
@param ndims Array dimensionality.
@param sz Array of integers specifying the array shape.
@param type Created matrix type.
*/
static MatExpr zeros(int ndims, const int* sz, int type);
CV_NODISCARD_STD static MatExpr zeros(int ndims, const int* sz, int type);
/** @brief Returns an array of all 1's of the specified size and type.
@ -1390,20 +1390,20 @@ public:
@param cols Number of columns.
@param type Created matrix type.
*/
static MatExpr ones(int rows, int cols, int type);
CV_NODISCARD_STD static MatExpr ones(int rows, int cols, int type);
/** @overload
@param size Alternative to the matrix size specification Size(cols, rows) .
@param type Created matrix type.
*/
static MatExpr ones(Size size, int type);
CV_NODISCARD_STD static MatExpr ones(Size size, int type);
/** @overload
@param ndims Array dimensionality.
@param sz Array of integers specifying the array shape.
@param type Created matrix type.
*/
static MatExpr ones(int ndims, const int* sz, int type);
CV_NODISCARD_STD static MatExpr ones(int ndims, const int* sz, int type);
/** @brief Returns an identity matrix of the specified size and type.
@ -1419,13 +1419,13 @@ public:
@param cols Number of columns.
@param type Created matrix type.
*/
static MatExpr eye(int rows, int cols, int type);
CV_NODISCARD_STD static MatExpr eye(int rows, int cols, int type);
/** @overload
@param size Alternative matrix size specification as Size(cols, rows) .
@param type Created matrix type.
*/
static MatExpr eye(Size size, int type);
CV_NODISCARD_STD static MatExpr eye(Size size, int type);
/** @brief Allocates new array data if needed.
@ -2288,7 +2288,7 @@ public:
Mat_ row(int y) const;
Mat_ col(int x) const;
Mat_ diag(int d=0) const;
Mat_ clone() const CV_NODISCARD;
CV_NODISCARD_STD Mat_ clone() const;
//! overridden forms of Mat::elemSize() etc.
size_t elemSize() const;
@ -2301,14 +2301,14 @@ public:
size_t stepT(int i=0) const;
//! overridden forms of Mat::zeros() etc. Data type is omitted, of course
static MatExpr zeros(int rows, int cols);
static MatExpr zeros(Size size);
static MatExpr zeros(int _ndims, const int* _sizes);
static MatExpr ones(int rows, int cols);
static MatExpr ones(Size size);
static MatExpr ones(int _ndims, const int* _sizes);
static MatExpr eye(int rows, int cols);
static MatExpr eye(Size size);
CV_NODISCARD_STD static MatExpr zeros(int rows, int cols);
CV_NODISCARD_STD static MatExpr zeros(Size size);
CV_NODISCARD_STD static MatExpr zeros(int _ndims, const int* _sizes);
CV_NODISCARD_STD static MatExpr ones(int rows, int cols);
CV_NODISCARD_STD static MatExpr ones(Size size);
CV_NODISCARD_STD static MatExpr ones(int _ndims, const int* _sizes);
CV_NODISCARD_STD static MatExpr eye(int rows, int cols);
CV_NODISCARD_STD static MatExpr eye(Size size);
//! some more overridden methods
Mat_& adjustROI( int dtop, int dbottom, int dleft, int dright );
@ -2451,11 +2451,11 @@ 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, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
static UMat diag(const UMat& d) { return diag(d, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
CV_NODISCARD_STD static UMat diag(const UMat& d, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
CV_NODISCARD_STD 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;
CV_NODISCARD_STD UMat clone() const;
//! copies the matrix content to "m".
// It calls m.create(this->size(), this->type()).
void copyTo( OutputArray m ) const;
@ -2486,22 +2486,22 @@ public:
double dot(InputArray m) const;
//! Matlab-style matrix initialization
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
CV_NODISCARD_STD static UMat zeros(int rows, int cols, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
CV_NODISCARD_STD static UMat zeros(Size size, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
CV_NODISCARD_STD static UMat zeros(int ndims, const int* sz, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
CV_NODISCARD_STD static UMat zeros(int rows, int cols, int type) { return zeros(rows, cols, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
CV_NODISCARD_STD static UMat zeros(Size size, int type) { return zeros(size, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
CV_NODISCARD_STD static UMat zeros(int ndims, const int* sz, int type) { return zeros(ndims, sz, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
CV_NODISCARD_STD static UMat ones(int rows, int cols, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
CV_NODISCARD_STD static UMat ones(Size size, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
CV_NODISCARD_STD static UMat ones(int ndims, const int* sz, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
CV_NODISCARD_STD static UMat ones(int rows, int cols, int type) { return ones(rows, cols, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
CV_NODISCARD_STD static UMat ones(Size size, int type) { return ones(size, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
CV_NODISCARD_STD static UMat ones(int ndims, const int* sz, int type) { return ones(ndims, sz, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
CV_NODISCARD_STD static UMat eye(int rows, int cols, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
CV_NODISCARD_STD static UMat eye(Size size, int type, UMatUsageFlags usageFlags /*= USAGE_DEFAULT*/);
CV_NODISCARD_STD static UMat eye(int rows, int cols, int type) { return eye(rows, cols, type, USAGE_DEFAULT); } // OpenCV 5.0: remove abi compatibility overload
CV_NODISCARD_STD 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.
@ -2767,7 +2767,7 @@ public:
SparseMat& operator = (const Mat& m);
//! creates full copy of the matrix
SparseMat clone() const CV_NODISCARD;
CV_NODISCARD_STD SparseMat clone() const;
//! copies all the data to the destination matrix. All the previous content of m is erased
void copyTo( SparseMat& m ) const;
@ -3004,7 +3004,7 @@ public:
SparseMat_& operator = (const Mat& m);
//! makes full copy of the matrix. All the elements are duplicated
SparseMat_ clone() const CV_NODISCARD;
CV_NODISCARD_STD SparseMat_ clone() const;
//! equivalent to cv::SparseMat::create(dims, _sizes, DataType<_Tp>::type)
void create(int dims, const int* _sizes);
//! converts sparse matrix to the old-style CvSparseMat. All the elements are copied

View File

@ -142,22 +142,22 @@ public:
Matx(std::initializer_list<_Tp>); //!< initialize from an initializer list
static Matx all(_Tp alpha);
static Matx zeros();
static Matx ones();
static Matx eye();
static Matx diag(const diag_type& d);
CV_NODISCARD_STD static Matx all(_Tp alpha);
CV_NODISCARD_STD static Matx zeros();
CV_NODISCARD_STD static Matx ones();
CV_NODISCARD_STD static Matx eye();
CV_NODISCARD_STD static Matx diag(const diag_type& d);
/** @brief Generates uniformly distributed random numbers
@param a Range boundary.
@param b The other range boundary (boundaries don't have to be ordered, the lower boundary is inclusive,
the upper one is exclusive).
*/
static Matx randu(_Tp a, _Tp b);
CV_NODISCARD_STD static Matx randu(_Tp a, _Tp b);
/** @brief Generates normally distributed random numbers
@param a Mean value.
@param b Standard deviation.
*/
static Matx randn(_Tp a, _Tp b);
CV_NODISCARD_STD static Matx randn(_Tp a, _Tp b);
//! dot product computed with the default precision
_Tp dot(const Matx<_Tp, m, n>& v) const;

View File

@ -5,6 +5,7 @@
#include "precomp.hpp"
#include "opencv2/core/bindings_utils.hpp"
#include <sstream>
#include <iomanip>
#include <opencv2/core/utils/filesystem.hpp>
#include <opencv2/core/utils/filesystem.private.hpp>
@ -210,6 +211,53 @@ CV_EXPORTS_W String dumpInputOutputArrayOfArrays(InputOutputArrayOfArrays argume
return ss.str();
}
static inline std::ostream& operator<<(std::ostream& os, const cv::Rect& rect)
{
return os << "[x=" << rect.x << ", y=" << rect.y << ", w=" << rect.width << ", h=" << rect.height << ']';
}
template <class T, class Formatter>
static inline String dumpVector(const std::vector<T>& vec, Formatter format)
{
std::ostringstream oss("[", std::ios::ate);
if (!vec.empty())
{
oss << format << vec[0];
for (std::size_t i = 1; i < vec.size(); ++i)
{
oss << ", " << format << vec[i];
}
}
oss << "]";
return oss.str();
}
static inline std::ostream& noFormat(std::ostream& os)
{
return os;
}
static inline std::ostream& floatFormat(std::ostream& os)
{
return os << std::fixed << std::setprecision(2);
}
String dumpVectorOfInt(const std::vector<int>& vec)
{
return dumpVector(vec, &noFormat);
}
String dumpVectorOfDouble(const std::vector<double>& vec)
{
return dumpVector(vec, &floatFormat);
}
String dumpVectorOfRect(const std::vector<Rect>& vec)
{
return dumpVector(vec, &noFormat);
}
namespace fs {
cv::String getCacheDirectoryForDownloads()
{

View File

@ -3677,6 +3677,8 @@ bool Kernel::empty() const
static cv::String dumpValue(size_t sz, const void* p)
{
if (!p)
return "NULL";
if (sz == 4)
return cv::format("%d / %uu / 0x%08x / %g", *(int*)p, *(int*)p, *(int*)p, *(float*)p);
if (sz == 8)

View File

@ -218,7 +218,7 @@ class dnn_test(NewOpenCVTests):
model.setInputParams(scale, size, mean)
out, _ = model.detect(frame)
self.assertTrue(type(out) == list)
self.assertTrue(type(out) == tuple, msg='actual type {}'.format(str(type(out))))
self.assertTrue(np.array(out).shape == (2, 4, 2))

View File

@ -1437,26 +1437,13 @@ bool OCL4DNNConvSpatial<float>::createGEMMLikeConvKernel(int32_t blockM,
ocl::Program program = compileKernel();
if (program.ptr())
{
size_t workgroupSize_used;
ocl::Kernel kernel(kernel_name_.c_str(), program);
if (kernel.empty())
return false;
workgroupSize_used = kernel.preferedWorkGroupSizeMultiple();
if (workgroupSize_used != simd_size)
{
std::cerr << "OpenCV(ocl4dnn): The OpenCL compiler chose a simd size (" << workgroupSize_used << ") that " << std::endl;
std::cerr << " does not equal the size (" << simd_size << ") kernel source required." << std::endl;
std::cerr << " Skip this kernel " << kernel_name_ << std::endl;
unloadProgram(kernel_name_);
return false;
}
else
{
kernelQueue.push_back(makePtr<kernelConfig>(kernel_name_, &global_size[0], &local_size[0], &workItemOutput[0],
true, KERNEL_TYPE_GEMM_LIKE));
return true;
}
kernelQueue.push_back(makePtr<kernelConfig>(kernel_name_, &global_size[0], &local_size[0], &workItemOutput[0],
true, KERNEL_TYPE_GEMM_LIKE));
return true;
}
else
return false;
@ -1502,26 +1489,13 @@ bool OCL4DNNConvSpatial<float>::createIDLFKernel(int32_t blockWidth,
ocl::Program program = compileKernel();
if (program.ptr())
{
size_t workgroupSize_used;
ocl::Kernel kernel(kernel_name_.c_str(), program);
if (kernel.empty())
return false;
workgroupSize_used = kernel.preferedWorkGroupSizeMultiple();
if (workgroupSize_used != simd_size)
{
std::cerr << "OpenCV(ocl4dnn): The OpenCL compiler chose a simd size (" << workgroupSize_used << ") that " << std::endl;
std::cerr << " does not equal the size (" << simd_size << ") kernel source required." << std::endl;
std::cerr << " Skip this kernel " << kernel_name_ << std::endl;
unloadProgram(kernel_name_);
return false;
}
else
{
kernelQueue.push_back(makePtr<kernelConfig>(kernel_name_, &global_size[0], &local_size[0], &workItemOutput[0],
true, KERNEL_TYPE_INTEL_IDLF));
return true;
}
kernelQueue.push_back(makePtr<kernelConfig>(kernel_name_, &global_size[0], &local_size[0], &workItemOutput[0],
true, KERNEL_TYPE_INTEL_IDLF));
return true;
}
else
return false;

View File

@ -534,7 +534,8 @@ void ONNXImporter::populateNet()
for (int j = 0; j < inpShape.size(); ++j)
{
inpShape[j] = tensorShape.dim(j).dim_value();
if (!tensorShape.dim(j).dim_param().empty())
// NHW, NCHW(NHWC), NCDHW(NDHWC); do not set this flag if only N is dynamic
if (!tensorShape.dim(j).dim_param().empty() && !(j == 0 && inpShape.size() >= 3))
hasDynamicShapes = true;
}
if (!inpShape.empty() && !hasDynamicShapes)
@ -1540,6 +1541,16 @@ void ONNXImporter::parseMul(LayerParams& layerParams, const opencv_onnx::NodePro
//Replace input to Power
node_proto.set_input(1, powerParams.name);
}
const MatShape& broadShape = outShapes[node_proto.input(1)];
const size_t outShapeSize = outShapes[node_proto.input(0)].size();
const size_t diff = outShapeSize - broadShape.size();
size_t axis;
for (axis = diff; axis < broadShape.size() && broadShape[axis - diff] == 1; ++axis) {}
CV_Assert(axis != outShapeSize);
layerParams.set("axis", static_cast<int>(axis));
layerParams.type = "Scale";
}
addLayer(layerParams, node_proto);
@ -2185,7 +2196,7 @@ void ONNXImporter::parseResize(LayerParams& layerParams, const opencv_onnx::Node
layerParams.set("align_corners", interp_mode == "align_corners");
if (layerParams.get<String>("mode") == "linear")
{
layerParams.set("mode", interp_mode == "pytorch_half_pixel" ?
layerParams.set("mode", interp_mode == "pytorch_half_pixel" || interp_mode == "half_pixel" ?
"opencv_linear" : "bilinear");
}
}

View File

@ -301,6 +301,7 @@ TEST_P(Test_ONNX_layers, Scale)
if (backend == DNN_BACKEND_INFERENCE_ENGINE_NN_BUILDER_2019)
applyTestTag(CV_TEST_TAG_DNN_SKIP_IE_NN_BUILDER);
testONNXModels("scale");
testONNXModels("scale_broadcast", npy, 0, 0, false, true, 3);
}
TEST_P(Test_ONNX_layers, ReduceMean3D)
@ -586,6 +587,11 @@ TEST_P(Test_ONNX_layers, DynamicResize)
testONNXModels("dynamic_resize_scale_11", npy, 0, 0, false, true, 2);
}
TEST_P(Test_ONNX_layers, Resize_HumanSeg)
{
testONNXModels("resize_humanseg");
}
TEST_P(Test_ONNX_layers, Div)
{
const String model = _tf("models/div.onnx");
@ -881,6 +887,7 @@ TEST_P(Test_ONNX_layers, DynamicAxes)
testONNXModels("resize_opset11_torch1.6_dynamic_axes");
testONNXModels("average_pooling_dynamic_axes");
testONNXModels("maxpooling_sigmoid_dynamic_axes");
testONNXModels("dynamic_batch");
}
TEST_P(Test_ONNX_layers, MaxPool1d)

View File

@ -517,8 +517,8 @@ try:
comp = cv.GComputation(cv.GIn(g_arr0, g_arr1), cv.GOut(g_out))
arr0 = [(2, 2), 2.0]
arr1 = [3, 'str']
arr0 = ((2, 2), 2.0)
arr1 = (3, 'str')
out = comp.apply(cv.gin(arr0, arr1),
args=cv.gapi.compile_args(cv.gapi.kernels(GConcatImpl)))

View File

@ -496,6 +496,33 @@ bool parseSequence(PyObject* obj, RefWrapper<T> (&value)[N], const ArgInfo& info
}
} // namespace
namespace traits {
template <bool Value>
struct BooleanConstant
{
static const bool value = Value;
typedef BooleanConstant<Value> type;
};
typedef BooleanConstant<true> TrueType;
typedef BooleanConstant<false> FalseType;
template <class T>
struct VoidType {
typedef void type;
};
template <class T, class DType = void>
struct IsRepresentableAsMatDataType : FalseType
{
};
template <class T>
struct IsRepresentableAsMatDataType<T, typename VoidType<typename DataType<T>::channel_type>::type> : TrueType
{
};
} // namespace traits
typedef std::vector<uchar> vector_uchar;
typedef std::vector<char> vector_char;
typedef std::vector<int> vector_int;
@ -1072,6 +1099,30 @@ bool pyopencv_to(PyObject* obj, uchar& value, const ArgInfo& info)
return ivalue != -1 || !PyErr_Occurred();
}
template<>
bool pyopencv_to(PyObject* obj, char& value, const ArgInfo& info)
{
if (!obj || obj == Py_None)
{
return true;
}
if (isBool(obj))
{
failmsg("Argument '%s' must be an integer, not bool", info.name);
return false;
}
if (PyArray_IsIntegerScalar(obj))
{
value = saturate_cast<char>(PyArray_PyIntAsInt(obj));
}
else
{
failmsg("Argument '%s' is required to be an integer", info.name);
return false;
}
return !CV_HAS_CONVERSION_ERROR(value);
}
template<>
PyObject* pyopencv_from(const double& value)
{
@ -1484,357 +1535,12 @@ PyObject* pyopencv_from(const Point3d& p)
return Py_BuildValue("(ddd)", p.x, p.y, p.z);
}
template<typename _Tp> struct pyopencvVecConverter
{
typedef typename DataType<_Tp>::channel_type _Cp;
static inline bool copyOneItem(PyObject *obj, size_t start, int channels, _Cp * data)
{
for(size_t j = 0; (int)j < channels; j++ )
{
SafeSeqItem sub_item_wrap(obj, start + j);
PyObject* item_ij = sub_item_wrap.item;
if( PyInt_Check(item_ij))
{
int v = (int)PyInt_AsLong(item_ij);
if( v == -1 && PyErr_Occurred() )
return false;
data[j] = saturate_cast<_Cp>(v);
}
else if( PyLong_Check(item_ij))
{
int v = (int)PyLong_AsLong(item_ij);
if( v == -1 && PyErr_Occurred() )
return false;
data[j] = saturate_cast<_Cp>(v);
}
else if( PyFloat_Check(item_ij))
{
double v = PyFloat_AsDouble(item_ij);
if( PyErr_Occurred() )
return false;
data[j] = saturate_cast<_Cp>(v);
}
else
return false;
}
return true;
}
static bool to(PyObject* obj, std::vector<_Tp>& value, const ArgInfo& info)
{
if(!obj || obj == Py_None)
return true;
if (PyArray_Check(obj))
{
Mat m;
pyopencv_to(obj, m, info);
m.copyTo(value);
return true;
}
else if (PySequence_Check(obj))
{
const int type = traits::Type<_Tp>::value;
const int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
size_t i, n = PySequence_Size(obj);
value.resize(n);
for (i = 0; i < n; i++ )
{
SafeSeqItem item_wrap(obj, i);
PyObject* item = item_wrap.item;
_Cp* data = (_Cp*)&value[i];
if( channels == 2 && PyComplex_Check(item) )
{
data[0] = saturate_cast<_Cp>(PyComplex_RealAsDouble(item));
data[1] = saturate_cast<_Cp>(PyComplex_ImagAsDouble(item));
}
else if( channels > 1 )
{
if( PyArray_Check(item))
{
Mat src;
pyopencv_to(item, src, info);
if( src.dims != 2 || src.channels() != 1 ||
((src.cols != 1 || src.rows != channels) &&
(src.cols != channels || src.rows != 1)))
break;
Mat dst(src.rows, src.cols, depth, data);
src.convertTo(dst, type);
if( dst.data != (uchar*)data )
break;
}
else if (PySequence_Check(item))
{
if (!copyOneItem(item, 0, channels, data))
break;
}
else
{
break;
}
}
else if (channels == 1)
{
if (!copyOneItem(obj, i, channels, data))
break;
}
else
{
break;
}
}
if (i != n)
{
failmsg("Can't convert vector element for '%s', index=%d", info.name, i);
}
return i == n;
}
failmsg("Can't convert object to vector for '%s', unsupported type", info.name);
return false;
}
static PyObject* from(const std::vector<_Tp>& value)
{
if(value.empty())
return PyTuple_New(0);
int type = traits::Type<_Tp>::value;
int depth = CV_MAT_DEPTH(type), channels = CV_MAT_CN(type);
Mat src((int)value.size(), channels, depth, (uchar*)&value[0]);
return pyopencv_from(src);
}
};
template<typename _Tp>
bool pyopencv_to(PyObject* obj, std::vector<_Tp>& value, const ArgInfo& info)
{
return pyopencvVecConverter<_Tp>::to(obj, value, info);
}
template<typename _Tp>
PyObject* pyopencv_from(const std::vector<_Tp>& value)
{
return pyopencvVecConverter<_Tp>::from(value);
}
template<typename _Tp> static inline bool pyopencv_to_generic_vec(PyObject* obj, std::vector<_Tp>& value, const ArgInfo& info)
{
if(!obj || obj == Py_None)
return true;
if (!PySequence_Check(obj))
return false;
size_t n = PySequence_Size(obj);
value.resize(n);
for(size_t i = 0; i < n; i++ )
{
SafeSeqItem item_wrap(obj, i);
if(!pyopencv_to(item_wrap.item, value[i], info))
return false;
}
return true;
}
template<> inline bool pyopencv_to_generic_vec(PyObject* obj, std::vector<bool>& value, const ArgInfo& info)
{
if(!obj || obj == Py_None)
return true;
if (!PySequence_Check(obj))
return false;
size_t n = PySequence_Size(obj);
value.resize(n);
for(size_t i = 0; i < n; i++ )
{
SafeSeqItem item_wrap(obj, i);
bool elem{};
if(!pyopencv_to(item_wrap.item, elem, info))
return false;
value[i] = elem;
}
return true;
}
template<typename _Tp> static inline PyObject* pyopencv_from_generic_vec(const std::vector<_Tp>& value)
{
int i, n = (int)value.size();
PyObject* seq = PyList_New(n);
for( i = 0; i < n; i++ )
{
_Tp elem = value[i];
PyObject* item = pyopencv_from(elem);
if(!item)
break;
PyList_SetItem(seq, i, item);
}
if( i < n )
{
Py_DECREF(seq);
return 0;
}
return seq;
}
template<> inline PyObject* pyopencv_from_generic_vec(const std::vector<bool>& value)
{
int i, n = (int)value.size();
PyObject* seq = PyList_New(n);
for( i = 0; i < n; i++ )
{
bool elem = value[i];
PyObject* item = pyopencv_from(elem);
if(!item)
break;
PyList_SetItem(seq, i, item);
}
if( i < n )
{
Py_DECREF(seq);
return 0;
}
return seq;
}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
convert_to_python_tuple(const std::tuple<Tp...>&, PyObject*) { }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
convert_to_python_tuple(const std::tuple<Tp...>& cpp_tuple, PyObject* py_tuple)
{
PyObject* item = pyopencv_from(std::get<I>(cpp_tuple));
if (!item)
return;
PyTuple_SetItem(py_tuple, I, item);
convert_to_python_tuple<I + 1, Tp...>(cpp_tuple, py_tuple);
}
template<typename... Ts>
PyObject* pyopencv_from(const std::tuple<Ts...>& cpp_tuple)
{
size_t size = sizeof...(Ts);
PyObject* py_tuple = PyTuple_New(size);
convert_to_python_tuple(cpp_tuple, py_tuple);
size_t actual_size = PyTuple_Size(py_tuple);
if (actual_size < size)
{
Py_DECREF(py_tuple);
return NULL;
}
return py_tuple;
}
template<>
PyObject* pyopencv_from(const std::pair<int, double>& src)
{
return Py_BuildValue("(id)", src.first, src.second);
}
template<typename _Tp, typename _Tr> struct pyopencvVecConverter<std::pair<_Tp, _Tr> >
{
static bool to(PyObject* obj, std::vector<std::pair<_Tp, _Tr> >& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<std::pair<_Tp, _Tr> >& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<typename _Tp> struct pyopencvVecConverter<std::vector<_Tp> >
{
static bool to(PyObject* obj, std::vector<std::vector<_Tp> >& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<std::vector<_Tp> >& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<Mat>
{
static bool to(PyObject* obj, std::vector<Mat>& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<Mat>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<UMat>
{
static bool to(PyObject* obj, std::vector<UMat>& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<UMat>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<KeyPoint>
{
static bool to(PyObject* obj, std::vector<KeyPoint>& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<KeyPoint>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<DMatch>
{
static bool to(PyObject* obj, std::vector<DMatch>& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<DMatch>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<String>
{
static bool to(PyObject* obj, std::vector<String>& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<String>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<> struct pyopencvVecConverter<RotatedRect>
{
static bool to(PyObject* obj, std::vector<RotatedRect>& value, const ArgInfo& info)
{
return pyopencv_to_generic_vec(obj, value, info);
}
static PyObject* from(const std::vector<RotatedRect>& value)
{
return pyopencv_from_generic_vec(value);
}
};
template<>
bool pyopencv_to(PyObject* obj, TermCriteria& dst, const ArgInfo& info)
{
@ -1962,6 +1668,266 @@ PyObject* pyopencv_from(const Moments& m)
"nu30", m.nu30, "nu21", m.nu21, "nu12", m.nu12, "nu03", m.nu03);
}
template <typename Tp>
struct pyopencvVecConverter;
template <typename Tp>
bool pyopencv_to(PyObject* obj, std::vector<Tp>& value, const ArgInfo& info)
{
if (!obj || obj == Py_None)
{
return true;
}
return pyopencvVecConverter<Tp>::to(obj, value, info);
}
template <typename Tp>
PyObject* pyopencv_from(const std::vector<Tp>& value)
{
return pyopencvVecConverter<Tp>::from(value);
}
template <typename Tp>
static bool pyopencv_to_generic_vec(PyObject* obj, std::vector<Tp>& value, const ArgInfo& info)
{
if (!obj || obj == Py_None)
{
return true;
}
if (!PySequence_Check(obj))
{
failmsg("Can't parse '%s'. Input argument doesn't provide sequence protocol", info.name);
return false;
}
const size_t n = static_cast<size_t>(PySequence_Size(obj));
value.resize(n);
for (size_t i = 0; i < n; i++)
{
SafeSeqItem item_wrap(obj, i);
if (!pyopencv_to(item_wrap.item, value[i], info))
{
failmsg("Can't parse '%s'. Sequence item with index %lu has a wrong type", info.name, i);
return false;
}
}
return true;
}
template<> inline bool pyopencv_to_generic_vec(PyObject* obj, std::vector<bool>& value, const ArgInfo& info)
{
if (!obj || obj == Py_None)
{
return true;
}
if (!PySequence_Check(obj))
{
failmsg("Can't parse '%s'. Input argument doesn't provide sequence protocol", info.name);
return false;
}
const size_t n = static_cast<size_t>(PySequence_Size(obj));
value.resize(n);
for (size_t i = 0; i < n; i++)
{
SafeSeqItem item_wrap(obj, i);
bool elem{};
if (!pyopencv_to(item_wrap.item, elem, info))
{
failmsg("Can't parse '%s'. Sequence item with index %lu has a wrong type", info.name, i);
return false;
}
value[i] = elem;
}
return true;
}
template <typename Tp>
static PyObject* pyopencv_from_generic_vec(const std::vector<Tp>& value)
{
Py_ssize_t n = static_cast<Py_ssize_t>(value.size());
PySafeObject seq(PyTuple_New(n));
for (Py_ssize_t i = 0; i < n; i++)
{
PyObject* item = pyopencv_from(value[i]);
// If item can't be assigned - PyTuple_SetItem raises exception and returns -1.
if (!item || PyTuple_SetItem(seq, i, item) == -1)
{
return NULL;
}
}
return seq.release();
}
template<> inline PyObject* pyopencv_from_generic_vec(const std::vector<bool>& value)
{
Py_ssize_t n = static_cast<Py_ssize_t>(value.size());
PySafeObject seq(PyTuple_New(n));
for (Py_ssize_t i = 0; i < n; i++)
{
bool elem = value[i];
PyObject* item = pyopencv_from(elem);
// If item can't be assigned - PyTuple_SetItem raises exception and returns -1.
if (!item || PyTuple_SetItem(seq, i, item) == -1)
{
return NULL;
}
}
return seq.release();
}
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I == sizeof...(Tp), void>::type
convert_to_python_tuple(const std::tuple<Tp...>&, PyObject*) { }
template<std::size_t I = 0, typename... Tp>
inline typename std::enable_if<I < sizeof...(Tp), void>::type
convert_to_python_tuple(const std::tuple<Tp...>& cpp_tuple, PyObject* py_tuple)
{
PyObject* item = pyopencv_from(std::get<I>(cpp_tuple));
if (!item)
return;
PyTuple_SetItem(py_tuple, I, item);
convert_to_python_tuple<I + 1, Tp...>(cpp_tuple, py_tuple);
}
template<typename... Ts>
PyObject* pyopencv_from(const std::tuple<Ts...>& cpp_tuple)
{
size_t size = sizeof...(Ts);
PyObject* py_tuple = PyTuple_New(size);
convert_to_python_tuple(cpp_tuple, py_tuple);
size_t actual_size = PyTuple_Size(py_tuple);
if (actual_size < size)
{
Py_DECREF(py_tuple);
return NULL;
}
return py_tuple;
}
template <typename Tp>
struct pyopencvVecConverter
{
typedef typename std::vector<Tp>::iterator VecIt;
static bool to(PyObject* obj, std::vector<Tp>& value, const ArgInfo& info)
{
if (!PyArray_Check(obj))
{
return pyopencv_to_generic_vec(obj, value, info);
}
// If user passed an array it is possible to make faster conversions in several cases
PyArrayObject* array_obj = reinterpret_cast<PyArrayObject*>(obj);
const NPY_TYPES target_type = asNumpyType<Tp>();
const NPY_TYPES source_type = static_cast<NPY_TYPES>(PyArray_TYPE(array_obj));
if (target_type == NPY_OBJECT)
{
// Non-planar arrays representing objects (e.g. array of N Rect is an array of shape Nx4) have NPY_OBJECT
// as their target type.
return pyopencv_to_generic_vec(obj, value, info);
}
if (PyArray_NDIM(array_obj) > 1)
{
failmsg("Can't parse %dD array as '%s' vector argument", PyArray_NDIM(array_obj), info.name);
return false;
}
if (target_type != source_type)
{
// Source type requires conversion
// Allowed conversions for target type is handled in the corresponding pyopencv_to function
return pyopencv_to_generic_vec(obj, value, info);
}
// For all other cases, all array data can be directly copied to std::vector data
// Simple `memcpy` is not possible because NumPy array can reference a slice of the bigger array:
// ```
// arr = np.ones((8, 4, 5), dtype=np.int32)
// convertible_to_vector_of_int = arr[:, 0, 1]
// ```
value.resize(static_cast<size_t>(PyArray_SIZE(array_obj)));
const npy_intp item_step = PyArray_STRIDE(array_obj, 0) / PyArray_ITEMSIZE(array_obj);
const Tp* data_ptr = static_cast<Tp*>(PyArray_DATA(array_obj));
for (VecIt it = value.begin(); it != value.end(); ++it, data_ptr += item_step) {
*it = *data_ptr;
}
return true;
}
static PyObject* from(const std::vector<Tp>& value)
{
if (value.empty())
{
return PyTuple_New(0);
}
return from(value, ::traits::IsRepresentableAsMatDataType<Tp>());
}
private:
static PyObject* from(const std::vector<Tp>& value, ::traits::FalseType)
{
// Underlying type is not representable as Mat Data Type
return pyopencv_from_generic_vec(value);
}
static PyObject* from(const std::vector<Tp>& value, ::traits::TrueType)
{
// Underlying type is representable as Mat Data Type, so faster return type is available
typedef DataType<Tp> DType;
typedef typename DType::channel_type UnderlyingArrayType;
// If Mat is always exposed as NumPy array this code path can be reduced to the following snipped:
// Mat src(value);
// PyObject* array = pyopencv_from(src);
// return PyArray_Squeeze(reinterpret_cast<PyArrayObject*>(array));
// This puts unnecessary restrictions on Mat object those might be avoided without losing the performance.
// Moreover, this version is a bit faster, because it doesn't create temporary objects with reference counting.
const NPY_TYPES target_type = asNumpyType<UnderlyingArrayType>();
const int cols = DType::channels;
PyObject* array = NULL;
if (cols == 1)
{
npy_intp dims = static_cast<npy_intp>(value.size());
array = PyArray_SimpleNew(1, &dims, target_type);
}
else
{
npy_intp dims[2] = {static_cast<npy_intp>(value.size()), cols};
array = PyArray_SimpleNew(2, dims, target_type);
}
if(!array)
{
// NumPy arrays with shape (N, 1) and (N) are not equal, so correct error message should distinguish
// them too.
String shape;
if (cols > 1)
{
shape = format("(%d x %d)", static_cast<int>(value.size()), cols);
}
else
{
shape = format("(%d)", static_cast<int>(value.size()));
}
const String error_message = format("Can't allocate NumPy array for vector with dtype=%d and shape=%s",
static_cast<int>(target_type), shape.c_str());
emit_failmsg(PyExc_MemoryError, error_message.c_str());
return array;
}
// Fill the array
PyArrayObject* array_obj = reinterpret_cast<PyArrayObject*>(array);
UnderlyingArrayType* array_data = static_cast<UnderlyingArrayType*>(PyArray_DATA(array_obj));
// if Tp is representable as Mat DataType, so the following cast is pretty safe...
const UnderlyingArrayType* value_data = reinterpret_cast<const UnderlyingArrayType*>(value.data());
memcpy(array_data, value_data, sizeof(UnderlyingArrayType) * value.size() * static_cast<size_t>(cols));
return array;
}
};
static int OnError(int status, const char *func_name, const char *err_msg, const char *file_name, int line, void *userdata)
{
PyGILState_STATE gstate;

View File

@ -20,8 +20,13 @@ class Hackathon244Tests(NewOpenCVTests):
flag, ajpg = cv.imencode("img_q90.jpg", a, [cv.IMWRITE_JPEG_QUALITY, 90])
self.assertEqual(flag, True)
self.assertEqual(ajpg.dtype, np.uint8)
self.assertGreater(ajpg.shape[0], 1)
self.assertEqual(ajpg.shape[1], 1)
self.assertTrue(isinstance(ajpg, np.ndarray), "imencode returned buffer of wrong type: {}".format(type(ajpg)))
self.assertEqual(len(ajpg.shape), 1, "imencode returned buffer with wrong shape: {}".format(ajpg.shape))
self.assertGreaterEqual(len(ajpg), 1, "imencode length of the returned buffer should be at least 1")
self.assertLessEqual(
len(ajpg), a.size,
"imencode length of the returned buffer shouldn't exceed number of elements in original image"
)
def test_projectPoints(self):
objpt = np.float64([[1,2,3]])

View File

@ -481,6 +481,109 @@ class Arguments(NewOpenCVTests):
cv.utils.testReservedKeywordConversion(20, lambda_=-4, from_=12), format_str.format(20, -4, 12)
)
def test_parse_vector_int_convertible(self):
np.random.seed(123098765)
try_to_convert = partial(self._try_to_convert, cv.utils.dumpVectorOfInt)
arr = np.random.randint(-20, 20, 40).astype(np.int32).reshape(10, 2, 2)
int_min, int_max = get_limits(ctypes.c_int)
for convertible in ((int_min, 1, 2, 3, int_max), [40, 50], tuple(),
np.array([int_min, -10, 24, int_max], dtype=np.int32),
np.array([10, 230, 12], dtype=np.uint8), arr[:, 0, 1],):
expected = "[" + ", ".join(map(str, convertible)) + "]"
actual = try_to_convert(convertible)
self.assertEqual(expected, actual,
msg=get_conversion_error_msg(convertible, expected, actual))
def test_parse_vector_int_not_convertible(self):
np.random.seed(123098765)
arr = np.random.randint(-20, 20, 40).astype(np.float).reshape(10, 2, 2)
int_min, int_max = get_limits(ctypes.c_int)
test_dict = {1: 2, 3: 10, 10: 20}
for not_convertible in ((int_min, 1, 2.5, 3, int_max), [True, 50], 'test', test_dict,
reversed([1, 2, 3]),
np.array([int_min, -10, 24, [1, 2]], dtype=np.object),
np.array([[1, 2], [3, 4]]), arr[:, 0, 1],):
with self.assertRaises(TypeError, msg=get_no_exception_msg(not_convertible)):
_ = cv.utils.dumpVectorOfInt(not_convertible)
def test_parse_vector_double_convertible(self):
np.random.seed(1230965)
try_to_convert = partial(self._try_to_convert, cv.utils.dumpVectorOfDouble)
arr = np.random.randint(-20, 20, 40).astype(np.int32).reshape(10, 2, 2)
for convertible in ((1, 2.12, 3.5), [40, 50], tuple(),
np.array([-10, 24], dtype=np.int32),
np.array([-12.5, 1.4], dtype=np.double),
np.array([10, 230, 12], dtype=np.float), arr[:, 0, 1], ):
expected = "[" + ", ".join(map(lambda v: "{:.2f}".format(v), convertible)) + "]"
actual = try_to_convert(convertible)
self.assertEqual(expected, actual,
msg=get_conversion_error_msg(convertible, expected, actual))
def test_parse_vector_double_not_convertible(self):
test_dict = {1: 2, 3: 10, 10: 20}
for not_convertible in (('t', 'e', 's', 't'), [True, 50.55], 'test', test_dict,
np.array([-10.1, 24.5, [1, 2]], dtype=np.object),
np.array([[1, 2], [3, 4]]),):
with self.assertRaises(TypeError, msg=get_no_exception_msg(not_convertible)):
_ = cv.utils.dumpVectorOfDouble(not_convertible)
def test_parse_vector_rect_convertible(self):
np.random.seed(1238765)
try_to_convert = partial(self._try_to_convert, cv.utils.dumpVectorOfRect)
arr_of_rect_int32 = np.random.randint(5, 20, 4 * 3).astype(np.int32).reshape(3, 4)
arr_of_rect_cast = np.random.randint(10, 40, 4 * 5).astype(np.uint8).reshape(5, 4)
for convertible in (((1, 2, 3, 4), (10, -20, 30, 10)), arr_of_rect_int32, arr_of_rect_cast,
arr_of_rect_int32.astype(np.int8), [[5, 3, 1, 4]],
((np.int8(4), np.uint8(10), np.int(32), np.int16(55)),)):
expected = "[" + ", ".join(map(lambda v: "[x={}, y={}, w={}, h={}]".format(*v), convertible)) + "]"
actual = try_to_convert(convertible)
self.assertEqual(expected, actual,
msg=get_conversion_error_msg(convertible, expected, actual))
def test_parse_vector_rect_not_convertible(self):
np.random.seed(1238765)
arr = np.random.randint(5, 20, 4 * 3).astype(np.float).reshape(3, 4)
for not_convertible in (((1, 2, 3, 4), (10.5, -20, 30.1, 10)), arr,
[[5, 3, 1, 4], []],
((np.float(4), np.uint8(10), np.int(32), np.int16(55)),)):
with self.assertRaises(TypeError, msg=get_no_exception_msg(not_convertible)):
_ = cv.utils.dumpVectorOfRect(not_convertible)
def test_vector_general_return(self):
expected_number_of_mats = 5
expected_shape = (10, 10, 3)
expected_type = np.uint8
mats = cv.utils.generateVectorOfMat(5, 10, 10, cv.CV_8UC3)
self.assertTrue(isinstance(mats, tuple),
"Vector of Mats objects should be returned as tuple. Got: {}".format(type(mats)))
self.assertEqual(len(mats), expected_number_of_mats, "Returned array has wrong length")
for mat in mats:
self.assertEqual(mat.shape, expected_shape, "Returned Mat has wrong shape")
self.assertEqual(mat.dtype, expected_type, "Returned Mat has wrong elements type")
empty_mats = cv.utils.generateVectorOfMat(0, 10, 10, cv.CV_32FC1)
self.assertTrue(isinstance(empty_mats, tuple),
"Empty vector should be returned as empty tuple. Got: {}".format(type(mats)))
self.assertEqual(len(empty_mats), 0, "Vector of size 0 should be returned as tuple of length 0")
def test_vector_fast_return(self):
expected_shape = (5, 4)
rects = cv.utils.generateVectorOfRect(expected_shape[0])
self.assertTrue(isinstance(rects, np.ndarray),
"Vector of rectangles should be returned as numpy array. Got: {}".format(type(rects)))
self.assertEqual(rects.dtype, np.int32, "Vector of rectangles has wrong elements type")
self.assertEqual(rects.shape, expected_shape, "Vector of rectangles has wrong shape")
empty_rects = cv.utils.generateVectorOfRect(0)
self.assertTrue(isinstance(empty_rects, tuple),
"Empty vector should be returned as empty tuple. Got: {}".format(type(empty_rects)))
self.assertEqual(len(empty_rects), 0, "Vector of size 0 should be returned as tuple of length 0")
expected_shape = (10,)
ints = cv.utils.generateVectorOfInt(expected_shape[0])
self.assertTrue(isinstance(ints, np.ndarray),
"Vector of integers should be returned as numpy array. Got: {}".format(type(ints)))
self.assertEqual(ints.dtype, np.int32, "Vector of integers has wrong elements type")
self.assertEqual(ints.shape, expected_shape, "Vector of integers has wrong shape.")
class SamplesFindFile(NewOpenCVTests):