@@ -88,6 +88,8 @@ static Mat getTensorContent(const tensorflow::TensorProto &tensor)
88
88
return Mat (1 , content.size () / sizeof (float ), CV_32FC1, (void *)content.c_str ()).clone ();
89
89
case tensorflow::DT_DOUBLE:
90
90
return Mat (1 , content.size () / sizeof (double ), CV_64FC1, (void *)content.c_str ()).clone ();
91
+ case tensorflow::DT_INT32:
92
+ return Mat (1 , content.size () / sizeof (int32_t ), CV_32SC1, (void *)content.c_str ()).clone ();
91
93
case tensorflow::DT_HALF:
92
94
{
93
95
Mat halfs;
@@ -563,16 +565,46 @@ void TFImporter::populateNet(Net dstNet)
563
565
564
566
for (int li = 0 ; li < layersSize; li++)
565
567
{
566
- const tensorflow::NodeDef & layer = net.node (li);
568
+ tensorflow::NodeDef layer = net.node (li);
567
569
String name = layer.name ();
568
570
String type = layer.op ();
569
571
LayerParams layerParams;
570
572
571
573
if (layers_to_ignore.find (li) != layers_to_ignore.end ())
572
574
continue ;
573
575
574
- if (type == " Conv2D" )
576
+ if (type == " Conv2D" || type == " SpaceToBatchND " )
575
577
{
578
+ // The first node of dilated convolution subgraph.
579
+ // Extract input node, dilation rate and paddings.
580
+ std::string input = layer.input (0 );
581
+ if (type == " SpaceToBatchND" )
582
+ {
583
+ // op: "SpaceToBatchND"
584
+ // input: "input"
585
+ // input: "SpaceToBatchND/block_shape"
586
+ // input: "SpaceToBatchND/paddings"
587
+ CV_Assert (layer.input_size () == 3 );
588
+
589
+ DictValue dilation = parseDims (getConstBlob (layer, value_id, 1 ));
590
+ CV_Assert (dilation.size () == 2 && dilation.get <int >(0 ) == dilation.get <int >(1 ));
591
+ layerParams.set (" dilation" , dilation.get <int >(0 ));
592
+
593
+ Mat paddings;
594
+ parseTensor<int >(getConstBlob (layer, value_id, 2 ), paddings);
595
+
596
+ // paddings is a 2x2 matrix: [[top, bot], [left, right]]
597
+ layerParams.set (" pad_h" , paddings.at <float >(0 ));
598
+ layerParams.set (" pad_w" , paddings.at <float >(2 ));
599
+
600
+ StrIntVector next_layers = getNextLayers (net, name, " Conv2D" );
601
+ CV_Assert (next_layers.size () == 1 );
602
+ layer = net.node (next_layers[0 ].second );
603
+ layers_to_ignore[next_layers[0 ].second ] = next_layers[0 ].first ;
604
+ name = layer.name ();
605
+ type = layer.op ();
606
+ }
607
+
576
608
layerParams.set (" bias_term" , false );
577
609
layerParams.blobs .resize (1 );
578
610
@@ -597,11 +629,21 @@ void TFImporter::populateNet(Net dstNet)
597
629
setStrides (layerParams, layer);
598
630
setPadding (layerParams, layer);
599
631
632
+ // The final node of dilated convolution subgraph.
633
+ next_layers = getNextLayers (net, name, " BatchToSpaceND" );
634
+ if (!next_layers.empty ())
635
+ {
636
+ layerParams.set (" pad_mode" , " " ); // We use padding values.
637
+ CV_Assert (next_layers.size () == 1 );
638
+ ExcludeLayer (net, next_layers[0 ].second , 0 , false );
639
+ layers_to_ignore[next_layers[0 ].second ] = next_layers[0 ].first ;
640
+ }
641
+
600
642
int id = dstNet.addLayer (name, " Convolution" , layerParams);
601
643
layer_id[name] = id;
602
644
603
645
// one input only
604
- connect (layer_id, dstNet, parsePin (layer. input ( 0 ) ), id, 0 );
646
+ connect (layer_id, dstNet, parsePin (input), id, 0 );
605
647
}
606
648
else if (type == " BiasAdd" || type == " Add" )
607
649
{
0 commit comments