Merge pull request #25605 from alexlyulkov:al/bool-dnn

Added bool support to dnn #25605

Added bool support to dnn pipeline (CPU, OpenVINO and CUDA pipelines).

Added bool support to these layers(CPU and OpenVINO):
- Equal, Greater, GreaterOrEqual, Less, LessOrEqual
- Not
- And, Or, Xor
- Where

Enabled all the conformance tests for these layers.

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
pull/25727/head
alexlyulkov 6 months ago committed by GitHub
parent 5bc450d211
commit 70df023317
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      modules/dnn/include/opencv2/dnn/all_layers.hpp
  2. 4
      modules/dnn/src/ie_ngraph.cpp
  3. 5
      modules/dnn/src/layers/blank_layer.cpp
  4. 35
      modules/dnn/src/layers/elementwise_layers.cpp
  5. 5
      modules/dnn/src/layers/flatten_layer.cpp
  6. 174
      modules/dnn/src/layers/nary_eltwise_layers.cpp
  7. 83
      modules/dnn/src/layers/not_layer.cpp
  8. 5
      modules/dnn/src/layers/reshape_layer.cpp
  9. 4
      modules/dnn/src/legacy_backend.cpp
  10. 4
      modules/dnn/src/net_impl_backend.cpp
  11. 5
      modules/dnn/src/onnx/onnx_graph_simplifier.cpp
  12. 4
      modules/dnn/src/onnx/onnx_importer.cpp
  13. 24
      modules/dnn/src/op_cuda.hpp
  14. 1
      modules/dnn/src/op_inf_engine.cpp
  15. 43
      modules/dnn/test/test_onnx_conformance_layer_parser_denylist.inl.hpp
  16. 6
      modules/ts/src/ts_func.cpp

@ -723,7 +723,7 @@ CV__DNN_INLINE_NS_BEGIN
static Ptr<SqrtLayer> create(const LayerParams &params);
};
class CV_EXPORTS NotLayer : public ActivationLayer
class CV_EXPORTS NotLayer : public Layer
{
public:
static Ptr<NotLayer> create(const LayerParams &params);

@ -61,6 +61,8 @@ ov::element::Type cvTypeToOvType(MatType cvType)
return ov::element::i32;
case CV_64S:
return ov::element::i64;
case CV_Bool:
return ov::element::boolean;
default:
CV_Error(Error::StsNotImplemented, format("Unsupported data type %s", typeToString(cvType).c_str()));
}
@ -84,6 +86,8 @@ MatType ovTypeToCvType(ov::element::Type ovType)
return CV_32S;
case ov::element::i64:
return CV_64S;
case ov::element::boolean:
return CV_Bool;
default:
CV_Error(Error::StsNotImplemented, format("Unsupported data type %s", ovType.get_type_name().c_str()));
}

@ -175,7 +175,10 @@ public:
) override
{
auto context = reinterpret_cast<csl::CSLContext*>(context_);
return make_cuda_node_with_type<cuda4dnn::ReshapeOp>(preferableTarget, inputs[0]->getHostMatDepth(), std::move(context->stream));
if (inputs[0]->getHostMatDepth() == CV_Bool)
return make_cuda_node_bool<cuda4dnn::ReshapeOp>(std::move(context->stream));
else
return make_cuda_node_with_type<cuda4dnn::ReshapeOp>(preferableTarget, inputs[0]->getHostMatDepth(), std::move(context->stream));
}
#endif
};

@ -1372,33 +1372,6 @@ struct SqrtFunctor : public BaseDefaultFunctor<SqrtFunctor>
template<>
const char* const BaseDefaultFunctor<SqrtFunctor>::ocl_kernel_name = "SqrtForward";
struct NotFunctor : public BaseDefaultFunctor<NotFunctor>
{
typedef NotLayer Layer;
bool supportBackend(int backendId, int)
{
return backendId == DNN_BACKEND_OPENCV || backendId == DNN_BACKEND_CUDA;
}
inline float calculate(float x) const
{
return floor(1.f - x);
}
#ifdef HAVE_CUDA
Ptr<BackendNode> initCUDA(int target, csl::Stream stream)
{
return make_cuda_node<cuda4dnn::NotOp>(target, stream);
}
#endif
int64 getFLOPSPerElement() const { return 2; }
};
template<>
const char* const BaseDefaultFunctor<NotFunctor>::ocl_kernel_name = "NotForward";
struct AcosFunctor : public BaseDefaultFunctor<AcosFunctor>
{
typedef AcosLayer Layer;
@ -2650,14 +2623,6 @@ Ptr<SqrtLayer> SqrtLayer::create(const LayerParams& params)
return l;
}
Ptr<NotLayer> NotLayer::create(const LayerParams& params)
{
Ptr<NotLayer> l(new ElementWiseLayer<NotFunctor>());
l->setParamsFrom(params);
return l;
}
Ptr<AcosLayer> AcosLayer::create(const LayerParams& params)
{
Ptr<AcosLayer> l(new ElementWiseLayer<AcosFunctor>());

@ -260,7 +260,10 @@ public:
) override
{
auto context = reinterpret_cast<csl::CSLContext*>(context_);
return make_cuda_node_with_type<cuda4dnn::ReshapeOp>(preferableTarget, inputs[0]->getHostMatDepth(), std::move(context->stream));
if (inputs[0]->getHostMatDepth() == CV_Bool)
return make_cuda_node_bool<cuda4dnn::ReshapeOp>(std::move(context->stream));
else
return make_cuda_node_with_type<cuda4dnn::ReshapeOp>(preferableTarget, inputs[0]->getHostMatDepth(), std::move(context->stream));
}
#endif

