mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 08:13:04 +04:00
Merge remote-tracking branch 'upstream/3.4' into merge-3.4
This commit is contained in:
@@ -98,6 +98,9 @@ public:
|
||||
stride = Size(1, 1);
|
||||
pad_t = pad_l = pad_b = pad_r = 0;
|
||||
|
||||
hasDynamicShapes = params.get<bool>("has_dynamic_shapes", false);
|
||||
shapesInitialized = !hasDynamicShapes;
|
||||
|
||||
if (params.has("pool") || params.has("kernel_size") ||
|
||||
params.has("kernel_w") || params.has("kernel_h"))
|
||||
{
|
||||
@@ -1191,25 +1194,33 @@ public:
|
||||
outShape.push_back(pooledSize.height);
|
||||
outShape.push_back(pooledSize.width);
|
||||
}
|
||||
else if (padMode.empty())
|
||||
{
|
||||
for (int i = 0; i < local_kernel.size(); i++) {
|
||||
float dst = (float)(inpShape[i] + pads_begin[i] + pads_end[i] - local_kernel[i]) / strides[i];
|
||||
outShape.push_back(1 + (ceilMode ? ceil(dst) : floor(dst)));
|
||||
}
|
||||
|
||||
// If we have padding, ensure that the last pooling starts strictly
|
||||
// inside the image (instead of at the padding); otherwise clip the last.
|
||||
for (int i = 0; i < pads_end.size(); i++) {
|
||||
if (pads_end[i] && (outShape[2 + i] - 1) * strides[i] >= inpShape[i] + pads_end[i]) {
|
||||
--outShape[2 + i];
|
||||
CV_Assert((outShape[2 + i] - 1) * strides[i] < inpShape[i] + pads_end[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getConvPoolOutParams(inpShape, local_kernel, strides, padMode, std::vector<size_t>(local_kernel.size(), 1), outShape);
|
||||
if (hasDynamicShapes && !shapesInitialized)
|
||||
{
|
||||
//Just copy input shapes for width and height to prevent errors on loading stage
|
||||
for (int i = 0; i < inpShape.size(); i++)
|
||||
outShape.push_back(inpShape[i]);
|
||||
}
|
||||
else if (padMode.empty())
|
||||
{
|
||||
for (int i = 0; i < local_kernel.size(); i++) {
|
||||
float dst = (float) (inpShape[i] + pads_begin[i] + pads_end[i] - local_kernel[i]) / strides[i];
|
||||
outShape.push_back(1 + (ceilMode ? ceil(dst) : floor(dst)));
|
||||
}
|
||||
|
||||
// If we have padding, ensure that the last pooling starts strictly
|
||||
// inside the image (instead of at the padding); otherwise clip the last.
|
||||
for (int i = 0; i < pads_end.size(); i++) {
|
||||
if (pads_end[i] && (outShape[2 + i] - 1) * strides[i] >= inpShape[i] + pads_end[i]) {
|
||||
--outShape[2 + i];
|
||||
CV_Assert((outShape[2 + i] - 1) * strides[i] < inpShape[i] + pads_end[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
getConvPoolOutParams(inpShape, local_kernel, strides, padMode,
|
||||
std::vector<size_t>(local_kernel.size(), 1), outShape);
|
||||
}
|
||||
}
|
||||
if (type == ROI)
|
||||
{
|
||||
@@ -1231,6 +1242,14 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool updateMemoryShapes(const std::vector<MatShape> &inputs) CV_OVERRIDE
|
||||
{
|
||||
int dims = inputs[0].size();
|
||||
CV_Assert(inputs[0][dims - 1] > 0 && inputs[0][dims - 2] > 0);
|
||||
shapesInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual int64 getFLOPS(const std::vector<MatShape> &inputs,
|
||||
const std::vector<MatShape> &outputs) const CV_OVERRIDE
|
||||
{
|
||||
@@ -1262,6 +1281,8 @@ private:
|
||||
ROI, // RoI pooling, https://arxiv.org/pdf/1504.08083.pdf
|
||||
PSROI // Position-sensitive RoI pooling, https://arxiv.org/pdf/1605.06409.pdf
|
||||
};
|
||||
bool hasDynamicShapes;
|
||||
bool shapesInitialized;
|
||||
};
|
||||
|
||||
Ptr<PoolingLayer> PoolingLayer::create(const LayerParams& params)
|
||||
|
||||
@@ -170,6 +170,9 @@ public:
|
||||
setParamsFrom(params);
|
||||
int axis = params.get<int>("axis", 0);
|
||||
int numAxes = params.get<int>("num_axes", -1);
|
||||
hasDynamicShapes = params.get<bool>("has_dynamic_shapes", false);
|
||||
shapesInitialized = !hasDynamicShapes;
|
||||
|
||||
CV_Assert(numAxes >= -1);
|
||||
newShapeRange = (numAxes == -1) ? Range(axis, INT_MAX) : Range(axis, axis + numAxes);
|
||||
|
||||
@@ -182,6 +185,25 @@ public:
|
||||
for (i = 0; i < dims; i++)
|
||||
newShapeDesc[i] = paramShape.get<int>(i);
|
||||
}
|
||||
if (hasDynamicShapes)
|
||||
{
|
||||
dynamicShapes.clear();
|
||||
inputIndices.clear();
|
||||
if (params.has("dynamic_axes")) {
|
||||
CV_Assert(params.has("input_indices"));
|
||||
const DictValue &dynamicAxes = params.get("dynamic_axes");
|
||||
const DictValue &dynamicInputShapes = params.get("input_indices");
|
||||
int i, dims = dynamicAxes.size();
|
||||
CV_Assert(dims == dynamicInputShapes.size());
|
||||
CV_Assert(dims > 0);
|
||||
dynamicShapes.resize(dims);
|
||||
inputIndices.resize(dims);
|
||||
for (i = 0; i < dims; i++) {
|
||||
dynamicShapes[i] = dynamicAxes.get<int>(i);
|
||||
inputIndices[i] = dynamicInputShapes.get<int>(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool supportBackend(int backendId) CV_OVERRIDE
|
||||
@@ -196,13 +218,21 @@ public:
|
||||
std::vector<MatShape> &outputs,
|
||||
std::vector<MatShape> &internals) const CV_OVERRIDE
|
||||
{
|
||||
|
||||
if (inputs.size() == 1 || inputs.size() == requiredOutputs)
|
||||
{
|
||||
outputs.clear();
|
||||
for (size_t i = 0; i < inputs.size(); i++)
|
||||
{
|
||||
outputs.push_back(MatShape());
|
||||
computeShapeByReshapeMask(inputs[i], newShapeDesc, newShapeRange, outputs.back());
|
||||
if (hasDynamicShapes && !shapesInitialized)
|
||||
{
|
||||
outputs.push_back(newShapeDesc);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputs.push_back(MatShape());
|
||||
computeShapeByReshapeMask(inputs[i], newShapeDesc, newShapeRange, outputs.back());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -213,6 +243,19 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool updateMemoryShapes(const std::vector<MatShape> &inputs) CV_OVERRIDE
|
||||
{
|
||||
if (hasDynamicShapes)
|
||||
{
|
||||
for (int i = 0; i < dynamicShapes.size(); ++i)
|
||||
{
|
||||
newShapeDesc[dynamicShapes[i]] = inputs[0][inputIndices[i]];
|
||||
}
|
||||
}
|
||||
shapesInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void finalize(InputArrayOfArrays, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
|
||||
{
|
||||
std::vector<Mat> outputs;
|
||||
@@ -310,6 +353,10 @@ public:
|
||||
|
||||
private:
|
||||
std::vector<MatShape> outShapes;
|
||||
std::vector<int> dynamicShapes; // Which axes shapes are dynamic and require reinitialization with new input
|
||||
std::vector<int> inputIndices; // Which axes from input are needed to compute correct output shape
|
||||
bool hasDynamicShapes;
|
||||
bool shapesInitialized;
|
||||
};
|
||||
|
||||
Ptr<ReshapeLayer> ReshapeLayer::create(const LayerParams& params)
|
||||
|
||||
@@ -72,6 +72,8 @@ public:
|
||||
setParamsFrom(params);
|
||||
axis = params.get<int>("axis", 1);
|
||||
num_split = params.get<int>("num_split", 0);
|
||||
hasDynamicShapes = params.get<bool>("has_dynamic_shapes", false);
|
||||
shapesInitialized = !hasDynamicShapes;
|
||||
if (params.has("slice_point"))
|
||||
{
|
||||
CV_Assert(!params.has("begin") && !params.has("size") && !params.has("end"));
|
||||
@@ -150,7 +152,8 @@ public:
|
||||
CV_Assert(sliceRanges[i].size() <= inpShape.size());
|
||||
for (int j = 0; j < sliceRanges[i].size(); ++j)
|
||||
{
|
||||
outputs[i][j] = clamp(sliceRanges[i][j], inpShape[j]).size();
|
||||
if (shapesInitialized || inpShape[j] > 0)
|
||||
outputs[i][j] = clamp(sliceRanges[i][j], inpShape[j]).size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,6 +168,12 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool updateMemoryShapes(const std::vector<MatShape> &inputs) CV_OVERRIDE
|
||||
{
|
||||
shapesInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void finalize(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr) CV_OVERRIDE
|
||||
{
|
||||
#ifdef HAVE_OPENCL
|
||||
@@ -597,6 +606,8 @@ public:
|
||||
protected:
|
||||
// The actual non-negative values determined from @p sliceRanges depends on input size.
|
||||
std::vector<std::vector<Range> > finalSliceRanges;
|
||||
bool hasDynamicShapes;
|
||||
bool shapesInitialized;
|
||||
};
|
||||
|
||||
class CropLayerImpl CV_FINAL : public SliceLayerImpl
|
||||
|
||||
Reference in New Issue
Block a user