|
|
|
@ -737,11 +737,18 @@ void TFImporter::populateNet(Net dstNet) |
|
|
|
|
int predictedLayout = predictOutputDataLayout(net, layer, data_layouts); |
|
|
|
|
data_layouts[name] = predictedLayout; |
|
|
|
|
|
|
|
|
|
if (type == "Conv2D" || type == "SpaceToBatchND" || type == "DepthwiseConv2dNative") |
|
|
|
|
if (type == "Conv2D" || type == "SpaceToBatchND" || type == "DepthwiseConv2dNative" || type == "Pad") |
|
|
|
|
{ |
|
|
|
|
// The first node of dilated convolution subgraph.
|
|
|
|
|
// Extract input node, dilation rate and paddings.
|
|
|
|
|
std::string input = layer.input(0); |
|
|
|
|
StrIntVector next_layers; |
|
|
|
|
if (type == "SpaceToBatchND" || type == "Pad") |
|
|
|
|
{ |
|
|
|
|
next_layers = getNextLayers(net, name, "Conv2D"); |
|
|
|
|
if (next_layers.empty()) |
|
|
|
|
next_layers = getNextLayers(net, name, "DepthwiseConv2dNative"); |
|
|
|
|
} |
|
|
|
|
if (type == "SpaceToBatchND") |
|
|
|
|
{ |
|
|
|
|
// op: "SpaceToBatchND"
|
|
|
|
@ -762,17 +769,57 @@ void TFImporter::populateNet(Net dstNet) |
|
|
|
|
layerParams.set("pad_h", paddings.at<float>(0)); |
|
|
|
|
layerParams.set("pad_w", paddings.at<float>(2)); |
|
|
|
|
|
|
|
|
|
StrIntVector next_layers = getNextLayers(net, name, "Conv2D"); |
|
|
|
|
if (next_layers.empty()) |
|
|
|
|
{ |
|
|
|
|
next_layers = getNextLayers(net, name, "DepthwiseConv2dNative"); |
|
|
|
|
} |
|
|
|
|
CV_Assert(next_layers.size() == 1); |
|
|
|
|
layer = net.node(next_layers[0].second); |
|
|
|
|
layers_to_ignore.insert(next_layers[0].first); |
|
|
|
|
name = layer.name(); |
|
|
|
|
type = layer.op(); |
|
|
|
|
} |
|
|
|
|
else if (type == "Pad") |
|
|
|
|
{ |
|
|
|
|
Mat paddings = getTensorContent(getConstBlob(layer, value_id, 1)); |
|
|
|
|
CV_Assert(paddings.type() == CV_32SC1); |
|
|
|
|
if (paddings.total() == 8) |
|
|
|
|
{ |
|
|
|
|
// Perhabs, we have NHWC padding dimensions order.
|
|
|
|
|
// N H W C
|
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
|
std::swap(paddings.at<int32_t>(2), paddings.at<int32_t>(6)); |
|
|
|
|
std::swap(paddings.at<int32_t>(3), paddings.at<int32_t>(7)); |
|
|
|
|
// N C W H
|
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
|
std::swap(paddings.at<int32_t>(4), paddings.at<int32_t>(6)); |
|
|
|
|
std::swap(paddings.at<int32_t>(5), paddings.at<int32_t>(7)); |
|
|
|
|
// N C H W
|
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
|
} |
|
|
|
|
if (next_layers.empty() || paddings.total() != 8 || |
|
|
|
|
paddings.at<int32_t>(4) != paddings.at<int32_t>(5) || |
|
|
|
|
paddings.at<int32_t>(6) != paddings.at<int32_t>(7)) |
|
|
|
|
{ |
|
|
|
|
// Just a single padding layer.
|
|
|
|
|
layerParams.set("paddings", DictValue::arrayInt<int*>((int*)paddings.data, paddings.total())); |
|
|
|
|
|
|
|
|
|
int id = dstNet.addLayer(name, "Padding", layerParams); |
|
|
|
|
layer_id[name] = id; |
|
|
|
|
|
|
|
|
|
connect(layer_id, dstNet, parsePin(input), id, 0); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
// Merge with subsequent convolutional layer.
|
|
|
|
|
CV_Assert(next_layers.size() == 1); |
|
|
|
|
|
|
|
|
|
layerParams.set("pad_h", paddings.at<int32_t>(4)); |
|
|
|
|
layerParams.set("pad_w", paddings.at<int32_t>(6)); |
|
|
|
|
|
|
|
|
|
layer = net.node(next_layers[0].second); |
|
|
|
|
layers_to_ignore.insert(next_layers[0].first); |
|
|
|
|
name = layer.name(); |
|
|
|
|
type = layer.op(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// For the object detection networks, TensorFlow Object Detection API
|
|
|
|
|
// predicts deltas for bounding boxes in yxYX (ymin, xmin, ymax, xmax)
|
|
|
|
@ -784,7 +831,7 @@ void TFImporter::populateNet(Net dstNet) |
|
|
|
|
layerParams.set("bias_term", false); |
|
|
|
|
layerParams.blobs.resize(1); |
|
|
|
|
|
|
|
|
|
StrIntVector next_layers = getNextLayers(net, name, "BiasAdd"); |
|
|
|
|
next_layers = getNextLayers(net, name, "BiasAdd"); |
|
|
|
|
if (next_layers.size() == 1) { |
|
|
|
|
layerParams.set("bias_term", true); |
|
|
|
|
layerParams.blobs.resize(2); |
|
|
|
@ -1416,31 +1463,6 @@ void TFImporter::populateNet(Net dstNet) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else if (type == "Pad") |
|
|
|
|
{ |
|
|
|
|
Mat paddings = getTensorContent(getConstBlob(layer, value_id, 1)); |
|
|
|
|
CV_Assert(paddings.type() == CV_32SC1); |
|
|
|
|
if (paddings.total() == 8) |
|
|
|
|
{ |
|
|
|
|
// Perhabs, we have NHWC padding dimensions order.
|
|
|
|
|
// N H W C
|
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
|
std::swap(*paddings.ptr<int32_t>(0, 2), *paddings.ptr<int32_t>(0, 6)); |
|
|
|
|
std::swap(*paddings.ptr<int32_t>(0, 3), *paddings.ptr<int32_t>(0, 7)); |
|
|
|
|
// N C W H
|
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
|
std::swap(*paddings.ptr<int32_t>(0, 4), *paddings.ptr<int32_t>(0, 6)); |
|
|
|
|
std::swap(*paddings.ptr<int32_t>(0, 5), *paddings.ptr<int32_t>(0, 7)); |
|
|
|
|
// N C H W
|
|
|
|
|
// 0 1 2 3 4 5 6 7
|
|
|
|
|
} |
|
|
|
|
layerParams.set("paddings", DictValue::arrayInt<int*>((int*)paddings.data, paddings.total())); |
|
|
|
|
|
|
|
|
|
int id = dstNet.addLayer(name, "Padding", layerParams); |
|
|
|
|
layer_id[name] = id; |
|
|
|
|
|
|
|
|
|
connect(layer_id, dstNet, parsePin(layer.input(0)), id, 0); |
|
|
|
|
} |
|
|
|
|
else if (type == "FusedBatchNorm") |
|
|
|
|
{ |
|
|
|
|
// op: "FusedBatchNorm"
|
|
|
|
|