Merge pull request #15203 from l-bat:determine_inp_shape

* Determine input shapes

* Add test

* Remove getInputShapes

* Fix model

* Fix constructors

* Add Caffe test

* Fix predict
This commit is contained in:
Lubov Batanina 2019-08-09 19:51:42 +03:00 committed by Alexander Alekhin
parent 358d69956a
commit f1ea9d86b9
5 changed files with 114 additions and 27 deletions

View File

@ -424,6 +424,36 @@ public:
}
dstNet.setInputsNames(netInputs);
std::vector<MatShape> inp_shapes;
if (net.input_shape_size() > 0 || (layersSize > 0 && net.layer(0).has_input_param() &&
net.layer(0).input_param().shape_size() > 0)) {
int size = (net.input_shape_size() > 0) ? net.input_shape_size() :
net.layer(0).input_param().shape_size();
for (int inp_id = 0; inp_id < size; inp_id++)
{
const caffe::BlobShape &_input_shape = (net.input_shape_size() > 0) ?
net.input_shape(inp_id) :
net.layer(0).input_param().shape(inp_id);
MatShape shape;
for (int i = 0; i < _input_shape.dim_size(); i++) {
shape.push_back((int)_input_shape.dim(i));
}
inp_shapes.push_back(shape);
}
}
else if (net.input_dim_size() > 0) {
MatShape shape;
for (int dim = 0; dim < net.input_dim_size(); dim++) {
shape.push_back(net.input_dim(dim));
}
inp_shapes.push_back(shape);
}
for (int inp_id = 0; inp_id < inp_shapes.size(); inp_id++) {
dstNet.setInput(Mat(inp_shapes[inp_id], CV_32F), netInputs[inp_id]);
}
addedBlobs.clear();
}

View File

@ -2455,6 +2455,18 @@ struct Net::Impl
{
std::vector<LayerPin>& inputLayerIds = layers[id].inputBlobsId;
if (inOutShapes[0].in[0].empty() && !layers[0].outputBlobs.empty())
{
ShapesVec shapes;
for (int i = 0; i < layers[0].outputBlobs.size(); i++)
{
Mat& inp = layers[0].outputBlobs[i];
CV_Assert(inp.total());
shapes.push_back(shape(inp));
}
inOutShapes[0].in = shapes;
}
if (inOutShapes[id].in.empty())
{
for(int i = 0; i < inputLayerIds.size(); i++)
@ -2595,14 +2607,23 @@ Net Net::readFromModelOptimizer(const String& xml, const String& bin)
InferenceEngine::CNNNetwork ieNet = reader.getNetwork();
std::vector<String> inputsNames;
std::vector<MatShape> inp_shapes;
for (auto& it : ieNet.getInputsInfo())
{
inputsNames.push_back(it.first);
std::vector<size_t> dims = it.second->getTensorDesc().getDims();
inp_shapes.push_back(std::vector<int>(dims.begin(), dims.end()));
}
Net cvNet;
cvNet.setInputsNames(inputsNames);
// set empty input to determine input shapes
for (int inp_id = 0; inp_id < inputsNames.size(); ++inp_id)
{
cvNet.setInput(Mat(inp_shapes[inp_id], CV_32F), inputsNames[inp_id]);
}
Ptr<InfEngineBackendNode> backendNode(new InfEngineBackendNode(InferenceEngine::Builder::Layer("")));
backendNode->net = Ptr<InfEngineBackendNet>(new InfEngineBackendNet(ieNet));
for (auto& it : ieNet.getOutputsInfo())

View File

@ -47,12 +47,22 @@ Model::Model(const String& model, const String& config)
: Net(readNet(model, config)), impl(new Impl)
{
impl->outNames = getUnconnectedOutLayersNames();
}
std::vector<MatShape> inLayerShapes;
std::vector<MatShape> outLayerShapes;
getLayerShapes(MatShape(), 0, inLayerShapes, outLayerShapes);
if (!inLayerShapes.empty() && inLayerShapes[0].size() == 4)
impl->size = Size(inLayerShapes[0][3], inLayerShapes[0][2]);
};
Model::Model(const Net& network) : Net(network), impl(new Impl)
{
impl->outNames = getUnconnectedOutLayersNames();
}
std::vector<MatShape> inLayerShapes;
std::vector<MatShape> outLayerShapes;
getLayerShapes(MatShape(), 0, inLayerShapes, outLayerShapes);
if (!inLayerShapes.empty() && inLayerShapes[0].size() == 4)
impl->size = Size(inLayerShapes[0][3], inLayerShapes[0][2]);
};
Model& Model::setInputSize(const Size& size)
{

View File

@ -479,18 +479,17 @@ TEST_P(Test_Caffe_nets, DenseNet_121)
applyTestTag(CV_TEST_TAG_MEMORY_512MB);
checkBackend();
const string proto = findDataFile("dnn/DenseNet_121.prototxt", false);
const string model = findDataFile("dnn/DenseNet_121.caffemodel", false);
const string weights = findDataFile("dnn/DenseNet_121.caffemodel", false);
Mat inp = imread(_tf("dog416.png"));
inp = blobFromImage(inp, 1.0 / 255, Size(224, 224), Scalar(), true, true);
Model model(proto, weights);
model.setInputScale(1.0 / 255).setInputSwapRB(true).setInputCrop(true);
std::vector<Mat> outs;
Mat ref = blobFromNPY(_tf("densenet_121_output.npy"));
Net net = readNetFromCaffe(proto, model);
net.setPreferableBackend(backend);
net.setPreferableTarget(target);
net.setInput(inp);
Mat out = net.forward();
model.setPreferableBackend(backend);
model.setPreferableTarget(target);
model.predict(inp, outs);
// Reference is an array of 1000 values from a range [-6.16, 7.9]
float l1 = default_l1, lInf = default_lInf;
@ -506,9 +505,9 @@ TEST_P(Test_Caffe_nets, DenseNet_121)
{
l1 = 0.11; lInf = 0.5;
}
normAssert(out, ref, "", l1, lInf);
normAssert(outs[0], ref, "", l1, lInf);
if (target != DNN_TARGET_MYRIAD || getInferenceEngineVPUType() != CV_DNN_INFERENCE_ENGINE_VPU_TYPE_MYRIAD_X)
expectNoFallbacksFromIE(net);
expectNoFallbacksFromIE(model);
}
TEST(Test_Caffe, multiple_inputs)

