Commit df38624e authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

Merge pull request #11812 from dkurt:dnn_interp_layer_impl

parents 70d6b877 e8e9d1d0
...@@ -592,6 +592,17 @@ CV__DNN_EXPERIMENTAL_NS_BEGIN ...@@ -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() ...@@ -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 @@ ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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) ...@@ -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: ...@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment