mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Implement Interp layer using Resize layer
This commit is contained in:
parent
1894f1a37f
commit
e8e9d1d021
@ -592,6 +592,17 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN
|
|||||||
static Ptr<ResizeLayer> create(const LayerParams& params);
|
static Ptr<ResizeLayer> create(const LayerParams& params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bilinear resize layer from https://github.com/cdmh/deeplab-public
|
||||||
|
*
|
||||||
|
* It differs from @ref ResizeLayer in output shape and resize scales computations.
|
||||||
|
*/
|
||||||
|
class CV_EXPORTS InterpLayer : public Layer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Ptr<Layer> create(const LayerParams& params);
|
||||||
|
};
|
||||||
|
|
||||||
class CV_EXPORTS ProposalLayer : public Layer
|
class CV_EXPORTS ProposalLayer : public Layer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -84,6 +84,7 @@ void initializeLayerFactory()
|
|||||||
CV_DNN_REGISTER_LAYER_CLASS(Reshape, ReshapeLayer);
|
CV_DNN_REGISTER_LAYER_CLASS(Reshape, ReshapeLayer);
|
||||||
CV_DNN_REGISTER_LAYER_CLASS(Flatten, FlattenLayer);
|
CV_DNN_REGISTER_LAYER_CLASS(Flatten, FlattenLayer);
|
||||||
CV_DNN_REGISTER_LAYER_CLASS(Resize, ResizeLayer);
|
CV_DNN_REGISTER_LAYER_CLASS(Resize, ResizeLayer);
|
||||||
|
CV_DNN_REGISTER_LAYER_CLASS(Interp, InterpLayer);
|
||||||
CV_DNN_REGISTER_LAYER_CLASS(CropAndResize, CropAndResizeLayer);
|
CV_DNN_REGISTER_LAYER_CLASS(CropAndResize, CropAndResizeLayer);
|
||||||
|
|
||||||
CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
|
CV_DNN_REGISTER_LAYER_CLASS(Convolution, ConvolutionLayer);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
namespace cv { namespace dnn {
|
namespace cv { namespace dnn {
|
||||||
|
|
||||||
class ResizeLayerImpl CV_FINAL : public ResizeLayer
|
class ResizeLayerImpl : public ResizeLayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ResizeLayerImpl(const LayerParams& params)
|
ResizeLayerImpl(const LayerParams& params)
|
||||||
@ -33,7 +33,7 @@ public:
|
|||||||
interpolation = params.get<String>("interpolation");
|
interpolation = params.get<String>("interpolation");
|
||||||
CV_Assert(interpolation == "nearest" || interpolation == "bilinear");
|
CV_Assert(interpolation == "nearest" || interpolation == "bilinear");
|
||||||
|
|
||||||
alignCorners = params.get<bool>("align_corners", false);
|
bool alignCorners = params.get<bool>("align_corners", false);
|
||||||
if (alignCorners)
|
if (alignCorners)
|
||||||
CV_Error(Error::StsNotImplemented, "Resize with align_corners=true is not implemented");
|
CV_Error(Error::StsNotImplemented, "Resize with align_corners=true is not implemented");
|
||||||
}
|
}
|
||||||
@ -66,6 +66,8 @@ public:
|
|||||||
outHeight = outputs[0].size[2];
|
outHeight = outputs[0].size[2];
|
||||||
outWidth = outputs[0].size[3];
|
outWidth = outputs[0].size[3];
|
||||||
}
|
}
|
||||||
|
scaleHeight = static_cast<float>(inputs[0]->size[2]) / outHeight;
|
||||||
|
scaleWidth = static_cast<float>(inputs[0]->size[3]) / outWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
|
void forward(InputArrayOfArrays inputs_arr, OutputArrayOfArrays outputs_arr, OutputArrayOfArrays internals_arr) CV_OVERRIDE
|
||||||
@ -103,8 +105,6 @@ public:
|
|||||||
const int inpWidth = inp.size[3];
|
const int inpWidth = inp.size[3];
|
||||||
const int inpSpatialSize = inpHeight * inpWidth;
|
const int inpSpatialSize = inpHeight * inpWidth;
|
||||||
const int outSpatialSize = outHeight * outWidth;
|
const int outSpatialSize = outHeight * outWidth;
|
||||||
const float heightScale = static_cast<float>(inpHeight) / (outHeight);
|
|
||||||
const float widthScale = static_cast<float>(inpWidth) / (outWidth);
|
|
||||||
const int numPlanes = inp.size[0] * inp.size[1];
|
const int numPlanes = inp.size[0] * inp.size[1];
|
||||||
CV_Assert(inp.isContinuous(), out.isContinuous());
|
CV_Assert(inp.isContinuous(), out.isContinuous());
|
||||||
|
|
||||||
@ -112,13 +112,13 @@ public:
|
|||||||
Mat outPlanes = out.reshape(1, numPlanes * outHeight);
|
Mat outPlanes = out.reshape(1, numPlanes * outHeight);
|
||||||
for (int y = 0; y < outHeight; ++y)
|
for (int y = 0; y < outHeight; ++y)
|
||||||
{
|
{
|
||||||
float input_y = y * heightScale;
|
float input_y = y * scaleHeight;
|
||||||
int y0 = static_cast<int>(input_y);
|
int y0 = static_cast<int>(input_y);
|
||||||
const float* inpData_row0 = inpPlanes.ptr<float>(y0);
|
const float* inpData_row0 = inpPlanes.ptr<float>(y0);
|
||||||
const float* inpData_row1 = inpPlanes.ptr<float>(std::min(y0 + 1, inpHeight - 1));
|
const float* inpData_row1 = inpPlanes.ptr<float>(std::min(y0 + 1, inpHeight - 1));
|
||||||
for (int x = 0; x < outWidth; ++x)
|
for (int x = 0; x < outWidth; ++x)
|
||||||
{
|
{
|
||||||
float input_x = x * widthScale;
|
float input_x = x * scaleWidth;
|
||||||
int x0 = static_cast<int>(input_x);
|
int x0 = static_cast<int>(input_x);
|
||||||
int x1 = std::min(x0 + 1, inpWidth - 1);
|
int x1 = std::min(x0 + 1, inpWidth - 1);
|
||||||
|
|
||||||
@ -162,10 +162,10 @@ public:
|
|||||||
return Ptr<BackendNode>();
|
return Ptr<BackendNode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
int outWidth, outHeight, zoomFactorWidth, zoomFactorHeight;
|
int outWidth, outHeight, zoomFactorWidth, zoomFactorHeight;
|
||||||
String interpolation;
|
String interpolation;
|
||||||
bool alignCorners;
|
float scaleWidth, scaleHeight;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -174,5 +174,44 @@ Ptr<ResizeLayer> ResizeLayer::create(const LayerParams& params)
|
|||||||
return Ptr<ResizeLayer>(new ResizeLayerImpl(params));
|
return Ptr<ResizeLayer>(new ResizeLayerImpl(params));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class InterpLayerImpl CV_FINAL : public ResizeLayerImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InterpLayerImpl(const LayerParams& params) : ResizeLayerImpl(params) {}
|
||||||
|
|
||||||
|
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() == 1, inputs[0].size() == 4);
|
||||||
|
outputs.resize(1, inputs[0]);
|
||||||
|
outputs[0][2] = outHeight > 0 ? outHeight : (1 + zoomFactorHeight * (outputs[0][2] - 1));
|
||||||
|
outputs[0][3] = outWidth > 0 ? outWidth : (1 + zoomFactorWidth * (outputs[0][3] - 1));
|
||||||
|
// We can work in-place (do nothing) if input shape == output shape.
|
||||||
|
return (outputs[0][2] == inputs[0][2]) && (outputs[0][3] == inputs[0][3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void finalize(const std::vector<Mat*>& inputs, std::vector<Mat> &outputs) CV_OVERRIDE
|
||||||
|
{
|
||||||
|
if (!outWidth && !outHeight)
|
||||||
|
{
|
||||||
|
outHeight = outputs[0].size[2];
|
||||||
|
outWidth = outputs[0].size[3];
|
||||||
|
}
|
||||||
|
int inpHeight = inputs[0]->size[2];
|
||||||
|
int inpWidth = inputs[0]->size[3];
|
||||||
|
scaleHeight = (outHeight > 1) ? (static_cast<float>(inpHeight - 1) / (outHeight - 1)) : 0.f;
|
||||||
|
scaleWidth = (outWidth > 1) ? (static_cast<float>(inpWidth - 1) / (outWidth - 1)) : 0.f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ptr<Layer> InterpLayer::create(const LayerParams& params)
|
||||||
|
{
|
||||||
|
LayerParams lp(params);
|
||||||
|
lp.set("interpolation", "bilinear");
|
||||||
|
return Ptr<Layer>(new InterpLayerImpl(lp));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dnn
|
} // namespace dnn
|
||||||
} // namespace cv
|
} // namespace cv
|
||||||
|
@ -1137,13 +1137,18 @@ private:
|
|||||||
int outWidth, outHeight, zoomFactor;
|
int outWidth, outHeight, zoomFactor;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST(Layer_Test_Interp, Accuracy)
|
TEST(Layer_Test_Interp_custom, Accuracy)
|
||||||
{
|
{
|
||||||
CV_DNN_REGISTER_LAYER_CLASS(Interp, InterpLayer);
|
CV_DNN_REGISTER_LAYER_CLASS(Interp, InterpLayer);
|
||||||
testLayerUsingCaffeModels("layer_interp", DNN_TARGET_CPU, false, false);
|
testLayerUsingCaffeModels("layer_interp", DNN_TARGET_CPU, false, false);
|
||||||
LayerFactory::unregisterLayer("Interp");
|
LayerFactory::unregisterLayer("Interp");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(Layer_Test_Interp, Accuracy)
|
||||||
|
{
|
||||||
|
testLayerUsingCaffeModels("layer_interp", DNN_TARGET_CPU, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(Layer_Test_PoolingIndices, Accuracy)
|
TEST(Layer_Test_PoolingIndices, Accuracy)
|
||||||
{
|
{
|
||||||
Net net;
|
Net net;
|
||||||
|
Loading…
Reference in New Issue
Block a user