@ -103,24 +103,6 @@ public:
}
}
void reInit(size_t newElemSize) {
std::vector<size_t> newElemSizes(elemsize.size(), newElemSize);
reInit(newElemSizes);
}
void reInit(std::vector<size_t> newElemSizes) {
for (size_t array_index = 0; array_index < orig_steps.size(); array_index++) {
auto &step = orig_steps[array_index];
int esz = elemsize[array_index];
int new_esz = newElemSizes[array_index];
for (size_t step_index = 0; step_index < step.size(); step_index++) {
step[step_index] = static_cast<size_t>(step[step_index] / esz * new_esz);
}
elemsize[array_index] = newElemSizes[array_index];
}
prepare_for_broadcast_op();
}
bool prepare_for_broadcast_op()
{
int i, j, k;
@ -281,8 +263,15 @@ public:
if (backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH)
return (op == OPERATION::ADD ||
op == OPERATION::PROD ||
op == OPERATION::EQUAL ||
op == OPERATION::GREATER ||
op == OPERATION::GREATER_EQUAL ||
op == OPERATION::LESS ||
op == OPERATION::LESS_EQUAL ||
op == OPERATION::AND ||
op == OPERATION::OR ||
op == OPERATION::XOR ||
op == OPERATION::WHERE ||
op == OPERATION::MOD ||
op == OPERATION::FMOD
);
@ -355,6 +344,22 @@ public:
std::vector<MatType>& outputs,
std::vector<MatType>& internals) const CV_OVERRIDE
{
if (op == OPERATION::WHERE)
{
CV_CheckTypeEQ(inputs[0], CV_Bool, "");
CV_CheckTypeEQ(inputs[1], inputs[2], "");
outputs.assign(1, inputs[1]);
return;
}
if (op == OPERATION::AND || op == OPERATION::OR || op == OPERATION::XOR)
{
CV_CheckTypeEQ(inputs[0], CV_Bool, "");
CV_CheckTypeEQ(inputs[1], CV_Bool, "");
outputs.assign(1, CV_Bool);
return;
}
CV_Assert(inputs.size());
for (auto input : inputs)
{
@ -365,11 +370,14 @@ public:
CV_CheckType(input, input == CV_32F || input == CV_8S || input == CV_8U || input == CV_32S || input == CV_64S, "");
}
outputs.assign(requiredOutputs, inputs[0]);
if (op == OPERATION::EQUAL || op == OPERATION::GREATER || op == OPERATION::GREATER_EQUAL || op == OPERATION::LESS || op == OPERATION::LESS_EQUAL)
outputs.assign(1, CV_Bool);
else
outputs.assign(requiredOutputs, inputs[0]);
}
template <typename T, typename Functor>
template <typename T, typename RESULT_T, typename Functor>
void binary_forward_impl(
int ndims, const std::vector<int>& shape,
const char* data1, const std::vector<size_t>& step1,
@ -385,7 +393,7 @@ public:
if (ndims >= 1) {
dp1 = step1[ndims-1]/sizeof(T);
dp2 = step2[ndims-1]/sizeof(T);
dp = step[ndims-1]/sizeof(T);
dp = step[ndims-1]/sizeof(RESULT_T);
n1 = shape[ndims-1];
if (ndims >= 2) {
@ -417,7 +425,7 @@ public:
{
const T* ptr1 = (const T*)ptr1_;
const T* ptr2 = (const T*)ptr2_;
T* ptr = (T*)ptr_;
RESULT_T* ptr = (RESULT_T*)ptr_;
if (dp1 == 1 && dp2 == 1 && dp == 1) {
for(int i1 = 0; i1 < n1; i1++)
ptr[i1] = op(ptr1[i1], ptr2[i1]);
@ -437,14 +445,14 @@ public:
}
}
template <typename T, typename Functor>
template <typename T, typename RESULT_T, typename Functor>
void binary_forward(const Functor& f, const std::vector<Mat>& inputs, std::vector<Mat>& outputs)
{
const Mat& a = inputs[0];
const Mat& b = inputs[1];
Mat& out = outputs[0];
CV_Assert(helper.shapes.size() == 3 && helper.steps.size() == 3);
binary_forward_impl<T, Functor>(
binary_forward_impl<T, RESULT_T, Functor>(
helper.max_ndims, helper.shapes[0], a.ptr<char>(), helper.steps[1],
b.ptr<char>(), helper.steps[2], out.ptr<char>(), helper.steps[0],
f);
@ -551,7 +559,7 @@ public:
f, scale, helper.ninputs, helper.max_ndims, helper.shapes[0], inp, out, helper.steps, helper.ptrs);
}
template <typename T, typename Functor>
template <typename T_INP1, typename T_INP2, typename T_INP3, typename T_OUT, typename Functor>
void trinary_forward(const Functor& f, const std::vector<Mat>& inputs, std::vector<Mat>& outputs)
{
const Mat& a = inputs[0];
@ -561,13 +569,13 @@ public:
CV_Assert(helper.shapes.size() == 4 && helper.steps.size() == 4);
trinary_forward_impl<T, Functor>(
trinary_forward_impl<T_INP1, T_INP2, T_INP3, T_OUT, Functor>(
helper.max_ndims, helper.shapes[0], a.ptr<char>(), helper.steps[1], b.ptr<char>(), helper.steps[2],
c.ptr<char>(), helper.steps[3], out.ptr<char>(), helper.steps[0],
f);
}
template <typename T, typename Functor>
template <typename T_INP1, typename T_INP2, typename T_INP3, typename T_OUT, typename Functor>
void trinary_forward_impl(
int ndims, const std::vector<int>& shape,
const char* data1, const std::vector<size_t>& step1,
@ -577,10 +585,10 @@ public:
const Functor& op)
{
assert(ndims >= 2);
size_t dp1 = step1[ndims-1]/sizeof(T);
size_t dp2 = step2[ndims-1]/sizeof(T);
size_t dp3 = step3[ndims-1]/sizeof(T);
size_t dp = step[ndims-1]/sizeof(T);
size_t dp1 = step1[ndims-1]/sizeof(T_INP1);
size_t dp2 = step2[ndims-1]/sizeof(T_INP2);
size_t dp3 = step3[ndims-1]/sizeof(T_INP3);
size_t dp = step[ndims-1]/sizeof(T_OUT);
int k, n1 = shape[ndims-1], n2 = shape[ndims-2];
size_t plane_idx, nplanes = 1;
for (k = 0; k < ndims-2; k++) nplanes *= shape[k];
@ -608,10 +616,10 @@ public:
ptr3_ += step3[ndims-2],
ptr_ += step[ndims-2])
{
const T* ptr1 = (const T*)ptr1_;
const T* ptr2 = (const T*)ptr2_;
const T* ptr3 = (const T*)ptr3_;
T* ptr = (T*)ptr_;
const T_INP1* ptr1 = (const T_INP1*)ptr1_;
const T_INP2* ptr2 = (const T_INP2*)ptr2_;
const T_INP3* ptr3 = (const T_INP3*)ptr3_;
T_OUT* ptr = (T_OUT*)ptr_;
if (dp1 == 1 && dp2 == 1 && dp3 == 1 && dp == 1)
{
@ -634,7 +642,6 @@ public:
if (inputs_arr.depth() == CV_16F)
{
helper.reInit(sizeof(float));
forward_fallback(inputs_arr, outputs_arr, internals_arr);
return;
}
@ -644,7 +651,7 @@ public:
outputs_arr.getMatVector(outputs);
// TODO: assert types
typeDispatch(outputs[0].type(), inputs.size(), inputs, outputs);
typeDispatch(inputs.back().type(), inputs.size(), inputs, outputs);
}
template<typename T, typename... Args>
@ -655,43 +662,43 @@ public:
case OPERATION::EQUAL:
{
auto equal = [](const T &a, const T &b) { return a == b; };
binary_forward<T>(equal, std::forward<Args>(args)...);
binary_forward<T, bool>(equal, std::forward<Args>(args)...);
break;
}
case OPERATION::GREATER:
{
auto greater = [](const T &a, const T &b) { return a > b; };
binary_forward<T>(greater, std::forward<Args>(args)...);
binary_forward<T, bool>(greater, std::forward<Args>(args)...);
break;
}
case OPERATION::GREATER_EQUAL:
{
auto greater_equal = [](const T &a, const T &b) { return a >= b; };
binary_forward<T>(greater_equal, std::forward<Args>(args)...);
binary_forward<T, bool>(greater_equal, std::forward<Args>(args)...);
break;
}
case OPERATION::LESS:
{
auto less = [](const T &a, const T &b) { return a < b; };
binary_forward<T>(less, std::forward<Args>(args)...);
binary_forward<T, bool>(less, std::forward<Args>(args)...);
break;
}
case OPERATION::LESS_EQUAL:
{
auto less_equal = [](const T &a, const T &b) { return a <= b; };
binary_forward<T>(less_equal, std::forward<Args>(args)...);
binary_forward<T, bool>(less_equal, std::forward<Args>(args)...);
break;
}
case OPERATION::POW:
{
auto pow = [] (const T& a, const T& b) { return std::pow(a, b); };
binary_forward<T>(pow, std::forward<Args>(args)...);
binary_forward<T, T>(pow, std::forward<Args>(args)...);
break;
}
case OPERATION::BITSHIFT:
{
auto bitshift = [] (const uint8_t &a, const uint8_t &b) { return a << b; };
binary_forward<T>(bitshift, std::forward<Args>(args)...);
binary_forward<T, T>(bitshift, std::forward<Args>(args)...);
break;
}
case OPERATION::MAX:
@ -715,25 +722,25 @@ public:
case OPERATION::MOD:
{
auto mod = [] (const T &a, const T &b) { return static_cast<T>(_mod(int(a), int(b))); };
binary_forward<T>(mod, std::forward<Args>(args)...);
binary_forward<T, T>(mod, std::forward<Args>(args)...);
break;
}
case OPERATION::FMOD:
{
auto fmod = [](const T &a, const T &b) { return std::fmod(a, b); };
binary_forward<T>(fmod, std::forward<Args>(args)...);
binary_forward<T, T>(fmod, std::forward<Args>(args)...);
break;
}
case OPERATION::PROD:
{
auto prod = [](const T &a, const T &b) { return a * b; };
binary_forward<T>(prod, std::forward<Args>(args)...);
binary_forward<T, T>(prod, std::forward<Args>(args)...);
break;
}
case OPERATION::SUB:
{
auto sub = [](const T &a, const T &b) { return a - b; };
binary_forward<T>(sub, std::forward<Args>(args)...);
binary_forward<T, T>(sub, std::forward<Args>(args)...);
break;
}
case OPERATION::SUM:
@ -745,37 +752,47 @@ public:
case OPERATION::ADD:
{
auto add = [](const T &a, const T &b) { return a + b; };
binary_forward<T>(add, std::forward<Args>(args)...);
binary_forward<T, T>(add, std::forward<Args>(args)...);
break;
}
case OPERATION::DIV:
{
auto div = [](const T &a, const T &b) { return a / b; };
binary_forward<T>(div, std::forward<Args>(args)...);
binary_forward<T, T>(div, std::forward<Args>(args)...);
break;
}
case OPERATION::AND:
case OPERATION::WHERE:
{
auto op_and = [](const uint8_t &a, const uint8_t &b) { return a & b; };
binary_forward<T>(op_and, std::forward<Args>(args)...);
auto op_where = [](const bool &a, const T &b, const T &c) { return a ? b : c; };
trinary_forward<bool, T, T, T>(op_where, std::forward<Args>(args)...);
break;
}
case OPERATION::OR:
default:
CV_Error(Error::StsBadArg, "Unsupported operation.");
};
}
template<typename... Args>
inline void boolOpDispatch(size_t ninputs, Args&&... args)
{
switch (op)
{
case OPERATION::AND:
{
auto op_or = [](const uint8_t &a, const uint8_t &b) { return a | b; };
binary_forward<T>(op_or, std::forward<Args>(args)...);
auto op_and = [](const bool &a, const bool &b) { return a && b; };
binary_forward<bool, bool>(op_and, std::forward<Args>(args)...);
break;
}
case OPERATION::XOR:
case OPERATION::OR:
{
auto op_xor = [](const uint8_t &a, const uint8_t &b) { return a ^ b; };
binary_forward<T>(op_xor, std::forward<Args>(args)...);
auto op_or = [](const bool &a, const bool &b) { return a || b; };
binary_forward<bool, bool>(op_or, std::forward<Args>(args)...);
break;
}
case OPERATION::WHERE:
case OPERATION::XOR:
{
auto op_where = [](const T &a, const T &b, const T &c) { return a ? b : c; };
trinary_forward<T>(op_where, std::forward<Args>(args)...);
auto op_xor = [](const bool &a, const bool &b) { return a != b; };
binary_forward<bool, bool>(op_xor, std::forward<Args>(args)...);
break;
}
default:
@ -788,17 +805,16 @@ public:
{
switch (type)
{
case CV_Bool:
boolOpDispatch(std::forward<Args>(args)...);
break;
case CV_8U:
// TODO: integrate with type inference
helper.reInit(sizeof(uint8_t));
opDispatch<uint8_t>(std::forward<Args>(args)...);
break;
case CV_8S:
opDispatch<int8_t>(std::forward<Args>(args)...);
break;
case CV_32S:
// TODO: integrate with type inference
helper.reInit(sizeof(int32_t));
opDispatch<int32_t>(std::forward<Args>(args)...);
break;
case CV_64S:
@ -916,11 +932,16 @@ public:
#ifdef HAVE_DNN_NGRAPH
virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inputs, const std::vector<Ptr<BackendNode> >& nodes) CV_OVERRIDE
{
CV_Assert(inputs.size() == 2);
if (op == OPERATION::WHERE)
CV_CheckEQ(inputs.size(), 3u, "");
else
CV_CheckEQ(inputs.size(), 2u, "");
auto& inp0 = nodes[0].dynamicCast<InfEngineNgraphNode>()->node;
auto& inp1 = nodes[1].dynamicCast<InfEngineNgraphNode>()->node;
if (inp0.get_element_type() != inp1.get_element_type()) {
if (op != OPERATION::WHERE && inp0.get_element_type() != inp1.get_element_type()) {
CV_Assert(inp0.get_element_type() == ov::element::f16 || inp0.get_element_type() == ov::element::f32);
CV_Assert(inp1.get_element_type() == ov::element::f16 || inp1.get_element_type() == ov::element::f32);
auto dtype = preferableTarget == DNN_TARGET_OPENCL_FP16 || preferableTarget == DNN_TARGET_MYRIAD ?
ov::element::f16 : ov::element::f32;
if (inp0.get_element_type() != dtype)
@ -934,10 +955,27 @@ public:
node = std::make_shared<ov::op::v1::Add>(inp0, inp1);
else if (op == OPERATION::PROD)
node = std::make_shared<ov::op::v1::Multiply>(inp0, inp1);
else if (op == OPERATION::EQUAL)
node = std::make_shared<ov::op::v1::Equal>(inp0, inp1);
else if (op == OPERATION::GREATER)
node = std::make_shared<ov::op::v1::Greater>(inp0, inp1);
else if (op == OPERATION::GREATER_EQUAL)
node = std::make_shared<ov::op::v1::GreaterEqual>(inp0, inp1);
else if (op == OPERATION::LESS)
node = std::make_shared<ov::op::v1::Less>(inp0, inp1);
else if (op == OPERATION::LESS_EQUAL)
node = std::make_shared<ov::op::v1::LessEqual>(inp0, inp1);
else if (op == OPERATION::AND)
node = std::make_shared<ov::op::v1::LogicalAnd>(inp0, inp1);
else if (op == OPERATION::OR)
node = std::make_shared<ov::op::v1::LogicalOr>(inp0, inp1);
else if (op == OPERATION::XOR)
node = std::make_shared<ov::op::v1::LogicalXor>(inp0, inp1);
else if (op == OPERATION::WHERE)
{
auto& inp2 = nodes[2].dynamicCast<InfEngineNgraphNode>()->node;
node = std::make_shared<ov::op::v1::Select>(inp0, inp1, inp2);
}
// Ideally we should do this but int32 internal blobs are converted to float32 data type in inference.
// TODO: Remove data type convertion when we have type inference.
else if (op == OPERATION::MOD) {

@ -0,0 +1,83 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "../precomp.hpp"
#include "layers_common.hpp"
#include "../op_inf_engine.hpp"
#include "../ie_ngraph.hpp"
namespace cv { namespace dnn {
class NotLayerImpl CV_FINAL : public NotLayer
{
public:
NotLayerImpl(const LayerParams& params)
{
setParamsFrom(params);
}
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_OPENCV ||
backendId == DNN_BACKEND_INFERENCE_ENGINE_NGRAPH;
}
virtual bool getMemoryShapes(const std::vector<MatShape> &inputs,
const int requiredOutputs,
std::vector<MatShape> &outputs,
std::vector<MatShape> &internals) const CV_OVERRIDE
{
CV_CheckEQ(inputs.size(), (size_t)1, "");
outputs.assign(1, inputs[0]);
return true;
}
virtual void getTypes(const std::vector<MatType>& inputs,
const int requiredOutputs,
const int requiredInternals,
std::vector<MatType>& outputs,
std::vector<MatType>& internals) const CV_OVERRIDE
{
CV_CheckTypeEQ(inputs[0], CV_Bool, "");
outputs.assign(1, CV_Bool);
}
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
{
CV_TRACE_FUNCTION();
CV_TRACE_ARG_VALUE(name, "name", name.c_str());
std::vector<Mat> inputs, outputs;
inputs_arr.getMatVector(inputs);
outputs_arr.getMatVector(outputs);
CV_CheckTypeEQ(inputs[0].type(), CV_Bool, "");
CV_CheckTypeEQ(outputs[0].type(), CV_Bool, "");
bool* input = inputs[0].ptr<bool>();
bool* output = outputs[0].ptr<bool>();
int size = inputs[0].total();
for (int i = 0; i < size; ++i)
output[i] = !input[i];
}
#ifdef HAVE_DNN_NGRAPH
virtual Ptr<BackendNode> initNgraph(const std::vector<Ptr<BackendWrapper> >& inputs,
const std::vector<Ptr<BackendNode> >& nodes) CV_OVERRIDE
{
auto node = std::make_shared<ov::op::v1::LogicalNot>(nodes[0].dynamicCast<InfEngineNgraphNode>()->node);
return Ptr<BackendNode>(new InfEngineNgraphNode(node));
}
#endif // HAVE_DNN_NGRAPH
};
Ptr<NotLayer> NotLayer::create(const LayerParams& params)
{
return makePtr<NotLayerImpl>(params);
}
}} // namespace cv::dnn

@ -417,7 +417,10 @@ public:
) override
{
auto context = reinterpret_cast<csl::CSLContext*>(context_);
return make_cuda_node_with_type<cuda4dnn::ReshapeOp>(preferableTarget, inputs[0]->getHostMatDepth(), std::move(context->stream));
if (inputs[0]->getHostMatDepth() == CV_Bool)
return make_cuda_node_bool<cuda4dnn::ReshapeOp>(std::move(context->stream));
else
return make_cuda_node_with_type<cuda4dnn::ReshapeOp>(preferableTarget, inputs[0]->getHostMatDepth(), std::move(context->stream));
}
#endif

@ -90,7 +90,7 @@ Ptr<BackendWrapper> wrapMat(int backendId, int targetId, cv::Mat& m)
CV_Assert(haveCUDA());
#ifdef HAVE_CUDA
CV_CheckType(m.depth(), m.depth() == CV_32F || m.depth() == CV_8S || m.depth() == CV_8U || m.depth() == CV_32S || m.depth() == CV_64S, "Unsupported type for CUDA");
CV_CheckType(m.depth(), m.depth() == CV_32F || m.depth() == CV_8S || m.depth() == CV_8U || m.depth() == CV_32S || m.depth() == CV_64S || m.depth() == CV_Bool, "Unsupported type for CUDA");
CV_Assert(IS_DNN_CUDA_TARGET(targetId));
switch (m.depth())
{
@ -107,6 +107,8 @@ Ptr<BackendWrapper> wrapMat(int backendId, int targetId, cv::Mat& m)
return CUDABackendWrapperINT32::create(m);
case CV_64S:
return CUDABackendWrapperINT64::create(m);
case CV_Bool:
return CUDABackendWrapperBOOL::create(m);
default:
CV_Error(Error::BadDepth, "Unsupported mat type for CUDA");
}

@ -62,7 +62,7 @@ Ptr<BackendWrapper> Net::Impl::wrap(Mat& host)
{
CV_Assert(haveCUDA());
#ifdef HAVE_CUDA
CV_CheckType(host.depth(), host.depth() == CV_32F || host.depth() == CV_8S || host.depth() == CV_8U || host.depth() == CV_32S || host.depth() == CV_64S, "Unsupported type for CUDA");
CV_CheckType(host.depth(), host.depth() == CV_32F || host.depth() == CV_8S || host.depth() == CV_8U || host.depth() == CV_32S || host.depth() == CV_64S || host.depth() == CV_Bool, "Unsupported type for CUDA");
CV_Assert(IS_DNN_CUDA_TARGET(preferableTarget));
switch (host.depth())
{
@ -79,6 +79,8 @@ Ptr<BackendWrapper> Net::Impl::wrap(Mat& host)
return CUDABackendWrapperINT32::create(baseBuffer, shape);
case CV_64S:
return CUDABackendWrapperINT64::create(baseBuffer, shape);
case CV_Bool:
return CUDABackendWrapperBOOL::create(baseBuffer, shape);
default:
CV_Error(Error::BadDepth, "Unsupported mat type for CUDA");
}

@ -1868,6 +1868,11 @@ Mat getMatFromTensor(const opencv_onnx::TensorProto& tensor_proto, bool uint8ToI
Mat(sizes, CV_8U, val).copyTo(blob);
}
}
else if (datatype == opencv_onnx::TensorProto_DataType_BOOL)
{
char* val = const_cast<char*>(tensor_proto.raw_data().c_str());
Mat(sizes, CV_Bool, val).copyTo(blob);
}
else
{
std::string errorMsg = "Unsupported data type: " +

@ -2839,7 +2839,7 @@ void ONNXImporter::parseCumSum(LayerParams& layerParams, const opencv_onnx::Node
addLayer(layerParams, node_proto);
}
// "Equal" "Greater" "Less" "Pow" "Add" "Sub" "Mul" "Div" "Sum" "Min" "Max" "GreaterOrEqual" "LessOrEqual"
// "Equal" "Greater" "Less" "Pow" "Add" "Sub" "Mul" "Div" "Sum" "Min" "Max" "GreaterOrEqual" "LessOrEqual" "And" "Or" "Xor"
void ONNXImporter::parseElementWise(LayerParams& layerParams, const opencv_onnx::NodeProto& node_proto_)
{
opencv_onnx::NodeProto node_proto = node_proto_;
@ -4038,7 +4038,7 @@ void ONNXImporter::buildDispatchMap_ONNX_AI(int opset_version)
dispatch["Equal"] = dispatch["Greater"] = dispatch["Less"] = dispatch["Pow"] = dispatch["Add"] =
dispatch["Sub"] = dispatch["Mul"] = dispatch["Div"] = dispatch["GreaterOrEqual"] =
dispatch["LessOrEqual"] = dispatch["Mod"] = &ONNXImporter::parseElementWise;
dispatch["LessOrEqual"] = dispatch["Mod"] = dispatch["And"] = dispatch["Or"] = dispatch["Xor"] = &ONNXImporter::parseElementWise;
dispatch["Sum"] = dispatch["Min"] = dispatch["Max"] = &ONNXImporter::parseElementWise;
dispatch["Where"] = &ONNXImporter::parseElementWise;

@ -273,6 +273,11 @@ namespace cv { namespace dnn {
return Ptr<BackendNode>();
}
template <template <class> class NodeType, class ...Args>
cv::Ptr<BackendNode> make_cuda_node_bool(Args&& ...args) {
return Ptr<BackendNode>(new NodeType<bool>(std::forward<Args>(args)...));
}
/* base class for all CUDA backend/target wrappers */
class CUDABackendWrapper : public BackendWrapper {
public:
@ -335,6 +340,11 @@ namespace cv { namespace dnn {
cuda4dnn::csl::memcpy<int64_t>(reinterpret_cast<int64_t*>(mat.data), view.data(), view.size(), stream);
}
template <> inline
void convert_D2H<bool, bool>(const cv::Mat& mat, cuda4dnn::csl::View<bool> view, cuda4dnn::csl::ManagedPtr<bool>& device_temp, const cuda4dnn::csl::Stream& stream) {
cuda4dnn::csl::memcpy<bool>(reinterpret_cast<bool*>(mat.data), view.data(), view.size(), stream);
}
template <class DEVICE_T, class HOST_T>
void convert_D2H_background(const cv::Mat& mat, cuda4dnn::csl::View<DEVICE_T> view, cuda4dnn::csl::ManagedPtr<HOST_T>& device_temp, const cuda4dnn::csl::Stream& stream, const cuda4dnn::csl::Stream& d2h_stream, cuda4dnn::csl::Event& d2h_event);
@ -393,6 +403,13 @@ namespace cv { namespace dnn {
cuda4dnn::csl::memcpy<int64_t>(reinterpret_cast<int64_t*>(mat.data), view.data(), view.size(), d2h_stream);
}
template <> inline
void convert_D2H_background<bool, bool>(const cv::Mat& mat, cuda4dnn::csl::View<bool> view, cuda4dnn::csl::ManagedPtr<bool>& device_temp, const cuda4dnn::csl::Stream& stream, const cuda4dnn::csl::Stream& d2h_stream, cuda4dnn::csl::Event& d2h_event) {
d2h_event.record(stream);
cuda4dnn::csl::StreamWaitOnEvent(d2h_stream, d2h_event);
cuda4dnn::csl::memcpy<bool>(reinterpret_cast<bool*>(mat.data), view.data(), view.size(), d2h_stream);
}
template <class DEVICE_T, class HOST_T>
void convert_H2D(cuda4dnn::csl::Span<DEVICE_T> span, const cv::Mat& mat, cuda4dnn::csl::ManagedPtr<HOST_T>& device_temp, const cuda4dnn::csl::Stream& stream);
@ -430,6 +447,11 @@ namespace cv { namespace dnn {
void convert_H2D<int64_t, int64_t>(cuda4dnn::csl::Span<int64_t> span, const cv::Mat& mat, cuda4dnn::csl::ManagedPtr<int64_t>& device_temp, const cuda4dnn::csl::Stream& stream) {
cuda4dnn::csl::memcpy<int64_t>(span.data(), reinterpret_cast<int64_t*>(mat.data), span.size(), stream);
}
template <> inline
void convert_H2D<bool, bool>(cuda4dnn::csl::Span<bool> span, const cv::Mat& mat, cuda4dnn::csl::ManagedPtr<bool>& device_temp, const cuda4dnn::csl::Stream& stream) {
cuda4dnn::csl::memcpy<bool>(span.data(), reinterpret_cast<bool*>(mat.data), span.size(), stream);
}
}} /* namespace cuda4dnn::detail */
template <class DEVICE_T, class HOST_T, int TargetID>
@ -662,6 +684,7 @@ namespace cv { namespace dnn {
using CUDABackendWrapperUINT8 = GenericCUDABackendWrapper<uint8_t, uint8_t, DNN_TARGET_CUDA>;
using CUDABackendWrapperINT32 = GenericCUDABackendWrapper<int32_t, int32_t, DNN_TARGET_CUDA>;
using CUDABackendWrapperINT64 = GenericCUDABackendWrapper<int64_t, int64_t, DNN_TARGET_CUDA>;
using CUDABackendWrapperBOOL = GenericCUDABackendWrapper<bool, bool, DNN_TARGET_CUDA>;
template <class T> struct GetCUDABackendWrapperType_ { };
template <> struct GetCUDABackendWrapperType_<half> { typedef CUDABackendWrapperFP16 type; };
@ -670,6 +693,7 @@ namespace cv { namespace dnn {
template <> struct GetCUDABackendWrapperType_<uint8_t> { typedef CUDABackendWrapperUINT8 type; };
template <> struct GetCUDABackendWrapperType_<int32_t> { typedef CUDABackendWrapperINT32 type; };
template <> struct GetCUDABackendWrapperType_<int64_t> { typedef CUDABackendWrapperINT64 type; };
template <> struct GetCUDABackendWrapperType_<bool> { typedef CUDABackendWrapperBOOL type; };
template <class T>
using GetCUDABackendWrapperType = typename GetCUDABackendWrapperType_<T>::type;

@ -53,6 +53,7 @@ Mat infEngineBlobToMat(const ov::Tensor& blob)
case ov::element::i32: type = CV_32S; break;
case ov::element::i64: type = CV_64S; break;
case ov::element::u8: type = CV_8U; break;
case ov::element::boolean: type = CV_Bool; break;
default:
CV_Error(Error::StsNotImplemented, "Unsupported blob precision");
}

@ -4,14 +4,6 @@
"test_adagrad_multiple", // ---- same as above ---
"test_adam", // Issues::Layer::Can't create layer "onnx_node_output_0!X1_new" of type "ai.onnx.preview.training.Adam" in function 'getLayerInstance'
"test_adam_multiple", // ---- same as above ---
"test_and2d", // Issue:: Unsupported data type BOOL
"test_and3d", // Issue:: Unsupported data type BOOL
"test_and4d", // Issue:: Unsupported data type BOOL
"test_and_bcast3v1d", // Issue:: Unsupported data type BOOL
"test_and_bcast3v2d", // Issue:: Unsupported data type BOOL
"test_and_bcast4v2d", // Issue:: Unsupported data type BOOL
"test_and_bcast4v3d", // Issue:: Unsupported data type BOOL
"test_and_bcast4v4d", // Issue:: Unsupported data type BOOL
"test_basic_convinteger", // Issues::Layer::Can't create layer "onnx_node_output_0!y" of type "ConvInteger" in function 'getLayerInstance'
"test_batchnorm_epsilon", // Issue:: Unkonwn error::Blob mean not found in const blobs in function 'getBlob'
"test_batchnorm_epsilon_training_mode", // ---- same as above ---
@ -102,8 +94,6 @@
"test_dynamicquantizelinear_min_adjusted_expanded", // ---- same as above ---
"test_edge_pad", // Issue::Parser::Weights are required as inputs
"test_einsum_inner_prod", // Issue::Output shape does not match with reference
"test_equal", // Issue:: Unsupported data type BOOL
"test_equal_bcast", // ---- same as above ---
"test_expand_dim_changed", // Issue:: Unkonwn error
"test_expand_dim_unchanged", // Issue:: Unkonwn error
"test_eyelike_populate_off_main_diagonal", // Issues::Layer::Can't create layer::Can't create layer "onnx_node_output_0!y" of type "EyeLike" in function 'getLayerInstance'
@ -121,12 +111,6 @@
"test_gemm_default_zero_bias", // Issue::Wrong output
"test_gemm_transposeA", // Issue::Wrong output
"test_gemm_transposeB", // Issue::Wrong output
"test_greater", // Issue:: Unsupported data type BOOL
"test_greater_bcast", // ---- same as above ---
"test_greater_equal", // ---- same as above ---
"test_greater_equal_bcast", // ---- same as above ---
"test_greater_equal_bcast_expanded", // ---- same as above ---
"test_greater_equal_expanded", // ---- same as above ---
"test_gridsample", // Issues::Layer::Can't create layer "onnx_node_output_0!Y" of type "GridSample" in function 'getLayerInstance'
"test_gridsample_aligncorners_true", // ---- same as above ---
"test_gridsample_bicubic", // ---- same as above ---
@ -155,12 +139,6 @@
"test_isinf_negative", // Issue:: Unsupported data type BOOL
"test_isinf_positive", // Issue:: Unsupported data type BOOL
"test_isnan", // Issue:: Unsupported data type BOOL
"test_less", // Issue:: Unsupported data type BOOL
"test_less_bcast", // Issue:: Unsupported data type BOOL
"test_less_equal", // Issue:: Unsupported data type BOOL
"test_less_equal_bcast", // Issue:: Unsupported data type BOOL
"test_less_equal_bcast_expanded", // Issue:: Unsupported data type BOOL
"test_less_equal_expanded", // Issue:: Unsupported data type BOOL
"test_loop11", // Issue:: Unsupported data type BOOL
"test_loop13_seq", // Issue:: Unsupported data type BOOL
"test_loop16_seq_none", // Issue:: Unsupported data type BOOL
@ -228,9 +206,6 @@
"test_nonmaxsuppression_two_batches", // ---- same as above ---
"test_nonmaxsuppression_two_classes", // ---- same as above ---
"test_nonzero_example", // Issue:: Unsupported data type: BOOL
"test_not_2d", // ---- same as above ---
"test_not_3d", // ---- same as above ---
"test_not_4d", // ---- same as above ---
"test_onehot_negative_indices", // Issue:: Layer does not exist (OneHot) :: Can't create layer "onnx_node_output_0!y" of type "OneHot" in function 'getLayerInstance'
"test_onehot_with_axis", // ---- same as above ---
"test_onehot_with_negative_axis", // ---- same as above ---
@ -239,14 +214,6 @@
"test_optional_get_element_sequence", // ---- same as above ---
"test_optional_has_element", // Issue:: Unsupported data type BOOL
"test_optional_has_element_empty", // ---- same as above ---
"test_or2d",
"test_or3d", // ---- same as above ---
"test_or4d", // ---- same as above ---
"test_or_bcast3v1d",
"test_or_bcast3v2d", // ---- same as above ---
"test_or_bcast4v2d", // ---- same as above ---
"test_or_bcast4v3d", // ---- same as above ---
"test_or_bcast4v4d", // ---- same as above ---
"test_pow_types_float", // Issue:: Unsupported data type
"test_pow_types_float32_int32", // ---- same as above ---
"test_pow_types_float32_int64", // ---- same as above ---
@ -471,16 +438,6 @@
"test_unsqueeze_three_axes", // ---- same as above ---
"test_unsqueeze_two_axes", // ---- same as above ---)
"test_unsqueeze_unsorted_axes", // ---- same as above ---)
"test_where_example", // Issue:: Parser: Unsupported data type: BOOL in function 'getMatFromTensor'
"test_where_long_example", // ---- same as above ---
"test_xor2d", // Issue:: Parser: Unsupported data type: BOOL in function 'getMatFromTensor'
"test_xor3d", // ---- same as above ---
"test_xor4d", // ---- same as above ---
"test_xor_bcast3v1d", // ---- same as above ---
"test_xor_bcast3v2d", // ---- same as above ---
"test_xor_bcast4v2d", // ---- same as above ---
"test_xor_bcast4v3d", // ---- same as above ---
"test_xor_bcast4v4d", // ---- same as above ---
// // Cumsum related issue: https://github.com/opencv/opencv/issues/24437
"test_cumsum_1d", //Issue:: output shape creation mismatch
"test_cumsum_1d_exclusive", // ---- same as above ---

@ -1416,6 +1416,9 @@ double norm(InputArray _src, int normType, InputArray _mask)
switch( depth )
{
case CV_Bool:
result = norm_((const bool*)sptr, total, cn, normType, result, mptr);
break;
case CV_8U:
result = norm_((const uchar*)sptr, total, cn, normType, result, mptr);
break;
@ -1522,6 +1525,9 @@ double norm(InputArray _src1, InputArray _src2, int normType, InputArray _mask)
switch( depth )
{
case CV_Bool:
result = norm_((const bool*)sptr1, (const bool*)sptr2, total, cn, normType, result, mptr);
break;
case CV_8U:
result = norm_((const uchar*)sptr1, (const uchar*)sptr2, total, cn, normType, result, mptr);
break;

Loading…
Cancel
Save