@@ -617,7 +617,7 @@ struct TorchImporter : public ::cv::dnn::Importer
617
617
curModule->modules .push_back (cv::Ptr<Module>(new Module (nnName, " Sigmoid" )));
618
618
readObject ();
619
619
}
620
- else if (nnName == " SpatialBatchNormalization" )
620
+ else if (nnName == " SpatialBatchNormalization" || nnName == " InstanceNormalization " )
621
621
{
622
622
newModule->apiType = " BatchNorm" ;
623
623
readTorchTable (scalarParams, tensorParams);
@@ -626,19 +626,31 @@ struct TorchImporter : public ::cv::dnn::Importer
626
626
float eps = float (scalarParams.get <double >(" eps" ));
627
627
layerParams.set (" eps" , eps);
628
628
629
- CV_Assert ((tensorParams.count (" running_var" ) || tensorParams.count (" running_std" )) &&
630
- tensorParams.count (" running_mean" ));
631
- layerParams.blobs .push_back (tensorParams[" running_mean" ].second );
629
+ if (tensorParams.count (" running_mean" ))
630
+ {
631
+ layerParams.blobs .push_back (tensorParams[" running_mean" ].second );
632
+ }
633
+ else
634
+ {
635
+ CV_Assert (scalarParams.has (" nOutput" ));
636
+ layerParams.blobs .push_back (Mat::zeros (1 , scalarParams.get <int >(" nOutput" ), CV_32F));
637
+ }
638
+
632
639
if (tensorParams.count (" running_var" ))
633
640
{
634
641
layerParams.blobs .push_back (tensorParams[" running_var" ].second );
635
642
}
636
- else
643
+ else if (tensorParams. count ( " running_std " ))
637
644
{
638
645
layerParams.blobs .push_back (tensorParams[" running_std" ].second );
639
646
pow (layerParams.blobs .back (), -2 , layerParams.blobs .back ());
640
647
subtract (layerParams.blobs .back (), eps, layerParams.blobs .back ());
641
648
}
649
+ else
650
+ {
651
+ CV_Assert (scalarParams.has (" nOutput" ));
652
+ layerParams.blobs .push_back (Mat::ones (1 , scalarParams.get <int >(" nOutput" ), CV_32F));
653
+ }
642
654
643
655
if (tensorParams.count (" weight" ))
644
656
{
@@ -652,6 +664,16 @@ struct TorchImporter : public ::cv::dnn::Importer
652
664
layerParams.blobs .push_back (tensorParams[" bias" ].second );
653
665
}
654
666
667
+ if (nnName == " InstanceNormalization" )
668
+ {
669
+ cv::Ptr<Module> mvnModule (new Module (nnName));
670
+ mvnModule->apiType = " MVN" ;
671
+ curModule->modules .push_back (mvnModule);
672
+
673
+ layerParams.blobs [0 ].setTo (0 ); // batch norm's mean
674
+ layerParams.blobs [1 ].setTo (1 ); // batch norm's std
675
+ }
676
+
655
677
curModule->modules .push_back (newModule);
656
678
}
657
679
else if (nnName == " PReLU" )
@@ -691,7 +713,9 @@ struct TorchImporter : public ::cv::dnn::Importer
691
713
layerParams.set (" scale" , scale);
692
714
curModule->modules .push_back (newModule);
693
715
}
694
- else if (nnName == " Identity" )
716
+ // TotalVariation layer is from fast-neural-style project: https://github.com/jcjohnson/fast-neural-style
717
+ // It's a loss function that has an Identity forward.
718
+ else if (nnName == " Identity" || nnName == " TotalVariation" )
695
719
{
696
720
readTorchTable (scalarParams, tensorParams);
697
721
newModule->apiType = " Identity" ;
@@ -866,7 +890,7 @@ struct TorchImporter : public ::cv::dnn::Importer
866
890
layerParams.set (" scale" , scalarParams.get <float >(" constant_scalar" ));
867
891
curModule->modules .push_back (newModule);
868
892
}
869
- else if (nnName == " SpatialZeroPadding" )
893
+ else if (nnName == " SpatialZeroPadding" || nnName == " SpatialReflectionPadding " )
870
894
{
871
895
readTorchTable (scalarParams, tensorParams);
872
896
CV_Assert (scalarParams.has (" pad_l" ), scalarParams.has (" pad_r" ),
@@ -889,6 +913,26 @@ struct TorchImporter : public ::cv::dnn::Importer
889
913
paddings[5 ] = padRight;
890
914
layerParams.set (" paddings" , DictValue::arrayInt<int *>(&paddings[0 ], paddings.size ()));
891
915
layerParams.set (" input_dims" , 3 );
916
+
917
+ if (nnName == " SpatialReflectionPadding" )
918
+ layerParams.set (" type" , " reflect" );
919
+
920
+ curModule->modules .push_back (newModule);
921
+ }
922
+ else if (nnName == " ShaveImage" )
923
+ {
924
+ // ShaveImage layer is from fast-neural-style project: https://github.com/jcjohnson/fast-neural-style
925
+ // It may be mapped to Slice layer.
926
+ readTorchTable (scalarParams, tensorParams);
927
+ CV_Assert (scalarParams.has (" size" ));
928
+ int size = scalarParams.get <int >(" size" );
929
+
930
+ int begins[] = {0 , 0 , size, size};
931
+ int ends[] = {-1 , -1 , -size - 1 , -size - 1 };
932
+
933
+ newModule->apiType = " Slice" ;
934
+ layerParams.set (" begin" , DictValue::arrayInt<int *>(&begins[0 ], 4 ));
935
+ layerParams.set (" end" , DictValue::arrayInt<int *>(&ends[0 ], 4 ));
892
936
curModule->modules .push_back (newModule);
893
937
}
894
938
else
0 commit comments