View File

@ -240,20 +240,6 @@ void runIE(Target target, const std::string& xmlPath, const std::string& binPath
infRequest.Infer();
}
std::vector<String> getOutputsNames(const Net& net)
{
std::vector<String> names;
if (names.empty())
{
std::vector<int> outLayers = net.getUnconnectedOutLayers();
std::vector<String> layersNames = net.getLayerNames();
names.resize(outLayers.size());
for (size_t i = 0; i < outLayers.size(); ++i)
names[i] = layersNames[outLayers[i] - 1];
}
return names;
}
void runCV(Target target, const std::string& xmlPath, const std::string& binPath,
const std::map<std::string, cv::Mat>& inputsMap,
std::map<std::string, cv::Mat>& outputsMap)
@ -263,7 +249,7 @@ void runCV(Target target, const std::string& xmlPath, const std::string& binPath
net.setInput(it.second, it.first);
net.setPreferableTarget(target);
std::vector<String> outNames = getOutputsNames(net);
std::vector<String> outNames = net.getUnconnectedOutLayersNames();
std::vector<Mat> outs;
net.forward(outs, outNames);
@ -319,5 +305,46 @@ INSTANTIATE_TEST_CASE_P(/**/,
)
);
typedef TestWithParam<Target> DNNTestHighLevelAPI;
TEST_P(DNNTestHighLevelAPI, predict)
{
initDLDTDataPath();
Target target = (dnn::Target)(int)GetParam();
bool isFP16 = (target == DNN_TARGET_OPENCL_FP16 || target == DNN_TARGET_MYRIAD);
OpenVINOModelTestCaseInfo modelInfo = getOpenVINOTestModels().find("age-gender-recognition-retail-0013")->second;
std::string modelPath = isFP16 ? modelInfo.modelPathFP16 : modelInfo.modelPathFP32;
std::string xmlPath = findDataFile(modelPath + ".xml");
std::string binPath = findDataFile(modelPath + ".bin");
Model model(xmlPath, binPath);
Mat frame = imread(findDataFile("dnn/googlenet_1.png"));
std::vector<Mat> outs;
model.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
model.setPreferableTarget(target);
model.predict(frame, outs);
Net net = readNet(xmlPath, binPath);
Mat input = blobFromImage(frame, 1.0, Size(62, 62));
net.setInput(input);
net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
net.setPreferableTarget(target);
std::vector<String> outNames = net.getUnconnectedOutLayersNames();
std::vector<Mat> refs;
net.forward(refs, outNames);
CV_Assert(refs.size() == outs.size());
for (int i = 0; i < refs.size(); ++i)
normAssert(outs[i], refs[i]);
}
INSTANTIATE_TEST_CASE_P(/**/,
DNNTestHighLevelAPI, testing::ValuesIn(getAvailableTargets(DNN_BACKEND_INFERENCE_ENGINE))
);
}}
#endif // HAVE_INF_ENGINE