Open Source Computer Vision Library https://opencv.org/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

343 lines
10 KiB

// 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.
#ifndef __OPENCV_DNN_SRC_LAYER_INTERNALS_HPP__
#define __OPENCV_DNN_SRC_LAYER_INTERNALS_HPP__
namespace cv { namespace dnn {
CV__DNN_INLINE_NS_BEGIN
inline namespace detail {
struct LayerPin
{
int lid;
int oid;
LayerPin(int layerId = -1, int outputId = -1)
: lid(layerId)
, oid(outputId)
{}
bool valid() const
{
return (lid >= 0 && oid >= 0);
}
bool equal(const LayerPin& r) const
{
return (lid == r.lid && oid == r.oid);
}
bool operator<(const LayerPin& r) const
{
return lid < r.lid || (lid == r.lid && oid < r.oid);
}
bool operator==(const LayerPin& r) const
{
return lid == r.lid && oid == r.oid;
}
};
struct LayerData
{
LayerData()
: id(-1)
, dtype(CV_32F)
, skip(false)
, flag(0)
{}
LayerData(int _id, const String& _name, const String& _type, const int& _dtype, LayerParams& _params)
: id(_id)
, name(_name)
, type(_type)
, dtype(_dtype)
, params(_params)
, skip(false)
, flag(0)
{
CV_TRACE_FUNCTION();
// add logging info
params.name = name;
params.type = type;
}
int id;
String name;
String type;
int dtype; // Datatype of output blobs.
LayerParams params;
std::vector<LayerPin> inputBlobsId;
std::set<int> inputLayersId;
std::set<int> requiredOutputs;
std::vector<LayerPin> consumers;
std::vector<Ptr<BackendWrapper>> outputBlobsWrappers;
std::vector<Ptr<BackendWrapper>> inputBlobsWrappers;
std::vector<Ptr<BackendWrapper>> internalBlobsWrappers;
#ifdef HAVE_CUDA
/* output ids which must be transferred to the host in the background
* after the completion of the forward pass of the layer
*/
std::vector<int> cudaD2HBackgroundTransfers;
#endif
Ptr<Layer> layerInstance;
std::vector<Mat> outputBlobs;
std::vector<Mat*> inputBlobs;
std::vector<Mat> internals;
// Computation nodes of implemented backends (except DEFAULT).
std::map<int, Ptr<BackendNode>> backendNodes;
// Flag for skip layer computation for specific backend.
bool skip;
int flag;
void resetAllocation()
{
if (id == 0)
return; // skip "input" layer (assertion in Net::Impl::allocateLayers)
layerInstance.release();
outputBlobs.clear();
inputBlobs.clear();
internals.clear();
outputBlobsWrappers.clear();
inputBlobsWrappers.clear();
internalBlobsWrappers.clear();
backendNodes.clear();
skip = false;
flag = 0;
#ifdef HAVE_CUDA
cudaD2HBackgroundTransfers.clear();
#endif
}
};
// fake layer containing network input blobs
struct DataLayer : public Layer
{
DataLayer()
: Layer()
{
skip = false;
}
virtual bool supportBackend(int backendId) CV_OVERRIDE
{
return backendId == DNN_BACKEND_OPENCV;
}
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());
// FIXIT: add wrapper without exception suppression
CV_OCL_RUN(IS_DNN_OPENCL_TARGET(preferableTarget),
forward_ocl(inputs_arr, outputs_arr, internals_arr))
bool isFP16 = outputs_arr.depth() == CV_16F;
std::vector<Mat> outputs, internals;
outputs_arr.getMatVector(outputs);
internals_arr.getMatVector(internals);
for (int i = 0; i < inputsData.size(); ++i)
{
double scale = scaleFactors[i];
Scalar& mean = means[i];
CV_Assert(mean == Scalar() || inputsData[i].size[1] <= 4);
if (isFP16)
CV_CheckTypeEQ(outputs[i].type(), CV_16FC1, "");
else
CV_CheckTypeEQ(outputs[i].type(), CV_32FC1, "");
bool singleMean = true;
for (int j = 1; j < std::min(4, inputsData[i].size[1]) && singleMean; ++j)
{
singleMean = mean[j] == mean[j - 1];
}
if (singleMean)
{
if (isFP16)
{
Mat input_f32;
inputsData[i].convertTo(input_f32, CV_32F, scale, -mean[0] * scale);
input_f32.convertTo(outputs[i], CV_16F);
}
else
{
inputsData[i].convertTo(outputs[i], CV_32F, scale, -mean[0] * scale);
}
}
else
{
for (int n = 0; n < inputsData[i].size[0]; ++n)
{
for (int c = 0; c < inputsData[i].size[1]; ++c)
{
Mat inp = getPlane(inputsData[i], n, c);
Mat out = getPlane(outputs[i], n, c);
if (isFP16)
{
Mat input_f32;
inp.convertTo(input_f32, CV_32F, scale, -mean[c] * scale);
input_f32.convertTo(out, CV_16F);
}
else
{
inp.convertTo(out, CV_32F, scale, -mean[c] * scale);
}
}
}
}
}
}
#ifdef HAVE_OPENCL
bool forward_ocl(InputArrayOfArrays, OutputArrayOfArrays outputs_, OutputArrayOfArrays internals_)
{
bool isFP16 = outputs_.depth() == CV_16F;
std::vector<UMat> outputs;
outputs_.getUMatVector(outputs);
for (int i = 0; i < inputsData.size(); ++i)
{
Mat inputData = inputsData[i];
double scale = scaleFactors[i];
Scalar& mean = means[i];
CV_Assert(mean == Scalar() || inputData.size[1] <= 4);
if (isFP16)
CV_CheckTypeEQ(outputs[i].type(), CV_16FC1, "");
else
CV_CheckTypeEQ(outputs[i].type(), CV_32FC1, "");
bool singleMean = true;
for (int j = 1; j < std::min(4, inputData.size[1]) && singleMean; ++j)
{
singleMean = mean[j] == mean[j - 1];
}
if (singleMean)
{
if (isFP16)
{
UMat input_i;
inputData.convertTo(input_i, CV_32F, scale, -mean[0] * scale);
input_i.convertTo(outputs[i], CV_16F);
}
else
{
inputData.convertTo(outputs[i], CV_32F, scale, -mean[0] * scale);
}
}
else
{
for (int n = 0; n < inputData.size[0]; ++n)
{
for (int c = 0; c < inputData.size[1]; ++c)
{
Mat inp = getPlane(inputData, n, c);
std::vector<cv::Range> plane(4, Range::all());
plane[0] = Range(n, n + 1);
plane[1] = Range(c, c + 1);
UMat out = outputs[i](plane).reshape(1, inp.dims, inp.size);
if (isFP16)
{
UMat input_i;
inp.convertTo(input_i, CV_32F, scale, -mean[c] * scale);
input_i.convertTo(out, CV_16F);
}
else
{
inp.convertTo(out, CV_32F, scale, -mean[c] * scale);
}
}
}
}
}
return true;
}
#endif
int outputNameToIndex(const String& tgtName) CV_OVERRIDE
{
int idx = (int)(std::find(outNames.begin(), outNames.end(), tgtName) - outNames.begin());
return (idx < (int)outNames.size()) ? idx : -1;
}
void setNames(const std::vector<String>& names)
{
outNames.assign(names.begin(), names.end());
shapes.clear();
shapes.resize(outNames.size());
}
void setInputShape(const String& tgtName, const MatShape& shape)
{
std::vector<String>::const_iterator it = std::find(outNames.begin(), outNames.end(), tgtName);
CV_Check(tgtName, it != outNames.end(), "Unknown input");
int idx = (int)(it - outNames.begin());
CV_Assert(idx < (int)shapes.size());
CV_Check(tgtName, shapes[idx].empty(), "Input shape redefinition is not allowed");
shapes[idx] = shape;
}
bool getMemoryShapes(const std::vector<MatShape>& inputs,
const int requiredOutputs,
std::vector<MatShape>& outputs,
std::vector<MatShape>& internals) const CV_OVERRIDE
{
CV_Assert(inputs.size() == requiredOutputs);
outputs.assign(inputs.begin(), inputs.end());
return false;
}
virtual void finalize(InputArrayOfArrays, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
{
std::vector<Mat> outputs;
outputs_arr.getMatVector(outputs);
CV_Assert_N(outputs.size() == scaleFactors.size(), outputs.size() == means.size(),
inputsData.size() == outputs.size());
skip = true;
for (int i = 0; skip && i < inputsData.size(); ++i)
{
if (inputsData[i].data != outputs[i].data || scaleFactors[i] != 1.0 || means[i] != Scalar())
skip = false;
}
}
std::vector<String> outNames;
std::vector<MatShape> shapes;
// Preprocessing parameters for each network's input.
std::vector<double> scaleFactors;
std::vector<Scalar> means;
std::vector<Mat> inputsData;
bool skip;
}; // DataLayer
} // namespace detail
CV__DNN_INLINE_NS_END
}} // namespace cv::dnn
#endif // __OPENCV_DNN_SRC_LAYER_INTERNALS_HPP__