#include "../precomp.hpp"
#include "layers_common.hpp"
-#include "op_halide.hpp"
+#include "../op_cuda.hpp"
+#include "../op_halide.hpp"
#include <opencv2/dnn/shape_utils.hpp>
-#include <iostream>
+#ifdef HAVE_CUDA
+#include "../cuda4dnn/primitives/max_unpooling.hpp"
+using namespace cv::dnn::cuda4dnn;
+#endif
namespace cv
{
namespace dnn
{
-class MaxUnpoolLayerImpl : public MaxUnpoolLayer
+class MaxUnpoolLayerImpl CV_FINAL : public MaxUnpoolLayer
{
public:
MaxUnpoolLayerImpl(const LayerParams& params)
poolStride = Size(params.get<int>("pool_stride_w"), params.get<int>("pool_stride_h"));
}
- virtual bool supportBackend(int backendId)
+ virtual bool supportBackend(int backendId) CV_OVERRIDE
{
- return backendId == DNN_BACKEND_DEFAULT ||
- backendId == DNN_BACKEND_HALIDE && haveHalide() &&
- !poolPad.width && !poolPad.height;
+ return backendId == DNN_BACKEND_OPENCV ||
+ backendId == DNN_BACKEND_CUDA ||
+ (backendId == DNN_BACKEND_HALIDE && haveHalide() && !poolPad.width && !poolPad.height);
}
bool getMemoryShapes(const std::vector<MatShape> &inputs,
const int requiredOutputs,
std::vector<MatShape> &outputs,
- std::vector<MatShape> &internals) const
+ std::vector<MatShape> &internals) const CV_OVERRIDE
{
- CV_Assert(inputs.size() == 2);
+ CV_Assert(inputs.size() == 2 || inputs.size() == 3);
CV_Assert(total(inputs[0]) == total(inputs[1]));
- MatShape outShape = inputs[0];
- outShape[2] = (outShape[2] - 1) * poolStride.height + poolKernel.height - 2 * poolPad.height;
- outShape[3] = (outShape[3] - 1) * poolStride.width + poolKernel.width - 2 * poolPad.width;
+ MatShape outShape;
+ if (inputs.size() == 2)
+ {
+ outShape = inputs[0];
+ outShape[2] = (outShape[2] - 1) * poolStride.height + poolKernel.height - 2 * poolPad.height;
+ outShape[3] = (outShape[3] - 1) * poolStride.width + poolKernel.width - 2 * poolPad.width;
+ }
+ else
+ outShape = inputs[2];
outputs.clear();
outputs.push_back(outShape);
return false;
}
- void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr)
+ 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());
- Layer::forward_fallback(inputs_arr, outputs_arr, internals_arr);
- }
+ if (inputs_arr.depth() == CV_16S)
+ {
+ forward_fallback(inputs_arr, outputs_arr, internals_arr);
+ return;
+ }
- void forward(std::vector<Mat*> &inputs, std::vector<Mat> &outputs, std::vector<Mat> &internals)
- {
- 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_Assert(inputs.size() == 2);
- Mat& input = *inputs[0];
- Mat& indices = *inputs[1];
+ CV_Assert(inputs.size() == 2 || inputs.size() == 3);
+ Mat& input = inputs[0];
+ Mat& indices = inputs[1];
CV_Assert(input.total() == indices.total());
CV_Assert(input.size[0] == 1);
}
}
- virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &input)
+#ifdef HAVE_CUDA
+ Ptr<BackendNode> initCUDA(
+ void *context_,
+ const std::vector<Ptr<BackendWrapper>>& inputs,
+ const std::vector<Ptr<BackendWrapper>>& outputs
+ ) override
+ {
+ auto context = reinterpret_cast<csl::CSLContext*>(context_);
+
+ cuda4dnn::MaxUnpoolingConfiguration config;
+ auto& window_size = config.window_size;
+ window_size.resize(2);
+ window_size[0] = poolKernel.height;
+ window_size[1] = poolKernel.width;
+
+ auto& strides = config.strides;
+ strides.resize(2);
+ strides[0] = poolStride.height;
+ strides[1] = poolStride.width;
+
+ auto& pads_begin = config.pads_begin;
+ pads_begin.resize(2);
+ pads_begin[0] = poolPad.height;
+ pads_begin[1] = poolPad.width;
+
+ return make_cuda_node<cuda4dnn::MaxUnpoolingOp>(preferableTarget, std::move(context->stream), config);
+ }
+#endif
+
+ virtual Ptr<BackendNode> initHalide(const std::vector<Ptr<BackendWrapper> > &input) CV_OVERRIDE
{
#ifdef HAVE_HALIDE
// Meaningless operation if false because if kernel > stride