From d94d9df8997631d305cd529c545909037487ed7a Mon Sep 17 00:00:00 2001 From: Mingbo Wan Date: Fri, 8 Nov 2019 12:14:38 -0800 Subject: [PATCH 001/357] Set up ShipIt fbshipit-source-id: 6d1fe41157de2f8c6825ec3c9eaafe31e1bec272 From b966741908d6ffc84c6bee5c0e928409ed64397b Mon Sep 17 00:00:00 2001 From: Will Feng Date: Sat, 16 Nov 2019 10:45:08 -0800 Subject: [PATCH 002/357] Remove input_channels / output_channels / with_bias from ConvOptions (#29838) Summary: Since torchvision is not using input_channels / output_channels / with_bias in ConvOptions anymore (https://github.com/pytorch/vision/pull/1576), we can remove the bridges now. Pull Request resolved: https://github.com/pytorch/pytorch/pull/29838 Differential Revision: D18531481 Pulled By: yf225 fbshipit-source-id: e48d9e8cf110095f83d9ed18b9fec020ec725f3e --- torchvision/csrc/models/densenet.cpp | 8 ++++---- torchvision/csrc/models/googlenet.cpp | 4 ++-- torchvision/csrc/models/inception.cpp | 4 ++-- torchvision/csrc/models/mnasnet.cpp | 14 +++++++------- torchvision/csrc/models/mobilenet.cpp | 6 +++--- torchvision/csrc/models/resnet.cpp | 4 ++-- torchvision/csrc/models/resnet.h | 2 +- torchvision/csrc/models/shufflenetv2.cpp | 8 ++++---- torchvision/csrc/models/squeezenet.cpp | 2 +- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index c523d08bfcb..97d78caa009 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -21,7 +21,7 @@ struct _DenseLayerImpl : torch::nn::SequentialImpl { "conv1", torch::nn::Conv2d(Options(num_input_features, bn_size * growth_rate, 1) .stride(1) - .with_bias(false))); + .bias(false))); push_back("norm2", torch::nn::BatchNorm(bn_size * growth_rate)); push_back("relu2", torch::nn::Functional(modelsimpl::relu_)); push_back( @@ -29,7 +29,7 @@ struct _DenseLayerImpl : torch::nn::SequentialImpl { torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) .stride(1) .padding(1) - .with_bias(false))); + .bias(false))); } torch::Tensor forward(torch::Tensor x) { @@ -75,7 +75,7 @@ struct _TransitionImpl : torch::nn::SequentialImpl { "conv", torch::nn::Conv2d(Options(num_input_features, num_output_features, 1) .stride(1) - .with_bias(false))); + .bias(false))); push_back("pool", torch::nn::Functional([](torch::Tensor input) { return torch::avg_pool2d(input, 2, 2, 0, false, true); })); @@ -102,7 +102,7 @@ DenseNetImpl::DenseNetImpl( torch::nn::Conv2d(Options(3, num_init_features, 7) .stride(2) .padding(3) - .with_bias(false))); + .bias(false))); features->push_back("norm0", torch::nn::BatchNorm(num_init_features)); features->push_back("relu0", torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/googlenet.cpp b/torchvision/csrc/models/googlenet.cpp index c053b65b4d6..15a4fd6ee2f 100644 --- a/torchvision/csrc/models/googlenet.cpp +++ b/torchvision/csrc/models/googlenet.cpp @@ -9,10 +9,10 @@ using Options = torch::nn::Conv2dOptions; namespace _googlenetimpl { BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions options) { - options.with_bias(false); + options.bias(false); conv = torch::nn::Conv2d(options); bn = torch::nn::BatchNorm( - torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); + torch::nn::BatchNormOptions(options.out_channels()).eps(0.001)); register_module("conv", conv); register_module("bn", bn); diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index ebb35089d33..1c5b7bbe1f7 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -9,10 +9,10 @@ namespace _inceptionimpl { BasicConv2dImpl::BasicConv2dImpl( torch::nn::Conv2dOptions options, double std_dev) { - options.with_bias(false); + options.bias(false); conv = torch::nn::Conv2d(options); bn = torch::nn::BatchNorm( - torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); + torch::nn::BatchNormOptions(options.out_channels()).eps(0.001)); register_module("conv", conv); register_module("bn", bn); diff --git a/torchvision/csrc/models/mnasnet.cpp b/torchvision/csrc/models/mnasnet.cpp index 75b63c9f5c5..96836d92d35 100644 --- a/torchvision/csrc/models/mnasnet.cpp +++ b/torchvision/csrc/models/mnasnet.cpp @@ -24,7 +24,7 @@ struct MNASNetInvertedResidualImpl : torch::nn::Module { apply_residual = input == output && stride == 1; layers->push_back( - torch::nn::Conv2d(Options(input, mid, 1).with_bias(false))); + torch::nn::Conv2d(Options(input, mid, 1).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(mid).momentum(bn_momentum))); layers->push_back( @@ -34,13 +34,13 @@ struct MNASNetInvertedResidualImpl : torch::nn::Module { .padding(kernel / 2) .stride(stride) .groups(mid) - .with_bias(false)))); + .bias(false)))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(mid).momentum(bn_momentum))); layers->push_back( torch::nn::Functional(torch::nn::Functional(modelsimpl::relu_))); layers->push_back( - torch::nn::Conv2d(Options(mid, output, 1).with_bias(false))); + torch::nn::Conv2d(Options(mid, output, 1).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(output).momentum(bn_momentum))); @@ -129,17 +129,17 @@ MNASNetImpl::MNASNetImpl(double alpha, int64_t num_classes, double dropout) { auto depths = scale_depths({24, 40, 80, 96, 192, 320}, alpha); layers->push_back(torch::nn::Conv2d( - Options(3, 32, 3).padding(1).stride(2).with_bias(false))); + Options(3, 32, 3).padding(1).stride(2).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(32).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); layers->push_back(torch::nn::Conv2d( - Options(32, 32, 3).padding(1).stride(1).groups(32).with_bias(false))); + Options(32, 32, 3).padding(1).stride(1).groups(32).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(32).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); layers->push_back(torch::nn::Conv2d( - Options(32, 16, 1).padding(0).stride(1).with_bias(false))); + Options(32, 16, 1).padding(0).stride(1).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(16).momentum(BN_MOMENTUM))); @@ -151,7 +151,7 @@ MNASNetImpl::MNASNetImpl(double alpha, int64_t num_classes, double dropout) { layers->push_back(stack(depths[4], depths[5], 3, 1, 6, 1, BN_MOMENTUM)); layers->push_back(torch::nn::Conv2d( - Options(depths[5], 1280, 1).padding(0).stride(1).with_bias(false))); + Options(depths[5], 1280, 1).padding(0).stride(1).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(1280).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/mobilenet.cpp b/torchvision/csrc/models/mobilenet.cpp index 2b49c844977..ad5aaf3c997 100644 --- a/torchvision/csrc/models/mobilenet.cpp +++ b/torchvision/csrc/models/mobilenet.cpp @@ -32,7 +32,7 @@ struct ConvBNReLUImpl : torch::nn::SequentialImpl { .stride(stride) .padding(padding) .groups(groups) - .with_bias(false))); + .bias(false))); push_back(torch::nn::BatchNorm(out_planes)); push_back(torch::nn::Functional(modelsimpl::relu6_)); } @@ -67,7 +67,7 @@ struct MobileNetInvertedResidualImpl : torch::nn::Module { conv->push_back(ConvBNReLU(hidden_dim, hidden_dim, 3, stride, hidden_dim)); conv->push_back(torch::nn::Conv2d( - Options(hidden_dim, output, 1).stride(1).padding(0).with_bias(false))); + Options(hidden_dim, output, 1).stride(1).padding(0).bias(false))); conv->push_back(torch::nn::BatchNorm(output)); register_module("conv", conv); @@ -136,7 +136,7 @@ MobileNetV2Impl::MobileNetV2Impl( if (auto M = dynamic_cast(module.get())) { torch::nn::init::kaiming_normal_( M->weight, 0, torch::nn::init::FanMode::FanOut); - if (M->options.with_bias()) + if (M->options.bias()) torch::nn::init::zeros_(M->bias); } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::ones_(M->weight); diff --git a/torchvision/csrc/models/resnet.cpp b/torchvision/csrc/models/resnet.cpp index 4dcd64dcea8..2be172ca03e 100644 --- a/torchvision/csrc/models/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -11,13 +11,13 @@ torch::nn::Conv2d conv3x3( int64_t stride, int64_t groups) { torch::nn::Conv2dOptions O(in, out, 3); - O.padding(1).stride(stride).groups(groups).with_bias(false); + O.padding(1).stride(stride).groups(groups).bias(false); return torch::nn::Conv2d(O); } torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride) { torch::nn::Conv2dOptions O(in, out, 1); - O.stride(stride).with_bias(false); + O.stride(stride).bias(false); return torch::nn::Conv2d(O); } diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index ae9f4613ebe..9c5f0a19fc5 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -124,7 +124,7 @@ ResNetImpl::ResNetImpl( : groups(groups), base_width(width_per_group), inplanes(64), - conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( + conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).bias( false)), bn1(64), layer1(_make_layer(64, layers[0])), diff --git a/torchvision/csrc/models/shufflenetv2.cpp b/torchvision/csrc/models/shufflenetv2.cpp index 2cf278e8d72..658842dd566 100644 --- a/torchvision/csrc/models/shufflenetv2.cpp +++ b/torchvision/csrc/models/shufflenetv2.cpp @@ -25,13 +25,13 @@ torch::Tensor channel_shuffle(torch::Tensor x, int64_t groups) { torch::nn::Conv2d conv11(int64_t input, int64_t output) { Options opts(input, output, 1); - opts = opts.stride(1).padding(0).with_bias(false); + opts = opts.stride(1).padding(0).bias(false); return torch::nn::Conv2d(opts); } torch::nn::Conv2d conv33(int64_t input, int64_t output, int64_t stride) { Options opts(input, output, 3); - opts = opts.stride(stride).padding(1).with_bias(false).groups(input); + opts = opts.stride(stride).padding(1).bias(false).groups(input); return torch::nn::Conv2d(opts); } @@ -107,7 +107,7 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( torch::nn::Conv2d(Options(input_channels, output_channels, 3) .stride(2) .padding(1) - .with_bias(false)), + .bias(false)), torch::nn::BatchNorm(output_channels), torch::nn::Functional(modelsimpl::relu_)); @@ -134,7 +134,7 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( torch::nn::Conv2d(Options(input_channels, output_channels, 1) .stride(1) .padding(0) - .with_bias(false)), + .bias(false)), torch::nn::BatchNorm(output_channels), torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index 16bcb6495bd..cfb26ea58eb 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -91,7 +91,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) else torch::nn::init::kaiming_uniform_(M->weight); - if (M->options.with_bias()) + if (M->options.bias()) torch::nn::init::constant_(M->bias, 0); } } From 0f41ec2470015db8be9b5fce00e328bfcb349d7e Mon Sep 17 00:00:00 2001 From: Will Feng Date: Mon, 18 Nov 2019 09:08:55 -0800 Subject: [PATCH 003/357] Revert D18531481: Remove input_channels / output_channels / with_bias from ConvOptions Differential Revision: D18531481 Original commit changeset: e48d9e8cf110 fbshipit-source-id: a233425cc10278552674c48b6b577ef53fca0632 --- torchvision/csrc/models/densenet.cpp | 8 ++++---- torchvision/csrc/models/googlenet.cpp | 4 ++-- torchvision/csrc/models/inception.cpp | 4 ++-- torchvision/csrc/models/mnasnet.cpp | 14 +++++++------- torchvision/csrc/models/mobilenet.cpp | 6 +++--- torchvision/csrc/models/resnet.cpp | 4 ++-- torchvision/csrc/models/resnet.h | 2 +- torchvision/csrc/models/shufflenetv2.cpp | 8 ++++---- torchvision/csrc/models/squeezenet.cpp | 2 +- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index 97d78caa009..c523d08bfcb 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -21,7 +21,7 @@ struct _DenseLayerImpl : torch::nn::SequentialImpl { "conv1", torch::nn::Conv2d(Options(num_input_features, bn_size * growth_rate, 1) .stride(1) - .bias(false))); + .with_bias(false))); push_back("norm2", torch::nn::BatchNorm(bn_size * growth_rate)); push_back("relu2", torch::nn::Functional(modelsimpl::relu_)); push_back( @@ -29,7 +29,7 @@ struct _DenseLayerImpl : torch::nn::SequentialImpl { torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) .stride(1) .padding(1) - .bias(false))); + .with_bias(false))); } torch::Tensor forward(torch::Tensor x) { @@ -75,7 +75,7 @@ struct _TransitionImpl : torch::nn::SequentialImpl { "conv", torch::nn::Conv2d(Options(num_input_features, num_output_features, 1) .stride(1) - .bias(false))); + .with_bias(false))); push_back("pool", torch::nn::Functional([](torch::Tensor input) { return torch::avg_pool2d(input, 2, 2, 0, false, true); })); @@ -102,7 +102,7 @@ DenseNetImpl::DenseNetImpl( torch::nn::Conv2d(Options(3, num_init_features, 7) .stride(2) .padding(3) - .bias(false))); + .with_bias(false))); features->push_back("norm0", torch::nn::BatchNorm(num_init_features)); features->push_back("relu0", torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/googlenet.cpp b/torchvision/csrc/models/googlenet.cpp index 15a4fd6ee2f..c053b65b4d6 100644 --- a/torchvision/csrc/models/googlenet.cpp +++ b/torchvision/csrc/models/googlenet.cpp @@ -9,10 +9,10 @@ using Options = torch::nn::Conv2dOptions; namespace _googlenetimpl { BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions options) { - options.bias(false); + options.with_bias(false); conv = torch::nn::Conv2d(options); bn = torch::nn::BatchNorm( - torch::nn::BatchNormOptions(options.out_channels()).eps(0.001)); + torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); register_module("conv", conv); register_module("bn", bn); diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index 1c5b7bbe1f7..ebb35089d33 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -9,10 +9,10 @@ namespace _inceptionimpl { BasicConv2dImpl::BasicConv2dImpl( torch::nn::Conv2dOptions options, double std_dev) { - options.bias(false); + options.with_bias(false); conv = torch::nn::Conv2d(options); bn = torch::nn::BatchNorm( - torch::nn::BatchNormOptions(options.out_channels()).eps(0.001)); + torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); register_module("conv", conv); register_module("bn", bn); diff --git a/torchvision/csrc/models/mnasnet.cpp b/torchvision/csrc/models/mnasnet.cpp index 96836d92d35..75b63c9f5c5 100644 --- a/torchvision/csrc/models/mnasnet.cpp +++ b/torchvision/csrc/models/mnasnet.cpp @@ -24,7 +24,7 @@ struct MNASNetInvertedResidualImpl : torch::nn::Module { apply_residual = input == output && stride == 1; layers->push_back( - torch::nn::Conv2d(Options(input, mid, 1).bias(false))); + torch::nn::Conv2d(Options(input, mid, 1).with_bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(mid).momentum(bn_momentum))); layers->push_back( @@ -34,13 +34,13 @@ struct MNASNetInvertedResidualImpl : torch::nn::Module { .padding(kernel / 2) .stride(stride) .groups(mid) - .bias(false)))); + .with_bias(false)))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(mid).momentum(bn_momentum))); layers->push_back( torch::nn::Functional(torch::nn::Functional(modelsimpl::relu_))); layers->push_back( - torch::nn::Conv2d(Options(mid, output, 1).bias(false))); + torch::nn::Conv2d(Options(mid, output, 1).with_bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(output).momentum(bn_momentum))); @@ -129,17 +129,17 @@ MNASNetImpl::MNASNetImpl(double alpha, int64_t num_classes, double dropout) { auto depths = scale_depths({24, 40, 80, 96, 192, 320}, alpha); layers->push_back(torch::nn::Conv2d( - Options(3, 32, 3).padding(1).stride(2).bias(false))); + Options(3, 32, 3).padding(1).stride(2).with_bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(32).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); layers->push_back(torch::nn::Conv2d( - Options(32, 32, 3).padding(1).stride(1).groups(32).bias(false))); + Options(32, 32, 3).padding(1).stride(1).groups(32).with_bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(32).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); layers->push_back(torch::nn::Conv2d( - Options(32, 16, 1).padding(0).stride(1).bias(false))); + Options(32, 16, 1).padding(0).stride(1).with_bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(16).momentum(BN_MOMENTUM))); @@ -151,7 +151,7 @@ MNASNetImpl::MNASNetImpl(double alpha, int64_t num_classes, double dropout) { layers->push_back(stack(depths[4], depths[5], 3, 1, 6, 1, BN_MOMENTUM)); layers->push_back(torch::nn::Conv2d( - Options(depths[5], 1280, 1).padding(0).stride(1).bias(false))); + Options(depths[5], 1280, 1).padding(0).stride(1).with_bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(1280).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/mobilenet.cpp b/torchvision/csrc/models/mobilenet.cpp index ad5aaf3c997..2b49c844977 100644 --- a/torchvision/csrc/models/mobilenet.cpp +++ b/torchvision/csrc/models/mobilenet.cpp @@ -32,7 +32,7 @@ struct ConvBNReLUImpl : torch::nn::SequentialImpl { .stride(stride) .padding(padding) .groups(groups) - .bias(false))); + .with_bias(false))); push_back(torch::nn::BatchNorm(out_planes)); push_back(torch::nn::Functional(modelsimpl::relu6_)); } @@ -67,7 +67,7 @@ struct MobileNetInvertedResidualImpl : torch::nn::Module { conv->push_back(ConvBNReLU(hidden_dim, hidden_dim, 3, stride, hidden_dim)); conv->push_back(torch::nn::Conv2d( - Options(hidden_dim, output, 1).stride(1).padding(0).bias(false))); + Options(hidden_dim, output, 1).stride(1).padding(0).with_bias(false))); conv->push_back(torch::nn::BatchNorm(output)); register_module("conv", conv); @@ -136,7 +136,7 @@ MobileNetV2Impl::MobileNetV2Impl( if (auto M = dynamic_cast(module.get())) { torch::nn::init::kaiming_normal_( M->weight, 0, torch::nn::init::FanMode::FanOut); - if (M->options.bias()) + if (M->options.with_bias()) torch::nn::init::zeros_(M->bias); } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::ones_(M->weight); diff --git a/torchvision/csrc/models/resnet.cpp b/torchvision/csrc/models/resnet.cpp index 2be172ca03e..4dcd64dcea8 100644 --- a/torchvision/csrc/models/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -11,13 +11,13 @@ torch::nn::Conv2d conv3x3( int64_t stride, int64_t groups) { torch::nn::Conv2dOptions O(in, out, 3); - O.padding(1).stride(stride).groups(groups).bias(false); + O.padding(1).stride(stride).groups(groups).with_bias(false); return torch::nn::Conv2d(O); } torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride) { torch::nn::Conv2dOptions O(in, out, 1); - O.stride(stride).bias(false); + O.stride(stride).with_bias(false); return torch::nn::Conv2d(O); } diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 9c5f0a19fc5..ae9f4613ebe 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -124,7 +124,7 @@ ResNetImpl::ResNetImpl( : groups(groups), base_width(width_per_group), inplanes(64), - conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).bias( + conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( false)), bn1(64), layer1(_make_layer(64, layers[0])), diff --git a/torchvision/csrc/models/shufflenetv2.cpp b/torchvision/csrc/models/shufflenetv2.cpp index 658842dd566..2cf278e8d72 100644 --- a/torchvision/csrc/models/shufflenetv2.cpp +++ b/torchvision/csrc/models/shufflenetv2.cpp @@ -25,13 +25,13 @@ torch::Tensor channel_shuffle(torch::Tensor x, int64_t groups) { torch::nn::Conv2d conv11(int64_t input, int64_t output) { Options opts(input, output, 1); - opts = opts.stride(1).padding(0).bias(false); + opts = opts.stride(1).padding(0).with_bias(false); return torch::nn::Conv2d(opts); } torch::nn::Conv2d conv33(int64_t input, int64_t output, int64_t stride) { Options opts(input, output, 3); - opts = opts.stride(stride).padding(1).bias(false).groups(input); + opts = opts.stride(stride).padding(1).with_bias(false).groups(input); return torch::nn::Conv2d(opts); } @@ -107,7 +107,7 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( torch::nn::Conv2d(Options(input_channels, output_channels, 3) .stride(2) .padding(1) - .bias(false)), + .with_bias(false)), torch::nn::BatchNorm(output_channels), torch::nn::Functional(modelsimpl::relu_)); @@ -134,7 +134,7 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( torch::nn::Conv2d(Options(input_channels, output_channels, 1) .stride(1) .padding(0) - .bias(false)), + .with_bias(false)), torch::nn::BatchNorm(output_channels), torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index cfb26ea58eb..16bcb6495bd 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -91,7 +91,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) else torch::nn::init::kaiming_uniform_(M->weight); - if (M->options.bias()) + if (M->options.with_bias()) torch::nn::init::constant_(M->bias, 0); } } From 004b0a1bc49c9a9a2fb93c69d827f99dea8fcd48 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 19 Nov 2019 11:01:19 -0800 Subject: [PATCH 004/357] Importing batch of PRs to fbsync and testing shipit Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1594 Reviewed By: yf225 Differential Revision: D18577030 Pulled By: fmassa fbshipit-source-id: c5e856984ee6eb8d1c6a47528879a76477d4ec22 --- .circleci/config.yml | 80 +++++++++---------- .circleci/config.yml.in | 8 +- .circleci/regenerate.py | 4 +- test/test_onnx.py | 4 + torchvision/csrc/models/densenet.cpp | 12 ++- torchvision/csrc/models/googlenet.cpp | 4 +- torchvision/csrc/models/inception.cpp | 4 +- torchvision/csrc/models/mnasnet.cpp | 20 +++-- torchvision/csrc/models/mobilenet.cpp | 6 +- torchvision/csrc/models/resnet.cpp | 4 +- torchvision/csrc/models/resnet.h | 4 +- torchvision/csrc/models/shufflenetv2.cpp | 8 +- torchvision/csrc/models/squeezenet.cpp | 2 +- torchvision/datasets/folder.py | 2 +- torchvision/datasets/samplers/clip_sampler.py | 10 +-- torchvision/models/_utils.py | 27 +------ torchvision/models/densenet.py | 26 +----- torchvision/models/segmentation/deeplabv3.py | 3 +- 18 files changed, 94 insertions(+), 134 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7e754846023..5bdb0e69e72 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -56,7 +56,7 @@ binary_common: &binary_common wheel_docker_image: description: "Wheel only: what docker image to use" type: string - default: "soumith/manylinux-cuda101" + default: "pytorch/manylinux-cuda101" environment: PYTHON_VERSION: << parameters.python_version >> BUILD_VERSION: << parameters.build_version >> @@ -94,7 +94,7 @@ jobs: binary_linux_conda: <<: *binary_common docker: - - image: "soumith/conda-cuda" + - image: "pytorch/conda-cuda" resource_class: 2xlarge+ steps: - checkout_merge @@ -159,7 +159,7 @@ jobs: name: Pull docker image command: | set -e - export DOCKER_IMAGE=soumith/conda-cuda + export DOCKER_IMAGE=pytorch/conda-cuda echo Pulling docker image $DOCKER_IMAGE docker pull $DOCKER_IMAGE >/dev/null @@ -170,7 +170,7 @@ jobs: cd ${HOME}/project/ - export DOCKER_IMAGE=soumith/conda-cuda + export DOCKER_IMAGE=pytorch/conda-cuda export VARS_TO_PASS="-e PYTHON_VERSION -e BUILD_VERSION -e PYTORCH_VERSION -e UNICODE_ABI -e CU_VERSION" docker run --gpus all --ipc=host -v $(pwd):/remote -w /remote ${VARS_TO_PASS} ${DOCKER_IMAGE} ./packaging/build_conda.sh @@ -308,24 +308,24 @@ workflows: cu_version: cu92 name: binary_linux_wheel_py2.7_cu92 python_version: '2.7' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_linux_wheel: cu_version: cu92 name: binary_linux_wheel_py2.7u_cu92 python_version: '2.7' unicode_abi: '1' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_linux_wheel: cu_version: cu100 name: binary_linux_wheel_py2.7_cu100 python_version: '2.7' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_wheel: cu_version: cu100 name: binary_linux_wheel_py2.7u_cu100 python_version: '2.7' unicode_abi: '1' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_wheel: cu_version: cu101 name: binary_linux_wheel_py2.7_cu101 @@ -343,12 +343,12 @@ workflows: cu_version: cu92 name: binary_linux_wheel_py3.5_cu92 python_version: '3.5' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_linux_wheel: cu_version: cu100 name: binary_linux_wheel_py3.5_cu100 python_version: '3.5' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_wheel: cu_version: cu101 name: binary_linux_wheel_py3.5_cu101 @@ -361,12 +361,12 @@ workflows: cu_version: cu92 name: binary_linux_wheel_py3.6_cu92 python_version: '3.6' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_linux_wheel: cu_version: cu100 name: binary_linux_wheel_py3.6_cu100 python_version: '3.6' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_wheel: cu_version: cu101 name: binary_linux_wheel_py3.6_cu101 @@ -379,12 +379,12 @@ workflows: cu_version: cu92 name: binary_linux_wheel_py3.7_cu92 python_version: '3.7' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_linux_wheel: cu_version: cu100 name: binary_linux_wheel_py3.7_cu100 python_version: '3.7' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_wheel: cu_version: cu101 name: binary_linux_wheel_py3.7_cu101 @@ -418,12 +418,12 @@ workflows: cu_version: cu92 name: binary_linux_conda_py2.7_cu92 python_version: '2.7' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_linux_conda: cu_version: cu100 name: binary_linux_conda_py2.7_cu100 python_version: '2.7' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_conda: cu_version: cu101 name: binary_linux_conda_py2.7_cu101 @@ -436,12 +436,12 @@ workflows: cu_version: cu92 name: binary_linux_conda_py3.5_cu92 python_version: '3.5' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_linux_conda: cu_version: cu100 name: binary_linux_conda_py3.5_cu100 python_version: '3.5' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_conda: cu_version: cu101 name: binary_linux_conda_py3.5_cu101 @@ -454,12 +454,12 @@ workflows: cu_version: cu92 name: binary_linux_conda_py3.6_cu92 python_version: '3.6' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_linux_conda: cu_version: cu100 name: binary_linux_conda_py3.6_cu100 python_version: '3.6' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_conda: cu_version: cu101 name: binary_linux_conda_py3.6_cu101 @@ -472,12 +472,12 @@ workflows: cu_version: cu92 name: binary_linux_conda_py3.7_cu92 python_version: '3.7' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_linux_conda: cu_version: cu100 name: binary_linux_conda_py3.7_cu100 python_version: '3.7' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_conda: cu_version: cu101 name: binary_linux_conda_py3.7_cu101 @@ -554,7 +554,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py2.7_cu92 python_version: '2.7' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_wheel_upload: context: org-member filters: @@ -572,7 +572,7 @@ workflows: name: nightly_binary_linux_wheel_py2.7u_cu92 python_version: '2.7' unicode_abi: '1' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_wheel_upload: context: org-member filters: @@ -589,7 +589,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py2.7_cu100 python_version: '2.7' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_wheel_upload: context: org-member filters: @@ -607,7 +607,7 @@ workflows: name: nightly_binary_linux_wheel_py2.7u_cu100 python_version: '2.7' unicode_abi: '1' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_wheel_upload: context: org-member filters: @@ -673,7 +673,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py3.5_cu92 python_version: '3.5' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_wheel_upload: context: org-member filters: @@ -690,7 +690,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py3.5_cu100 python_version: '3.5' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_wheel_upload: context: org-member filters: @@ -739,7 +739,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py3.6_cu92 python_version: '3.6' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_wheel_upload: context: org-member filters: @@ -756,7 +756,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py3.6_cu100 python_version: '3.6' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_wheel_upload: context: org-member filters: @@ -805,7 +805,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py3.7_cu92 python_version: '3.7' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_wheel_upload: context: org-member filters: @@ -822,7 +822,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py3.7_cu100 python_version: '3.7' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_wheel_upload: context: org-member filters: @@ -951,7 +951,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py2.7_cu92 python_version: '2.7' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_conda_upload: context: org-member filters: @@ -967,7 +967,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py2.7_cu100 python_version: '2.7' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_conda_upload: context: org-member filters: @@ -1013,7 +1013,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py3.5_cu92 python_version: '3.5' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_conda_upload: context: org-member filters: @@ -1029,7 +1029,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py3.5_cu100 python_version: '3.5' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_conda_upload: context: org-member filters: @@ -1075,7 +1075,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py3.6_cu92 python_version: '3.6' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_conda_upload: context: org-member filters: @@ -1091,7 +1091,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py3.6_cu100 python_version: '3.6' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_conda_upload: context: org-member filters: @@ -1137,7 +1137,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py3.7_cu92 python_version: '3.7' - wheel_docker_image: soumith/manylinux-cuda92 + wheel_docker_image: pytorch/manylinux-cuda92 - binary_conda_upload: context: org-member filters: @@ -1153,7 +1153,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py3.7_cu100 python_version: '3.7' - wheel_docker_image: soumith/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda100 - binary_conda_upload: context: org-member filters: diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 999904576b9..e3747134c6f 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -56,7 +56,7 @@ binary_common: &binary_common wheel_docker_image: description: "Wheel only: what docker image to use" type: string - default: "soumith/manylinux-cuda101" + default: "pytorch/manylinux-cuda101" environment: PYTHON_VERSION: << parameters.python_version >> BUILD_VERSION: << parameters.build_version >> @@ -94,7 +94,7 @@ jobs: binary_linux_conda: <<: *binary_common docker: - - image: "soumith/conda-cuda" + - image: "pytorch/conda-cuda" resource_class: 2xlarge+ steps: - checkout_merge @@ -159,7 +159,7 @@ jobs: name: Pull docker image command: | set -e - export DOCKER_IMAGE=soumith/conda-cuda + export DOCKER_IMAGE=pytorch/conda-cuda echo Pulling docker image $DOCKER_IMAGE docker pull $DOCKER_IMAGE >/dev/null @@ -170,7 +170,7 @@ jobs: cd ${HOME}/project/ - export DOCKER_IMAGE=soumith/conda-cuda + export DOCKER_IMAGE=pytorch/conda-cuda export VARS_TO_PASS="-e PYTHON_VERSION -e BUILD_VERSION -e PYTORCH_VERSION -e UNICODE_ABI -e CU_VERSION" docker run --gpus all --ipc=host -v $(pwd):/remote -w /remote ${VARS_TO_PASS} ${DOCKER_IMAGE} ./packaging/build_conda.sh diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index e7d85d2f911..6925ffa6d45 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -62,9 +62,9 @@ def generate_base_workflow(base_workflow_name, python_version, cu_version, d["unicode_abi"] = '1' if cu_version == "cu92": - d["wheel_docker_image"] = "soumith/manylinux-cuda92" + d["wheel_docker_image"] = "pytorch/manylinux-cuda92" elif cu_version == "cu100": - d["wheel_docker_image"] = "soumith/manylinux-cuda100" + d["wheel_docker_image"] = "pytorch/manylinux-cuda100" if filter_branch is not None: d["filters"] = {"branches": {"only": filter_branch}} diff --git a/test/test_onnx.py b/test/test_onnx.py index 090f16cc550..a42d88103df 100644 --- a/test/test_onnx.py +++ b/test/test_onnx.py @@ -299,6 +299,10 @@ def test_faster_rcnn(self): # This test also compares both paste_masks_in_image and _onnx_paste_masks_in_image # (since jit_trace witll call _onnx_paste_masks_in_image). def test_paste_mask_in_image(self): + # disable profiling + torch._C._jit_set_profiling_executor(False) + torch._C._jit_set_profiling_mode(False) + masks = torch.rand(10, 1, 26, 26) boxes = torch.rand(10, 4) boxes[:, 2:] += torch.rand(10, 2) diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index c523d08bfcb..3c83f3ad137 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -21,7 +21,7 @@ struct _DenseLayerImpl : torch::nn::SequentialImpl { "conv1", torch::nn::Conv2d(Options(num_input_features, bn_size * growth_rate, 1) .stride(1) - .with_bias(false))); + .bias(false))); push_back("norm2", torch::nn::BatchNorm(bn_size * growth_rate)); push_back("relu2", torch::nn::Functional(modelsimpl::relu_)); push_back( @@ -29,7 +29,7 @@ struct _DenseLayerImpl : torch::nn::SequentialImpl { torch::nn::Conv2d(Options(bn_size * growth_rate, growth_rate, 3) .stride(1) .padding(1) - .with_bias(false))); + .bias(false))); } torch::Tensor forward(torch::Tensor x) { @@ -75,7 +75,7 @@ struct _TransitionImpl : torch::nn::SequentialImpl { "conv", torch::nn::Conv2d(Options(num_input_features, num_output_features, 1) .stride(1) - .with_bias(false))); + .bias(false))); push_back("pool", torch::nn::Functional([](torch::Tensor input) { return torch::avg_pool2d(input, 2, 2, 0, false, true); })); @@ -99,10 +99,8 @@ DenseNetImpl::DenseNetImpl( features = torch::nn::Sequential(); features->push_back( "conv0", - torch::nn::Conv2d(Options(3, num_init_features, 7) - .stride(2) - .padding(3) - .with_bias(false))); + torch::nn::Conv2d( + Options(3, num_init_features, 7).stride(2).padding(3).bias(false))); features->push_back("norm0", torch::nn::BatchNorm(num_init_features)); features->push_back("relu0", torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/googlenet.cpp b/torchvision/csrc/models/googlenet.cpp index c053b65b4d6..15a4fd6ee2f 100644 --- a/torchvision/csrc/models/googlenet.cpp +++ b/torchvision/csrc/models/googlenet.cpp @@ -9,10 +9,10 @@ using Options = torch::nn::Conv2dOptions; namespace _googlenetimpl { BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions options) { - options.with_bias(false); + options.bias(false); conv = torch::nn::Conv2d(options); bn = torch::nn::BatchNorm( - torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); + torch::nn::BatchNormOptions(options.out_channels()).eps(0.001)); register_module("conv", conv); register_module("bn", bn); diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index ebb35089d33..1c5b7bbe1f7 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -9,10 +9,10 @@ namespace _inceptionimpl { BasicConv2dImpl::BasicConv2dImpl( torch::nn::Conv2dOptions options, double std_dev) { - options.with_bias(false); + options.bias(false); conv = torch::nn::Conv2d(options); bn = torch::nn::BatchNorm( - torch::nn::BatchNormOptions(options.output_channels()).eps(0.001)); + torch::nn::BatchNormOptions(options.out_channels()).eps(0.001)); register_module("conv", conv); register_module("bn", bn); diff --git a/torchvision/csrc/models/mnasnet.cpp b/torchvision/csrc/models/mnasnet.cpp index 75b63c9f5c5..c6373f78999 100644 --- a/torchvision/csrc/models/mnasnet.cpp +++ b/torchvision/csrc/models/mnasnet.cpp @@ -23,8 +23,7 @@ struct MNASNetInvertedResidualImpl : torch::nn::Module { auto mid = int64_t(input * expansion_factor); apply_residual = input == output && stride == 1; - layers->push_back( - torch::nn::Conv2d(Options(input, mid, 1).with_bias(false))); + layers->push_back(torch::nn::Conv2d(Options(input, mid, 1).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(mid).momentum(bn_momentum))); layers->push_back( @@ -34,13 +33,12 @@ struct MNASNetInvertedResidualImpl : torch::nn::Module { .padding(kernel / 2) .stride(stride) .groups(mid) - .with_bias(false)))); + .bias(false)))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(mid).momentum(bn_momentum))); layers->push_back( torch::nn::Functional(torch::nn::Functional(modelsimpl::relu_))); - layers->push_back( - torch::nn::Conv2d(Options(mid, output, 1).with_bias(false))); + layers->push_back(torch::nn::Conv2d(Options(mid, output, 1).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(output).momentum(bn_momentum))); @@ -128,18 +126,18 @@ void MNASNetImpl::_initialize_weights() { MNASNetImpl::MNASNetImpl(double alpha, int64_t num_classes, double dropout) { auto depths = scale_depths({24, 40, 80, 96, 192, 320}, alpha); - layers->push_back(torch::nn::Conv2d( - Options(3, 32, 3).padding(1).stride(2).with_bias(false))); + layers->push_back( + torch::nn::Conv2d(Options(3, 32, 3).padding(1).stride(2).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(32).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); layers->push_back(torch::nn::Conv2d( - Options(32, 32, 3).padding(1).stride(1).groups(32).with_bias(false))); + Options(32, 32, 3).padding(1).stride(1).groups(32).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(32).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); - layers->push_back(torch::nn::Conv2d( - Options(32, 16, 1).padding(0).stride(1).with_bias(false))); + layers->push_back( + torch::nn::Conv2d(Options(32, 16, 1).padding(0).stride(1).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(16).momentum(BN_MOMENTUM))); @@ -151,7 +149,7 @@ MNASNetImpl::MNASNetImpl(double alpha, int64_t num_classes, double dropout) { layers->push_back(stack(depths[4], depths[5], 3, 1, 6, 1, BN_MOMENTUM)); layers->push_back(torch::nn::Conv2d( - Options(depths[5], 1280, 1).padding(0).stride(1).with_bias(false))); + Options(depths[5], 1280, 1).padding(0).stride(1).bias(false))); layers->push_back(torch::nn::BatchNorm( torch::nn::BatchNormOptions(1280).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/mobilenet.cpp b/torchvision/csrc/models/mobilenet.cpp index 2b49c844977..ad5aaf3c997 100644 --- a/torchvision/csrc/models/mobilenet.cpp +++ b/torchvision/csrc/models/mobilenet.cpp @@ -32,7 +32,7 @@ struct ConvBNReLUImpl : torch::nn::SequentialImpl { .stride(stride) .padding(padding) .groups(groups) - .with_bias(false))); + .bias(false))); push_back(torch::nn::BatchNorm(out_planes)); push_back(torch::nn::Functional(modelsimpl::relu6_)); } @@ -67,7 +67,7 @@ struct MobileNetInvertedResidualImpl : torch::nn::Module { conv->push_back(ConvBNReLU(hidden_dim, hidden_dim, 3, stride, hidden_dim)); conv->push_back(torch::nn::Conv2d( - Options(hidden_dim, output, 1).stride(1).padding(0).with_bias(false))); + Options(hidden_dim, output, 1).stride(1).padding(0).bias(false))); conv->push_back(torch::nn::BatchNorm(output)); register_module("conv", conv); @@ -136,7 +136,7 @@ MobileNetV2Impl::MobileNetV2Impl( if (auto M = dynamic_cast(module.get())) { torch::nn::init::kaiming_normal_( M->weight, 0, torch::nn::init::FanMode::FanOut); - if (M->options.with_bias()) + if (M->options.bias()) torch::nn::init::zeros_(M->bias); } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::ones_(M->weight); diff --git a/torchvision/csrc/models/resnet.cpp b/torchvision/csrc/models/resnet.cpp index 4dcd64dcea8..2be172ca03e 100644 --- a/torchvision/csrc/models/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -11,13 +11,13 @@ torch::nn::Conv2d conv3x3( int64_t stride, int64_t groups) { torch::nn::Conv2dOptions O(in, out, 3); - O.padding(1).stride(stride).groups(groups).with_bias(false); + O.padding(1).stride(stride).groups(groups).bias(false); return torch::nn::Conv2d(O); } torch::nn::Conv2d conv1x1(int64_t in, int64_t out, int64_t stride) { torch::nn::Conv2dOptions O(in, out, 1); - O.stride(stride).with_bias(false); + O.stride(stride).bias(false); return torch::nn::Conv2d(O); } diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index ae9f4613ebe..5aada26af2f 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -124,8 +124,8 @@ ResNetImpl::ResNetImpl( : groups(groups), base_width(width_per_group), inplanes(64), - conv1(torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).with_bias( - false)), + conv1( + torch::nn::Conv2dOptions(3, 64, 7).stride(2).padding(3).bias(false)), bn1(64), layer1(_make_layer(64, layers[0])), layer2(_make_layer(128, layers[1], 2)), diff --git a/torchvision/csrc/models/shufflenetv2.cpp b/torchvision/csrc/models/shufflenetv2.cpp index 2cf278e8d72..658842dd566 100644 --- a/torchvision/csrc/models/shufflenetv2.cpp +++ b/torchvision/csrc/models/shufflenetv2.cpp @@ -25,13 +25,13 @@ torch::Tensor channel_shuffle(torch::Tensor x, int64_t groups) { torch::nn::Conv2d conv11(int64_t input, int64_t output) { Options opts(input, output, 1); - opts = opts.stride(1).padding(0).with_bias(false); + opts = opts.stride(1).padding(0).bias(false); return torch::nn::Conv2d(opts); } torch::nn::Conv2d conv33(int64_t input, int64_t output, int64_t stride) { Options opts(input, output, 3); - opts = opts.stride(stride).padding(1).with_bias(false).groups(input); + opts = opts.stride(stride).padding(1).bias(false).groups(input); return torch::nn::Conv2d(opts); } @@ -107,7 +107,7 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( torch::nn::Conv2d(Options(input_channels, output_channels, 3) .stride(2) .padding(1) - .with_bias(false)), + .bias(false)), torch::nn::BatchNorm(output_channels), torch::nn::Functional(modelsimpl::relu_)); @@ -134,7 +134,7 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( torch::nn::Conv2d(Options(input_channels, output_channels, 1) .stride(1) .padding(0) - .with_bias(false)), + .bias(false)), torch::nn::BatchNorm(output_channels), torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/squeezenet.cpp b/torchvision/csrc/models/squeezenet.cpp index 16bcb6495bd..cfb26ea58eb 100644 --- a/torchvision/csrc/models/squeezenet.cpp +++ b/torchvision/csrc/models/squeezenet.cpp @@ -91,7 +91,7 @@ SqueezeNetImpl::SqueezeNetImpl(double version, int64_t num_classes) else torch::nn::init::kaiming_uniform_(M->weight); - if (M->options.with_bias()) + if (M->options.bias()) torch::nn::init::constant_(M->bias, 0); } } diff --git a/torchvision/datasets/folder.py b/torchvision/datasets/folder.py index f0546daa93d..dffa0a9bfc8 100644 --- a/torchvision/datasets/folder.py +++ b/torchvision/datasets/folder.py @@ -44,7 +44,7 @@ def is_valid_file(x): d = os.path.join(dir, target) if not os.path.isdir(d): continue - for root, _, fnames in sorted(os.walk(d)): + for root, _, fnames in sorted(os.walk(d, followlinks=True)): for fname in sorted(fnames): path = os.path.join(root, fname) if is_valid_file(path): diff --git a/torchvision/datasets/samplers/clip_sampler.py b/torchvision/datasets/samplers/clip_sampler.py index b3c01c5e508..2432a6d20de 100644 --- a/torchvision/datasets/samplers/clip_sampler.py +++ b/torchvision/datasets/samplers/clip_sampler.py @@ -2,7 +2,7 @@ import torch from torch.utils.data import Sampler import torch.distributed as dist -import torchvision.datasets.video_utils +from torchvision.datasets.video_utils import VideoClips class DistributedSampler(Sampler): @@ -96,7 +96,7 @@ def set_epoch(self, epoch): self.epoch = epoch -class UniformClipSampler(torch.utils.data.Sampler): +class UniformClipSampler(Sampler): """ Sample `num_video_clips_per_video` clips for each video, equally spaced. When number of unique clips in the video is fewer than num_video_clips_per_video, @@ -107,7 +107,7 @@ class UniformClipSampler(torch.utils.data.Sampler): num_clips_per_video (int): number of clips to be sampled per video """ def __init__(self, video_clips, num_clips_per_video): - if not isinstance(video_clips, torchvision.datasets.video_utils.VideoClips): + if not isinstance(video_clips, VideoClips): raise TypeError("Expected video_clips to be an instance of VideoClips, " "got {}".format(type(video_clips))) self.video_clips = video_clips @@ -139,7 +139,7 @@ def __len__(self): ) -class RandomClipSampler(torch.utils.data.Sampler): +class RandomClipSampler(Sampler): """ Samples at most `max_video_clips_per_video` clips for each video randomly @@ -148,7 +148,7 @@ class RandomClipSampler(torch.utils.data.Sampler): max_clips_per_video (int): maximum number of clips to be sampled per video """ def __init__(self, video_clips, max_clips_per_video): - if not isinstance(video_clips, torchvision.datasets.video_utils.VideoClips): + if not isinstance(video_clips, VideoClips): raise TypeError("Expected video_clips to be an instance of VideoClips, " "got {}".format(type(video_clips))) self.video_clips = video_clips diff --git a/torchvision/models/_utils.py b/torchvision/models/_utils.py index 3f70f8dd25a..617778116b4 100644 --- a/torchvision/models/_utils.py +++ b/torchvision/models/_utils.py @@ -5,7 +5,7 @@ from torch.jit.annotations import Dict -class IntermediateLayerGetter(nn.Module): +class IntermediateLayerGetter(nn.ModuleDict): """ Module wrapper that returns intermediate layers from a model @@ -45,8 +45,6 @@ class IntermediateLayerGetter(nn.Module): def __init__(self, model, return_layers): if not set(return_layers).issubset([name for name, _ in model.named_children()]): raise ValueError("return_layers are not present in model") - super(IntermediateLayerGetter, self).__init__() - orig_return_layers = return_layers return_layers = {k: v for k, v in return_layers.items()} layers = OrderedDict() @@ -57,33 +55,14 @@ def __init__(self, model, return_layers): if not return_layers: break - self.layers = nn.ModuleDict(layers) + super(IntermediateLayerGetter, self).__init__(layers) self.return_layers = orig_return_layers def forward(self, x): out = OrderedDict() - for name, module in self.layers.items(): + for name, module in self.items(): x = module(x) if name in self.return_layers: out_name = self.return_layers[name] out[out_name] = x return out - - @torch.jit.ignore - def _load_from_state_dict(self, state_dict, prefix, local_metadata, strict, - missing_keys, unexpected_keys, error_msgs): - version = local_metadata.get('version', None) - if (version is None or version < 2): - # now we have a new nesting level for torchscript support - for new_key in self.state_dict().keys(): - # remove prefix "layers." - old_key = new_key[len("layers."):] - old_key = prefix + old_key - new_key = prefix + new_key - if old_key in state_dict: - value = state_dict[old_key] - del state_dict[old_key] - state_dict[new_key] = value - super(IntermediateLayerGetter, self)._load_from_state_dict( - state_dict, prefix, local_metadata, strict, - missing_keys, unexpected_keys, error_msgs) diff --git a/torchvision/models/densenet.py b/torchvision/models/densenet.py index 06bbc3653b7..d4dc283a5f5 100644 --- a/torchvision/models/densenet.py +++ b/torchvision/models/densenet.py @@ -90,13 +90,12 @@ def forward(self, input): # noqa: F811 return new_features -class _DenseBlock(nn.Module): +class _DenseBlock(nn.ModuleDict): _version = 2 __constants__ = ['layers'] def __init__(self, num_layers, num_input_features, bn_size, growth_rate, drop_rate, memory_efficient=False): super(_DenseBlock, self).__init__() - self.layers = nn.ModuleDict() for i in range(num_layers): layer = _DenseLayer( num_input_features + i * growth_rate, @@ -105,34 +104,15 @@ def __init__(self, num_layers, num_input_features, bn_size, growth_rate, drop_ra drop_rate=drop_rate, memory_efficient=memory_efficient, ) - self.layers['denselayer%d' % (i + 1)] = layer + self.add_module('denselayer%d' % (i + 1), layer) def forward(self, init_features): features = [init_features] - for name, layer in self.layers.items(): + for name, layer in self.items(): new_features = layer(features) features.append(new_features) return torch.cat(features, 1) - @torch.jit.ignore - def _load_from_state_dict(self, state_dict, prefix, local_metadata, strict, - missing_keys, unexpected_keys, error_msgs): - version = local_metadata.get('version', None) - if (version is None or version < 2): - # now we have a new nesting level for torchscript support - for new_key in self.state_dict().keys(): - # remove prefix "layers." - old_key = new_key[len("layers."):] - old_key = prefix + old_key - new_key = prefix + new_key - if old_key in state_dict: - value = state_dict[old_key] - del state_dict[old_key] - state_dict[new_key] = value - super(_DenseBlock, self)._load_from_state_dict( - state_dict, prefix, local_metadata, strict, - missing_keys, unexpected_keys, error_msgs) - class _Transition(nn.Sequential): def __init__(self, num_input_features, num_output_features): diff --git a/torchvision/models/segmentation/deeplabv3.py b/torchvision/models/segmentation/deeplabv3.py index 94215071728..ae652cd7d2a 100644 --- a/torchvision/models/segmentation/deeplabv3.py +++ b/torchvision/models/segmentation/deeplabv3.py @@ -57,7 +57,8 @@ def __init__(self, in_channels, out_channels): def forward(self, x): size = x.shape[-2:] - x = super(ASPPPooling, self).forward(x) + for mod in self: + x = mod(x) return F.interpolate(x, size=size, mode='bilinear', align_corners=False) From 0282cc0a905db879682f021ebc4223ae1c870742 Mon Sep 17 00:00:00 2001 From: Lara Haidar Date: Mon, 25 Nov 2019 12:27:07 -0800 Subject: [PATCH 005/357] Changes to Enable KeypointRCNN ONNX Export (#1593) (#1603) Summary: * code changes to enable onnx export for keypoint rcnn * add import * fix copy paste error Pull Request resolved: https://github.com/pytorch/vision/pull/1603 Reviewed By: zhangguanheng66 Differential Revision: D18638672 Pulled By: fmassa fbshipit-source-id: c3a7cb18f35e48e9e10a7b6550cfb73e53385ea4 --- test/test_onnx.py | 37 ++++++++++++ torchvision/models/detection/roi_heads.py | 69 ++++++++++++++++++++++- torchvision/models/detection/transform.py | 9 ++- 3 files changed, 112 insertions(+), 3 deletions(-) diff --git a/test/test_onnx.py b/test/test_onnx.py index a42d88103df..75af8a90b85 100644 --- a/test/test_onnx.py +++ b/test/test_onnx.py @@ -338,6 +338,43 @@ def test_mask_rcnn(self): model(images) self.run_model(model, [(images,), (test_images,)]) + # Verify that heatmaps_to_keypoints behaves the same in tracing. + # This test also compares both heatmaps_to_keypoints and _onnx_heatmaps_to_keypoints + # (since jit_trace witll call _heatmaps_to_keypoints). + # @unittest.skip("Disable test until Resize bug fixed in ORT") + def test_heatmaps_to_keypoints(self): + # disable profiling + torch._C._jit_set_profiling_executor(False) + torch._C._jit_set_profiling_mode(False) + + maps = torch.rand(10, 1, 26, 26) + rois = torch.rand(10, 4) + from torchvision.models.detection.roi_heads import heatmaps_to_keypoints + out = heatmaps_to_keypoints(maps, rois) + jit_trace = torch.jit.trace(heatmaps_to_keypoints, (maps, rois)) + out_trace = jit_trace(maps, rois) + + assert torch.all(out[0].eq(out_trace[0])) + assert torch.all(out[1].eq(out_trace[1])) + + maps2 = torch.rand(20, 2, 21, 21) + rois2 = torch.rand(20, 4) + from torchvision.models.detection.roi_heads import heatmaps_to_keypoints + out2 = heatmaps_to_keypoints(maps2, rois2) + out_trace2 = jit_trace(maps2, rois2) + + assert torch.all(out2[0].eq(out_trace2[0])) + assert torch.all(out2[1].eq(out_trace2[1])) + + @unittest.skip("Disable test until Argmax is updated in ONNX") + def test_keypoint_rcnn(self): + images, test_images = self.get_test_images() + + model = models.detection.keypoint_rcnn.keypointrcnn_resnet50_fpn(pretrained=True, min_size=200, max_size=300) + model.eval() + model(test_images) + self.run_model(model, [(images,), (test_images,)]) + if __name__ == '__main__': unittest.main() diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index 7ec34c68c92..63d3977c847 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -1,3 +1,4 @@ +from __future__ import division import torch import torchvision @@ -164,6 +165,58 @@ def keypoints_to_heatmap(keypoints, rois, heatmap_size): return heatmaps, valid +def _onnx_heatmaps_to_keypoints(maps, maps_i, roi_map_width, roi_map_height, + widths_i, heights_i, offset_x_i, offset_y_i): + num_keypoints = torch.scalar_tensor(maps.size(1), dtype=torch.int64) + + width_correction = widths_i / roi_map_width + height_correction = heights_i / roi_map_height + + roi_map = torch.nn.functional.interpolate( + maps_i[None], size=(int(roi_map_height), int(roi_map_width)), mode='bicubic', align_corners=False)[0] + + w = torch.scalar_tensor(roi_map.size(2), dtype=torch.int64) + pos = roi_map.reshape(num_keypoints, -1).argmax(dim=1) + + x_int = (pos % w) + y_int = ((pos - x_int) / w) + + x = (torch.tensor(0.5, dtype=torch.float32) + x_int.to(dtype=torch.float32)) * \ + width_correction.to(dtype=torch.float32) + y = (torch.tensor(0.5, dtype=torch.float32) + y_int.to(dtype=torch.float32)) * \ + height_correction.to(dtype=torch.float32) + + xy_preds_i_0 = x + offset_x_i.to(dtype=torch.float32) + xy_preds_i_1 = y + offset_y_i.to(dtype=torch.float32) + xy_preds_i_2 = torch.ones((xy_preds_i_1.shape), dtype=torch.float32) + xy_preds_i = torch.stack([xy_preds_i_0.to(dtype=torch.float32), + xy_preds_i_1.to(dtype=torch.float32), + xy_preds_i_2.to(dtype=torch.float32)], 0) + + # TODO: simplify when indexing without rank will be supported by ONNX + end_scores_i = roi_map.index_select(1, y_int.to(dtype=torch.int64)) \ + .index_select(2, x_int.to(dtype=torch.int64))[:num_keypoints, 0, 0] + return xy_preds_i, end_scores_i + + +@torch.jit.script +def _onnx_heatmaps_to_keypoints_loop(maps, rois, widths_ceil, heights_ceil, + widths, heights, offset_x, offset_y, num_keypoints): + xy_preds = torch.zeros((0, 3, int(num_keypoints)), dtype=torch.float32, device=maps.device) + end_scores = torch.zeros((0, int(num_keypoints)), dtype=torch.float32, device=maps.device) + + for i in range(int(rois.size(0))): + xy_preds_i, end_scores_i = _onnx_heatmaps_to_keypoints(maps, maps[i], + widths_ceil[i], heights_ceil[i], + widths[i], heights[i], + offset_x[i], offset_y[i]) + xy_preds = torch.cat((xy_preds.to(dtype=torch.float32), + xy_preds_i.unsqueeze(0).to(dtype=torch.float32)), 0) + end_scores = torch.cat((end_scores.to(dtype=torch.float32), + end_scores_i.to(dtype=torch.float32).unsqueeze(0)), 0) + return xy_preds, end_scores + + def heatmaps_to_keypoints(maps, rois): """Extract predicted keypoint locations from heatmaps. Output has shape (#rois, 4, #keypoints) with the 4 rows corresponding to (x, y, logit, prob) @@ -185,6 +238,14 @@ def heatmaps_to_keypoints(maps, rois): heights_ceil = heights.ceil() num_keypoints = maps.shape[1] + + if torchvision._is_tracing(): + xy_preds, end_scores = _onnx_heatmaps_to_keypoints_loop(maps, rois, + widths_ceil, heights_ceil, widths, heights, + offset_x, offset_y, + torch.scalar_tensor(num_keypoints, dtype=torch.int64)) + return xy_preds.permute(0, 2, 1), end_scores + xy_preds = torch.zeros((len(rois), 3, num_keypoints), dtype=torch.float32, device=maps.device) end_scores = torch.zeros((len(rois), num_keypoints), dtype=torch.float32, device=maps.device) for i in range(len(rois)): @@ -244,7 +305,13 @@ def keypointrcnn_inference(x, boxes): kp_probs = [] kp_scores = [] - boxes_per_image = [len(box) for box in boxes] + boxes_per_image = [box.size(0) for box in boxes] + + if len(boxes_per_image) == 1: + # TODO : remove when dynamic split supported in ONNX + kp_prob, scores = heatmaps_to_keypoints(x, boxes[0]) + return [kp_prob], [scores] + x2 = x.split(boxes_per_image, dim=0) for xx, bb in zip(x2, boxes): diff --git a/torchvision/models/detection/transform.py b/torchvision/models/detection/transform.py index a10d5c6a384..8ce96eec723 100644 --- a/torchvision/models/detection/transform.py +++ b/torchvision/models/detection/transform.py @@ -154,8 +154,13 @@ def resize_keypoints(keypoints, original_size, new_size): ratios = tuple(float(s) / float(s_orig) for s, s_orig in zip(new_size, original_size)) ratio_h, ratio_w = ratios resized_data = keypoints.clone() - resized_data[..., 0] *= ratio_w - resized_data[..., 1] *= ratio_h + if torch._C._get_tracing_state(): + resized_data_0 = resized_data[:, :, 0] * ratio_w + resized_data_1 = resized_data[:, :, 1] * ratio_h + resized_data = torch.stack((resized_data_0, resized_data_1, resized_data[:, :, 2]), dim=2) + else: + resized_data[..., 0] *= ratio_w + resized_data[..., 1] *= ratio_h return resized_data From 2dba31ea26bad64a3fabbd41bfe29a47ee4d5158 Mon Sep 17 00:00:00 2001 From: James Thewlis Date: Wed, 18 Dec 2019 09:30:37 -0800 Subject: [PATCH 006/357] Move VideoClips dummy dataset to top level for pickling (#1649) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1685 Reviewed By: stephenyan1231 Differential Revision: D19157328 Pulled By: fmassa fbshipit-source-id: 968d433cd8efd7b8b57ebd2013d06be4ea52e7a8 --- torchvision/datasets/video_utils.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/torchvision/datasets/video_utils.py b/torchvision/datasets/video_utils.py index 61044248845..de3f6fae3bf 100644 --- a/torchvision/datasets/video_utils.py +++ b/torchvision/datasets/video_utils.py @@ -43,6 +43,21 @@ def unfold(tensor, size, step, dilation=1): return torch.as_strided(tensor, new_size, new_stride) +class _DummyDataset(object): + """ + Dummy dataset used for DataLoader in VideoClips. + Defined at top level so it can be pickled when forking. + """ + def __init__(self, x): + self.x = x + + def __len__(self): + return len(self.x) + + def __getitem__(self, idx): + return read_video_timestamps(self.x[idx]) + + class VideoClips(object): """ Given a list of video files, computes all consecutive subvideos of size @@ -95,19 +110,9 @@ def _compute_frame_pts(self): # strategy: use a DataLoader to parallelize read_video_timestamps # so need to create a dummy dataset first - class DS(object): - def __init__(self, x): - self.x = x - - def __len__(self): - return len(self.x) - - def __getitem__(self, idx): - return read_video_timestamps(self.x[idx]) - import torch.utils.data dl = torch.utils.data.DataLoader( - DS(self.video_paths), + _DummyDataset(self.video_paths), batch_size=16, num_workers=self.num_workers, collate_fn=lambda x: x) From 60bab62468e994f2faad692c962068a8bd621938 Mon Sep 17 00:00:00 2001 From: Oana Florescu <35745326+flores-o@users.noreply.github.com> Date: Wed, 18 Dec 2019 09:32:17 -0800 Subject: [PATCH 007/357] VideoClips windows fixes (#1661) (#1686) Summary: * remove windows skips from video_utils tests, now that they pass * replace lambda in videoclips in order to be pickled on windows and update tests Pull Request resolved: https://github.com/pytorch/vision/pull/1686 Reviewed By: stephenyan1231 Differential Revision: D19157330 Pulled By: fmassa fbshipit-source-id: e27219fc269969aeee4a508f643da9a7cd933997 --- test/test_datasets_video_utils.py | 6 ++---- torchvision/datasets/video_utils.py | 5 ++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/test/test_datasets_video_utils.py b/test/test_datasets_video_utils.py index 2488edc613d..1a5c087cd75 100644 --- a/test/test_datasets_video_utils.py +++ b/test/test_datasets_video_utils.py @@ -59,10 +59,9 @@ def test_unfold(self): self.assertTrue(r.equal(expected)) @unittest.skipIf(not io.video._av_available(), "this test requires av") - @unittest.skipIf(sys.platform == 'win32', 'temporarily disabled on Windows') def test_video_clips(self): with get_list_of_videos(num_videos=3) as video_list: - video_clips = VideoClips(video_list, 5, 5) + video_clips = VideoClips(video_list, 5, 5, num_workers=2) self.assertEqual(video_clips.num_clips(), 1 + 2 + 3) for i, (v_idx, c_idx) in enumerate([(0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2)]): video_idx, clip_idx = video_clips.get_clip_location(i) @@ -84,12 +83,11 @@ def test_video_clips(self): self.assertEqual(clip_idx, c_idx) @unittest.skipIf(not io.video._av_available(), "this test requires av") - @unittest.skipIf(sys.platform == 'win32', 'temporarily disabled on Windows') def test_video_clips_custom_fps(self): with get_list_of_videos(num_videos=3, sizes=[12, 12, 12], fps=[3, 4, 6]) as video_list: num_frames = 4 for fps in [1, 3, 4, 10]: - video_clips = VideoClips(video_list, num_frames, num_frames, fps) + video_clips = VideoClips(video_list, num_frames, num_frames, fps, num_workers=2) for i in range(video_clips.num_clips()): video, audio, info, video_idx = video_clips.get_clip(i) self.assertEqual(video.shape[0], num_frames) diff --git a/torchvision/datasets/video_utils.py b/torchvision/datasets/video_utils.py index de3f6fae3bf..d2a5e12316e 100644 --- a/torchvision/datasets/video_utils.py +++ b/torchvision/datasets/video_utils.py @@ -104,6 +104,9 @@ def __init__(self, video_paths, clip_length_in_frames=16, frames_between_clips=1 self._init_from_metadata(_precomputed_metadata) self.compute_clips(clip_length_in_frames, frames_between_clips, frame_rate) + def _collate_fn(self, x): + return x + def _compute_frame_pts(self): self.video_pts = [] self.video_fps = [] @@ -115,7 +118,7 @@ def _compute_frame_pts(self): _DummyDataset(self.video_paths), batch_size=16, num_workers=self.num_workers, - collate_fn=lambda x: x) + collate_fn=self._collate_fn) with tqdm(total=len(dl)) as pbar: for batch in dl: From 0eb8aedea02c5e62818222845954ffe59c83317b Mon Sep 17 00:00:00 2001 From: Will Brennan Date: Thu, 19 Dec 2019 06:34:58 -0800 Subject: [PATCH 008/357] Fix broken bitwise operation in Similarity Reference loss (#1604) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1679 Reviewed By: cpuhrsch Differential Revision: D19156833 Pulled By: fmassa fbshipit-source-id: 77165540505982c3677e1b74f97c94c5cbc35b8f --- references/similarity/loss.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/references/similarity/loss.py b/references/similarity/loss.py index 3e467b74c52..1fa4a89c762 100644 --- a/references/similarity/loss.py +++ b/references/similarity/loss.py @@ -77,7 +77,7 @@ def batch_all_triplet_loss(labels, embeddings, margin, p): def _get_triplet_mask(labels): # Check that i, j and k are distinct - indices_equal = torch.eye(labels.size(0), dtype=torch.uint8, device=labels.device) + indices_equal = torch.eye(labels.size(0), dtype=torch.bool, device=labels.device) indices_not_equal = ~indices_equal i_not_equal_j = indices_not_equal.unsqueeze(2) i_not_equal_k = indices_not_equal.unsqueeze(1) @@ -96,7 +96,7 @@ def _get_triplet_mask(labels): def _get_anchor_positive_triplet_mask(labels): # Check that i and j are distinct - indices_equal = torch.eye(labels.size(0), dtype=torch.uint8, device=labels.device) + indices_equal = torch.eye(labels.size(0), dtype=torch.bool, device=labels.device) indices_not_equal = ~indices_equal # Check if labels[i] == labels[j] From 5037e0ee22ab114114455a8292ebdad121c0e322 Mon Sep 17 00:00:00 2001 From: Rahul Somani Date: Thu, 19 Dec 2019 06:39:56 -0800 Subject: [PATCH 009/357] Adding args for names of train and val directories (#1544) (#1683) Summary: * Generalised for custom dataset * Typo, redundant code, sensible default * Args for name of train and val dir Pull Request resolved: https://github.com/pytorch/vision/pull/1683 Reviewed By: cpuhrsch Differential Revision: D19156990 Pulled By: fmassa fbshipit-source-id: eb865c4ed3e7eaf455ce5d03d5ac64e0c153d6de --- references/video_classification/train.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/references/video_classification/train.py b/references/video_classification/train.py index 8e41f9ec474..67905f83338 100644 --- a/references/video_classification/train.py +++ b/references/video_classification/train.py @@ -116,8 +116,8 @@ def main(args): # Data loading code print("Loading data") - traindir = os.path.join(args.data_path, 'train_avi-480p') - valdir = os.path.join(args.data_path, 'val_avi-480p') + traindir = os.path.join(args.data_path, args.train_dir) + valdir = os.path.join(args.data_path, args.val_dir) normalize = T.Normalize(mean=[0.43216, 0.394666, 0.37645], std=[0.22803, 0.22145, 0.216989]) @@ -274,6 +274,8 @@ def parse_args(): parser = argparse.ArgumentParser(description='PyTorch Classification Training') parser.add_argument('--data-path', default='/datasets01_101/kinetics/070618/', help='dataset') + parser.add_argument('--train-dir', default='train_avi-480p', help='name of train dir') + parser.add_argument('--val-dir', default='val_avi-480p', help='name of val dir') parser.add_argument('--model', default='r2plus1d_18', help='model') parser.add_argument('--device', default='cuda', help='device') parser.add_argument('--clip-len', default=16, type=int, metavar='N', From 678243bf6e28d3c850887adb6a15e556a675b9d3 Mon Sep 17 00:00:00 2001 From: Oana Florescu <35745326+flores-o@users.noreply.github.com> Date: Thu, 19 Dec 2019 06:42:04 -0800 Subject: [PATCH 010/357] fixed test for windows by closing the created temporary files (#1662) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1687 Reviewed By: cpuhrsch Differential Revision: D19157332 Pulled By: fmassa fbshipit-source-id: 7ab6deae603d6937ca688f745550dc158cfe3de3 --- test/test_io.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/test_io.py b/test/test_io.py index db292b73e0f..92c43a4431b 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -58,14 +58,14 @@ def temp_video(num_frames, height, width, fps, lossless=False, video_codec=None, data = _create_video_frames(num_frames, height, width) with tempfile.NamedTemporaryFile(suffix='.mp4') as f: + f.close() io.write_video(f.name, data, fps=fps, video_codec=video_codec, options=options) yield f.name, data - + os.unlink(f.name) @unittest.skipIf(get_video_backend() != "pyav" and not io._HAS_VIDEO_OPT, "video_reader backend not available") @unittest.skipIf(av is None, "PyAV unavailable") -@unittest.skipIf(sys.platform == 'win32', 'temporarily disabled on Windows') class Tester(unittest.TestCase): # compression adds artifacts, thus we add a tolerance of # 6 in 0-255 range @@ -106,6 +106,7 @@ def test_read_timestamps(self): expected_pts = [i * pts_step for i in range(num_frames)] self.assertEqual(pts, expected_pts) + container.close() def test_read_partial_video(self): with temp_video(10, 300, 300, 5, lossless=True) as (f_name, data): @@ -176,6 +177,7 @@ def test_read_timestamps_from_packet(self): expected_pts = [i * pts_step for i in range(num_frames)] self.assertEqual(pts, expected_pts) + container.close() def test_read_video_pts_unit_sec(self): with temp_video(10, 300, 300, 5, lossless=True) as (f_name, data): @@ -196,6 +198,7 @@ def test_read_timestamps_pts_unit_sec(self): expected_pts = [i * pts_step * stream.time_base for i in range(num_frames)] self.assertEqual(pts, expected_pts) + container.close() def test_read_partial_video_pts_unit_sec(self): with temp_video(10, 300, 300, 5, lossless=True) as (f_name, data): @@ -218,6 +221,7 @@ def test_read_partial_video_pts_unit_sec(self): # when the given start pts is not matching any frame pts self.assertEqual(len(lv), 4) self.assertTrue(data[4:8].equal(lv)) + container.close() def test_read_video_corrupted_file(self): with tempfile.NamedTemporaryFile(suffix='.mp4') as f: From 9c467532af11079789852fc17d915920155e87c8 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Thu, 19 Dec 2019 06:42:15 -0800 Subject: [PATCH 011/357] Fix documentation for NMS (#1614) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1682 Reviewed By: cpuhrsch Differential Revision: D19156986 Pulled By: fmassa fbshipit-source-id: 15c945acf9b4e44d62cc6b0252efe7c143ce570d --- torchvision/ops/boxes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index 239a2446e22..219c13b36e7 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -19,7 +19,7 @@ def nms(boxes, scores, iou_threshold): scores for each one of the boxes iou_threshold : float discards all overlapping - boxes with IoU < iou_threshold + boxes with IoU > iou_threshold Returns ------- @@ -49,7 +49,7 @@ def batched_nms(boxes, scores, idxs, iou_threshold): indices of the categories for each one of the boxes. iou_threshold : float discards all overlapping boxes - with IoU < iou_threshold + with IoU > iou_threshold Returns ------- From a039d645cbca898f88efc06a619c80a4c4e1aec1 Mon Sep 17 00:00:00 2001 From: Yoshitomo Matsubara Date: Thu, 19 Dec 2019 06:42:23 -0800 Subject: [PATCH 012/357] update default parameters (#1611) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1684 Reviewed By: cpuhrsch Differential Revision: D19156997 Pulled By: fmassa fbshipit-source-id: dca753d7e1e9041a9973f0c45a8046358e687188 --- references/detection/train.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/references/detection/train.py b/references/detection/train.py index 3b928611b4f..507d4faebae 100644 --- a/references/detection/train.py +++ b/references/detection/train.py @@ -8,6 +8,14 @@ The default hyperparameters are tuned for training on 8 gpus and 2 images per gpu. --lr 0.02 --batch-size 2 --world-size 8 If you use different number of gpus, the learning rate should be changed to 0.02/8*$NGPU. + +On top of that, for training Faster/Mask R-CNN, the default hyperparameters are + --epochs 26 --lr-steps 16 22 --aspect-ratio-group-factor 3 + +Also, if you train Keypoint R-CNN, the default hyperparameters are + --epochs 46 --lr-steps 36 43 --aspect-ratio-group-factor 3 +Because the number of images is smaller in the person keypoint subset of COCO, +the number of epochs should be adapted so that we have the same number of iterations. """ import datetime import os @@ -145,7 +153,7 @@ def main(args): parser.add_argument('--device', default='cuda', help='device') parser.add_argument('-b', '--batch-size', default=2, type=int, help='images per gpu, the total batch size is $NGPU x batch_size') - parser.add_argument('--epochs', default=13, type=int, metavar='N', + parser.add_argument('--epochs', default=26, type=int, metavar='N', help='number of total epochs to run') parser.add_argument('-j', '--workers', default=4, type=int, metavar='N', help='number of data loading workers (default: 4)') @@ -158,12 +166,12 @@ def main(args): metavar='W', help='weight decay (default: 1e-4)', dest='weight_decay') parser.add_argument('--lr-step-size', default=8, type=int, help='decrease lr every step-size epochs') - parser.add_argument('--lr-steps', default=[8, 11], nargs='+', type=int, help='decrease lr every step-size epochs') + parser.add_argument('--lr-steps', default=[16, 22], nargs='+', type=int, help='decrease lr every step-size epochs') parser.add_argument('--lr-gamma', default=0.1, type=float, help='decrease lr by a factor of lr-gamma') parser.add_argument('--print-freq', default=20, type=int, help='print frequency') parser.add_argument('--output-dir', default='.', help='path where to save') parser.add_argument('--resume', default='', help='resume from checkpoint') - parser.add_argument('--aspect-ratio-group-factor', default=0, type=int) + parser.add_argument('--aspect-ratio-group-factor', default=3, type=int) parser.add_argument( "--test-only", dest="test_only", From 1032c0dc893fe204d3bbdab67ce3eed4383e4ebd Mon Sep 17 00:00:00 2001 From: Yoshitomo Matsubara Date: Thu, 19 Dec 2019 06:46:50 -0800 Subject: [PATCH 013/357] add a README for training object detection models (#1612) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1681 Reviewed By: cpuhrsch Differential Revision: D19156982 Pulled By: fmassa fbshipit-source-id: d0afdedb9232bd81166d7d3f5336caba4e3d872c --- references/detection/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 references/detection/README.md diff --git a/references/detection/README.md b/references/detection/README.md new file mode 100644 index 00000000000..7aec36aefa3 --- /dev/null +++ b/references/detection/README.md @@ -0,0 +1,31 @@ +# Object detection reference training scripts + +This folder contains reference training scripts for object detection. +They serve as a log of how to train specific models, as provide baseline +training and evaluation scripts to quickly bootstrap research. + +Except otherwise noted, all models have been trained on 8x V100 GPUs. + +### Faster R-CNN +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py\ + --dataset coco --model fasterrcnn_resnet50_fpn --epochs 26\ + --lr-steps 16 22 --aspect-ratio-group-factor 3 +``` + + +### Mask R-CNN +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py\ + --dataset coco --model maskrcnn_resnet50_fpn --epochs 26\ + --lr-steps 16 22 --aspect-ratio-group-factor 3 +``` + + +### Keypoint R-CNN +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py\ + --dataset coco_kp --model keypointrcnn_resnet50_fpn --epochs 46\ + --lr-steps 36 43 --aspect-ratio-group-factor 3 +``` + From 90f5aac1fe8f3da55cc8c316033419fad9272d7f Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 14 Jan 2020 04:14:40 -0800 Subject: [PATCH 014/357] Testing CI (#1735) (#1748) Summary: * Testing CI * Disable tests for Pillow 7 Pull Request resolved: https://github.com/pytorch/vision/pull/1748 Reviewed By: drothermel Differential Revision: D19390268 Pulled By: fmassa fbshipit-source-id: fd4a825ac463aa7b02f7061ea8a6913491e7d94e --- README.rst | 1 + test/test_transforms.py | 1 + 2 files changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 30dce8b4639..718ff01c898 100644 --- a/README.rst +++ b/README.rst @@ -16,6 +16,7 @@ torchvision The torchvision package consists of popular datasets, model architectures, and common image transformations for computer vision. + Installation ============ diff --git a/test/test_transforms.py b/test/test_transforms.py index 1bbe1165f93..a801360424c 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -892,6 +892,7 @@ def test_adjust_contrast(self): y_ans = np.array(y_ans, dtype=np.uint8).reshape(x_shape) self.assertTrue(np.allclose(y_np, y_ans)) + @unittest.skipIf(Image.__version__ >= '7', "Temporarily disabled") def test_adjust_saturation(self): x_shape = [2, 2, 3] x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] From 3fb7cb013bef0456d997ff681c78610d04e3bce1 Mon Sep 17 00:00:00 2001 From: Yuri Putivsky Date: Tue, 14 Jan 2020 12:42:55 -0800 Subject: [PATCH 015/357] Base decoder for video. (#1747) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1747 Pull Request resolved: https://github.com/pytorch/vision/pull/1746 Added the implementation of ffmpeg based decoder with functionality that can be used in VUE and TorchVision. Reviewed By: fmassa Differential Revision: D19358914 fbshipit-source-id: abb672f89bfaca6351dda2354f0d35cf8e47fa0f --- setup.py | 48 +- .../csrc/cpu/decoder/audio_sampler.cpp | 199 ++++++ torchvision/csrc/cpu/decoder/audio_sampler.h | 46 ++ torchvision/csrc/cpu/decoder/audio_stream.cpp | 122 ++++ torchvision/csrc/cpu/decoder/audio_stream.h | 37 ++ torchvision/csrc/cpu/decoder/cc_stream.cpp | 26 + torchvision/csrc/cpu/decoder/cc_stream.h | 24 + torchvision/csrc/cpu/decoder/decoder.cpp | 608 ++++++++++++++++++ torchvision/csrc/cpu/decoder/decoder.h | 77 +++ torchvision/csrc/cpu/decoder/defs.h | 345 ++++++++++ .../csrc/cpu/decoder/seekable_buffer.cpp | 148 +++++ .../csrc/cpu/decoder/seekable_buffer.h | 46 ++ torchvision/csrc/cpu/decoder/stream.cpp | 165 +++++ torchvision/csrc/cpu/decoder/stream.h | 74 +++ .../csrc/cpu/decoder/subtitle_sampler.cpp | 46 ++ .../csrc/cpu/decoder/subtitle_sampler.h | 39 ++ .../csrc/cpu/decoder/subtitle_stream.cpp | 108 ++++ .../csrc/cpu/decoder/subtitle_stream.h | 43 ++ torchvision/csrc/cpu/decoder/sync_decoder.cpp | 90 +++ torchvision/csrc/cpu/decoder/sync_decoder.h | 46 ++ .../csrc/cpu/decoder/sync_decoder_test.cpp | 22 + torchvision/csrc/cpu/decoder/time_keeper.cpp | 40 ++ torchvision/csrc/cpu/decoder/time_keeper.h | 27 + torchvision/csrc/cpu/decoder/util.cpp | 374 +++++++++++ torchvision/csrc/cpu/decoder/util.h | 33 + .../csrc/cpu/decoder/video_sampler.cpp | 274 ++++++++ torchvision/csrc/cpu/decoder/video_sampler.h | 52 ++ torchvision/csrc/cpu/decoder/video_stream.cpp | 143 ++++ torchvision/csrc/cpu/decoder/video_stream.h | 39 ++ 29 files changed, 3330 insertions(+), 11 deletions(-) create mode 100644 torchvision/csrc/cpu/decoder/audio_sampler.cpp create mode 100644 torchvision/csrc/cpu/decoder/audio_sampler.h create mode 100644 torchvision/csrc/cpu/decoder/audio_stream.cpp create mode 100644 torchvision/csrc/cpu/decoder/audio_stream.h create mode 100644 torchvision/csrc/cpu/decoder/cc_stream.cpp create mode 100644 torchvision/csrc/cpu/decoder/cc_stream.h create mode 100644 torchvision/csrc/cpu/decoder/decoder.cpp create mode 100644 torchvision/csrc/cpu/decoder/decoder.h create mode 100644 torchvision/csrc/cpu/decoder/defs.h create mode 100644 torchvision/csrc/cpu/decoder/seekable_buffer.cpp create mode 100644 torchvision/csrc/cpu/decoder/seekable_buffer.h create mode 100644 torchvision/csrc/cpu/decoder/stream.cpp create mode 100644 torchvision/csrc/cpu/decoder/stream.h create mode 100644 torchvision/csrc/cpu/decoder/subtitle_sampler.cpp create mode 100644 torchvision/csrc/cpu/decoder/subtitle_sampler.h create mode 100644 torchvision/csrc/cpu/decoder/subtitle_stream.cpp create mode 100644 torchvision/csrc/cpu/decoder/subtitle_stream.h create mode 100644 torchvision/csrc/cpu/decoder/sync_decoder.cpp create mode 100644 torchvision/csrc/cpu/decoder/sync_decoder.h create mode 100644 torchvision/csrc/cpu/decoder/sync_decoder_test.cpp create mode 100644 torchvision/csrc/cpu/decoder/time_keeper.cpp create mode 100644 torchvision/csrc/cpu/decoder/time_keeper.h create mode 100644 torchvision/csrc/cpu/decoder/util.cpp create mode 100644 torchvision/csrc/cpu/decoder/util.h create mode 100644 torchvision/csrc/cpu/decoder/video_sampler.cpp create mode 100644 torchvision/csrc/cpu/decoder/video_sampler.h create mode 100644 torchvision/csrc/cpu/decoder/video_stream.cpp create mode 100644 torchvision/csrc/cpu/decoder/video_stream.h diff --git a/setup.py b/setup.py index 8ece63ce739..c1c6514383c 100644 --- a/setup.py +++ b/setup.py @@ -127,17 +127,6 @@ def get_extensions(): include_dirs = [extensions_dir] - ffmpeg_exe = distutils.spawn.find_executable('ffmpeg') - has_ffmpeg = ffmpeg_exe is not None - if has_ffmpeg: - ffmpeg_bin = os.path.dirname(ffmpeg_exe) - ffmpeg_root = os.path.dirname(ffmpeg_bin) - ffmpeg_include_dir = os.path.join(ffmpeg_root, 'include') - - # TorchVision video reader - video_reader_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'video_reader') - video_reader_src = glob.glob(os.path.join(video_reader_src_dir, "*.cpp")) - ext_modules = [ extension( 'torchvision._C', @@ -157,7 +146,19 @@ def get_extensions(): extra_compile_args=extra_compile_args, ) ) + + ffmpeg_exe = distutils.spawn.find_executable('ffmpeg') + has_ffmpeg = ffmpeg_exe is not None + if has_ffmpeg: + ffmpeg_bin = os.path.dirname(ffmpeg_exe) + ffmpeg_root = os.path.dirname(ffmpeg_bin) + ffmpeg_include_dir = os.path.join(ffmpeg_root, 'include') + + # TorchVision video reader + video_reader_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'video_reader') + video_reader_src = glob.glob(os.path.join(video_reader_src_dir, "*.cpp")) + ext_modules.append( CppExtension( 'torchvision.video_reader', @@ -179,6 +180,31 @@ def get_extensions(): ) ) + # TorchVision base decoder + base_decoder_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'decoder') + base_decoder_src = glob.glob(os.path.join(base_decoder_src_dir, "[!sync_decoder_test]*.cpp")) + + ext_modules.append( + CppExtension( + 'torchvision.base_decoder', + base_decoder_src, + include_dirs=[ + base_decoder_src_dir, + ffmpeg_include_dir, + extensions_dir, + ], + libraries=[ + 'avcodec', + 'avformat', + 'avutil', + 'swresample', + 'swscale', + ], + extra_compile_args=["-std=c++14"], + extra_link_args=["-std=c++14"], + ) + ) + return ext_modules diff --git a/torchvision/csrc/cpu/decoder/audio_sampler.cpp b/torchvision/csrc/cpu/decoder/audio_sampler.cpp new file mode 100644 index 00000000000..c10fceb852d --- /dev/null +++ b/torchvision/csrc/cpu/decoder/audio_sampler.cpp @@ -0,0 +1,199 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "audio_sampler.h" +#include +#include "util.h" + +// www.ffmpeg.org/doxygen/1.1/doc_2examples_2resampling_audio_8c-example.html#a24 + +#ifndef SWR_CH_MAX +#define SWR_CH_MAX 32 +#endif + +namespace ffmpeg { + +namespace { +int preparePlanes( + const AudioFormat& fmt, + const uint8_t* buffer, + int numSamples, + uint8_t** planes) { + int result; + if ((result = av_samples_fill_arrays( + planes, + nullptr, // linesize is not needed + buffer, + fmt.channels, + numSamples, + (AVSampleFormat)fmt.format, + 1)) < 0) { + LOG(ERROR) << "av_samples_fill_arrays failed, err: " + << Util::generateErrorDesc(result) + << ", numSamples: " << numSamples << ", fmt: " << fmt.format; + } + return result; +} +} // namespace + +AudioSampler::AudioSampler(void* logCtx) : logCtx_(logCtx) {} + +AudioSampler::~AudioSampler() { + cleanUp(); +} + +void AudioSampler::shutdown() { + cleanUp(); +} + +bool AudioSampler::init(const SamplerParameters& params) { + cleanUp(); + + if (params.type != MediaType::TYPE_AUDIO) { + LOG(ERROR) << "Invalid media type, expected MediaType::TYPE_AUDIO"; + return false; + } + + swrContext_ = swr_alloc_set_opts( + nullptr, + av_get_default_channel_layout(params.out.audio.channels), + (AVSampleFormat)params.out.audio.format, + params.out.audio.samples, + av_get_default_channel_layout(params.in.audio.channels), + (AVSampleFormat)params.in.audio.format, + params.in.audio.samples, + 0, + logCtx_); + if (swrContext_ == nullptr) { + LOG(ERROR) << "Cannot allocate SwrContext"; + return false; + } + + int result; + if ((result = swr_init(swrContext_)) < 0) { + LOG(ERROR) << "swr_init faield, err: " << Util::generateErrorDesc(result) + << ", in -> format: " << params.in.audio.format + << ", channels: " << params.in.audio.channels + << ", samples: " << params.in.audio.samples + << ", out -> format: " << params.out.audio.format + << ", channels: " << params.out.audio.channels + << ", samples: " << params.out.audio.samples; + return false; + } + + // set formats + params_ = params; + return true; +} + +int AudioSampler::numOutputSamples(int inSamples) const { + return av_rescale_rnd( + swr_get_delay(swrContext_, params_.in.audio.samples) + inSamples, + params_.out.audio.samples, + params_.in.audio.samples, + AV_ROUND_UP); +} + +int AudioSampler::getSamplesBytes(AVFrame* frame) const { + return av_get_bytes_per_sample((AVSampleFormat)params_.out.audio.format) * + numOutputSamples(frame ? frame->nb_samples : 0) * + params_.out.audio.channels; +} + +int AudioSampler::sample( + const uint8_t* inPlanes[], + int inNumSamples, + ByteStorage* out, + int outNumSamples) { + uint8_t* outPlanes[SWR_CH_MAX] = {nullptr}; + int result; + if ((result = preparePlanes( + params_.out.audio, out->writableTail(), outNumSamples, outPlanes)) < + 0) { + return result; + } + + if ((result = swr_convert( + swrContext_, &outPlanes[0], outNumSamples, inPlanes, inNumSamples)) < + 0) { + LOG(ERROR) << "swr_convert faield, err: " + << Util::generateErrorDesc(result); + return result; + } + + CHECK_LE(result, outNumSamples); + + if ((result = av_samples_get_buffer_size( + nullptr, + params_.out.audio.channels, + result, + (AVSampleFormat)params_.out.audio.format, + 1)) > 0) { + out->append(result); + } + return result; +} + +int AudioSampler::sample(AVFrame* frame, ByteStorage* out) { + const auto outNumSamples = numOutputSamples(frame ? frame->nb_samples : 0); + + if (!outNumSamples) { + return 0; + } + + const auto samplesBytes = + av_get_bytes_per_sample((AVSampleFormat)params_.out.audio.format) * + outNumSamples * params_.out.audio.channels; + + // bytes must be allocated + CHECK_LE(samplesBytes, out->tail()); + + return sample( + frame ? (const uint8_t**)&frame->data[0] : nullptr, + frame ? frame->nb_samples : 0, + out, + outNumSamples); +} + +int AudioSampler::sample(const ByteStorage* in, ByteStorage* out) { + const auto inSampleSize = + av_get_bytes_per_sample((AVSampleFormat)params_.in.audio.format); + + const auto inNumSamples = + !in ? 0 : in->length() / inSampleSize / params_.in.audio.channels; + + const auto outNumSamples = numOutputSamples(inNumSamples); + + if (!outNumSamples) { + return 0; + } + + const auto samplesBytes = + av_get_bytes_per_sample((AVSampleFormat)params_.out.audio.format) * + outNumSamples * params_.out.audio.channels; + + out->clear(); + out->ensure(samplesBytes); + + uint8_t* inPlanes[SWR_CH_MAX] = {nullptr}; + int result; + if (in && + (result = preparePlanes( + params_.in.audio, in->data(), inNumSamples, inPlanes)) < 0) { + return result; + } + + return sample( + in ? (const uint8_t**)inPlanes : nullptr, + inNumSamples, + out, + outNumSamples); +} + +void AudioSampler::cleanUp() { + if (swrContext_) { + swr_free(&swrContext_); + swrContext_ = nullptr; + } +} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/audio_sampler.h b/torchvision/csrc/cpu/decoder/audio_sampler.h new file mode 100644 index 00000000000..d68a21ea20e --- /dev/null +++ b/torchvision/csrc/cpu/decoder/audio_sampler.h @@ -0,0 +1,46 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "defs.h" + +extern "C" { +#include +} + +namespace ffmpeg { + +/** + * Class transcode audio frames from one format into another + */ + +class AudioSampler : public MediaSampler { + public: + explicit AudioSampler(void* logCtx); + ~AudioSampler() override; + + // MediaSampler overrides + bool init(const SamplerParameters& params) override; + int sample(const ByteStorage* in, ByteStorage* out) override; + void shutdown() override; + + int getSamplesBytes(AVFrame* frame) const; + int sample(AVFrame* frame, ByteStorage* out); + + private: + // close resources + void cleanUp(); + // helper functions for rescaling, cropping, etc. + int numOutputSamples(int inSamples) const; + int sample( + const uint8_t* inPlanes[], + int inNumSamples, + ByteStorage* out, + int outNumSamples); + + private: + SwrContext* swrContext_{nullptr}; + void* logCtx_{nullptr}; +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/audio_stream.cpp b/torchvision/csrc/cpu/decoder/audio_stream.cpp new file mode 100644 index 00000000000..17ab9fceb7b --- /dev/null +++ b/torchvision/csrc/cpu/decoder/audio_stream.cpp @@ -0,0 +1,122 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "audio_stream.h" +#include +#include +#include "util.h" + +namespace ffmpeg { + +namespace { +bool operator==(const AudioFormat& x, const AVCodecContext& y) { + return x.samples == y.sample_rate && x.channels == y.channels && + x.format == y.sample_fmt; +} + +AudioFormat& toAudioFormat(AudioFormat& x, const AVCodecContext& y) { + x.samples = y.sample_rate; + x.channels = y.channels; + x.format = y.sample_fmt; + return x; +} +} // namespace + +AudioStream::AudioStream( + AVFormatContext* inputCtx, + int index, + bool convertPtsToWallTime, + const AudioFormat& format) + : Stream( + inputCtx, + MediaFormat::makeMediaFormat(format, index), + convertPtsToWallTime) {} + +AudioStream::~AudioStream() { + if (sampler_) { + sampler_->shutdown(); + sampler_.reset(); + } +} + +void AudioStream::ensureSampler() { + if (!sampler_) { + sampler_ = std::make_unique(codecCtx_); + } +} + +int AudioStream::initFormat() { + // set output format + if (format_.format.audio.samples == 0) { + format_.format.audio.samples = codecCtx_->sample_rate; + } + if (format_.format.audio.channels == 0) { + format_.format.audio.channels = codecCtx_->channels; + } + if (format_.format.audio.format == AV_SAMPLE_FMT_NONE) { + format_.format.audio.format = codecCtx_->sample_fmt; + } + + return format_.format.audio.samples != 0 && + format_.format.audio.channels != 0 && + format_.format.audio.format != AV_SAMPLE_FMT_NONE + ? 0 + : -1; +} + +int AudioStream::estimateBytes(bool flush) { + ensureSampler(); + if (!(sampler_->getInputFormat().audio == *codecCtx_)) { + // - reinit sampler + SamplerParameters params; + params.type = format_.type; + params.out = format_.format; + toAudioFormat(params.in.audio, *codecCtx_); + if (flush || !sampler_->init(params)) { + return -1; + } + + VLOG(1) << "Set input audio sampler format" + << ", samples: " << params.in.audio.samples + << ", channels: " << params.in.audio.channels + << ", format: " << params.in.audio.format + << " : output audio sampler format" + << ", samples: " << format_.format.audio.samples + << ", channels: " << format_.format.audio.channels + << ", format: " << format_.format.audio.format; + } + return sampler_->getSamplesBytes(frame_); +} + +int AudioStream::copyFrameBytes(ByteStorage* out, bool flush) { + ensureSampler(); + return sampler_->sample(flush ? nullptr : frame_, out); +} + +void AudioStream::setHeader(DecoderHeader* header) { + header->seqno = numGenerator_++; + + if (codecCtx_->time_base.num != 0) { + header->pts = av_rescale_q( + av_frame_get_best_effort_timestamp(frame_), + codecCtx_->time_base, + AV_TIME_BASE_Q); + } else { + // If the codec time_base is missing then we would've skipped the + // rescalePackage step to rescale to codec time_base, so here we can + // rescale straight from the stream time_base into AV_TIME_BASE_Q. + header->pts = av_rescale_q( + av_frame_get_best_effort_timestamp(frame_), + inputCtx_->streams[format_.stream]->time_base, + AV_TIME_BASE_Q); + } + + if (convertPtsToWallTime_) { + keeper_.adjust(header->pts); + } + + header->keyFrame = 1; + header->fps = std::numeric_limits::quiet_NaN(); + header->format = format_; +} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/audio_stream.h b/torchvision/csrc/cpu/decoder/audio_stream.h new file mode 100644 index 00000000000..c7708a3356d --- /dev/null +++ b/torchvision/csrc/cpu/decoder/audio_stream.h @@ -0,0 +1,37 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "audio_sampler.h" +#include "stream.h" +#include "time_keeper.h" + +namespace ffmpeg { + +/** + * Class uses FFMPEG library to decode one audio stream. + */ + +class AudioStream : public Stream { + public: + AudioStream( + AVFormatContext* inputCtx, + int index, + bool convertPtsToWallTime, + const AudioFormat& format); + ~AudioStream() override; + + private: + int initFormat() override; + int estimateBytes(bool flush) override; + int copyFrameBytes(ByteStorage* out, bool flush) override; + void setHeader(DecoderHeader* header) override; + + void ensureSampler(); + + private: + std::unique_ptr sampler_; + TimeKeeper keeper_; +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/cc_stream.cpp b/torchvision/csrc/cpu/decoder/cc_stream.cpp new file mode 100644 index 00000000000..47de485b100 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/cc_stream.cpp @@ -0,0 +1,26 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "cc_stream.h" + +namespace ffmpeg { + +CCStream::CCStream( + AVFormatContext* inputCtx, + int index, + bool convertPtsToWallTime, + const SubtitleFormat& format) + : SubtitleStream(inputCtx, index, convertPtsToWallTime, format) { + format_.type = TYPE_CC; +} + +AVCodec* CCStream::findCodec(AVCodecContext* ctx) { + if (ctx->codec_id == AV_CODEC_ID_BIN_DATA && + ctx->codec_type == AVMEDIA_TYPE_DATA) { + // obtain subtitles codec + ctx->codec_id = AV_CODEC_ID_MOV_TEXT; + ctx->codec_type = AVMEDIA_TYPE_SUBTITLE; + } + return Stream::findCodec(ctx); +} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/cc_stream.h b/torchvision/csrc/cpu/decoder/cc_stream.h new file mode 100644 index 00000000000..34506d3259f --- /dev/null +++ b/torchvision/csrc/cpu/decoder/cc_stream.h @@ -0,0 +1,24 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "subtitle_stream.h" + +namespace ffmpeg { + +/** + * Class uses FFMPEG library to decode one closed captions stream. + */ +class CCStream : public SubtitleStream { + public: + CCStream( + AVFormatContext* inputCtx, + int index, + bool convertPtsToWallTime, + const SubtitleFormat& format); + + private: + AVCodec* findCodec(AVCodecContext* ctx) override; +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/decoder.cpp b/torchvision/csrc/cpu/decoder/decoder.cpp new file mode 100644 index 00000000000..d8f324863e4 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/decoder.cpp @@ -0,0 +1,608 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "decoder.h" +#include +#include +#include +#include +#include "audio_stream.h" +#include "cc_stream.h" +#include "subtitle_stream.h" +#include "util.h" +#include "video_stream.h" + +namespace ffmpeg { + +namespace { + +constexpr ssize_t kMinSeekBufferSize = 1024; +constexpr ssize_t kMaxSeekBufferSize = 4 * 1024; +constexpr size_t kIoBufferSize = 4 * 1024; +constexpr size_t kLogBufferSize = 1024; + +int ffmpeg_lock(void** mutex, enum AVLockOp op) { + std::mutex** handle = (std::mutex**)mutex; + switch (op) { + case AV_LOCK_CREATE: + *handle = new std::mutex(); + break; + case AV_LOCK_OBTAIN: + (*handle)->lock(); + break; + case AV_LOCK_RELEASE: + (*handle)->unlock(); + break; + case AV_LOCK_DESTROY: + delete *handle; + break; + } + return 0; +} + +bool mapFfmpegType(AVMediaType media, MediaType* type) { + switch (media) { + case AVMEDIA_TYPE_AUDIO: + *type = TYPE_AUDIO; + return true; + case AVMEDIA_TYPE_VIDEO: + *type = TYPE_VIDEO; + return true; + case AVMEDIA_TYPE_SUBTITLE: + *type = TYPE_SUBTITLE; + return true; + case AVMEDIA_TYPE_DATA: + *type = TYPE_CC; + return true; + default: + return false; + } +} + +std::unique_ptr createStream( + MediaType type, + AVFormatContext* ctx, + int idx, + bool convertPtsToWallTime, + const FormatUnion& format, + int64_t loggingUuid) { + switch (type) { + case TYPE_AUDIO: + return std::make_unique( + ctx, idx, convertPtsToWallTime, format.audio); + case TYPE_VIDEO: + return std::make_unique( + // negative loggingUuid indicates video streams. + ctx, + idx, + convertPtsToWallTime, + format.video, + -loggingUuid); + case TYPE_SUBTITLE: + return std::make_unique( + ctx, idx, convertPtsToWallTime, format.subtitle); + case TYPE_CC: + return std::make_unique( + ctx, idx, convertPtsToWallTime, format.subtitle); + default: + return nullptr; + } +} + +} // Namespace + +/* static */ +void Decoder::logFunction(void* avcl, int level, const char* cfmt, va_list vl) { + if (!avcl) { + // Nothing can be done here + return; + } + + AVClass* avclass = *reinterpret_cast(avcl); + if (!avclass) { + // Nothing can be done here + return; + } + Decoder* decoder = nullptr; + if (strcmp(avclass->class_name, "AVFormatContext") == 0) { + AVFormatContext* context = reinterpret_cast(avcl); + if (context) { + decoder = reinterpret_cast(context->opaque); + } + } else if (strcmp(avclass->class_name, "AVCodecContext") == 0) { + AVCodecContext* context = reinterpret_cast(avcl); + if (context) { + decoder = reinterpret_cast(context->opaque); + } + } else if (strcmp(avclass->class_name, "AVIOContext") == 0) { + AVIOContext* context = reinterpret_cast(avcl); + // only if opaque was assigned to Decoder pointer + if (context && context->read_packet == Decoder::readFunction) { + decoder = reinterpret_cast(context->opaque); + } + } else if (strcmp(avclass->class_name, "SWResampler") == 0) { + // expect AVCodecContext as parent + if (avclass->parent_log_context_offset) { + AVClass** parent = + *(AVClass***)(((uint8_t*)avcl) + avclass->parent_log_context_offset); + AVCodecContext* context = reinterpret_cast(parent); + if (context) { + decoder = reinterpret_cast(context->opaque); + } + } + } else if (strcmp(avclass->class_name, "SWScaler") == 0) { + // cannot find a way to pass context pointer through SwsContext struct + } else { + VLOG(2) << "Unknown context class: " << avclass->class_name; + } + + if (decoder != nullptr && decoder->enableLogLevel(level)) { + char buf[kLogBufferSize] = {0}; + // Format the line + int* prefix = decoder->getPrintPrefix(); + *prefix = 1; + av_log_format_line(avcl, level, cfmt, vl, buf, sizeof(buf) - 1, prefix); + // pass message to the decoder instance + std::string msg(buf); + decoder->logCallback(level, msg); + } +} + +bool Decoder::enableLogLevel(int level) const { + return ssize_t(level) <= params_.logLevel; +} + +void Decoder::logCallback(int level, const std::string& message) { + LOG(INFO) << "Msg, level: " << level << ", msg: " << message; +} + +/* static */ +int Decoder::shutdownFunction(void* ctx) { + Decoder* decoder = (Decoder*)ctx; + if (decoder == nullptr) { + return 1; + } + return decoder->shutdownCallback(); +} + +int Decoder::shutdownCallback() { + return interrupted_ ? 1 : 0; +} + +/* static */ +int Decoder::readFunction(void* opaque, uint8_t* buf, int size) { + Decoder* decoder = reinterpret_cast(opaque); + if (decoder == nullptr) { + return 0; + } + return decoder->readCallback(buf, size); +} + +/* static */ +int64_t Decoder::seekFunction(void* opaque, int64_t offset, int whence) { + Decoder* decoder = reinterpret_cast(opaque); + if (decoder == nullptr) { + return -1; + } + return decoder->seekCallback(offset, whence); +} + +int Decoder::readCallback(uint8_t* buf, int size) { + return seekableBuffer_.read(buf, size, params_.timeoutMs); +} + +int64_t Decoder::seekCallback(int64_t offset, int whence) { + return seekableBuffer_.seek(offset, whence, params_.timeoutMs); +} + +/* static */ +void Decoder::initOnce() { + static std::once_flag flagInit; + std::call_once(flagInit, []() { + av_register_all(); + avcodec_register_all(); + avformat_network_init(); + // register ffmpeg lock manager + av_lockmgr_register(&ffmpeg_lock); + av_log_set_callback(Decoder::logFunction); + av_log_set_level(AV_LOG_ERROR); + LOG(INFO) << "Registered ffmpeg libs"; + }); +} + +Decoder::Decoder() { + initOnce(); +} + +Decoder::~Decoder() { + cleanUp(); +} + +bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { + cleanUp(); + + if ((params.uri.empty() || in) && (!params.uri.empty() || !in)) { + LOG(ERROR) << "Either external URI gets provided" + << " or explicit input callback"; + return false; + } + + // set callback and params + params_ = params; + + auto tmpCtx = avformat_alloc_context(); + + if (!tmpCtx) { + LOG(ERROR) << "Cannot allocate format context"; + return false; + } + + AVInputFormat* fmt = nullptr; + if (in) { + const size_t avioCtxBufferSize = kIoBufferSize; + uint8_t* avioCtxBuffer = (uint8_t*)av_malloc(avioCtxBufferSize); + if (!avioCtxBuffer) { + LOG(ERROR) << "av_malloc cannot allocate " << avioCtxBufferSize + << " bytes"; + avformat_close_input(&tmpCtx); + cleanUp(); + return false; + } + + bool canSeek = in(nullptr, 0, 0) == 0; + + if (!seekableBuffer_.init( + std::forward(in), + kMinSeekBufferSize, + kMaxSeekBufferSize, + params_.timeoutMs)) { + LOG(ERROR) << "seekable buffer initialization failed"; + av_free(avioCtxBuffer); + avformat_close_input(&tmpCtx); + cleanUp(); + return false; + } + + if (params_.isImage) { + const char* fmtName = "image2"; + switch (seekableBuffer_.getImageType()) { + case ImageType::JPEG: + fmtName = "jpeg_pipe"; + break; + case ImageType::PNG: + fmtName = "png_pipe"; + break; + case ImageType::TIFF: + fmtName = "tiff_pipe"; + break; + default: + break; + } + + fmt = av_find_input_format(fmtName); + } + + if (!(avioCtx_ = avio_alloc_context( + avioCtxBuffer, + avioCtxBufferSize, + 0, + reinterpret_cast(this), + &Decoder::readFunction, + nullptr, + canSeek ? &Decoder::seekFunction : nullptr))) { + LOG(ERROR) << "avio_alloc_context failed"; + av_free(avioCtxBuffer); + avformat_close_input(&tmpCtx); + cleanUp(); + return false; + } + + tmpCtx->pb = avioCtx_; + } + + interrupted_ = false; + // ffmpeg avformat_open_input call can hang if media source doesn't respond + // set a guard for handle such situations + std::promise p; + std::future f = p.get_future(); + std::thread guard([&f, this]() { + auto timeout = std::chrono::milliseconds(params_.timeoutMs); + if (std::future_status::timeout == f.wait_for(timeout)) { + LOG(ERROR) << "Cannot open stream within " << params_.timeoutMs << " ms"; + interrupted_ = true; + } + }); + + tmpCtx->opaque = reinterpret_cast(this); + tmpCtx->interrupt_callback.callback = Decoder::shutdownFunction; + tmpCtx->interrupt_callback.opaque = reinterpret_cast(this); + + // add network timeout + tmpCtx->flags |= AVFMT_FLAG_NONBLOCK; + + AVDictionary* options = nullptr; + av_dict_set_int(&options, "analyzeduration", params_.timeoutMs * 1000, 0); + av_dict_set_int(&options, "stimeout", params_.timeoutMs * 1000, 0); + if (params_.listen) { + av_dict_set_int(&options, "listen", 1, 0); + } + + int result = 0; + if (fmt) { + result = avformat_open_input(&tmpCtx, nullptr, fmt, &options); + } else { + result = + avformat_open_input(&tmpCtx, params_.uri.c_str(), nullptr, &options); + } + av_dict_free(&options); + + p.set_value(true); + guard.join(); + + inputCtx_ = tmpCtx; + + if (result < 0 || interrupted_) { + LOG(ERROR) << "avformat_open_input failed, error: " + << Util::generateErrorDesc(result); + cleanUp(); + return false; + } + + result = avformat_find_stream_info(inputCtx_, nullptr); + + if (result < 0) { + LOG(ERROR) << "avformat_find_stream_info failed, error: " + << Util::generateErrorDesc(result); + cleanUp(); + return false; + } + + if (!activateStreams()) { + LOG(ERROR) << "Cannot activate streams"; + cleanUp(); + return false; + } + + onInit(); + + if (params.startOffsetMs != 0) { + av_seek_frame( + inputCtx_, + -1, + params.startOffsetMs * AV_TIME_BASE / 1000, + AVSEEK_FLAG_FRAME | AVSEEK_FLAG_ANY); + } + + LOG(INFO) << "Decoder initialized, log level: " << params_.logLevel; + outOfRange_ = false; + return true; +} + +bool Decoder::activateStreams() { + for (int i = 0; i < inputCtx_->nb_streams; i++) { + // - find the corespondent format at params_.formats set + MediaFormat format; + const auto media = inputCtx_->streams[i]->codec->codec_type; + if (!mapFfmpegType(media, &format.type)) { + VLOG(1) << "Stream media: " << media << " at index " << i + << " gets ignored, unknown type"; + + continue; // unsupported type + } + + // check format + auto it = params_.formats.find(format); + if (it == params_.formats.end()) { + VLOG(1) << "Stream type: " << format.type << " at index: " << i + << " gets ignored, caller is not interested"; + continue; // clients don't care about this media format + } + + // do we have stream of this type? + auto stream = findByType(format); + + // should we process this stream? + + if (it->stream == -2 || // all streams of this type are welcome + (!stream && (it->stream == -1 || it->stream == i))) { // new stream + VLOG(1) << "Stream type: " << format.type << " found, at index: " << i; + auto stream = createStream( + format.type, + inputCtx_, + i, + params_.convertPtsToWallTime, + it->format, + params_.loggingUuid); + CHECK(stream); + if (stream->openCodec() < 0) { + LOG(ERROR) << "Cannot open codec " << i; + return false; + } + streams_.emplace(i, std::move(stream)); + } + } + + return true; +} + +void Decoder::shutdown() { + cleanUp(); +} + +void Decoder::interrupt() { + interrupted_ = true; +} + +void Decoder::cleanUp() { + if (!interrupted_) { + interrupted_ = true; + } + + if (inputCtx_) { + for (auto& stream : streams_) { + // Drain stream buffers. + DecoderOutputMessage msg; + while (msg.payload = createByteStorage(0), + stream.second->flush(&msg, params_.headerOnly) > 0) { + } + stream.second.reset(); + } + streams_.clear(); + avformat_close_input(&inputCtx_); + } + if (avioCtx_) { + av_freep(&avioCtx_->buffer); + av_freep(&avioCtx_); + } + + // reset callback + seekableBuffer_.shutdown(); +} + +int Decoder::getBytes(size_t workingTimeInMs) { + if (outOfRange_) { + return ENODATA; + } + // decode frames until cache is full and leave thread + // once decode() method gets called and grab some bytes + // run this method again + // init package + AVPacket avPacket; + av_init_packet(&avPacket); + avPacket.data = nullptr; + avPacket.size = 0; + + auto end = std::chrono::steady_clock::now() + + std::chrono::milliseconds(workingTimeInMs); + // return true if elapsed time less than timeout + auto watcher = [end]() -> bool { + return std::chrono::steady_clock::now() <= end; + }; + + int result = ETIMEDOUT; + size_t decodingErrors = 0; + while (!interrupted_ && watcher()) { + result = av_read_frame(inputCtx_, &avPacket); + if (result == AVERROR(EAGAIN)) { + VLOG(4) << "Decoder is busy..."; + result = 0; // reset error, EAGAIN is not an error at all + break; + } else if (result == AVERROR_EOF) { + flushStreams(); + VLOG(1) << "End of stream"; + result = ENODATA; + break; + } else if (result < 0) { + flushStreams(); + LOG(ERROR) << "Error detected: " << Util::generateErrorDesc(result); + break; + } + + // get stream + auto stream = findByIndex(avPacket.stream_index); + if (stream == nullptr) { + av_packet_unref(&avPacket); + continue; + } + + stream->rescalePackage(&avPacket); + + AVPacket copyPacket = avPacket; + + size_t numConsecutiveNoBytes = 0; + // it can be only partial decoding of the package bytes + do { + // decode package + if ((result = processPacket(stream, ©Packet)) < 0) { + break; + } + + if (result == 0 && params_.maxProcessNoBytes != 0 && + ++numConsecutiveNoBytes > params_.maxProcessNoBytes) { + LOG(ERROR) << "Exceeding max amount of consecutive no bytes"; + break; + } + if (result > 0) { + numConsecutiveNoBytes = 0; + } + + copyPacket.size -= result; + copyPacket.data += result; + } while (copyPacket.size > 0); + + // post loop check + if (result < 0) { + if (params_.maxPackageErrors != 0 && // check errors + ++decodingErrors >= params_.maxPackageErrors) { // reached the limit + break; + } + } else { + decodingErrors = 0; // reset on success + } + + result = 0; + + av_packet_unref(&avPacket); + } + + av_packet_unref(&avPacket); + + return result; +} + +Stream* Decoder::findByIndex(int streamIndex) const { + auto it = streams_.find(streamIndex); + return it != streams_.end() ? it->second.get() : nullptr; +} + +Stream* Decoder::findByType(const MediaFormat& format) const { + for (auto& stream : streams_) { + if (stream.second->getMediaFormat().type == format.type) { + return stream.second.get(); + } + } + return nullptr; +} + +int Decoder::processPacket(Stream* stream, AVPacket* packet) { + // decode package + int gotFrame = 0; + int result; + DecoderOutputMessage msg; + msg.payload = createByteStorage(0); + if ((result = stream->decodeFrame(packet, &gotFrame)) >= 0 && gotFrame && + stream->getFrameBytes(&msg, params_.headerOnly) > 0) { + // check end offset + if (params_.endOffsetMs <= 0 || + !(outOfRange_ = msg.header.pts > params_.endOffsetMs * 1000)) { + push(std::move(msg)); + } + } + return result; +} + +void Decoder::flushStreams() { + VLOG(1) << "Flushing streams..."; + for (auto& stream : streams_) { + DecoderOutputMessage msg; + while (msg.payload = createByteStorage(0), + stream.second->flush(&msg, params_.headerOnly) > 0) { + // check end offset + if (params_.endOffsetMs <= 0 || + !(outOfRange_ = msg.header.pts > params_.endOffsetMs * 1000)) { + push(std::move(msg)); + } + } + } +} + +int Decoder::decode_all(const DecoderOutCallback& callback) { + int result; + do { + DecoderOutputMessage out; + if (0 == (result = decode(&out, params_.timeoutMs))) { + callback(std::move(out)); + } + } while (result == 0); + return result; +} +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/decoder.h b/torchvision/csrc/cpu/decoder/decoder.h new file mode 100644 index 00000000000..971eec10aa4 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/decoder.h @@ -0,0 +1,77 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "seekable_buffer.h" +#include "stream.h" + +namespace ffmpeg { + +/** + * Class uses FFMPEG library to decode media streams. + * Media bytes can be explicitly provided through read-callback + * or fetched internally by FFMPEG library + */ +class Decoder : public MediaDecoder { + public: + Decoder(); + ~Decoder() override; + + // MediaDecoder overrides + bool init(const DecoderParameters& params, DecoderInCallback&& in) override; + int decode_all(const DecoderOutCallback& callback) override; + void shutdown() override; + void interrupt() override; + + protected: + // function does actual work, derived class calls it in working thread + // periodically. On success method returns 0, ENOADATA on EOF and error on + // unrecoverable error. + int getBytes(size_t workingTimeInMs = 100); + + // Derived class must override method and consume the provided message + virtual void push(DecoderOutputMessage&& buffer) = 0; + + // Fires on init call + virtual void onInit() {} + + public: + // C-style FFMPEG API requires C/static methods for callbacks + static void logFunction(void* avcl, int level, const char* cfmt, va_list vl); + static int shutdownFunction(void* ctx); + static int readFunction(void* opaque, uint8_t* buf, int size); + static int64_t seekFunction(void* opaque, int64_t offset, int whence); + // can be called by any classes or API + static void initOnce(); + + int* getPrintPrefix() { + return &printPrefix; + } + + private: + // mark below function for a proper invocation + virtual bool enableLogLevel(int level) const; + virtual void logCallback(int level, const std::string& message); + virtual int readCallback(uint8_t* buf, int size); + virtual int64_t seekCallback(int64_t offset, int whence); + virtual int shutdownCallback(); + + bool activateStreams(); + Stream* findByIndex(int streamIndex) const; + Stream* findByType(const MediaFormat& format) const; + int processPacket(Stream* stream, AVPacket* packet); + void flushStreams(); + void cleanUp(); + + private: + DecoderParameters params_; + SeekableBuffer seekableBuffer_; + int printPrefix{1}; + + std::atomic interrupted_{false}; + AVFormatContext* inputCtx_{nullptr}; + AVIOContext* avioCtx_{nullptr}; + std::unordered_map> streams_; + bool outOfRange_{false}; +}; +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/defs.h b/torchvision/csrc/cpu/decoder/defs.h new file mode 100644 index 00000000000..62854668b90 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/defs.h @@ -0,0 +1,345 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace ffmpeg { + +// bit mask of formats, keep them in form 2^n +enum MediaType : size_t { + TYPE_AUDIO = 1, + TYPE_VIDEO = 2, + TYPE_SUBTITLE = 4, + TYPE_CC = 8, // closed captions from transport streams +}; + +// audio +struct AudioFormat { + // fields are initialized for the auto detection + // caller can specify some/all of field values if specific output is desirable + bool operator==(const AudioFormat& x) const { + return x.format == format && x.samples == samples && x.channels == channels; + } + + size_t samples{0}; // number samples per second (frequency) + size_t channels{0}; // number of channels + ssize_t format{-1}; // AVSampleFormat, auto AV_SAMPLE_FMT_NONE + size_t padding[2]; + // -- alignment 40 bytes +}; + +// video +struct VideoFormat { + // fields are initialized for the auto detection + // caller can specify some/all of field values if specific output is desirable + bool operator==(const VideoFormat& x) const { + return x.format == format && x.width == width && x.height == height; + } + + size_t width{0}; // width in pixels + size_t height{0}; // height in pixels + ssize_t format{-1}; // AVPixelFormat, auto AV_PIX_FMT_NONE + size_t minDimension{0}; // choose min dimension and rescale accordingly + size_t cropImage{0}; // request image crop + // -- alignment 40 bytes +}; + +// subtitle/cc +struct SubtitleFormat { + ssize_t type{0}; // AVSubtitleType, auto SUBTITLE_NONE + size_t padding[4]; + // -- alignment 40 bytes +}; + +union FormatUnion { + FormatUnion() : audio() {} + explicit FormatUnion(int) : video() {} + explicit FormatUnion(char) : subtitle() {} + explicit FormatUnion(double) : subtitle() {} + AudioFormat audio; + VideoFormat video; + SubtitleFormat subtitle; + // -- alignment 40 bytes +}; + +/* + MediaFormat data structure serves as input/output parameter. + Caller assigns values for input formats + or leave default values for auto detection + For output formats all fields will be set to the specific values +*/ +struct MediaFormat { + // for using map/set data structures + bool operator<(const MediaFormat& x) const { + return type < x.type; + } + bool operator==(const MediaFormat& x) const { + if (type != x.type) { + return false; + } + switch (type) { + case TYPE_AUDIO: + return format.audio == x.format.audio; + case TYPE_VIDEO: + return format.video == x.format.video; + case TYPE_SUBTITLE: + case TYPE_CC: + return true; + default: + return false; + } + } + + explicit MediaFormat(ssize_t s = -1) + : type(TYPE_AUDIO), stream(s), format() {} + explicit MediaFormat(int x, ssize_t s = -1) + : type(TYPE_VIDEO), stream(s), format(x) {} + explicit MediaFormat(char x, ssize_t s = -1) + : type(TYPE_SUBTITLE), stream(s), format(x) {} + explicit MediaFormat(double x, ssize_t s = -1) + : type(TYPE_CC), stream(s), format(x) {} + + static MediaFormat makeMediaFormat(AudioFormat format, ssize_t stream) { + MediaFormat result(stream); + result.format.audio = format; + return result; + } + + static MediaFormat makeMediaFormat(VideoFormat format, ssize_t stream) { + MediaFormat result(0, stream); + result.format.video = format; + return result; + } + + static MediaFormat makeMediaFormat(SubtitleFormat format, ssize_t stream) { + MediaFormat result('0', stream); + result.format.subtitle = format; + return result; + } + + // format type + MediaType type; + // stream index: + // set -1 for one stream auto detection, -2 for all streams auto detection, + // >= 0, specified stream, if caller knows the stream index (unlikely) + ssize_t stream; + // union keeps one of the possible formats, defined by MediaType + FormatUnion format; + + // output parameters, ignored while initialization + // time base numerator + ssize_t num{0}; + // time base denominator + ssize_t den{1}; + // duration of the stream, in stream time base, if available + ssize_t duration{-1}; +}; + +struct DecoderParameters { + // local file, remote file, http url, rtmp stream uri, etc. anything that + // ffmpeg can recognize + std::string uri; + // timeout on getting bytes for decoding + size_t timeoutMs{1000}; + // logging level, default AV_LOG_PANIC + ssize_t logLevel{0}; + // when decoder would give up, 0 means never + size_t maxPackageErrors{0}; + // max allowed consecutive times no bytes are processed. 0 means for infinite. + size_t maxProcessNoBytes{0}; + // start offset + ssize_t startOffsetMs{0}; + // end offset + ssize_t endOffsetMs{-1}; + // logging id + int64_t loggingUuid{0}; + // adjust header pts to the epoch time + bool convertPtsToWallTime{false}; + // indicate if input stream is an encoded image + bool isImage{false}; + // what media types should be processed, default none + std::set formats; + // listen and wait for new rtmp stream + bool listen{false}; + // don't copy frame body, only header + bool headerOnly{false}; + // seek tolerated accuracy + double seekAccuracySec{1.0}; +}; + +struct DecoderHeader { + // message id, from 0 till ... + size_t seqno{0}; + // decoded timestamp in microseconds from either beginning of the stream or + // from epoch time, see DecoderParameters::convertPtsToWallTime + ssize_t pts{0}; + // decoded key frame + size_t keyFrame{0}; + // frames per second, valid only for video streams + double fps{0}; + // format specifies what kind frame is in a payload + MediaFormat format; +}; + +// Abstract interface ByteStorage class +class ByteStorage { + public: + virtual ~ByteStorage() = default; + // makes sure that buffer has at least n bytes available for writing, if not + // storage must reallocate memory. + virtual void ensure(size_t n) = 0; + // caller must not to write more than available bytes + virtual uint8_t* writableTail() = 0; + // caller confirms that n bytes were written to the writable tail + virtual void append(size_t n) = 0; + // caller confirms that n bytes were read from the read buffer + virtual void trim(size_t n) = 0; + // gives an access to the beginning of the read buffer + virtual const uint8_t* data() const = 0; + // returns the stored size in bytes + virtual size_t length() const = 0; + // returns available capacity for writable tail + virtual size_t tail() const = 0; + // clears content, keeps capacity + virtual void clear() = 0; +}; + +struct DecoderOutputMessage { + DecoderHeader header; + std::unique_ptr payload; +}; + +/* + * External provider of the ecnoded bytes, specific implementation is left for + * different use cases, like file, memory, external network end-points, etc. + * Normally input/output parameter @out set to valid, not null buffer pointer, + * which indicates "read" call, however there are "seek" modes as well. + + * @out != nullptr, @size != 0, @timeoutMs != 0 => read from the current offset + * @size bytes => return number bytes read, 0 if no more bytes available, < 0 + * on error. + + * @out == nullptr, @size == 0, @timeoutMs == 0 => does provider support "seek" + * capability in a first place? return 0 on success, < 0 if "seek" mode is not + * supported. + + * @out == nullptr, @size > 0 => seek the absolute offset == @size, return + * 0 on success and < 0 on error. + + * @out == nullptr, @size < 0 => seek the end of the media, return 0 on success + * and < 0 on failure. Provider might support seek doesn't know the media size. + + * Additionally if @out is set to null AND @size is set to zero AND + * @timeoutMs is set to zero, caller requests the seek capability of the + * provider, i.e. returns 0 on success and error if provider is not supporting + * seek. + */ +using DecoderInCallback = + std::function; + +using DecoderOutCallback = std::function; + +/** + * Abstract class for decoding media bytes + * It has two diffrent modes. Internal media bytes retrieval for given uri and + * external media bytes provider in case of memory streams + */ +class MediaDecoder { + public: + virtual ~MediaDecoder() = default; + + /** + * Initializes media decoder with parameters, + * calls callback when media bytes are available. + * Media bytes get fetched internally from provided URI + * or invokes provided input callback to get media bytes. + * Input callback must be empty for the internal media provider + */ + virtual bool init( + const DecoderParameters& params, + DecoderInCallback&& in) = 0; + + /** + * Polls available decoded one frame from decoder + * Returns error code, 0 - for success + */ + virtual int decode(DecoderOutputMessage* out, uint64_t timeoutMs) = 0; + + /** + * Polls available decoded bytes from decoder, till EOF or error + */ + virtual int decode_all(const DecoderOutCallback& callback) = 0; + + /** + * Stops calling callback, releases resources + */ + virtual void shutdown() = 0; + + /** + * Interrupts whatever decoder is doing at any time + */ + virtual void interrupt() = 0; + + /** + * Factory to create ByteStorage class instances, particular implementation is + * left to the derived class. Caller provides the initially allocated size + */ + virtual std::unique_ptr createByteStorage(size_t n) = 0; +}; + +struct SamplerParameters { + MediaType type{TYPE_AUDIO}; + FormatUnion in; + FormatUnion out; + int64_t loggingUuid{0}; +}; + +/** + * Abstract class for sampling media bytes + */ +class MediaSampler { + public: + virtual ~MediaSampler() = default; + + /** + * Initializes media sampler with parameters + */ + virtual bool init(const SamplerParameters& params) = 0; + + /** + * Samples media bytes + * Returns error code < 0, or >=0 - for success, indicating number of bytes + * processed. + * set @in to null for flushing data + */ + virtual int sample(const ByteStorage* in, ByteStorage* out) = 0; + + /** + * Releases resources + */ + virtual void shutdown() = 0; + + /* + * Returns media type + */ + MediaType getMediaType() const { + return params_.type; + } + /* + * Returns formats + */ + FormatUnion getInputFormat() const { + return params_.in; + } + FormatUnion getOutFormat() const { + return params_.out; + } + + protected: + SamplerParameters params_; +}; +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp new file mode 100644 index 00000000000..8d159b789bf --- /dev/null +++ b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp @@ -0,0 +1,148 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "seekable_buffer.h" +#include +#include + +extern "C" { +#include +} + +namespace ffmpeg { + +bool SeekableBuffer::init( + DecoderInCallback&& in, + ssize_t minSize, + ssize_t maxSize, + uint64_t timeoutMs) { + inCallback_ = std::forward(in); + len_ = minSize; + buffer_.resize(len_); + pos_ = 0; + end_ = 0; + eof_ = 0; + + auto end = + std::chrono::steady_clock::now() + std::chrono::milliseconds(timeoutMs); + auto watcher = [end]() -> bool { + return std::chrono::steady_clock::now() <= end; + }; + + bool hasTime = false; + while (!eof_ && end_ < maxSize && (hasTime = watcher())) { + // lets read all bytes into available buffer + auto res = inCallback_(buffer_.data() + end_, len_ - end_, timeoutMs); + if (res > 0) { + end_ += res; + if (end_ == len_) { + len_ = std::min(len_ * 4, maxSize); + buffer_.resize(len_); + } + } else if (res == 0) { + eof_ = 1; + } else { + // error + return false; + } + } + + if (!hasTime) { + return false; + } + + if (buffer_.size() > 2 && buffer_[0] == 0xFF && buffer_[1] == 0xD8 && + buffer_[2] == 0xFF) { + imageType_ = ImageType::JPEG; + } else if ( + buffer_.size() > 3 && buffer_[1] == 'P' && buffer_[2] == 'N' && + buffer_[3] == 'G') { + imageType_ = ImageType::PNG; + } else if ( + buffer_.size() > 1 && + ((buffer_[0] == 0x49 && buffer_[1] == 0x49) || + (buffer_[0] == 0x4D && buffer_[1] == 0x4D))) { + imageType_ = ImageType::TIFF; + } + + return true; +} + +int SeekableBuffer::read(uint8_t* buf, int size, uint64_t timeoutMs) { + // 1. pos_ < end_ + if (pos_ < end_) { + auto available = std::min(int(end_ - pos_), size); + memcpy(buf, buffer_.data() + pos_, available); + pos_ += available; + return available; + } else if (!eof_) { + auto res = inCallback_(buf, size, timeoutMs); // read through + if (res > 0) { + pos_ += res; + if (pos_ > end_ && !buffer_.empty()) { + std::vector().swap(buffer_); + } + } else if (res == 0) { + eof_ = 1; + } + return res; + } else { + return 0; + } +} + +int64_t SeekableBuffer::seek(int64_t offset, int whence, uint64_t timeoutMs) { + // remove force flag + whence &= ~AVSEEK_FORCE; + // get size request + int size = whence & AVSEEK_SIZE; + // remove size flag + whence &= ~AVSEEK_SIZE; + + if (size) { + return eof_ ? end_ : AVERROR(EINVAL); + } else { + switch (whence) { + case SEEK_SET: + if (offset < 0) { + return AVERROR(EINVAL); + } + if (offset <= end_) { + pos_ = offset; + return pos_; + } + if (!inCallback_(0, offset, timeoutMs)) { + pos_ = offset; + return 0; + } + break; + case SEEK_END: + if (eof_ && pos_ <= end_ && offset < 0 && end_ + offset >= 0) { + pos_ = end_ + offset; + return 0; + } + break; + case SEEK_CUR: + if (pos_ + offset < 0) { + return AVERROR(EINVAL); + } + if (pos_ + offset <= end_) { + pos_ += offset; + return 0; + } + if (!inCallback_(0, pos_ + offset, timeoutMs)) { + pos_ += offset; + return 0; + } + break; + default: + LOG(ERROR) << "Unknown whence flag gets provided: " << whence; + } + } + return AVERROR(EINVAL); // we have no idea what the media size is +} + +void SeekableBuffer::shutdown() { + inCallback_ = nullptr; +} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/seekable_buffer.h b/torchvision/csrc/cpu/decoder/seekable_buffer.h new file mode 100644 index 00000000000..e8ba327e4ea --- /dev/null +++ b/torchvision/csrc/cpu/decoder/seekable_buffer.h @@ -0,0 +1,46 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "defs.h" + +namespace ffmpeg { + +/** + * Class uses internal buffer to store initial size bytes as a seekable cache + * from Media provider and let ffmpeg to seek and read bytes from cache + * and beyond - reading bytes directly from Media provider + */ +enum class ImageType { + UNKNOWN = 0, + JPEG = 1, + PNG = 2, + TIFF = 3, +}; + +class SeekableBuffer { + public: + // try to fill out buffer, returns true if EOF detected (seek will supported) + bool init( + DecoderInCallback&& in, + ssize_t minSize, + ssize_t maxSize, + uint64_t timeoutMs); + int read(uint8_t* buf, int size, uint64_t timeoutMs); + int64_t seek(int64_t offset, int whence, uint64_t timeoutMs); + void shutdown(); + ImageType getImageType() const { + return imageType_; + } + + private: + DecoderInCallback inCallback_; + std::vector buffer_; // resized at init time + ssize_t len_{0}; // current buffer size + ssize_t pos_{0}; // current position (SEEK_CUR iff pos_ < end_) + ssize_t end_{0}; // bytes in buffer [0, buffer_.size()] + ssize_t eof_{0}; // indicates the EOF + ImageType imageType_{ImageType::UNKNOWN}; +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/stream.cpp b/torchvision/csrc/cpu/decoder/stream.cpp new file mode 100644 index 00000000000..767136657b6 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/stream.cpp @@ -0,0 +1,165 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "stream.h" +#include +#include "util.h" + +namespace ffmpeg { + +namespace { +const size_t kDecoderHeaderSize = sizeof(DecoderHeader); +} + +Stream::Stream( + AVFormatContext* inputCtx, + MediaFormat format, + bool convertPtsToWallTime) + : inputCtx_(inputCtx), + format_(format), + convertPtsToWallTime_(convertPtsToWallTime) {} + +Stream::~Stream() { + if (frame_) { + av_free(frame_); // Copyright 2004-present Facebook. All Rights Reserved. + } + if (codecCtx_) { + avcodec_free_context(&codecCtx_); + } +} + +AVCodec* Stream::findCodec(AVCodecContext* ctx) { + return avcodec_find_decoder(ctx->codec_id); +} + +int Stream::openCodec() { + AVStream* steam = inputCtx_->streams[format_.stream]; + auto codec_id = steam->codecpar->codec_id; + AVCodec* codec = avcodec_find_decoder(codec_id); + if (!codec) { + LOG(ERROR) << "avcodec_find_decoder failed for codec_id: " << int(codec_id); + return AVERROR(EINVAL); + } + + if (!(codecCtx_ = avcodec_alloc_context3(codec))) { + LOG(ERROR) << "avcodec_alloc_context3 fails"; + return AVERROR(ENOMEM); + } + + int ret; + // Copy codec parameters from input stream to output codec context + if ((ret = avcodec_parameters_to_context(codecCtx_, steam->codecpar)) < 0) { + LOG(ERROR) << "Failed to copy codec parameters to decoder context"; + return ret; + } + + // after avcodec_open2, value of codecCtx_->time_base is NOT meaningful + if ((ret = avcodec_open2(codecCtx_, codec, nullptr)) < 0) { + LOG(ERROR) << "avcodec_open2 failed. " << Util::generateErrorDesc(ret); + avcodec_free_context(&codecCtx_); + codecCtx_ = nullptr; + return ret; + } + + frame_ = av_frame_alloc(); + + format_.num = inputCtx_->streams[format_.stream]->time_base.num; + format_.den = inputCtx_->streams[format_.stream]->time_base.den; + format_.duration = inputCtx_->streams[format_.stream]->duration; + + return initFormat(); +} + +// rescale package +void Stream::rescalePackage(AVPacket* packet) { + if (codecCtx_->time_base.num != 0) { + av_packet_rescale_ts( + packet, + inputCtx_->streams[format_.stream]->time_base, + codecCtx_->time_base); + } +} + +int Stream::analyzePacket(const AVPacket* packet, int* gotFramePtr) { + int consumed = 0; + int result = avcodec_send_packet(codecCtx_, packet); + if (result == AVERROR(EAGAIN)) { + *gotFramePtr = 0; // no bytes get consumed, fetch frame + } else if (result == AVERROR_EOF) { + *gotFramePtr = 0; // more than one flush packet + if (packet) { + // got packet after flush, this is an error + return result; + } + } else if (result < 0) { + LOG(ERROR) << "avcodec_send_packet failed, err: " + << Util::generateErrorDesc(result); + return result; // error + } else { + consumed = packet ? packet->size : 0; // all bytes get consumed + } + + result = avcodec_receive_frame(codecCtx_, frame_); + + if (result >= 0) { + *gotFramePtr = 1; // frame is available + } else if (result == AVERROR(EAGAIN)) { + *gotFramePtr = 0; // no frames at this time, needs more packets + if (!consumed) { + // precaution, if no packages got consumed and no frames are available + return result; + } + } else if (result == AVERROR_EOF) { + *gotFramePtr = 0; // the last frame has been flushed + // precaution, if no more frames are available assume we consume all bytes + consumed = packet ? packet->size : 0; + } else { // error + LOG(ERROR) << "avcodec_receive_frame failed, err: " + << Util::generateErrorDesc(result); + return result; + } + return consumed; +} + +int Stream::decodeFrame(const AVPacket* packet, int* gotFramePtr) { + return analyzePacket(packet, gotFramePtr); +} + +int Stream::getFrameBytes(DecoderOutputMessage* out, bool headerOnly) { + return fillBuffer(out, false, headerOnly); +} + +int Stream::flush(DecoderOutputMessage* out, bool headerOnly) { + int gotFramePtr = 0; + int result; + if (analyzePacket(nullptr, &gotFramePtr) >= 0 && gotFramePtr && + (result = fillBuffer(out, false, headerOnly)) > 0) { + return result; + } else if ((result = fillBuffer(out, true, headerOnly)) > 0) { + return result; + } + return result; +} + +int Stream::fillBuffer(DecoderOutputMessage* out, bool flush, bool headerOnly) { + int result = -1; + if (!codecCtx_) { + LOG(INFO) << "Codec is not initialized"; + return result; + } + + // assign message + setHeader(&out->header); + + if (headerOnly) { + return sizeof(out->header); + } + + // init sampler, if any and return required bytes + if ((result = estimateBytes(flush)) < 0) { + return result; + } + out->payload->ensure(result); + return copyFrameBytes(out->payload.get(), flush); +} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/stream.h b/torchvision/csrc/cpu/decoder/stream.h new file mode 100644 index 00000000000..fd83b90428c --- /dev/null +++ b/torchvision/csrc/cpu/decoder/stream.h @@ -0,0 +1,74 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include +#include "defs.h" + +extern "C" { +#include +#include +#include +} + +namespace ffmpeg { + +/** + * Class uses FFMPEG library to decode one media stream (audio or video). + */ + +class Stream { + public: + Stream( + AVFormatContext* inputCtx, + MediaFormat format, + bool convertPtsToWallTime); + virtual ~Stream(); + + // returns 0 - on success or negative error + int openCodec(); + // returns number processed bytes from packet, or negative error + int decodeFrame(const AVPacket* packet, int* gotFramePtr); + // returns stream index + int getIndex() const { + return format_.stream; + } + // returns number decoded/sampled bytes + int getFrameBytes(DecoderOutputMessage* out, bool headerOnly); + // returns number decoded/sampled bytes + int flush(DecoderOutputMessage* out, bool headerOnly); + // rescale package + void rescalePackage(AVPacket* packet); + // return media format + MediaFormat getMediaFormat() const { + return format_; + } + + protected: + virtual int initFormat() = 0; + // returns number processed bytes from packet, or negative error + virtual int analyzePacket(const AVPacket* packet, int* gotFramePtr); + // returns number decoded/sampled bytes, or negative error + virtual int copyFrameBytes(ByteStorage* out, bool flush) = 0; + // initialize codec, returns output buffer size, or negative error + virtual int estimateBytes(bool flush) = 0; + // sets output format + virtual void setHeader(DecoderHeader* header) = 0; + // finds codec + virtual AVCodec* findCodec(AVCodecContext* ctx); + + private: + int fillBuffer(DecoderOutputMessage* out, bool flush, bool headerOnly); + + protected: + AVFormatContext* const inputCtx_; + MediaFormat format_; + const bool convertPtsToWallTime_; + + AVCodecContext* codecCtx_{nullptr}; + AVFrame* frame_{nullptr}; + + std::atomic numGenerator_{0}; +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp b/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp new file mode 100644 index 00000000000..02859c19187 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp @@ -0,0 +1,46 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "subtitle_sampler.h" +#include "util.h" + +namespace ffmpeg { + +SubtitleSampler::~SubtitleSampler() { + cleanUp(); +} + +void SubtitleSampler::shutdown() { + cleanUp(); +} + +bool SubtitleSampler::init(const SamplerParameters& params) { + cleanUp(); + // set formats + params_ = params; + return true; +} + +int SubtitleSampler::getSamplesBytes(AVSubtitle* sub) const { + return Util::size(*sub); +} + +int SubtitleSampler::sample(AVSubtitle* sub, ByteStorage* out) { + if (!sub) { + return 0; // flush + } + + return Util::serialize(*sub, out); +} + +int SubtitleSampler::sample(const ByteStorage* in, ByteStorage* out) { + if (in) { + // Get a writable copy + *out = *in; + return out->length(); + } + return 0; +} + +void SubtitleSampler::cleanUp() {} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/subtitle_sampler.h b/torchvision/csrc/cpu/decoder/subtitle_sampler.h new file mode 100644 index 00000000000..4846fe4d7c5 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/subtitle_sampler.h @@ -0,0 +1,39 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "defs.h" + +extern "C" { +#include +} + +namespace ffmpeg { + +/** + * Class transcode audio frames from one format into another + */ + +class SubtitleSampler : public MediaSampler { + public: + SubtitleSampler() = default; + ~SubtitleSampler() override; + + bool init(const SamplerParameters& params) override; + int sample(const ByteStorage* in, ByteStorage* out) override; + void shutdown() override; + + // returns number processed/scaling bytes + int sample(AVSubtitle* sub, ByteStorage* out); + int getSamplesBytes(AVSubtitle* sub) const; + + // helper serialization/deserialization methods + static void serialize(const AVSubtitle& sub, ByteStorage* out); + static bool deserialize(const ByteStorage& buf, AVSubtitle* sub); + + private: + // close resources + void cleanUp(); +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/subtitle_stream.cpp b/torchvision/csrc/cpu/decoder/subtitle_stream.cpp new file mode 100644 index 00000000000..b699a0507cf --- /dev/null +++ b/torchvision/csrc/cpu/decoder/subtitle_stream.cpp @@ -0,0 +1,108 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "subtitle_stream.h" +#include +#include +#include "util.h" + +namespace ffmpeg { + +namespace { + +bool operator==(const SubtitleFormat&, const AVCodecContext&) { + return true; +} + +SubtitleFormat& toSubtitleFormat(SubtitleFormat& x, const AVCodecContext&) { + return x; +} +} // namespace + +SubtitleStream::SubtitleStream( + AVFormatContext* inputCtx, + int index, + bool convertPtsToWallTime, + const SubtitleFormat& format) + : Stream( + inputCtx, + MediaFormat::makeMediaFormat(format, index), + convertPtsToWallTime) { + memset(&sub_, 0, sizeof(sub_)); +} + +void SubtitleStream::releaseSubtitle() { + if (sub_.release) { + avsubtitle_free(&sub_); + memset(&sub_, 0, sizeof(sub_)); + } +} + +SubtitleStream::~SubtitleStream() { + releaseSubtitle(); + sampler_.shutdown(); +} + +int SubtitleStream::initFormat() { + if (!codecCtx_->subtitle_header) { + LOG(ERROR) << "No subtitle header found"; + } else { + LOG(INFO) << "Subtitle header found!"; + } + return 0; +} + +int SubtitleStream::analyzePacket(const AVPacket* packet, int* gotFramePtr) { + // clean-up + releaseSubtitle(); + // check flush packet + AVPacket avPacket; + av_init_packet(&avPacket); + avPacket.data = nullptr; + + auto pkt = packet ? *packet : avPacket; + int result = avcodec_decode_subtitle2(codecCtx_, &sub_, gotFramePtr, &pkt); + + if (result < 0) { + VLOG(1) << "avcodec_decode_subtitle2 failed, err: " + << Util::generateErrorDesc(result); + } else if (result == 0) { + result = packet ? packet->size : 0; // discard the rest of the package + } + + sub_.release = *gotFramePtr; + return result; +} + +int SubtitleStream::estimateBytes(bool flush) { + if (!(sampler_.getInputFormat().subtitle == *codecCtx_)) { + // - reinit sampler + SamplerParameters params; + params.type = MediaType::TYPE_SUBTITLE; + toSubtitleFormat(params.in.subtitle, *codecCtx_); + if (flush || !sampler_.init(params)) { + return -1; + } + + VLOG(1) << "Set input subtitle sampler format"; + } + return sampler_.getSamplesBytes(&sub_); +} + +int SubtitleStream::copyFrameBytes(ByteStorage* out, bool flush) { + return sampler_.sample(flush ? nullptr : &sub_, out); +} + +void SubtitleStream::setHeader(DecoderHeader* header) { + header->seqno = numGenerator_++; + + header->pts = sub_.pts; // already in us + + if (convertPtsToWallTime_) { + keeper_.adjust(header->pts); + } + + header->keyFrame = 0; + header->fps = std::numeric_limits::quiet_NaN(); + header->format = format_; +} +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/subtitle_stream.h b/torchvision/csrc/cpu/decoder/subtitle_stream.h new file mode 100644 index 00000000000..8669f15e0ce --- /dev/null +++ b/torchvision/csrc/cpu/decoder/subtitle_stream.h @@ -0,0 +1,43 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "stream.h" +#include "subtitle_sampler.h" +#include "time_keeper.h" + +namespace ffmpeg { + +/** + * Class uses FFMPEG library to decode one subtitle stream. + */ +struct AVSubtitleKeeper : AVSubtitle { + int64_t release{0}; +}; + +class SubtitleStream : public Stream { + public: + SubtitleStream( + AVFormatContext* inputCtx, + int index, + bool convertPtsToWallTime, + const SubtitleFormat& format); + ~SubtitleStream() override; + + protected: + void setHeader(DecoderHeader* header) override; + + private: + int initFormat() override; + int analyzePacket(const AVPacket* packet, int* gotFramePtr) override; + int estimateBytes(bool flush) override; + int copyFrameBytes(ByteStorage* out, bool flush) override; + void releaseSubtitle(); + + private: + SubtitleSampler sampler_; + TimeKeeper keeper_; + AVSubtitleKeeper sub_; +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/sync_decoder.cpp b/torchvision/csrc/cpu/decoder/sync_decoder.cpp new file mode 100644 index 00000000000..6387837218e --- /dev/null +++ b/torchvision/csrc/cpu/decoder/sync_decoder.cpp @@ -0,0 +1,90 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "sync_decoder.h" +#include + +namespace ffmpeg { + +SyncDecoder::VectorByteStorage::VectorByteStorage(size_t n) { + buffer_.resize(n); +} + +void SyncDecoder::VectorByteStorage::ensure(size_t n) { + if (tail() < n) { + buffer_.resize(offset_ + length_ + n); + } +} + +uint8_t* SyncDecoder::VectorByteStorage::writableTail() { + CHECK_LE(offset_ + length_, buffer_.size()); + return buffer_.data() + offset_ + length_; +} + +void SyncDecoder::VectorByteStorage::append(size_t n) { + CHECK_LE(n, tail()); + length_ += n; +} + +void SyncDecoder::VectorByteStorage::trim(size_t n) { + CHECK_LE(n, length_); + offset_ += n; + length_ -= n; +} + +const uint8_t* SyncDecoder::VectorByteStorage::data() const { + return buffer_.data() + offset_; +} + +size_t SyncDecoder::VectorByteStorage::length() const { + return length_; +} + +size_t SyncDecoder::VectorByteStorage::tail() const { + auto size = buffer_.size(); + CHECK_LE(offset_ + length_, buffer_.size()); + return size - offset_ - length_; +} + +void SyncDecoder::VectorByteStorage::clear() { + buffer_.clear(); + offset_ = 0; + length_ = 0; +} + +std::unique_ptr SyncDecoder::createByteStorage(size_t n) { + return std::make_unique(n); +} + +void SyncDecoder::onInit() { + eof_ = false; + queue_.clear(); +} + +int SyncDecoder::decode(DecoderOutputMessage* out, uint64_t timeoutMs) { + if (eof_ && queue_.empty()) { + return ENODATA; + } + + if (queue_.empty()) { + int result = getBytes(timeoutMs); + eof_ = result == ENODATA; + + if (result && result != ENODATA) { + return result; + } + + // still empty + if (queue_.empty()) { + return ETIMEDOUT; + } + } + + *out = std::move(queue_.front()); + queue_.pop_front(); + return 0; +} + +void SyncDecoder::push(DecoderOutputMessage&& buffer) { + queue_.push_back(std::move(buffer)); +} +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/sync_decoder.h b/torchvision/csrc/cpu/decoder/sync_decoder.h new file mode 100644 index 00000000000..76c347fe707 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/sync_decoder.h @@ -0,0 +1,46 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include +#include "decoder.h" + +namespace ffmpeg { + +/** + * Class uses FFMPEG library to decode media streams. + * Media bytes can be explicitly provided through read-callback + * or fetched internally by FFMPEG library + */ +class SyncDecoder : public Decoder { + class VectorByteStorage : public ByteStorage { + public: + VectorByteStorage(size_t n); + void ensure(size_t n) override; + uint8_t* writableTail() override; + void append(size_t n) override; + void trim(size_t n) override; + const uint8_t* data() const override; + size_t length() const override; + size_t tail() const override; + void clear() override; + + private: + size_t offset_{0}; + size_t length_{0}; + std::vector buffer_; + }; + + public: + int decode(DecoderOutputMessage* out, uint64_t timeoutMs) override; + + private: + void push(DecoderOutputMessage&& buffer) override; + void onInit() override; + std::unique_ptr createByteStorage(size_t n) override; + + private: + std::list queue_; + bool eof_{false}; +}; +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp b/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp new file mode 100644 index 00000000000..ee0fe3fcf3c --- /dev/null +++ b/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp @@ -0,0 +1,22 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include +#include +#include "sync_decoder.h" + +using namespace ffmpeg; + +TEST(SyncDecoder, Test) { + SyncDecoder decoder; + DecoderParameters params; + params.timeoutMs = 10000; + params.startOffsetMs = 1000; + params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; + params.uri = "pytorch/vision/test/assets/videos/R6llTwEh07w.mp4"; + CHECK(decoder.init(params, nullptr)); + DecoderOutputMessage out; + while (0 == decoder.decode(&out, 100)) { + LOG(INFO) << "Decoded frame, timestamp(us): " << out.header.pts; + } + decoder.shutdown(); +} diff --git a/torchvision/csrc/cpu/decoder/time_keeper.cpp b/torchvision/csrc/cpu/decoder/time_keeper.cpp new file mode 100644 index 00000000000..a0da56a1f64 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/time_keeper.cpp @@ -0,0 +1,40 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "time_keeper.h" + +extern "C" { +#include +} + +namespace ffmpeg { + +namespace { +const ssize_t kMaxTimeBaseDiference = 10; +} + +ssize_t TimeKeeper::adjust(ssize_t& decoderTimestamp) { + const ssize_t now = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); + + if (startTime_ == 0) { + startTime_ = now; + } + if (streamTimestamp_ == 0) { + streamTimestamp_ = decoderTimestamp; + } + + const auto runOut = startTime_ + decoderTimestamp - streamTimestamp_; + + if (std::labs((now - runOut) / AV_TIME_BASE) > kMaxTimeBaseDiference) { + streamTimestamp_ = startTime_ - now + decoderTimestamp; + } + + const auto sleepAdvised = runOut - now; + + decoderTimestamp += startTime_ - streamTimestamp_; + + return sleepAdvised > 0 ? sleepAdvised : 0; +} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/time_keeper.h b/torchvision/csrc/cpu/decoder/time_keeper.h new file mode 100644 index 00000000000..c9d06025b2c --- /dev/null +++ b/torchvision/csrc/cpu/decoder/time_keeper.h @@ -0,0 +1,27 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include +#include + +namespace ffmpeg { + +/** + * Class keeps the track of the decoded timestamps (us) for media streams. + */ + +class TimeKeeper { + public: + TimeKeeper() = default; + + // adjust provided @timestamp to the corrected value + // return advised sleep time before next frame processing in (us) + ssize_t adjust(ssize_t& decoderTimestamp); + + private: + ssize_t startTime_{0}; + ssize_t streamTimestamp_{0}; +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/util.cpp b/torchvision/csrc/cpu/decoder/util.cpp new file mode 100644 index 00000000000..6ae888838ea --- /dev/null +++ b/torchvision/csrc/cpu/decoder/util.cpp @@ -0,0 +1,374 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "util.h" +#include + +namespace ffmpeg { + +namespace Serializer { + +// fixed size types +template +inline size_t getSize(const T& x) { + return sizeof(x); +} + +template +inline bool serializeItem( + uint8_t* dest, + size_t len, + size_t& pos, + const T& src) { + VLOG(6) << "Generic serializeItem"; + const auto required = sizeof(src); + if (len < pos + required) { + return false; + } + memcpy(dest + pos, &src, required); + pos += required; + return true; +} + +template +inline bool deserializeItem( + const uint8_t* src, + size_t len, + size_t& pos, + T& dest) { + const auto required = sizeof(dest); + if (len < pos + required) { + return false; + } + memcpy(&dest, src + pos, required); + pos += required; + return true; +} + +// AVSubtitleRect specialization +inline size_t getSize(const AVSubtitleRect& x) { + auto rectBytes = [](const AVSubtitleRect& y) -> size_t { + size_t s = 0; + switch (y.type) { + case SUBTITLE_BITMAP: + for (int i = 0; i < y.nb_colors; ++i) { + s += sizeof(y.pict.linesize[i]); + s += y.pict.linesize[i]; + } + break; + case SUBTITLE_TEXT: + s += sizeof(size_t); + s += strlen(y.text); + break; + case SUBTITLE_ASS: + s += sizeof(size_t); + s += strlen(y.ass); + break; + default: + break; + } + return s; + }; + return getSize(x.x) + getSize(x.y) + getSize(x.w) + getSize(x.h) + + getSize(x.nb_colors) + getSize(x.type) + getSize(x.flags) + rectBytes(x); +} + +// AVSubtitle specialization +inline size_t getSize(const AVSubtitle& x) { + auto rectBytes = [](const AVSubtitle& y) -> size_t { + size_t s = getSize(y.num_rects); + for (unsigned i = 0; i < y.num_rects; ++i) { + s += getSize(*y.rects[i]); + } + return s; + }; + return getSize(x.format) + getSize(x.start_display_time) + + getSize(x.end_display_time) + getSize(x.pts) + rectBytes(x); +} + +inline bool serializeItem( + uint8_t* dest, + size_t len, + size_t& pos, + const AVSubtitleRect& src) { + auto rectSerialize = + [](uint8_t* d, size_t l, size_t& p, const AVSubtitleRect& x) -> size_t { + switch (x.type) { + case SUBTITLE_BITMAP: + for (int i = 0; i < x.nb_colors; ++i) { + if (!serializeItem(d, l, p, x.pict.linesize[i])) { + return false; + } + if (p + x.pict.linesize[i] > l) { + return false; + } + memcpy(d + p, x.pict.data[i], x.pict.linesize[i]); + p += x.pict.linesize[i]; + } + return true; + case SUBTITLE_TEXT: { + const size_t s = strlen(x.text); + if (!serializeItem(d, l, p, s)) { + return false; + } + if (p + s > l) { + return false; + } + memcpy(d + p, x.text, s); + p += s; + return true; + } + case SUBTITLE_ASS: { + const size_t s = strlen(x.ass); + if (!serializeItem(d, l, p, s)) { + return false; + } + if (p + s > l) { + return false; + } + memcpy(d + p, x.ass, s); + p += s; + return true; + } + default: + return true; + } + }; + return serializeItem(dest, len, pos, src.x) && + serializeItem(dest, len, pos, src.y) && + serializeItem(dest, len, pos, src.w) && + serializeItem(dest, len, pos, src.h) && + serializeItem(dest, len, pos, src.nb_colors) && + serializeItem(dest, len, pos, src.type) && + serializeItem(dest, len, pos, src.flags) && + rectSerialize(dest, len, pos, src); +} + +inline bool serializeItem( + uint8_t* dest, + size_t len, + size_t& pos, + const AVSubtitle& src) { + auto rectSerialize = + [](uint8_t* d, size_t l, size_t& p, const AVSubtitle& x) -> bool { + bool res = serializeItem(d, l, p, x.num_rects); + for (unsigned i = 0; res && i < x.num_rects; ++i) { + res = serializeItem(d, l, p, *(x.rects[i])); + } + return res; + }; + VLOG(6) << "AVSubtitle serializeItem"; + return serializeItem(dest, len, pos, src.format) && + serializeItem(dest, len, pos, src.start_display_time) && + serializeItem(dest, len, pos, src.end_display_time) && + serializeItem(dest, len, pos, src.pts) && + rectSerialize(dest, len, pos, src); +} + +inline bool deserializeItem( + const uint8_t* src, + size_t len, + size_t& pos, + AVSubtitleRect& dest) { + auto rectDeserialize = + [](const uint8_t* y, size_t l, size_t& p, AVSubtitleRect& x) -> bool { + switch (x.type) { + case SUBTITLE_BITMAP: + for (int i = 0; i < x.nb_colors; ++i) { + if (!deserializeItem(y, l, p, x.pict.linesize[i])) { + return false; + } + if (p + x.pict.linesize[i] > l) { + return false; + } + x.pict.data[i] = (uint8_t*)av_malloc(x.pict.linesize[i]); + memcpy(x.pict.data[i], y + p, x.pict.linesize[i]); + p += x.pict.linesize[i]; + } + return true; + case SUBTITLE_TEXT: { + size_t s = 0; + if (!deserializeItem(y, l, p, s)) { + return false; + } + if (p + s > l) { + return false; + } + x.text = (char*)av_malloc(s + 1); + memcpy(x.text, y + p, s); + x.text[s] = 0; + p += s; + return true; + } + case SUBTITLE_ASS: { + size_t s = 0; + if (!deserializeItem(y, l, p, s)) { + return false; + } + if (p + s > l) { + return false; + } + x.ass = (char*)av_malloc(s + 1); + memcpy(x.ass, y + p, s); + x.ass[s] = 0; + p += s; + return true; + } + default: + return true; + } + }; + + return deserializeItem(src, len, pos, dest.x) && + deserializeItem(src, len, pos, dest.y) && + deserializeItem(src, len, pos, dest.w) && + deserializeItem(src, len, pos, dest.h) && + deserializeItem(src, len, pos, dest.nb_colors) && + deserializeItem(src, len, pos, dest.type) && + deserializeItem(src, len, pos, dest.flags) && + rectDeserialize(src, len, pos, dest); +} + +inline bool deserializeItem( + const uint8_t* src, + size_t len, + size_t& pos, + AVSubtitle& dest) { + auto rectDeserialize = + [](const uint8_t* y, size_t l, size_t& p, AVSubtitle& x) -> bool { + bool res = deserializeItem(y, l, p, x.num_rects); + if (res && x.num_rects) { + x.rects = + (AVSubtitleRect**)av_malloc(x.num_rects * sizeof(AVSubtitleRect*)); + } + for (unsigned i = 0; res && i < x.num_rects; ++i) { + x.rects[i] = (AVSubtitleRect*)av_malloc(sizeof(AVSubtitleRect)); + memset(x.rects[i], 0, sizeof(AVSubtitleRect)); + res = deserializeItem(y, l, p, *x.rects[i]); + } + return res; + }; + return deserializeItem(src, len, pos, dest.format) && + deserializeItem(src, len, pos, dest.start_display_time) && + deserializeItem(src, len, pos, dest.end_display_time) && + deserializeItem(src, len, pos, dest.pts) && + rectDeserialize(src, len, pos, dest); +} +} // namespace Serializer + +namespace Util { +std::string generateErrorDesc(int errorCode) { + std::array buffer; + if (av_strerror(errorCode, buffer.data(), buffer.size()) < 0) { + return std::string("Unknown error code: ") + std::to_string(errorCode); + } + buffer.back() = 0; + return std::string(buffer.data()); +} + +size_t serialize(const AVSubtitle& sub, ByteStorage* out) { + const auto len = size(sub); + CHECK_LE(len, out->tail()); + size_t pos = 0; + if (!Serializer::serializeItem(out->writableTail(), len, pos, sub)) { + return 0; + } + out->append(len); + return len; +} + +bool deserialize(const ByteStorage& buf, AVSubtitle* sub) { + size_t pos = 0; + return Serializer::deserializeItem(buf.data(), buf.length(), pos, *sub); +} + +size_t size(const AVSubtitle& sub) { + return Serializer::getSize(sub); +} + +bool validateVideoFormat(const VideoFormat& f) { + /* + Valid parameters values for decoder + ______________________________________________________________ + | W | H | minDimension | cropImage | algorithm | + |_____________________________________________________________| + | 0 | 0 | 0 | N/A | original | + |_____________________________________________________________| + | >0 | 0 | N/A | N/A | scale keeping W | + |_____________________________________________________________| + | 0 | >0 | N/A | N/A | scale keeping H | + |_____________________________________________________________| + | >0 | >0 | N/A | 0 | stretch/scale | + |_____________________________________________________________| + | >0 | >0 | N/A | >0 | scale/crop | + |_____________________________________________________________| + | 0 | 0 | >0 | N/A |scale to min dimension| + |_____|_____|______________|___________|______________________| + */ + return (f.width == 0 && // #1 and #6 + f.height == 0 && f.cropImage == 0) || + (f.width != 0 && // #4 and #5 + f.height != 0 && f.minDimension == 0) || + (((f.width != 0 && // #2 + f.height == 0) || + (f.width == 0 && // #3 + f.height != 0)) && + f.minDimension == 0 && f.cropImage == 0); +} + +void setFormatDimensions( + size_t& destW, + size_t& destH, + size_t userW, + size_t userH, + size_t srcW, + size_t srcH, + size_t minDimension, + size_t cropImage) { + // rounding rules + // int -> double -> round up + // if fraction is >= 0.5 or round down if fraction is < 0.5 + // int result = double(value) + 0.5 + // here we rounding double to int according to the above rule + if (userW == 0 && userH == 0) { + if (minDimension > 0) { + if (srcW > srcH) { + // landscape + destH = minDimension; + destW = round(double(srcW * minDimension) / srcH); + } else { + // portrait + destW = minDimension; + destH = round(double(srcH * minDimension) / srcW); + } + } else { + destW = srcW; + destH = srcH; + } + } else if (userW != 0 && userH == 0) { + destW = userW; + destH = round(double(srcH * userW) / srcW); + } else if (userW == 0 && userH != 0) { + destW = round(double(srcW * userH) / srcH); + destH = userH; + } else { // userW != 0 && userH != 0 + if (cropImage == 0) { + destW = userW; + destH = userH; + } else { + double userSlope = double(userH) / userW; + double srcSlope = double(srcH) / srcW; + if (srcSlope < userSlope) { + destW = round(double(srcW * userH) / srcH); + destH = userH; + } else { + destW = userW; + destH = round(double(srcH * userW) / srcW); + } + } + } + // prevent zeros + destW = std::max(destW, 1UL); + destH = std::max(destH, 1UL); +} +} // namespace Util +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/util.h b/torchvision/csrc/cpu/decoder/util.h new file mode 100644 index 00000000000..6a985d78559 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/util.h @@ -0,0 +1,33 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "defs.h" + +extern "C" { +#include +} + +namespace ffmpeg { + +/** + * FFMPEG library utility functions. + */ + +namespace Util { +std::string generateErrorDesc(int errorCode); +size_t serialize(const AVSubtitle& sub, ByteStorage* out); +bool deserialize(const ByteStorage& buf, AVSubtitle* sub); +size_t size(const AVSubtitle& sub); +void setFormatDimensions( + size_t& destW, + size_t& destH, + size_t userW, + size_t userH, + size_t srcW, + size_t srcH, + size_t minDimension, + size_t cropImage); +bool validateVideoFormat(const VideoFormat& format); +} // namespace Util +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/video_sampler.cpp b/torchvision/csrc/cpu/decoder/video_sampler.cpp new file mode 100644 index 00000000000..1a91c82a371 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/video_sampler.cpp @@ -0,0 +1,274 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "video_sampler.h" +#include +#include "util.h" + +extern "C" { +#include +} + +// www.ffmpeg.org/doxygen/0.5/swscale-example_8c-source.html + +namespace ffmpeg { + +namespace { +int preparePlanes( + const VideoFormat& fmt, + const uint8_t* buffer, + uint8_t** planes, + int* lineSize) { + int result; + + if ((result = av_image_fill_arrays( + planes, + lineSize, + buffer, + (AVPixelFormat)fmt.format, + fmt.width, + fmt.height, + 1)) < 0) { + LOG(ERROR) << "av_image_fill_arrays failed, err: " + << Util::generateErrorDesc(result); + } + return result; +} + +int transformImage( + SwsContext* context, + const uint8_t* const srcSlice[], + int srcStride[], + VideoFormat inFormat, + VideoFormat outFormat, + uint8_t* out, + uint8_t* planes[], + int lines[]) { + int result; + if ((result = preparePlanes(outFormat, out, planes, lines)) < 0) { + return result; + } + + if ((result = sws_scale( + context, srcSlice, srcStride, 0, inFormat.height, planes, lines)) < + 0) { + LOG(ERROR) << "sws_scale failed, err: " << Util::generateErrorDesc(result); + return result; + } + return 0; +} +} // namespace + +VideoSampler::VideoSampler(int swsFlags, int64_t loggingUuid) + : swsFlags_(swsFlags), loggingUuid_(loggingUuid) {} + +VideoSampler::~VideoSampler() { + cleanUp(); +} + +void VideoSampler::shutdown() { + cleanUp(); +} + +bool VideoSampler::init(const SamplerParameters& params) { + cleanUp(); + + if (params.out.video.cropImage != 0) { + if (!Util::validateVideoFormat(params.out.video)) { + LOG(ERROR) << "Invalid video format" + << ", width: " << params.out.video.width + << ", height: " << params.out.video.height + << ", format: " << params.out.video.format + << ", minDimension: " << params.out.video.minDimension + << ", crop: " << params.out.video.cropImage; + + return false; + } + + scaleFormat_.format = params.out.video.format; + Util::setFormatDimensions( + scaleFormat_.width, + scaleFormat_.height, + params.out.video.width, + params.out.video.height, + params.in.video.width, + params.in.video.height, + 0, + 1); + + if (!(scaleFormat_ == params_.out.video)) { // crop required + cropContext_ = sws_getContext( + params.out.video.width, + params.out.video.height, + (AVPixelFormat)params_.out.video.format, + params.out.video.width, + params.out.video.height, + (AVPixelFormat)params.out.video.format, + swsFlags_, + nullptr, + nullptr, + nullptr); + + if (!cropContext_) { + LOG(ERROR) << "sws_getContext failed for crop context"; + return false; + } + + const auto scaleImageSize = av_image_get_buffer_size( + (AVPixelFormat)scaleFormat_.format, + scaleFormat_.width, + scaleFormat_.height, + 1); + scaleBuffer_.resize(scaleImageSize); + } + } else { + scaleFormat_ = params.out.video; + } + + VLOG(1) << "Input format #" << loggingUuid_ << ", width " + << params.in.video.width << ", height " << params.in.video.height + << ", format " << params.in.video.format << ", minDimension " + << params.in.video.minDimension << ", cropImage " + << params.in.video.cropImage; + VLOG(1) << "Scale format #" << loggingUuid_ << ", width " + << scaleFormat_.width << ", height " << scaleFormat_.height + << ", format " << scaleFormat_.format << ", minDimension " + << scaleFormat_.minDimension << ", cropImage " + << scaleFormat_.cropImage; + VLOG(1) << "Crop format #" << loggingUuid_ << ", width " + << params.out.video.width << ", height " << params.out.video.height + << ", format " << params.out.video.format << ", minDimension " + << params.out.video.minDimension << ", cropImage " + << params.out.video.cropImage; + + scaleContext_ = sws_getContext( + params.in.video.width, + params.in.video.height, + (AVPixelFormat)params.in.video.format, + scaleFormat_.width, + scaleFormat_.height, + (AVPixelFormat)scaleFormat_.format, + swsFlags_, + nullptr, + nullptr, + nullptr); + + // set output format + params_ = params; + + return scaleContext_ != nullptr; +} + +int VideoSampler::getImageBytes() const { + return av_image_get_buffer_size( + (AVPixelFormat)params_.out.video.format, + params_.out.video.width, + params_.out.video.height, + 1); +} + +int VideoSampler::sample( + const uint8_t* const srcSlice[], + int srcStride[], + ByteStorage* out, + bool allocateBuffer) { + int result; + // scaled and cropped image + const auto outImageSize = getImageBytes(); + if (allocateBuffer) { + out->clear(); + out->ensure(outImageSize); + } + CHECK_LE(outImageSize, out->tail()); + + uint8_t* scalePlanes[4] = {nullptr}; + int scaleLines[4] = {0}; + // perform scale first + if ((result = transformImage( + scaleContext_, + srcSlice, + srcStride, + params_.in.video, + scaleFormat_, + // for crop use internal buffer + cropContext_ ? scaleBuffer_.data() : out->writableTail(), + scalePlanes, + scaleLines))) { + return result; + } + + // is crop required? + if (cropContext_) { + uint8_t* cropPlanes[4] = {nullptr}; + int cropLines[4] = {0}; + + if (params_.out.video.height < scaleFormat_.height) { + // Destination image is wider of source image: cut top and bottom + for (size_t i = 0; i < 4 && scalePlanes[i] != nullptr; ++i) { + scalePlanes[i] += scaleLines[i] * + (scaleFormat_.height - params_.out.video.height) / 2; + } + } else { + // Source image is wider of destination image: cut sides + for (size_t i = 0; i < 4 && scalePlanes[i] != nullptr; ++i) { + scalePlanes[i] += scaleLines[i] * + (scaleFormat_.width - params_.out.video.width) / 2 / + scaleFormat_.width; + } + } + + // crop image + if ((result = transformImage( + cropContext_, + scalePlanes, + scaleLines, + params_.out.video, + params_.out.video, + out->writableTail(), + cropPlanes, + cropLines))) { + return result; + } + } + + out->append(outImageSize); + return outImageSize; +} + +int VideoSampler::sample(AVFrame* frame, ByteStorage* out) { + if (!frame) { + return 0; // no flush for videos + } + + return sample(frame->data, frame->linesize, out, false); +} + +int VideoSampler::sample(const ByteStorage* in, ByteStorage* out) { + if (!in) { + return 0; // no flush for videos + } + + int result; + uint8_t* inPlanes[4] = {nullptr}; + int inLineSize[4] = {0}; + + if ((result = preparePlanes( + params_.in.video, in->data(), inPlanes, inLineSize)) < 0) { + return result; + } + + return sample(inPlanes, inLineSize, out, true); +} + +void VideoSampler::cleanUp() { + if (scaleContext_) { + sws_freeContext(scaleContext_); + scaleContext_ = nullptr; + } + if (cropContext_) { + sws_freeContext(cropContext_); + cropContext_ = nullptr; + scaleBuffer_.clear(); + } +} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/video_sampler.h b/torchvision/csrc/cpu/decoder/video_sampler.h new file mode 100644 index 00000000000..73997c213e1 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/video_sampler.h @@ -0,0 +1,52 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "defs.h" + +extern "C" { +#include +#include "libswscale/swscale.h" +} + +namespace ffmpeg { + +/** + * Class transcode video frames from one format into another + */ + +class VideoSampler : public MediaSampler { + public: + VideoSampler(int swsFlags = SWS_AREA, int64_t loggingUuid = 0); + + ~VideoSampler() override; + + // MediaSampler overrides + bool init(const SamplerParameters& params) override; + int sample(const ByteStorage* in, ByteStorage* out) override; + void shutdown() override; + + // returns number processed/scaling bytes + int sample(AVFrame* frame, ByteStorage* out); + int getImageBytes() const; + + private: + // close resources + void cleanUp(); + // helper functions for rescaling, cropping, etc. + int sample( + const uint8_t* const srcSlice[], + int srcStride[], + ByteStorage* out, + bool allocateBuffer); + + private: + VideoFormat scaleFormat_; + SwsContext* scaleContext_{nullptr}; + SwsContext* cropContext_{nullptr}; + int swsFlags_{SWS_AREA}; + std::vector scaleBuffer_; + int64_t loggingUuid_{0}; +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/video_stream.cpp b/torchvision/csrc/cpu/decoder/video_stream.cpp new file mode 100644 index 00000000000..9c6b77d0bfc --- /dev/null +++ b/torchvision/csrc/cpu/decoder/video_stream.cpp @@ -0,0 +1,143 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "video_stream.h" +#include +#include "util.h" + +namespace ffmpeg { + +namespace { +bool operator==(const VideoFormat& x, const AVFrame& y) { + return x.width == y.width && x.height == y.height && x.format == y.format; +} + +VideoFormat& toVideoFormat(VideoFormat& x, const AVFrame& y) { + x.width = y.width; + x.height = y.height; + x.format = y.format; + return x; +} +} // namespace + +VideoStream::VideoStream( + AVFormatContext* inputCtx, + int index, + bool convertPtsToWallTime, + const VideoFormat& format, + int64_t loggingUuid) + : Stream( + inputCtx, + MediaFormat::makeMediaFormat(format, index), + convertPtsToWallTime), + loggingUuid_(loggingUuid) {} + +VideoStream::~VideoStream() { + if (sampler_) { + sampler_->shutdown(); + sampler_.reset(); + } +} + +void VideoStream::ensureSampler() { + if (!sampler_) { + sampler_ = std::make_unique(SWS_AREA, loggingUuid_); + } +} + +int VideoStream::initFormat() { + // set output format + if (!Util::validateVideoFormat(format_.format.video)) { + LOG(ERROR) << "Invalid video format" + << ", width: " << format_.format.video.width + << ", height: " << format_.format.video.height + << ", format: " << format_.format.video.format + << ", minDimension: " << format_.format.video.minDimension + << ", crop: " << format_.format.video.cropImage; + return -1; + } + + // keep aspect ratio + Util::setFormatDimensions( + format_.format.video.width, + format_.format.video.height, + format_.format.video.width, + format_.format.video.height, + codecCtx_->width, + codecCtx_->height, + format_.format.video.minDimension, + 0); + + if (format_.format.video.format == AV_PIX_FMT_NONE) { + format_.format.video.format = codecCtx_->pix_fmt; + } + return format_.format.video.width != 0 && format_.format.video.height != 0 && + format_.format.video.format != AV_PIX_FMT_NONE + ? 0 + : -1; +} + +int VideoStream::estimateBytes(bool flush) { + ensureSampler(); + // check if input format gets changed + if (!flush && !(sampler_->getInputFormat().video == *frame_)) { + // - reinit sampler + SamplerParameters params; + params.type = format_.type; + params.out = format_.format; + toVideoFormat(params.in.video, *frame_); + if (!sampler_->init(params)) { + return -1; + } + + VLOG(1) << "Set input video sampler format" + << ", width: " << params.in.video.width + << ", height: " << params.in.video.height + << ", format: " << params.in.video.format + << " : output video sampler format" + << ", width: " << format_.format.video.width + << ", height: " << format_.format.video.height + << ", format: " << format_.format.video.format + << ", minDimension: " << format_.format.video.minDimension + << ", crop: " << format_.format.video.cropImage; + } + return sampler_->getImageBytes(); +} + +int VideoStream::copyFrameBytes(ByteStorage* out, bool flush) { + ensureSampler(); + return sampler_->sample(flush ? nullptr : frame_, out); +} + +void VideoStream::setHeader(DecoderHeader* header) { + header->seqno = numGenerator_++; + + if (codecCtx_->time_base.num != 0) { + header->pts = av_rescale_q( + av_frame_get_best_effort_timestamp(frame_), + codecCtx_->time_base, + AV_TIME_BASE_Q); + } else { + // If the codec time_base is missing then we would've skipped the + // rescalePackage step to rescale to codec time_base, so here we can + // rescale straight from the stream time_base into AV_TIME_BASE_Q. + header->pts = av_rescale_q( + av_frame_get_best_effort_timestamp(frame_), + inputCtx_->streams[format_.stream]->time_base, + AV_TIME_BASE_Q); + } + + if (convertPtsToWallTime_) { + keeper_.adjust(header->pts); + } + + header->keyFrame = frame_->key_frame; + auto fpsRational = inputCtx_->streams[format_.stream]->avg_frame_rate; + if (fpsRational.den) { + header->fps = av_q2d(fpsRational); + } else { + header->fps = std::numeric_limits::quiet_NaN(); + } + header->format = format_; +} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/video_stream.h b/torchvision/csrc/cpu/decoder/video_stream.h new file mode 100644 index 00000000000..af1e3fb960f --- /dev/null +++ b/torchvision/csrc/cpu/decoder/video_stream.h @@ -0,0 +1,39 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include "stream.h" +#include "time_keeper.h" +#include "video_sampler.h" + +namespace ffmpeg { + +/** + * Class uses FFMPEG library to decode one video stream. + */ + +class VideoStream : public Stream { + public: + VideoStream( + AVFormatContext* inputCtx, + int index, + bool convertPtsToWallTime, + const VideoFormat& format, + int64_t loggingUuid = 0); + ~VideoStream() override; + + private: + int initFormat() override; + int estimateBytes(bool flush) override; + int copyFrameBytes(ByteStorage* out, bool flush) override; + void setHeader(DecoderHeader* header) override; + + void ensureSampler(); + + private: + std::unique_ptr sampler_; + TimeKeeper keeper_; + int64_t loggingUuid_{0}; +}; + +} // namespace ffmpeg From 3a536c99d32c844fab619aeecf2831331693ce24 Mon Sep 17 00:00:00 2001 From: Jon Guerin Date: Tue, 21 Jan 2020 09:44:56 -0800 Subject: [PATCH 016/357] torchscriptable functions for video io (#1653) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1653 created new torchscriptable video io functions as part of the api: read_video_meta_data_from_memory and read_video_from_memory. Updated the implementation of some of the internal functions to be torchscriptable. Reviewed By: stephenyan1231 Differential Revision: D18720474 fbshipit-source-id: 4ee646b66afecd2dc338a71fd8f249f25a3263bc --- test/test_datasets_video_utils.py | 4 +- test/test_io.py | 8 +- test/test_video_reader.py | 169 ++++++++++++++----- torchvision/datasets/video_utils.py | 106 ++++++++---- torchvision/io/__init__.py | 37 +++- torchvision/io/_video_opt.py | 250 +++++++++++++++++++--------- torchvision/io/video.py | 154 ++++++++++++----- 7 files changed, 512 insertions(+), 216 deletions(-) diff --git a/test/test_datasets_video_utils.py b/test/test_datasets_video_utils.py index 1a5c087cd75..a3af7366157 100644 --- a/test/test_datasets_video_utils.py +++ b/test/test_datasets_video_utils.py @@ -1,5 +1,4 @@ import contextlib -import sys import os import torch import unittest @@ -91,8 +90,7 @@ def test_video_clips_custom_fps(self): for i in range(video_clips.num_clips()): video, audio, info, video_idx = video_clips.get_clip(i) self.assertEqual(video.shape[0], num_frames) - self.assertEqual(info["video_fps"], fps) - self.assertEqual(info, {"video_fps": fps}) + self.assertEqual(info.video_fps, fps) # TODO add tests checking that the content is right def test_compute_clips_for_video(self): diff --git a/test/test_io.py b/test/test_io.py index 92c43a4431b..4c01f9ecb32 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -81,8 +81,8 @@ def test_write_read_video(self): def test_probe_video_from_file(self): with temp_video(10, 300, 300, 5) as (f_name, data): video_info = io._probe_video_from_file(f_name) - self.assertAlmostEqual(video_info["video_duration"], 2, delta=0.1) - self.assertAlmostEqual(video_info["video_fps"], 5, delta=0.1) + self.assertAlmostEqual(video_info.video_duration, 2, delta=0.1) + self.assertAlmostEqual(video_info.video_fps, 5, delta=0.1) @unittest.skipIf(not io._HAS_VIDEO_OPT, "video_reader backend is not chosen") def test_probe_video_from_memory(self): @@ -90,8 +90,8 @@ def test_probe_video_from_memory(self): with open(f_name, "rb") as fp: filebuffer = fp.read() video_info = io._probe_video_from_memory(filebuffer) - self.assertAlmostEqual(video_info["video_duration"], 2, delta=0.1) - self.assertAlmostEqual(video_info["video_fps"], 5, delta=0.1) + self.assertAlmostEqual(video_info.video_duration, 2, delta=0.1) + self.assertAlmostEqual(video_info.video_fps, 5, delta=0.1) def test_read_timestamps(self): with temp_video(10, 300, 300, 5) as (f_name, data): diff --git a/test/test_video_reader.py b/test/test_video_reader.py index bf59eb7dc4d..ec0fa75da1d 100644 --- a/test/test_video_reader.py +++ b/test/test_video_reader.py @@ -1,18 +1,21 @@ import collections -from common_utils import get_tmp_dir -from fractions import Fraction import math -import numpy as np import os import sys import time +import unittest +from fractions import Fraction + +import numpy as np import torch import torchvision.io as io -import unittest from numpy.random import randint +from torchvision.io import _HAS_VIDEO_OPT + try: import av + # Do a version test too io.video._check_av_available() except ImportError: @@ -25,9 +28,6 @@ from urllib.error import URLError -from torchvision.io import _HAS_VIDEO_OPT - - VIDEO_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "videos") CheckerConfig = [ @@ -39,10 +39,7 @@ "check_aframes", "check_aframe_pts", ] -GroundTruth = collections.namedtuple( - "GroundTruth", - " ".join(CheckerConfig) -) +GroundTruth = collections.namedtuple("GroundTruth", " ".join(CheckerConfig)) all_check_config = GroundTruth( duration=0, @@ -193,9 +190,9 @@ def _decode_frames_by_av_module( frames are read """ if video_end_pts is None: - video_end_pts = float('inf') + video_end_pts = float("inf") if audio_end_pts is None: - audio_end_pts = float('inf') + audio_end_pts = float("inf") container = av.open(full_path) video_frames = [] @@ -282,8 +279,10 @@ class TestVideoReader(unittest.TestCase): def check_separate_decoding_result(self, tv_result, config): """check the decoding results from TorchVision decoder """ - vframes, vframe_pts, vtimebase, vfps, vduration, aframes, aframe_pts, \ - atimebase, asample_rate, aduration = tv_result + vframes, vframe_pts, vtimebase, vfps, vduration, \ + aframes, aframe_pts, atimebase, asample_rate, aduration = ( + tv_result + ) video_duration = vduration.item() * Fraction( vtimebase[0].item(), vtimebase[1].item() @@ -321,6 +320,13 @@ def check_probe_result(self, result, config): ) self.assertAlmostEqual(audio_duration, config.duration, delta=0.5) + def check_meta_result(self, result, config): + self.assertAlmostEqual(result.video_duration, config.duration, delta=0.5) + self.assertAlmostEqual(result.video_fps, config.video_fps, delta=0.5) + if result.has_audio > 0: + self.assertEqual(result.audio_sample_rate, config.audio_sample_rate) + self.assertAlmostEqual(result.audio_duration, config.duration, delta=0.5) + def compare_decoding_result(self, tv_result, ref_result, config=all_check_config): """ Compare decoding results from two sources. @@ -330,8 +336,10 @@ def compare_decoding_result(self, tv_result, ref_result, config=all_check_config decoder or TorchVision decoder with getPtsOnly = 1 config: config of decoding results checker """ - vframes, vframe_pts, vtimebase, _vfps, _vduration, aframes, aframe_pts, \ - atimebase, _asample_rate, _aduration = tv_result + vframes, vframe_pts, vtimebase, _vfps, _vduration, \ + aframes, aframe_pts, atimebase, _asample_rate, _aduration = ( + tv_result + ) if isinstance(ref_result, list): # the ref_result is from new video_reader decoder ref_result = DecoderResult( @@ -344,22 +352,34 @@ def compare_decoding_result(self, tv_result, ref_result, config=all_check_config ) if vframes.numel() > 0 and ref_result.vframes.numel() > 0: - mean_delta = torch.mean(torch.abs(vframes.float() - ref_result.vframes.float())) + mean_delta = torch.mean( + torch.abs(vframes.float() - ref_result.vframes.float()) + ) self.assertAlmostEqual(mean_delta, 0, delta=8.0) - mean_delta = torch.mean(torch.abs(vframe_pts.float() - ref_result.vframe_pts.float())) + mean_delta = torch.mean( + torch.abs(vframe_pts.float() - ref_result.vframe_pts.float()) + ) self.assertAlmostEqual(mean_delta, 0, delta=1.0) is_same = torch.all(torch.eq(vtimebase, ref_result.vtimebase)).item() self.assertEqual(is_same, True) - if config.check_aframes and aframes.numel() > 0 and ref_result.aframes.numel() > 0: + if ( + config.check_aframes + and aframes.numel() > 0 + and ref_result.aframes.numel() > 0 + ): """Audio stream is available and audio frame is required to return from decoder""" is_same = torch.all(torch.eq(aframes, ref_result.aframes)).item() self.assertEqual(is_same, True) - if config.check_aframe_pts and aframe_pts.numel() > 0 and ref_result.aframe_pts.numel() > 0: + if ( + config.check_aframe_pts + and aframe_pts.numel() > 0 + and ref_result.aframe_pts.numel() > 0 + ): """Audio stream is available""" is_same = torch.all(torch.eq(aframe_pts, ref_result.aframe_pts)).item() self.assertEqual(is_same, True) @@ -492,15 +512,19 @@ def test_read_video_from_file_read_single_stream_only(self): audio_timebase_den, ) - vframes, vframe_pts, vtimebase, vfps, vduration, aframes, aframe_pts, \ - atimebase, asample_rate, aduration = tv_result + vframes, vframe_pts, vtimebase, vfps, vduration, \ + aframes, aframe_pts, atimebase, asample_rate, aduration = ( + tv_result + ) self.assertEqual(vframes.numel() > 0, readVideoStream) self.assertEqual(vframe_pts.numel() > 0, readVideoStream) self.assertEqual(vtimebase.numel() > 0, readVideoStream) self.assertEqual(vfps.numel() > 0, readVideoStream) - expect_audio_data = readAudioStream == 1 and config.audio_sample_rate is not None + expect_audio_data = ( + readAudioStream == 1 and config.audio_sample_rate is not None + ) self.assertEqual(aframes.numel() > 0, expect_audio_data) self.assertEqual(aframe_pts.numel() > 0, expect_audio_data) self.assertEqual(atimebase.numel() > 0, expect_audio_data) @@ -543,7 +567,9 @@ def test_read_video_from_file_rescale_min_dimension(self): audio_timebase_num, audio_timebase_den, ) - self.assertEqual(min_dimension, min(tv_result[0].size(1), tv_result[0].size(2))) + self.assertEqual( + min_dimension, min(tv_result[0].size(1), tv_result[0].size(2)) + ) def test_read_video_from_file_rescale_width(self): """ @@ -669,10 +695,7 @@ def test_read_video_from_file_audio_resampling(self): audio waveform are resampled """ - for samples in [ - 9600, # downsampling - 96000, # upsampling - ]: + for samples in [9600, 96000]: # downsampling # upsampling # video related width, height, min_dimension = 0, 0, 0 video_start_pts, video_end_pts = 0, -1 @@ -705,13 +728,19 @@ def test_read_video_from_file_audio_resampling(self): audio_timebase_num, audio_timebase_den, ) - vframes, vframe_pts, vtimebase, vfps, vduration, aframes, aframe_pts, \ - atimebase, asample_rate, aduration = tv_result + vframes, vframe_pts, vtimebase, vfps, vduration, \ + aframes, aframe_pts, atimebase, asample_rate, aduration = ( + tv_result + ) if aframes.numel() > 0: self.assertEqual(samples, asample_rate.item()) self.assertEqual(1, aframes.size(1)) # when audio stream is found - duration = float(aframe_pts[-1]) * float(atimebase[0]) / float(atimebase[1]) + duration = ( + float(aframe_pts[-1]) + * float(atimebase[0]) + / float(atimebase[1]) + ) self.assertAlmostEqual( aframes.size(0), int(duration * asample_rate.item()), @@ -929,8 +958,10 @@ def test_read_video_in_range_from_memory(self): audio_timebase_num, audio_timebase_den, ) - vframes, vframe_pts, vtimebase, vfps, vduration, aframes, aframe_pts, \ - atimebase, asample_rate, aduration = tv_result + vframes, vframe_pts, vtimebase, vfps, vduration, \ + aframes, aframe_pts, atimebase, asample_rate, aduration = ( + tv_result + ) self.assertAlmostEqual(config.video_fps, vfps.item(), delta=0.01) for num_frames in [4, 8, 16, 32, 64, 128]: @@ -983,31 +1014,41 @@ def test_read_video_in_range_from_memory(self): ) # pass 3: decode frames in range using PyAv - video_timebase_av, audio_timebase_av = _get_timebase_by_av_module(full_path) + video_timebase_av, audio_timebase_av = _get_timebase_by_av_module( + full_path + ) video_start_pts_av = _pts_convert( video_start_pts.item(), Fraction(video_timebase_num.item(), video_timebase_den.item()), - Fraction(video_timebase_av.numerator, video_timebase_av.denominator), + Fraction( + video_timebase_av.numerator, video_timebase_av.denominator + ), math.floor, ) video_end_pts_av = _pts_convert( video_end_pts.item(), Fraction(video_timebase_num.item(), video_timebase_den.item()), - Fraction(video_timebase_av.numerator, video_timebase_av.denominator), + Fraction( + video_timebase_av.numerator, video_timebase_av.denominator + ), math.ceil, ) if audio_timebase_av: audio_start_pts = _pts_convert( video_start_pts.item(), Fraction(video_timebase_num.item(), video_timebase_den.item()), - Fraction(audio_timebase_av.numerator, audio_timebase_av.denominator), + Fraction( + audio_timebase_av.numerator, audio_timebase_av.denominator + ), math.floor, ) audio_end_pts = _pts_convert( video_end_pts.item(), Fraction(video_timebase_num.item(), video_timebase_den.item()), - Fraction(audio_timebase_av.numerator, audio_timebase_av.denominator), + Fraction( + audio_timebase_av.numerator, audio_timebase_av.denominator + ), math.ceil, ) @@ -1044,6 +1085,54 @@ def test_probe_video_from_memory(self): probe_result = torch.ops.video_reader.probe_video_from_memory(video_tensor) self.check_probe_result(probe_result, config) + def test_read_video_meta_data_from_memory_script(self): + scripted_fun = torch.jit.script(io.read_video_meta_data_from_memory) + self.assertIsNotNone(scripted_fun) + + for test_video, config in test_videos.items(): + full_path, video_tensor = _get_video_tensor(VIDEO_DIR, test_video) + probe_result = scripted_fun(video_tensor) + self.check_meta_result(probe_result, config) + + def test_read_video_from_memory_scripted(self): + """ + Test the case when video is already in memory, and decoder reads data in memory + """ + # video related + width, height, min_dimension = 0, 0, 0 + video_start_pts, video_end_pts = 0, -1 + video_timebase_num, video_timebase_den = 0, 1 + # audio related + samples, channels = 0, 0 + audio_start_pts, audio_end_pts = 0, -1 + audio_timebase_num, audio_timebase_den = 0, 1 + + scripted_fun = torch.jit.script(io.read_video_from_memory) + self.assertIsNotNone(scripted_fun) + + for test_video, _config in test_videos.items(): + full_path, video_tensor = _get_video_tensor(VIDEO_DIR, test_video) + + # decode all frames using cpp decoder + scripted_fun( + video_tensor, + seek_frame_margin, + 1, # readVideoStream + width, + height, + min_dimension, + [video_start_pts, video_end_pts], + video_timebase_num, + video_timebase_den, + 1, # readAudioStream + samples, + channels, + [audio_start_pts, audio_end_pts], + audio_timebase_num, + audio_timebase_den, + ) + # FUTURE: check value of video / audio frames + -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/torchvision/datasets/video_utils.py b/torchvision/datasets/video_utils.py index d2a5e12316e..055d3d5cd8c 100644 --- a/torchvision/datasets/video_utils.py +++ b/torchvision/datasets/video_utils.py @@ -1,13 +1,15 @@ import bisect -from fractions import Fraction import math +from fractions import Fraction + import torch from torchvision.io import ( - _read_video_timestamps_from_file, + _probe_video_from_file, _read_video_from_file, - _probe_video_from_file + _read_video_timestamps_from_file, + read_video, + read_video_timestamps, ) -from torchvision.io import read_video_timestamps, read_video from .utils import tqdm @@ -48,6 +50,7 @@ class _DummyDataset(object): Dummy dataset used for DataLoader in VideoClips. Defined at top level so it can be pickled when forking. """ + def __init__(self, x): self.x = x @@ -83,10 +86,21 @@ class VideoClips(object): num_workers (int): how many subprocesses to use for data loading. 0 means that the data will be loaded in the main process. (default: 0) """ - def __init__(self, video_paths, clip_length_in_frames=16, frames_between_clips=1, - frame_rate=None, _precomputed_metadata=None, num_workers=0, - _video_width=0, _video_height=0, _video_min_dimension=0, - _audio_samples=0, _audio_channels=0): + + def __init__( + self, + video_paths, + clip_length_in_frames=16, + frames_between_clips=1, + frame_rate=None, + _precomputed_metadata=None, + num_workers=0, + _video_width=0, + _video_height=0, + _video_min_dimension=0, + _audio_samples=0, + _audio_channels=0, + ): self.video_paths = video_paths self.num_workers = num_workers @@ -114,11 +128,13 @@ def _compute_frame_pts(self): # strategy: use a DataLoader to parallelize read_video_timestamps # so need to create a dummy dataset first import torch.utils.data + dl = torch.utils.data.DataLoader( _DummyDataset(self.video_paths), batch_size=16, num_workers=self.num_workers, - collate_fn=self._collate_fn) + collate_fn=self._collate_fn, + ) with tqdm(total=len(dl)) as pbar: for batch in dl: @@ -140,7 +156,7 @@ def metadata(self): _metadata = { "video_paths": self.video_paths, "video_pts": self.video_pts, - "video_fps": self.video_fps + "video_fps": self.video_fps, } return _metadata @@ -151,15 +167,21 @@ def subset(self, indices): metadata = { "video_paths": video_paths, "video_pts": video_pts, - "video_fps": video_fps + "video_fps": video_fps, } - return type(self)(video_paths, self.num_frames, self.step, self.frame_rate, - _precomputed_metadata=metadata, num_workers=self.num_workers, - _video_width=self._video_width, - _video_height=self._video_height, - _video_min_dimension=self._video_min_dimension, - _audio_samples=self._audio_samples, - _audio_channels=self._audio_channels) + return type(self)( + video_paths, + self.num_frames, + self.step, + self.frame_rate, + _precomputed_metadata=metadata, + num_workers=self.num_workers, + _video_width=self._video_width, + _video_height=self._video_height, + _video_min_dimension=self._video_min_dimension, + _audio_samples=self._audio_samples, + _audio_channels=self._audio_channels, + ) @staticmethod def compute_clips_for_video(video_pts, num_frames, step, fps, frame_rate): @@ -170,7 +192,9 @@ def compute_clips_for_video(video_pts, num_frames, step, fps, frame_rate): if frame_rate is None: frame_rate = fps total_frames = len(video_pts) * (float(frame_rate) / fps) - idxs = VideoClips._resample_video_idx(int(math.floor(total_frames)), fps, frame_rate) + idxs = VideoClips._resample_video_idx( + int(math.floor(total_frames)), fps, frame_rate + ) video_pts = video_pts[idxs] clips = unfold(video_pts, num_frames, step) if isinstance(idxs, slice): @@ -195,7 +219,9 @@ def compute_clips(self, num_frames, step, frame_rate=None): self.clips = [] self.resampling_idxs = [] for video_pts, fps in zip(self.video_pts, self.video_fps): - clips, idxs = self.compute_clips_for_video(video_pts, num_frames, step, fps, frame_rate) + clips, idxs = self.compute_clips_for_video( + video_pts, num_frames, step, fps, frame_rate + ) self.clips.append(clips) self.resampling_idxs.append(idxs) clip_lengths = torch.as_tensor([len(v) for v in self.clips]) @@ -251,13 +277,16 @@ def get_clip(self, idx): video_idx (int): index of the video in `video_paths` """ if idx >= self.num_clips(): - raise IndexError("Index {} out of range " - "({} number of clips)".format(idx, self.num_clips())) + raise IndexError( + "Index {} out of range " + "({} number of clips)".format(idx, self.num_clips()) + ) video_idx, clip_idx = self.get_clip_location(idx) video_path = self.video_paths[video_idx] clip_pts = self.clips[video_idx][clip_idx] from torchvision import get_video_backend + backend = get_video_backend() if backend == "pyav": @@ -267,7 +296,9 @@ def get_clip(self, idx): if self._video_height != 0: raise ValueError("pyav backend doesn't support _video_height != 0") if self._video_min_dimension != 0: - raise ValueError("pyav backend doesn't support _video_min_dimension != 0") + raise ValueError( + "pyav backend doesn't support _video_min_dimension != 0" + ) if self._audio_samples != 0: raise ValueError("pyav backend doesn't support _audio_samples != 0") @@ -277,7 +308,7 @@ def get_clip(self, idx): video, audio, info = read_video(video_path, start_pts, end_pts) else: info = _probe_video_from_file(video_path) - video_fps = info["video_fps"] + video_fps = info.video_fps audio_fps = None video_start_pts = clip_pts[0].item() @@ -285,28 +316,27 @@ def get_clip(self, idx): audio_start_pts, audio_end_pts = 0, -1 audio_timebase = Fraction(0, 1) - if "audio_timebase" in info: - audio_timebase = info["audio_timebase"] + video_timebase = Fraction( + info.video_timebase.numerator, info.video_timebase.denominator + ) + if info.has_audio: + audio_timebase = Fraction( + info.audio_timebase.numerator, info.audio_timebase.denominator + ) audio_start_pts = pts_convert( - video_start_pts, - info["video_timebase"], - info["audio_timebase"], - math.floor, + video_start_pts, video_timebase, audio_timebase, math.floor ) audio_end_pts = pts_convert( - video_end_pts, - info["video_timebase"], - info["audio_timebase"], - math.ceil, + video_end_pts, video_timebase, audio_timebase, math.ceil ) - audio_fps = info["audio_sample_rate"] + audio_fps = info.audio_sample_rate video, audio, info = _read_video_from_file( video_path, video_width=self._video_width, video_height=self._video_height, video_min_dimension=self._video_min_dimension, video_pts_range=(video_start_pts, video_end_pts), - video_timebase=info["video_timebase"], + video_timebase=video_timebase, audio_samples=self._audio_samples, audio_channels=self._audio_channels, audio_pts_range=(audio_start_pts, audio_end_pts), @@ -323,5 +353,7 @@ def get_clip(self, idx): resampling_idx = resampling_idx - resampling_idx[0] video = video[resampling_idx] info["video_fps"] = self.frame_rate - assert len(video) == self.num_frames, "{} x {}".format(video.shape, self.num_frames) + assert len(video) == self.num_frames, "{} x {}".format( + video.shape, self.num_frames + ) return video, audio, info, video_idx diff --git a/torchvision/io/__init__.py b/torchvision/io/__init__.py index 0f093b65538..713113a0ae1 100644 --- a/torchvision/io/__init__.py +++ b/torchvision/io/__init__.py @@ -1,17 +1,38 @@ -from .video import write_video, read_video, read_video_timestamps, _HAS_VIDEO_OPT from ._video_opt import ( - _read_video_from_file, - _read_video_timestamps_from_file, + Timebase, + VideoMetaData, + _HAS_VIDEO_OPT, _probe_video_from_file, + _probe_video_from_memory, + _read_video_from_file, _read_video_from_memory, + _read_video_timestamps_from_file, _read_video_timestamps_from_memory, - _probe_video_from_memory, +) +from .video import ( + read_video, + read_video_from_memory, + read_video_meta_data_from_memory, + read_video_timestamps, + write_video, ) __all__ = [ - 'write_video', 'read_video', 'read_video_timestamps', - '_read_video_from_file', '_read_video_timestamps_from_file', '_probe_video_from_file', - '_read_video_from_memory', '_read_video_timestamps_from_memory', '_probe_video_from_memory', - '_HAS_VIDEO_OPT', + "write_video", + "read_video", + "read_video_timestamps", + "read_video_meta_data_from_memory", + "read_video_from_memory", + "_read_video_from_file", + "_read_video_timestamps_from_file", + "_probe_video_from_file", + "_read_video_from_memory", + "_read_video_timestamps_from_memory", + "_probe_video_from_memory", + "_HAS_VIDEO_OPT", + "_read_video_clip_from_memory", + "_read_video_meta_data", + "VideoMetaData", + "Timebase", ] diff --git a/torchvision/io/_video_opt.py b/torchvision/io/_video_opt.py index fa215680363..aa4b4244962 100644 --- a/torchvision/io/_video_opt.py +++ b/torchvision/io/_video_opt.py @@ -1,41 +1,124 @@ -from fractions import Fraction + +import imp import math +import os +import warnings +from fractions import Fraction +from typing import List, Tuple + import numpy as np import torch -import warnings + + +_HAS_VIDEO_OPT = False + +try: + lib_dir = os.path.join(os.path.dirname(__file__), "..") + _, path, description = imp.find_module("video_reader", [lib_dir]) + torch.ops.load_library(path) + _HAS_VIDEO_OPT = True +except (ImportError, OSError): + pass default_timebase = Fraction(0, 1) +# simple class for torch scripting +# the complex Fraction class from fractions module is not scriptable +@torch.jit.script +class Timebase(object): + __annotations__ = {"numerator": int, "denominator": int} + __slots__ = ["numerator", "denominator"] + + def __init__( + self, + numerator, # type: int + denominator, # type: int + ): + # type: (...) -> None + self.numerator = numerator + self.denominator = denominator + + +@torch.jit.script +class VideoMetaData(object): + __annotations__ = { + "has_video": bool, + "video_timebase": Timebase, + "video_duration": float, + "video_fps": float, + "has_audio": bool, + "audio_timebase": Timebase, + "audio_duration": float, + "audio_sample_rate": float, + } + __slots__ = [ + "has_video", + "video_timebase", + "video_duration", + "video_fps", + "has_audio", + "audio_timebase", + "audio_duration", + "audio_sample_rate", + ] + + def __init__(self): + self.has_video = False + self.video_timebase = Timebase(0, 1) + self.video_duration = 0.0 + self.video_fps = 0.0 + self.has_audio = False + self.audio_timebase = Timebase(0, 1) + self.audio_duration = 0.0 + self.audio_sample_rate = 0.0 + + def _validate_pts(pts_range): + # type: (List[int]) if pts_range[1] > 0: - assert pts_range[0] <= pts_range[1], \ - """Start pts should not be smaller than end pts, got - start pts: %d and end pts: %d""" % (pts_range[0], pts_range[1]) + assert ( + pts_range[0] <= pts_range[1] + ), """Start pts should not be smaller than end pts, got + start pts: %d and end pts: %d""" % ( + pts_range[0], + pts_range[1], + ) def _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration): - info = {} + # type: (torch.Tensor,torch.Tensor,torch.Tensor,torch.Tensor,torch.Tensor,torch.Tensor) -> VideoMetaData + """ + Build update VideoMetaData struct with info about the video + """ + meta = VideoMetaData() if vtimebase.numel() > 0: - info["video_timebase"] = Fraction(vtimebase[0].item(), vtimebase[1].item()) + meta.video_timebase = Timebase( + int(vtimebase[0].item()), int(vtimebase[1].item()) + ) + timebase = vtimebase[0].item() / float(vtimebase[1].item()) if vduration.numel() > 0: - video_duration = vduration.item() * info["video_timebase"] - info["video_duration"] = video_duration + meta.has_video = True + meta.video_duration = float(vduration.item()) * timebase if vfps.numel() > 0: - info["video_fps"] = vfps.item() + meta.video_fps = float(vfps.item()) if atimebase.numel() > 0: - info["audio_timebase"] = Fraction(atimebase[0].item(), atimebase[1].item()) + meta.audio_timebase = Timebase( + int(atimebase[0].item()), int(atimebase[1].item()) + ) + timebase = atimebase[0].item() / float(atimebase[1].item()) if aduration.numel() > 0: - audio_duration = aduration.item() * info["audio_timebase"] - info["audio_duration"] = audio_duration + meta.has_audio = True + meta.audio_duration = float(aduration.item()) * timebase if asample_rate.numel() > 0: - info["audio_sample_rate"] = asample_rate.item() + meta.audio_sample_rate = float(asample_rate.item()) - return info + return meta def _align_audio_frames(aframes, aframe_pts, audio_pts_range): + # type: (torch.Tensor, torch.Tensor, List[int]) -> torch.Tensor start, end = aframe_pts[0], aframe_pts[-1] num_samples = aframes.size(0) step_per_aframe = float(end - start + 1) / float(num_samples) @@ -136,8 +219,10 @@ def _read_video_from_file( audio_timebase.numerator, audio_timebase.denominator, ) - vframes, _vframe_pts, vtimebase, vfps, vduration, aframes, aframe_pts, atimebase, \ - asample_rate, aduration = result + vframes, _vframe_pts, vtimebase, vfps, vduration, \ + aframes, aframe_pts, atimebase, asample_rate, aduration = ( + result + ) info = _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration) if aframes.numel() > 0: # when audio stream is found @@ -171,8 +256,8 @@ def _read_video_timestamps_from_file(filename): 0, # audio_timebase_num 1, # audio_timebase_den ) - _vframes, vframe_pts, vtimebase, vfps, vduration, _aframes, aframe_pts, atimebase, \ - asample_rate, aduration = result + _vframes, vframe_pts, vtimebase, vfps, vduration, \ + _aframes, aframe_pts, atimebase, asample_rate, aduration = (result) info = _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration) vframe_pts = vframe_pts.numpy().tolist() @@ -182,10 +267,7 @@ def _read_video_timestamps_from_file(filename): def _probe_video_from_file(filename): """ - Probe a video file. - Return: - info [dict]: contain video meta information, including video_timebase, - video_duration, video_fps, audio_timebase, audio_duration, audio_sample_rate + Probe a video file and return VideoMetaData with info about the video """ result = torch.ops.video_reader.probe_video_from_file(filename) vtimebase, vfps, vduration, atimebase, asample_rate, aduration = result @@ -194,23 +276,27 @@ def _probe_video_from_file(filename): def _read_video_from_memory( - video_data, - seek_frame_margin=0.25, - read_video_stream=1, - video_width=0, - video_height=0, - video_min_dimension=0, - video_pts_range=(0, -1), - video_timebase=default_timebase, - read_audio_stream=1, - audio_samples=0, - audio_channels=0, - audio_pts_range=(0, -1), - audio_timebase=default_timebase, + video_data, # type: torch.Tensor + seek_frame_margin=0.25, # type: float + read_video_stream=1, # type: int + video_width=0, # type: int + video_height=0, # type: int + video_min_dimension=0, # type: int + video_pts_range=(0, -1), # type: List[int] + video_timebase_numerator=0, # type: int + video_timebase_denominator=1, # type: int + read_audio_stream=1, # type: int + audio_samples=0, # type: int + audio_channels=0, # type: int + audio_pts_range=(0, -1), # type: List[int] + audio_timebase_numerator=0, # type: int + audio_timebase_denominator=1, # type: int ): + # type: (...) -> Tuple[torch.Tensor, torch.Tensor] """ Reads a video from memory, returning both the video frames as well as the audio frames + This function is torchscriptable. Args ---------- @@ -234,8 +320,8 @@ def _read_video_from_memory( are set to $video_width and $video_height, respectively video_pts_range : list(int), optional the start and end presentation timestamp of video stream - video_timebase: Fraction, optional - a Fraction rational number which denotes timebase in video stream + video_timebase_numerator / video_timebase_denominator: optional + a rational number which denotes timebase in video stream read_audio_stream: int, optional whether read audio stream. If yes, set to 1. Otherwise, 0 audio_samples: int, optional @@ -244,8 +330,8 @@ def _read_video_from_memory( audio audio_channels audio_pts_range : list(int), optional the start and end presentation timestamp of audio stream - audio_timebase: Fraction, optional - a Fraction rational number which denotes time base in audio stream + audio_timebase_numerator / audio_timebase_denominator: optional + a rational number which denotes time base in audio stream Returns ------- @@ -254,17 +340,11 @@ def _read_video_from_memory( aframes : Tensor[L, K] the audio frames, where `L` is the number of points and `K` is the number of channels - info : Dict - metadata for the video and audio. Can contain the fields video fps (float) - and audio sample rate (int) """ _validate_pts(video_pts_range) _validate_pts(audio_pts_range) - if not isinstance(video_data, torch.Tensor): - video_data = torch.from_numpy(np.frombuffer(video_data, dtype=np.uint8)) - result = torch.ops.video_reader.read_video_from_memory( video_data, seek_frame_margin, @@ -275,24 +355,27 @@ def _read_video_from_memory( video_min_dimension, video_pts_range[0], video_pts_range[1], - video_timebase.numerator, - video_timebase.denominator, + video_timebase_numerator, + video_timebase_denominator, read_audio_stream, audio_samples, audio_channels, audio_pts_range[0], audio_pts_range[1], - audio_timebase.numerator, - audio_timebase.denominator, + audio_timebase_numerator, + audio_timebase_denominator, ) - vframes, _vframe_pts, vtimebase, vfps, vduration, aframes, aframe_pts, \ - atimebase, asample_rate, aduration = result - info = _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration) + vframes, _vframe_pts, vtimebase, vfps, vduration, \ + aframes, aframe_pts, atimebase, asample_rate, aduration = ( + result + ) + if aframes.numel() > 0: # when audio stream is found aframes = _align_audio_frames(aframes, aframe_pts, audio_pts_range) - return vframes, aframes, info + + return vframes, aframes def _read_video_timestamps_from_memory(video_data): @@ -323,8 +406,10 @@ def _read_video_timestamps_from_memory(video_data): 0, # audio_timebase_num 1, # audio_timebase_den ) - _vframes, vframe_pts, vtimebase, vfps, vduration, _aframes, aframe_pts, \ - atimebase, asample_rate, aduration = result + _vframes, vframe_pts, vtimebase, vfps, vduration, \ + _aframes, aframe_pts, atimebase, asample_rate, aduration = ( + result + ) info = _fill_info(vtimebase, vfps, vduration, atimebase, asample_rate, aduration) vframe_pts = vframe_pts.numpy().tolist() @@ -333,11 +418,10 @@ def _read_video_timestamps_from_memory(video_data): def _probe_video_from_memory(video_data): + # type: (torch.Tensor) -> VideoMetaData """ - Probe a video in memory. - Return: - info [dict]: contain video meta information, including video_timebase, - video_duration, video_fps, audio_timebase, audio_duration, audio_sample_rate + Probe a video in memory and return VideoMetaData with info about the video + This function is torchscriptable """ if not isinstance(video_data, torch.Tensor): video_data = torch.from_numpy(np.frombuffer(video_data, dtype=np.uint8)) @@ -347,23 +431,25 @@ def _probe_video_from_memory(video_data): return info -def _read_video(filename, start_pts=0, end_pts=None, pts_unit='pts'): +def _read_video(filename, start_pts=0, end_pts=None, pts_unit="pts"): if end_pts is None: end_pts = float("inf") - if pts_unit == 'pts': - warnings.warn("The pts_unit 'pts' gives wrong results and will be removed in a " + - "follow-up version. Please use pts_unit 'sec'.") + if pts_unit == "pts": + warnings.warn( + "The pts_unit 'pts' gives wrong results and will be removed in a " + + "follow-up version. Please use pts_unit 'sec'." + ) info = _probe_video_from_file(filename) - has_video = 'video_timebase' in info - has_audio = 'audio_timebase' in info + has_video = info.has_video + has_audio = info.has_audio def get_pts(time_base): start_offset = start_pts end_offset = end_pts - if pts_unit == 'sec': + if pts_unit == "sec": start_offset = int(math.floor(start_pts * (1 / time_base))) if end_offset != float("inf"): end_offset = int(math.ceil(end_pts * (1 / time_base))) @@ -374,13 +460,17 @@ def get_pts(time_base): video_pts_range = (0, -1) video_timebase = default_timebase if has_video: - video_timebase = info['video_timebase'] + video_timebase = Fraction( + info.video_timebase.numerator, info.video_timebase.denominator + ) video_pts_range = get_pts(video_timebase) audio_pts_range = (0, -1) audio_timebase = default_timebase if has_audio: - audio_timebase = info['audio_timebase'] + audio_timebase = Fraction( + info.audio_timebase.numerator, info.audio_timebase.denominator + ) audio_pts_range = get_pts(audio_timebase) vframes, aframes, info = _read_video_from_file( @@ -394,24 +484,28 @@ def get_pts(time_base): ) _info = {} if has_video: - _info['video_fps'] = info['video_fps'] + _info["video_fps"] = info.video_fps if has_audio: - _info['audio_fps'] = info['audio_sample_rate'] + _info["audio_fps"] = info.audio_sample_rate return vframes, aframes, _info -def _read_video_timestamps(filename, pts_unit='pts'): - if pts_unit == 'pts': - warnings.warn("The pts_unit 'pts' gives wrong results and will be removed in a " + - "follow-up version. Please use pts_unit 'sec'.") +def _read_video_timestamps(filename, pts_unit="pts"): + if pts_unit == "pts": + warnings.warn( + "The pts_unit 'pts' gives wrong results and will be removed in a " + + "follow-up version. Please use pts_unit 'sec'." + ) pts, _, info = _read_video_timestamps_from_file(filename) - if pts_unit == 'sec': - video_time_base = info['video_timebase'] + if pts_unit == "sec": + video_time_base = Fraction( + info.video_timebase.numerator, info.video_timebase.denominator + ) pts = [x * video_time_base for x in pts] - video_fps = info.get('video_fps', None) + video_fps = info.video_fps if info.has_video else None return pts, video_fps diff --git a/torchvision/io/video.py b/torchvision/io/video.py index ea23b57db18..fc56c015473 100644 --- a/torchvision/io/video.py +++ b/torchvision/io/video.py @@ -1,43 +1,38 @@ -import re -import imp import gc -import os -import torch -import numpy as np import math +import re import warnings +from typing import Tuple, List -from . import _video_opt - - -_HAS_VIDEO_OPT = False +import numpy as np +import torch -try: - lib_dir = os.path.join(os.path.dirname(__file__), '..') - _, path, description = imp.find_module("video_reader", [lib_dir]) - torch.ops.load_library(path) - _HAS_VIDEO_OPT = True -except (ImportError, OSError): - pass +from . import _video_opt +from ._video_opt import VideoMetaData try: import av + av.logging.set_level(av.logging.ERROR) - if not hasattr(av.video.frame.VideoFrame, 'pict_type'): - av = ImportError("""\ + if not hasattr(av.video.frame.VideoFrame, "pict_type"): + av = ImportError( + """\ Your version of PyAV is too old for the necessary video operations in torchvision. If you are on Python 3.5, you will have to build from source (the conda-forge packages are not up-to-date). See https://github.com/mikeboers/PyAV#installation for instructions on how to install PyAV on your system. -""") +""" + ) except ImportError: - av = ImportError("""\ + av = ImportError( + """\ PyAV is not installed, and is necessary for the video operations in torchvision. See https://github.com/mikeboers/PyAV#installation for instructions on how to install PyAV on your system. -""") +""" + ) def _check_av_available(): @@ -54,7 +49,7 @@ def _av_available(): _GC_COLLECTION_INTERVAL = 10 -def write_video(filename, video_array, fps, video_codec='libx264', options=None): +def write_video(filename, video_array, fps, video_codec="libx264", options=None): """ Writes a 4d tensor in [T, H, W, C] format in a video file @@ -70,17 +65,17 @@ def write_video(filename, video_array, fps, video_codec='libx264', options=None) _check_av_available() video_array = torch.as_tensor(video_array, dtype=torch.uint8).numpy() - container = av.open(filename, mode='w') + container = av.open(filename, mode="w") stream = container.add_stream(video_codec, rate=fps) stream.width = video_array.shape[2] stream.height = video_array.shape[1] - stream.pix_fmt = 'yuv420p' if video_codec != 'libx264rgb' else 'rgb24' + stream.pix_fmt = "yuv420p" if video_codec != "libx264rgb" else "rgb24" stream.options = options or {} for img in video_array: - frame = av.VideoFrame.from_ndarray(img, format='rgb24') - frame.pict_type = 'NONE' + frame = av.VideoFrame.from_ndarray(img, format="rgb24") + frame.pict_type = "NONE" for packet in stream.encode(frame): container.mux(packet) @@ -92,19 +87,23 @@ def write_video(filename, video_array, fps, video_codec='libx264', options=None) container.close() -def _read_from_stream(container, start_offset, end_offset, pts_unit, stream, stream_name): +def _read_from_stream( + container, start_offset, end_offset, pts_unit, stream, stream_name +): global _CALLED_TIMES, _GC_COLLECTION_INTERVAL _CALLED_TIMES += 1 if _CALLED_TIMES % _GC_COLLECTION_INTERVAL == _GC_COLLECTION_INTERVAL - 1: gc.collect() - if pts_unit == 'sec': + if pts_unit == "sec": start_offset = int(math.floor(start_offset * (1 / stream.time_base))) if end_offset != float("inf"): end_offset = int(math.ceil(end_offset * (1 / stream.time_base))) else: - warnings.warn("The pts_unit 'pts' gives wrong results and will be removed in a " + - "follow-up version. Please use pts_unit 'sec'.") + warnings.warn( + "The pts_unit 'pts' gives wrong results and will be removed in a " + + "follow-up version. Please use pts_unit 'sec'." + ) frames = {} should_buffer = False @@ -141,7 +140,7 @@ def _read_from_stream(container, start_offset, end_offset, pts_unit, stream, str return [] buffer_count = 0 try: - for idx, frame in enumerate(container.decode(**stream_name)): + for _idx, frame in enumerate(container.decode(**stream_name)): frames[frame.pts] = frame if frame.pts >= end_offset: if should_buffer and buffer_count < max_buffer_size: @@ -152,7 +151,9 @@ def _read_from_stream(container, start_offset, end_offset, pts_unit, stream, str # TODO add a warning pass # ensure that the results are sorted wrt the pts - result = [frames[i] for i in sorted(frames) if start_offset <= frames[i].pts <= end_offset] + result = [ + frames[i] for i in sorted(frames) if start_offset <= frames[i].pts <= end_offset + ] if len(frames) > 0 and start_offset > 0 and start_offset not in frames: # if there is no frame that exactly matches the pts of start_offset # add the last frame smaller than start_offset, to guarantee that @@ -177,7 +178,7 @@ def _align_audio_frames(aframes, audio_frames, ref_start, ref_end): return aframes[:, s_idx:e_idx] -def read_video(filename, start_pts=0, end_pts=None, pts_unit='pts'): +def read_video(filename, start_pts=0, end_pts=None, pts_unit="pts"): """ Reads a video from a file, returning both the video frames as well as the audio frames @@ -208,6 +209,7 @@ def read_video(filename, start_pts=0, end_pts=None, pts_unit='pts'): """ from torchvision import get_video_backend + if get_video_backend() != "pyav": return _video_opt._read_video(filename, start_pts, end_pts, pts_unit) @@ -217,30 +219,44 @@ def read_video(filename, start_pts=0, end_pts=None, pts_unit='pts'): end_pts = float("inf") if end_pts < start_pts: - raise ValueError("end_pts should be larger than start_pts, got " - "start_pts={} and end_pts={}".format(start_pts, end_pts)) + raise ValueError( + "end_pts should be larger than start_pts, got " + "start_pts={} and end_pts={}".format(start_pts, end_pts) + ) info = {} video_frames = [] audio_frames = [] try: - container = av.open(filename, metadata_errors='ignore') + container = av.open(filename, metadata_errors="ignore") except av.AVError: # TODO raise a warning? pass else: if container.streams.video: - video_frames = _read_from_stream(container, start_pts, end_pts, pts_unit, - container.streams.video[0], {'video': 0}) + video_frames = _read_from_stream( + container, + start_pts, + end_pts, + pts_unit, + container.streams.video[0], + {"video": 0}, + ) video_fps = container.streams.video[0].average_rate # guard against potentially corrupted files if video_fps is not None: info["video_fps"] = float(video_fps) if container.streams.audio: - audio_frames = _read_from_stream(container, start_pts, end_pts, pts_unit, - container.streams.audio[0], {'audio': 0}) + audio_frames = _read_from_stream( + container, + start_pts, + end_pts, + pts_unit, + container.streams.audio[0], + {"audio": 0}, + ) info["audio_fps"] = container.streams.audio[0].rate container.close() @@ -272,7 +288,7 @@ def _can_read_timestamps_from_packets(container): return False -def read_video_timestamps(filename, pts_unit='pts'): +def read_video_timestamps(filename, pts_unit="pts"): """ List the video frames timestamps. @@ -295,6 +311,7 @@ def read_video_timestamps(filename, pts_unit='pts'): """ from torchvision import get_video_backend + if get_video_backend() != "pyav": return _video_opt._read_video_timestamps(filename, pts_unit) @@ -304,7 +321,7 @@ def read_video_timestamps(filename, pts_unit='pts'): video_fps = None try: - container = av.open(filename, metadata_errors='ignore') + container = av.open(filename, metadata_errors="ignore") except av.AVError: # TODO add a warning pass @@ -314,16 +331,61 @@ def read_video_timestamps(filename, pts_unit='pts'): video_time_base = video_stream.time_base if _can_read_timestamps_from_packets(container): # fast path - video_frames = [x for x in container.demux(video=0) if x.pts is not None] + video_frames = [ + x for x in container.demux(video=0) if x.pts is not None + ] else: - video_frames = _read_from_stream(container, 0, float("inf"), pts_unit, - video_stream, {'video': 0}) + video_frames = _read_from_stream( + container, 0, float("inf"), pts_unit, video_stream, {"video": 0} + ) video_fps = float(video_stream.average_rate) container.close() pts = [x.pts for x in video_frames] - if pts_unit == 'sec': + if pts_unit == "sec": pts = [x * video_time_base for x in pts] return pts, video_fps + + +def read_video_meta_data_from_memory(video_data): + # type: (torch.Tensor) -> VideoMetaData + return _video_opt._probe_video_from_memory(video_data) + + +def read_video_from_memory( + video_data, # type: torch.Tensor + seek_frame_margin=0.25, # type: float + read_video_stream=1, # type: int + video_width=0, # type: int + video_height=0, # type: int + video_min_dimension=0, # type: int + video_pts_range=(0, -1), # type: List[int] + video_timebase_numerator=0, # type: int + video_timebase_denominator=1, # type: int + read_audio_stream=1, # type: int + audio_samples=0, # type: int + audio_channels=0, # type: int + audio_pts_range=(0, -1), # type: List[int] + audio_timebase_numerator=0, # type: int + audio_timebase_denominator=1, # type: int +): + # type: (...) -> Tuple[torch.Tensor, torch.Tensor] + return _video_opt._read_video_from_memory( + video_data, + seek_frame_margin, + read_audio_stream, + video_width, + video_height, + video_min_dimension, + video_pts_range, + video_timebase_numerator, + video_timebase_denominator, + read_audio_stream, + audio_samples, + audio_channels, + audio_pts_range, + audio_timebase_numerator, + audio_timebase_denominator, + ) From bf987443e99c907c3ad20daf95c3f7bfdff56c16 Mon Sep 17 00:00:00 2001 From: Zhicheng Yan Date: Wed, 22 Jan 2020 12:40:19 -0800 Subject: [PATCH 017/357] concatenate small tensors into big ones to reduce the use of shared file descriptor (#1694) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1694 - PT dataloader forks worker process to speed up the fetching of dataset example. The recommended way of multiprocess context is `forkserver` rather than `fork`. - Main process and worker processes will share the dataset class instance, which avoid duplicating the dataset and save memory. In this process, `ForkPickler(..).dumps(...)` will be called to serialize the objects, including objects within dataset instance recursively. `VideoClips` instance internally uses O(N) `torch.Tensor` to store per-video information, such as pts, and possible clips, where N is the No. of videos. - During dumping, each `torch.Tensor` will use one File Descriptor (FD). The OS default max limit of FD is 65K by using `ulimit -n` to query. The number of tensors in `VideoClips` often exceeds the limit. - To resolve this issue, we use a few big tensors by concatenating small tensors in the `__getstate__()` method, which will be called during pickling. This will only require O(1) tensors. - When this diff is landed, we can abondon D19173248 In D19173397, in ClassyVision, we change the mp context from `fork` to `forkserver`, and finally can run the PT dataloader without hanging issues. Reviewed By: fmassa Differential Revision: D19179991 fbshipit-source-id: c8716775c7c154aa33d93b25d112d2a59ea688a9 --- torchvision/datasets/hmdb51.py | 7 +++-- torchvision/datasets/ucf101.py | 7 +++-- torchvision/datasets/video_utils.py | 47 ++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/torchvision/datasets/hmdb51.py b/torchvision/datasets/hmdb51.py index bd06ea6e5c9..21d09a475e1 100644 --- a/torchvision/datasets/hmdb51.py +++ b/torchvision/datasets/hmdb51.py @@ -78,14 +78,17 @@ def __init__(self, root, annotation_path, frames_per_clip, step_between_clips=1, _video_min_dimension=_video_min_dimension, _audio_samples=_audio_samples, ) - self.video_clips_metadata = video_clips.metadata + # we bookkeep the full version of video clips because we want to be able + # to return the meta data of full version rather than the subset version of + # video clips + self.full_video_clips = video_clips self.indices = self._select_fold(video_list, annotation_path, fold, train) self.video_clips = video_clips.subset(self.indices) self.transform = transform @property def metadata(self): - return self.video_clips_metadata + return self.full_video_clips.metadata def _select_fold(self, video_list, annotation_path, fold, train): target_tag = 1 if train else 2 diff --git a/torchvision/datasets/ucf101.py b/torchvision/datasets/ucf101.py index 43d8124bd4b..2e59047d6f1 100644 --- a/torchvision/datasets/ucf101.py +++ b/torchvision/datasets/ucf101.py @@ -71,14 +71,17 @@ def __init__(self, root, annotation_path, frames_per_clip, step_between_clips=1, _video_min_dimension=_video_min_dimension, _audio_samples=_audio_samples, ) - self.video_clips_metadata = video_clips.metadata + # we bookkeep the full version of video clips because we want to be able + # to return the meta data of full version rather than the subset version of + # video clips + self.full_video_clips = video_clips self.indices = self._select_fold(video_list, annotation_path, fold, train) self.video_clips = video_clips.subset(self.indices) self.transform = transform @property def metadata(self): - return self.video_clips_metadata + return self.full_video_clips.metadata def _select_fold(self, video_list, annotation_path, fold, train): name = "train" if train else "test" diff --git a/torchvision/datasets/video_utils.py b/torchvision/datasets/video_utils.py index 055d3d5cd8c..303a3375953 100644 --- a/torchvision/datasets/video_utils.py +++ b/torchvision/datasets/video_utils.py @@ -140,7 +140,10 @@ def _compute_frame_pts(self): for batch in dl: pbar.update(1) clips, fps = list(zip(*batch)) - clips = [torch.as_tensor(c) for c in clips] + # we need to specify dtype=torch.long because for empty list, + # torch.as_tensor will use torch.float as default dtype. This + # happens when decoding fails and no pts is returned in the list. + clips = [torch.as_tensor(c, dtype=torch.long) for c in clips] self.video_pts.extend(clips) self.video_fps.extend(fps) @@ -357,3 +360,45 @@ def get_clip(self, idx): video.shape, self.num_frames ) return video, audio, info, video_idx + + def __getstate__(self): + video_pts_sizes = [len(v) for v in self.video_pts] + # To be back-comptiable, we convert data to dtype torch.long as nedded + # because for empty list, in legacy implementation, torch.as_tensor will + # use torch.float as default dtype. This happens when decoding fails and + # no pts is returned in the list. + video_pts = [x.to(torch.long) for x in self.video_pts] + video_pts = torch.cat(video_pts) + # avoid bug in https://github.com/pytorch/pytorch/issues/32351 + # TODO: Revert it once the bug is fixed. + video_pts = video_pts.numpy() + + # make a copy of the fields of self + d = self.__dict__.copy() + d["video_pts_sizes"] = video_pts_sizes + d["video_pts"] = video_pts + # delete the following attributes to reduce the size of dictionary. They + # will be re-computed in "__setstate__()" + del d["clips"] + del d["resampling_idxs"] + del d["cumulative_sizes"] + + # for backwards-compatibility + d["_version"] = 2 + return d + + def __setstate__(self, d): + # for backwards-compatibility + if "_version" not in d: + self.__dict__ = d + return + + video_pts = torch.as_tensor(d["video_pts"]) + video_pts = torch.split(video_pts, d["video_pts_sizes"], dim=0) + # don't need this info anymore + del d["video_pts_sizes"] + + d["video_pts"] = video_pts + self.__dict__ = d + # recompute attributes "clips", "resampling_idxs" and other derivative ones + self.compute_clips(self.num_frames, self.step, self.frame_rate) From 4347fc06b476dba8482ebae5cf8bd340d2f70afe Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 28 Jan 2020 03:00:58 -0800 Subject: [PATCH 018/357] Bugfix introduced in #1653 (#1796) Summary: Upon updating torchvision master with latest version of fbsync, I realized that there was a missing part of the codebase which wasn't updated. Pull Request resolved: https://github.com/pytorch/vision/pull/1796 Test Plan: Imported from GitHub, without a `Test Plan:` line. Tests in https://github.com/pytorch/vision/pull/1794 pass now Reviewed By: lerks Differential Revision: D19585272 Pulled By: fmassa fbshipit-source-id: 83a2a62b6f3646a093fb626617a8157a24dc2dd7 --- test/test_datasets_video_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_datasets_video_utils.py b/test/test_datasets_video_utils.py index a3af7366157..f038302e428 100644 --- a/test/test_datasets_video_utils.py +++ b/test/test_datasets_video_utils.py @@ -90,7 +90,7 @@ def test_video_clips_custom_fps(self): for i in range(video_clips.num_clips()): video, audio, info, video_idx = video_clips.get_clip(i) self.assertEqual(video.shape[0], num_frames) - self.assertEqual(info.video_fps, fps) + self.assertEqual(info["video_fps"], fps) # TODO add tests checking that the content is right def test_compute_clips_for_video(self): From 2991f9f98ff78b2c8a9b71656ee86a888589785e Mon Sep 17 00:00:00 2001 From: gslotman <58558601+gslotman@users.noreply.github.com> Date: Tue, 28 Jan 2020 04:44:26 -0800 Subject: [PATCH 019/357] Fix header includes for cpu (#1644) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1799 Reviewed By: lerks Differential Revision: D19598565 Pulled By: fmassa fbshipit-source-id: 87c62184b0ae73c840cff3850b62961b67962758 --- torchvision/csrc/cpu/ROIAlign_cpu.cpp | 2 +- torchvision/csrc/cpu/nms_cpu.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/torchvision/csrc/cpu/ROIAlign_cpu.cpp b/torchvision/csrc/cpu/ROIAlign_cpu.cpp index 56ca3fbc50d..0b8f8a490fc 100644 --- a/torchvision/csrc/cpu/ROIAlign_cpu.cpp +++ b/torchvision/csrc/cpu/ROIAlign_cpu.cpp @@ -1,5 +1,5 @@ #include -#include "cpu/vision_cpu.h" +#include "vision_cpu.h" // implementation taken from Caffe2 template diff --git a/torchvision/csrc/cpu/nms_cpu.cpp b/torchvision/csrc/cpu/nms_cpu.cpp index 47b771fa943..55afb03a4e9 100644 --- a/torchvision/csrc/cpu/nms_cpu.cpp +++ b/torchvision/csrc/cpu/nms_cpu.cpp @@ -1,4 +1,4 @@ -#include "cpu/vision_cpu.h" +#include "vision_cpu.h" template at::Tensor nms_cpu_kernel( From 7f01de9865abdd999f7787995224f9b64efa60d0 Mon Sep 17 00:00:00 2001 From: xkszltl Date: Tue, 28 Jan 2020 04:44:34 -0800 Subject: [PATCH 020/357] PyTorch has switched to C++14. (#1635) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1800 Reviewed By: lerks Differential Revision: D19598570 Pulled By: fmassa fbshipit-source-id: 733c328a34b6ce95e58ba77d272b50a484961023 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df77482c870..f78ec47a4a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.8) project(torchvision) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) find_package(Torch REQUIRED) From 797557457022c39ba0e4811ac5f830cad5499595 Mon Sep 17 00:00:00 2001 From: Ankit Jha <45779665+PyExtreme@users.noreply.github.com> Date: Tue, 28 Jan 2020 04:44:53 -0800 Subject: [PATCH 021/357] Add scriptable transform: center_crop, five crop and ten_crop (#1615) (#1803) Summary: * add scriptable transform: center_crop * add test: center_crop * add scriptable transform: five_crop * add scriptable transform: five_crop * add scriptable transform: fix minor issues Pull Request resolved: https://github.com/pytorch/vision/pull/1803 Reviewed By: lerks Differential Revision: D19598584 Pulled By: fmassa fbshipit-source-id: 6cd619da2982aed00104300b9086cc8ca69ecd82 --- test/test_functional_tensor.py | 47 +++++++++++ torchvision/transforms/functional_tensor.py | 91 +++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/test/test_functional_tensor.py b/test/test_functional_tensor.py index e318420102b..e464bf733a8 100644 --- a/test/test_functional_tensor.py +++ b/test/test_functional_tensor.py @@ -76,6 +76,53 @@ def test_rgb_to_grayscale(self): max_diff = (grayscale_tensor - grayscale_pil_img).abs().max() self.assertLess(max_diff, 1.0001) + def test_center_crop(self): + img_tensor = torch.randint(0, 255, (1, 32, 32), dtype=torch.uint8) + cropped_tensor = F_t.center_crop(img_tensor, [10, 10]) + cropped_pil_image = F.center_crop(transforms.ToPILImage()(img_tensor), [10, 10]) + cropped_pil_tensor = (transforms.ToTensor()(cropped_pil_image) * 255).to(torch.uint8) + self.assertTrue(torch.equal(cropped_tensor, cropped_pil_tensor)) + + def test_five_crop(self): + img_tensor = torch.randint(0, 255, (1, 32, 32), dtype=torch.uint8) + cropped_tensor = F_t.five_crop(img_tensor, [10, 10]) + cropped_pil_image = F.five_crop(transforms.ToPILImage()(img_tensor), [10, 10]) + self.assertTrue(torch.equal(cropped_tensor[0], + (transforms.ToTensor()(cropped_pil_image[0]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[1], + (transforms.ToTensor()(cropped_pil_image[2]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[2], + (transforms.ToTensor()(cropped_pil_image[1]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[3], + (transforms.ToTensor()(cropped_pil_image[3]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[4], + (transforms.ToTensor()(cropped_pil_image[4]) * 255).to(torch.uint8))) + + def test_ten_crop(self): + img_tensor = torch.randint(0, 255, (1, 32, 32), dtype=torch.uint8) + cropped_tensor = F_t.ten_crop(img_tensor, [10, 10]) + cropped_pil_image = F.ten_crop(transforms.ToPILImage()(img_tensor), [10, 10]) + self.assertTrue(torch.equal(cropped_tensor[0], + (transforms.ToTensor()(cropped_pil_image[0]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[1], + (transforms.ToTensor()(cropped_pil_image[2]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[2], + (transforms.ToTensor()(cropped_pil_image[1]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[3], + (transforms.ToTensor()(cropped_pil_image[3]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[4], + (transforms.ToTensor()(cropped_pil_image[4]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[5], + (transforms.ToTensor()(cropped_pil_image[5]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[6], + (transforms.ToTensor()(cropped_pil_image[7]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[7], + (transforms.ToTensor()(cropped_pil_image[6]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[8], + (transforms.ToTensor()(cropped_pil_image[8]) * 255).to(torch.uint8))) + self.assertTrue(torch.equal(cropped_tensor[9], + (transforms.ToTensor()(cropped_pil_image[9]) * 255).to(torch.uint8))) + if __name__ == '__main__': unittest.main() diff --git a/torchvision/transforms/functional_tensor.py b/torchvision/transforms/functional_tensor.py index c741ab2e7e8..bd56ae3a131 100644 --- a/torchvision/transforms/functional_tensor.py +++ b/torchvision/transforms/functional_tensor.py @@ -125,6 +125,97 @@ def adjust_saturation(img, saturation_factor): return _blend(img, rgb_to_grayscale(img), saturation_factor) +def center_crop(img, output_size): + """Crop the Image Tensor and resize it to desired size. + + Args: + img (Tensor): Image to be cropped. (0,0) denotes the top left corner of the image. + output_size (sequence or int): (height, width) of the crop box. If int, + it is used for both directions + + Returns: + Tensor: Cropped image. + """ + if not F._is_tensor_image(img): + raise TypeError('tensor is not a torch image.') + + _, image_width, image_height = img.size() + crop_height, crop_width = output_size + crop_top = int(round((image_height - crop_height) / 2.)) + crop_left = int(round((image_width - crop_width) / 2.)) + + return crop(img, crop_top, crop_left, crop_height, crop_width) + + +def five_crop(img, size): + """Crop the given Image Tensor into four corners and the central crop. + .. Note:: + This transform returns a tuple of Tensors and there may be a + mismatch in the number of inputs and targets your ``Dataset`` returns. + + Args: + size (sequence or int): Desired output size of the crop. If size is an + int instead of sequence like (h, w), a square crop (size, size) is + made. + + Returns: + tuple: tuple (tl, tr, bl, br, center) + Corresponding top left, top right, bottom left, bottom right and center crop. + """ + if not F._is_tensor_image(img): + raise TypeError('tensor is not a torch image.') + + assert len(size) == 2, "Please provide only two dimensions (h, w) for size." + + _, image_width, image_height = img.size() + crop_height, crop_width = size + if crop_width > image_width or crop_height > image_height: + msg = "Requested crop size {} is bigger than input size {}" + raise ValueError(msg.format(size, (image_height, image_width))) + + tl = crop(img, 0, 0, crop_width, crop_height) + tr = crop(img, image_width - crop_width, 0, image_width, crop_height) + bl = crop(img, 0, image_height - crop_height, crop_width, image_height) + br = crop(img, image_width - crop_width, image_height - crop_height, image_width, image_height) + center = center_crop(img, (crop_height, crop_width)) + + return (tl, tr, bl, br, center) + + +def ten_crop(img, size, vertical_flip=False): + """Crop the given Image Tensor into four corners and the central crop plus the + flipped version of these (horizontal flipping is used by default). + .. Note:: + This transform returns a tuple of images and there may be a + mismatch in the number of inputs and targets your ``Dataset`` returns. + + Args: + size (sequence or int): Desired output size of the crop. If size is an + int instead of sequence like (h, w), a square crop (size, size) is + made. + vertical_flip (bool): Use vertical flipping instead of horizontal + + Returns: + tuple: tuple (tl, tr, bl, br, center, tl_flip, tr_flip, bl_flip, br_flip, center_flip) + Corresponding top left, top right, bottom left, bottom right and center crop + and same for the flipped image's tensor. + """ + if not F._is_tensor_image(img): + raise TypeError('tensor is not a torch image.') + + assert len(size) == 2, "Please provide only two dimensions (h, w) for size." + first_five = five_crop(img, size) + + if vertical_flip: + img = vflip(img) + else: + img = hflip(img) + + second_five = five_crop(img, size) + + return first_five + second_five + + def _blend(img1, img2, ratio): bound = 1 if img1.dtype.is_floating_point else 255 return (ratio * img1 + (1 - ratio) * img2).clamp(0, bound).to(img1.dtype) From 48eaf2e79effea9f8bb420b79fc3672228900dab Mon Sep 17 00:00:00 2001 From: Surgan Jandial Date: Tue, 28 Jan 2020 04:45:02 -0800 Subject: [PATCH 022/357] add .tgz support to extract_archive (#1650) (#1798) Summary: * tgz updates * tgz updates * tgz updates Pull Request resolved: https://github.com/pytorch/vision/pull/1798 Reviewed By: lerks Differential Revision: D19598564 Pulled By: fmassa fbshipit-source-id: 64aec5e661feba7b4222ea11ea337eea1f5bb5a8 --- test/test_datasets_utils.py | 2 +- torchvision/datasets/utils.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/test_datasets_utils.py b/test/test_datasets_utils.py index 14a53b75c54..dadbb99ab92 100644 --- a/test/test_datasets_utils.py +++ b/test/test_datasets_utils.py @@ -86,7 +86,7 @@ def test_extract_zip(self): @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') def test_extract_tar(self): - for ext, mode in zip(['.tar', '.tar.gz'], ['w', 'w:gz']): + for ext, mode in zip(['.tar', '.tar.gz', '.tgz'], ['w', 'w:gz', 'w:gz']): with get_tmp_dir() as temp_dir: with tempfile.NamedTemporaryFile() as bf: bf.write("this is the content".encode()) diff --git a/torchvision/datasets/utils.py b/torchvision/datasets/utils.py index 6616c98d445..aa61237a6d2 100644 --- a/torchvision/datasets/utils.py +++ b/torchvision/datasets/utils.py @@ -213,6 +213,10 @@ def _is_targz(filename): return filename.endswith(".tar.gz") +def _is_tgz(filename): + return filename.endswith(".tgz") + + def _is_gzip(filename): return filename.endswith(".gz") and not filename.endswith(".tar.gz") @@ -228,7 +232,7 @@ def extract_archive(from_path, to_path=None, remove_finished=False): if _is_tar(from_path): with tarfile.open(from_path, 'r') as tar: tar.extractall(path=to_path) - elif _is_targz(from_path): + elif _is_targz(from_path) or _is_tgz(from_path): with tarfile.open(from_path, 'r:gz') as tar: tar.extractall(path=to_path) elif _is_tarxz(from_path) and PY3: From 653323f72f97521f16ad4509579e9d621e1f847a Mon Sep 17 00:00:00 2001 From: Gerald Baier Date: Tue, 28 Jan 2020 04:46:19 -0800 Subject: [PATCH 023/357] update dead LSUN link (#1626) (#1804) Summary: The current link to the dataset is dead. The change links to the dataset's author's personal page, which describe the dataset and is also referenced at https://github.com/fyu/lsun. Pull Request resolved: https://github.com/pytorch/vision/pull/1804 Reviewed By: lerks Differential Revision: D19598593 Pulled By: fmassa fbshipit-source-id: 88f6bdd53a76e0e426d4961ea1667cbdc07867f6 --- torchvision/datasets/lsun.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/datasets/lsun.py b/torchvision/datasets/lsun.py index 548df0e788b..8127fc9cbf4 100644 --- a/torchvision/datasets/lsun.py +++ b/torchvision/datasets/lsun.py @@ -62,7 +62,7 @@ def __len__(self): class LSUN(VisionDataset): """ - `LSUN `_ dataset. + `LSUN `_ dataset. Args: root (string): Root directory for the database files. From 59b2386571ae1f08c1222419611ef3750eed44aa Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 28 Jan 2020 04:49:22 -0800 Subject: [PATCH 024/357] Fix VOC on Windows (#1641) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1802 Reviewed By: lerks Differential Revision: D19598581 Pulled By: fmassa fbshipit-source-id: b1e5592c5119b91f06fd374678fabc4b28850522 --- torchvision/datasets/voc.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/torchvision/datasets/voc.py b/torchvision/datasets/voc.py index 001a6b367f3..57e885610d7 100644 --- a/torchvision/datasets/voc.py +++ b/torchvision/datasets/voc.py @@ -17,37 +17,37 @@ 'url': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar', 'filename': 'VOCtrainval_11-May-2012.tar', 'md5': '6cd6e144f989b92b3379bac3b3de84fd', - 'base_dir': 'VOCdevkit/VOC2012' + 'base_dir': os.path.join('VOCdevkit', 'VOC2012') }, '2011': { 'url': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2011/VOCtrainval_25-May-2011.tar', 'filename': 'VOCtrainval_25-May-2011.tar', 'md5': '6c3384ef61512963050cb5d687e5bf1e', - 'base_dir': 'TrainVal/VOCdevkit/VOC2011' + 'base_dir': os.path.join('TrainVal', 'VOCdevkit', 'VOC2011') }, '2010': { 'url': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2010/VOCtrainval_03-May-2010.tar', 'filename': 'VOCtrainval_03-May-2010.tar', 'md5': 'da459979d0c395079b5c75ee67908abb', - 'base_dir': 'VOCdevkit/VOC2010' + 'base_dir': os.path.join('VOCdevkit', 'VOC2010') }, '2009': { 'url': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2009/VOCtrainval_11-May-2009.tar', 'filename': 'VOCtrainval_11-May-2009.tar', 'md5': '59065e4b188729180974ef6572f6a212', - 'base_dir': 'VOCdevkit/VOC2009' + 'base_dir': os.path.join('VOCdevkit', 'VOC2009') }, '2008': { 'url': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2008/VOCtrainval_14-Jul-2008.tar', 'filename': 'VOCtrainval_11-May-2012.tar', 'md5': '2629fa636546599198acfcfbfcf1904a', - 'base_dir': 'VOCdevkit/VOC2008' + 'base_dir': os.path.join('VOCdevkit', 'VOC2008') }, '2007': { 'url': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar', 'filename': 'VOCtrainval_06-Nov-2007.tar', 'md5': 'c52e279531787c972589f7e41ab4ae64', - 'base_dir': 'VOCdevkit/VOC2007' + 'base_dir': os.path.join('VOCdevkit', 'VOC2007') } } From 6dbdadfbf0f6c12398fbed7c496fbd0d31d643b4 Mon Sep 17 00:00:00 2001 From: MultiK <596286458@qq.com> Date: Tue, 28 Jan 2020 05:17:06 -0800 Subject: [PATCH 025/357] fix a little bug about resume (#1628) (#1806) Summary: * fix a little bug about resume When resuming, we need to start from the last epoch not 0. * the second way for resuming the second way for resuming Pull Request resolved: https://github.com/pytorch/vision/pull/1806 Reviewed By: javier-m Differential Revision: D19599039 Pulled By: fmassa fbshipit-source-id: 22ebe14bd1ba7728cbdc5149ee181429b834a307 --- references/detection/train.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/references/detection/train.py b/references/detection/train.py index 507d4faebae..722f4b4f72c 100644 --- a/references/detection/train.py +++ b/references/detection/train.py @@ -108,20 +108,21 @@ def main(args): # lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=args.lr_step_size, gamma=args.lr_gamma) lr_scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=args.lr_steps, gamma=args.lr_gamma) - + if args.resume: checkpoint = torch.load(args.resume, map_location='cpu') model_without_ddp.load_state_dict(checkpoint['model']) optimizer.load_state_dict(checkpoint['optimizer']) lr_scheduler.load_state_dict(checkpoint['lr_scheduler']) - + args.start_epoch = checkpoint['epoch'] + 1 + if args.test_only: evaluate(model, data_loader_test, device=device) return print("Start training") start_time = time.time() - for epoch in range(args.epochs): + for epoch in range(args.start_epoch, args.epochs): if args.distributed: train_sampler.set_epoch(epoch) train_one_epoch(model, optimizer, data_loader, device, epoch, args.print_freq) @@ -131,7 +132,8 @@ def main(args): 'model': model_without_ddp.state_dict(), 'optimizer': optimizer.state_dict(), 'lr_scheduler': lr_scheduler.state_dict(), - 'args': args}, + 'args': args, + 'epoch': epoch}, os.path.join(args.output_dir, 'model_{}.pth'.format(epoch))) # evaluate after every epoch @@ -171,6 +173,7 @@ def main(args): parser.add_argument('--print-freq', default=20, type=int, help='print frequency') parser.add_argument('--output-dir', default='.', help='path where to save') parser.add_argument('--resume', default='', help='resume from checkpoint') + parser.add_argument('--start_epoch', default=0, type=int, help='start epoch') parser.add_argument('--aspect-ratio-group-factor', default=3, type=int) parser.add_argument( "--test-only", From b2e55c24e4ef302ae58663b0a870233ce2244838 Mon Sep 17 00:00:00 2001 From: Eli Uriegas Date: Tue, 28 Jan 2020 05:21:12 -0800 Subject: [PATCH 026/357] ci: Remove Python 2.7 (#1761) (#1810) Summary: Python 2.7 was EOL on January 1, 2020 The last torchvision release to support Python 2.7 was 0.5.0 Signed-off-by: Eli Uriegas Pull Request resolved: https://github.com/pytorch/vision/pull/1810 Reviewed By: javier-m Differential Revision: D19599104 Pulled By: fmassa fbshipit-source-id: 064d7e4c3cc5c372c83e459584fda1d52d4204e9 --- .circleci/config.yml | 317 ---------------------------------------- .circleci/regenerate.py | 2 +- .travis.yml | 8 - 3 files changed, 1 insertion(+), 326 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5bdb0e69e72..b16fae311aa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -295,46 +295,6 @@ workflows: build: jobs: - circleci_consistency - - binary_linux_wheel: - cu_version: cpu - name: binary_linux_wheel_py2.7_cpu - python_version: '2.7' - - binary_linux_wheel: - cu_version: cpu - name: binary_linux_wheel_py2.7u_cpu - python_version: '2.7' - unicode_abi: '1' - - binary_linux_wheel: - cu_version: cu92 - name: binary_linux_wheel_py2.7_cu92 - python_version: '2.7' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_wheel: - cu_version: cu92 - name: binary_linux_wheel_py2.7u_cu92 - python_version: '2.7' - unicode_abi: '1' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_wheel: - cu_version: cu100 - name: binary_linux_wheel_py2.7_cu100 - python_version: '2.7' - wheel_docker_image: pytorch/manylinux-cuda100 - - binary_linux_wheel: - cu_version: cu100 - name: binary_linux_wheel_py2.7u_cu100 - python_version: '2.7' - unicode_abi: '1' - wheel_docker_image: pytorch/manylinux-cuda100 - - binary_linux_wheel: - cu_version: cu101 - name: binary_linux_wheel_py2.7_cu101 - python_version: '2.7' - - binary_linux_wheel: - cu_version: cu101 - name: binary_linux_wheel_py2.7u_cu101 - python_version: '2.7' - unicode_abi: '1' - binary_linux_wheel: cu_version: cpu name: binary_linux_wheel_py3.5_cpu @@ -389,15 +349,6 @@ workflows: cu_version: cu101 name: binary_linux_wheel_py3.7_cu101 python_version: '3.7' - - binary_macos_wheel: - cu_version: cpu - name: binary_macos_wheel_py2.7_cpu - python_version: '2.7' - - binary_macos_wheel: - cu_version: cpu - name: binary_macos_wheel_py2.7u_cpu - python_version: '2.7' - unicode_abi: '1' - binary_macos_wheel: cu_version: cpu name: binary_macos_wheel_py3.5_cpu @@ -410,24 +361,6 @@ workflows: cu_version: cpu name: binary_macos_wheel_py3.7_cpu python_version: '3.7' - - binary_linux_conda: - cu_version: cpu - name: binary_linux_conda_py2.7_cpu - python_version: '2.7' - - binary_linux_conda: - cu_version: cu92 - name: binary_linux_conda_py2.7_cu92 - python_version: '2.7' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_conda: - cu_version: cu100 - name: binary_linux_conda_py2.7_cu100 - python_version: '2.7' - wheel_docker_image: pytorch/manylinux-cuda100 - - binary_linux_conda: - cu_version: cu101 - name: binary_linux_conda_py2.7_cu101 - python_version: '2.7' - binary_linux_conda: cu_version: cpu name: binary_linux_conda_py3.5_cpu @@ -482,10 +415,6 @@ workflows: cu_version: cu101 name: binary_linux_conda_py3.7_cu101 python_version: '3.7' - - binary_macos_conda: - cu_version: cpu - name: binary_macos_conda_py2.7_cpu - python_version: '2.7' - binary_macos_conda: cu_version: cpu name: binary_macos_conda_py3.5_cpu @@ -514,142 +443,6 @@ workflows: nightly: jobs: - circleci_consistency - - binary_linux_wheel: - cu_version: cpu - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7_cpu - python_version: '2.7' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7_cpu_upload - requires: - - nightly_binary_linux_wheel_py2.7_cpu - subfolder: cpu/ - - binary_linux_wheel: - cu_version: cpu - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7u_cpu - python_version: '2.7' - unicode_abi: '1' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7u_cpu_upload - requires: - - nightly_binary_linux_wheel_py2.7u_cpu - subfolder: cpu/ - - binary_linux_wheel: - cu_version: cu92 - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7_cu92 - python_version: '2.7' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7_cu92_upload - requires: - - nightly_binary_linux_wheel_py2.7_cu92 - subfolder: cu92/ - - binary_linux_wheel: - cu_version: cu92 - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7u_cu92 - python_version: '2.7' - unicode_abi: '1' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7u_cu92_upload - requires: - - nightly_binary_linux_wheel_py2.7u_cu92 - subfolder: cu92/ - - binary_linux_wheel: - cu_version: cu100 - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7_cu100 - python_version: '2.7' - wheel_docker_image: pytorch/manylinux-cuda100 - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7_cu100_upload - requires: - - nightly_binary_linux_wheel_py2.7_cu100 - subfolder: cu100/ - - binary_linux_wheel: - cu_version: cu100 - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7u_cu100 - python_version: '2.7' - unicode_abi: '1' - wheel_docker_image: pytorch/manylinux-cuda100 - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7u_cu100_upload - requires: - - nightly_binary_linux_wheel_py2.7u_cu100 - subfolder: cu100/ - - binary_linux_wheel: - cu_version: cu101 - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7_cu101 - python_version: '2.7' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7_cu101_upload - requires: - - nightly_binary_linux_wheel_py2.7_cu101 - subfolder: cu101/ - - binary_linux_wheel: - cu_version: cu101 - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7u_cu101 - python_version: '2.7' - unicode_abi: '1' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_wheel_py2.7u_cu101_upload - requires: - - nightly_binary_linux_wheel_py2.7u_cu101 - subfolder: cu101/ - binary_linux_wheel: cu_version: cpu filters: @@ -848,39 +641,6 @@ workflows: requires: - nightly_binary_linux_wheel_py3.7_cu101 subfolder: cu101/ - - binary_macos_wheel: - cu_version: cpu - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py2.7_cpu - python_version: '2.7' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py2.7_cpu_upload - requires: - - nightly_binary_macos_wheel_py2.7_cpu - subfolder: '' - - binary_macos_wheel: - cu_version: cpu - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py2.7u_cpu - python_version: '2.7' - unicode_abi: '1' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py2.7u_cpu_upload - requires: - - nightly_binary_macos_wheel_py2.7u_cpu - subfolder: '' - binary_macos_wheel: cu_version: cpu filters: @@ -929,68 +689,6 @@ workflows: requires: - nightly_binary_macos_wheel_py3.7_cpu subfolder: '' - - binary_linux_conda: - cu_version: cpu - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py2.7_cpu - python_version: '2.7' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py2.7_cpu_upload - requires: - - nightly_binary_linux_conda_py2.7_cpu - - binary_linux_conda: - cu_version: cu92 - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py2.7_cu92 - python_version: '2.7' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py2.7_cu92_upload - requires: - - nightly_binary_linux_conda_py2.7_cu92 - - binary_linux_conda: - cu_version: cu100 - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py2.7_cu100 - python_version: '2.7' - wheel_docker_image: pytorch/manylinux-cuda100 - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py2.7_cu100_upload - requires: - - nightly_binary_linux_conda_py2.7_cu100 - - binary_linux_conda: - cu_version: cu101 - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py2.7_cu101 - python_version: '2.7' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_linux_conda_py2.7_cu101_upload - requires: - - nightly_binary_linux_conda_py2.7_cu101 - binary_linux_conda: cu_version: cpu filters: @@ -1177,21 +875,6 @@ workflows: name: nightly_binary_linux_conda_py3.7_cu101_upload requires: - nightly_binary_linux_conda_py3.7_cu101 - - binary_macos_conda: - cu_version: cpu - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py2.7_cpu - python_version: '2.7' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py2.7_cpu_upload - requires: - - nightly_binary_macos_conda_py2.7_cpu - binary_macos_conda: cu_version: cpu filters: diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 6925ffa6d45..f47533d0016 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -23,7 +23,7 @@ def workflows(prefix='', filter_branch=None, upload=False, indentation=6): w = [] for btype in ["wheel", "conda"]: for os_type in ["linux", "macos"]: - for python_version in ["2.7", "3.5", "3.6", "3.7"]: + for python_version in ["3.5", "3.6", "3.7"]: for cu_version in (["cpu", "cu92", "cu100", "cu101"] if os_type == "linux" else ["cpu"]): for unicode in ([False, True] if btype == "wheel" and python_version == "2.7" else [False]): w += workflow_pair( diff --git a/.travis.yml b/.travis.yml index 69c34f0f690..eae4967d542 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,19 +15,11 @@ matrix: before_install: skip install: skip script: ./travis-scripts/run-clang-format/run-clang-format.py -r torchvision/csrc - - env: LINT_CHECK - python: "2.7" - install: pip install flake8 typing - script: flake8 --exclude .circleci - after_success: [] - env: LINT_CHECK python: "3.6" install: pip install flake8 typing script: flake8 .circleci after_success: [] - - python: "2.7" - env: IMAGE_BACKEND=Pillow-SIMD - - python: "2.7" - python: "3.6" env: IMAGE_BACKEND=Pillow-SIMD - python: "3.6" From ce9fad0ded161ffbdb017c0026bc6df378d92f84 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 28 Jan 2020 05:21:12 -0800 Subject: [PATCH 027/357] =?UTF-8?q?Bugfix=20on=20GroupedBatchSampler=20for?= =?UTF-8?q?=20corner=20case=20where=20there=20are=20not=20eno=E2=80=A6=20(?= =?UTF-8?q?#1805)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: …ugh examples in a category to form a batch (https://github.com/pytorch/vision/issues/1677) Pull Request resolved: https://github.com/pytorch/vision/pull/1805 Reviewed By: javier-m Differential Revision: D19599038 Pulled By: fmassa fbshipit-source-id: a0ba882167459f5821a04381df85039db016014c --- references/detection/group_by_aspect_ratio.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/references/detection/group_by_aspect_ratio.py b/references/detection/group_by_aspect_ratio.py index 61694cd63a4..517056056e2 100644 --- a/references/detection/group_by_aspect_ratio.py +++ b/references/detection/group_by_aspect_ratio.py @@ -1,6 +1,8 @@ import bisect from collections import defaultdict import copy +from itertools import repeat, chain +import math import numpy as np import torch @@ -12,6 +14,12 @@ from PIL import Image +def _repeat_to_at_least(iterable, n): + repeat_times = math.ceil(n / len(iterable)) + repeated = chain.from_iterable(repeat(iterable, repeat_times)) + return list(repeated) + + class GroupedBatchSampler(BatchSampler): """ Wraps another sampler to yield a mini-batch of indices. @@ -63,8 +71,8 @@ def __iter__(self): for group_id, _ in sorted(buffer_per_group.items(), key=lambda x: len(x[1]), reverse=True): remaining = self.batch_size - len(buffer_per_group[group_id]) - buffer_per_group[group_id].extend( - samples_per_group[group_id][:remaining]) + samples_from_group_id = _repeat_to_at_least(samples_per_group[group_id], remaining) + buffer_per_group[group_id].extend(samples_from_group_id[:remaining]) assert len(buffer_per_group[group_id]) == self.batch_size yield buffer_per_group[group_id] num_remaining -= 1 From 3f6c3c076ad693d6cd7359813aa6c1c864ddb3e0 Mon Sep 17 00:00:00 2001 From: Soumith Chintala Date: Tue, 28 Jan 2020 05:21:31 -0800 Subject: [PATCH 028/357] CUDA_SUFFIX -> PYTORCH_VERSION_SUFFIX Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1813 Reviewed By: javier-m Differential Revision: D19599112 Pulled By: fmassa fbshipit-source-id: cccdd1aaa402f6c6da8110800c344d4a91adcf3e --- packaging/pkg_helpers.bash | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 5d7109efe93..e082959f601 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -184,7 +184,7 @@ setup_pip_pytorch_version() { export PYTORCH_VERSION="$(pip show torch | grep ^Version: | sed 's/Version: *//')" fi else - pip_install "torch==$PYTORCH_VERSION$CUDA_SUFFIX" \ + pip_install "torch==$PYTORCH_VERSION$PYTORCH_VERSION_SUFFIX" \ -f https://download.pytorch.org/whl/torch_stable.html \ -f https://download.pytorch.org/whl/nightly/torch_nightly.html fi @@ -193,7 +193,7 @@ setup_pip_pytorch_version() { # Fill PYTORCH_VERSION with the latest conda nightly version, and # CONDA_CHANNEL_FLAGS with appropriate flags to retrieve these versions # -# You MUST have populated CUDA_SUFFIX before hand. +# You MUST have populated PYTORCH_VERSION_SUFFIX before hand. setup_conda_pytorch_constraint() { if [[ -z "$PYTORCH_VERSION" ]]; then export CONDA_CHANNEL_FLAGS="-c pytorch-nightly" From f8a7758a99618473f0bfc33c2045fc85fd2d71ed Mon Sep 17 00:00:00 2001 From: Soumith Chintala Date: Tue, 28 Jan 2020 05:22:44 -0800 Subject: [PATCH 029/357] master version bump 0.5 -> 0.6 Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1811 Reviewed By: javier-m Differential Revision: D19599108 Pulled By: fmassa fbshipit-source-id: 8aeed41c383f395e1c664e23ddba91106ebe85c6 --- packaging/build_conda.sh | 2 +- packaging/build_wheel.sh | 2 +- packaging/windows/internal/nightly_defaults.bat | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/build_conda.sh b/packaging/build_conda.sh index aaddf0710c8..61022f3c5fa 100755 --- a/packaging/build_conda.sh +++ b/packaging/build_conda.sh @@ -5,7 +5,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" . "$script_dir/pkg_helpers.bash" export BUILD_TYPE=conda -setup_env 0.5.0 +setup_env 0.6.0 export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint setup_conda_cudatoolkit_constraint diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index 7d37239563d..f83bd2101c5 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -5,7 +5,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" . "$script_dir/pkg_helpers.bash" export BUILD_TYPE=wheel -setup_env 0.5.0 +setup_env 0.6.0 setup_wheel_python pip_install numpy pyyaml future ninja # TODO remove after https://github.com/pytorch/pytorch/pull/27282 gets merged diff --git a/packaging/windows/internal/nightly_defaults.bat b/packaging/windows/internal/nightly_defaults.bat index 1bba23209b1..e87acf78cd2 100644 --- a/packaging/windows/internal/nightly_defaults.bat +++ b/packaging/windows/internal/nightly_defaults.bat @@ -144,7 +144,7 @@ if "%CUDA_VERSION%" == "cpu" ( :: pytorch-nightly==1.0.0.dev20180908 :: or in manylinux like :: torch_nightly-1.0.0.dev20180908-cp27-cp27m-linux_x86_64.whl -if "%TORCHVISION_BUILD_VERSION%" == "" set TORCHVISION_BUILD_VERSION=0.5.0.dev%NIGHTLIES_DATE_COMPACT% +if "%TORCHVISION_BUILD_VERSION%" == "" set TORCHVISION_BUILD_VERSION=0.6.0.dev%NIGHTLIES_DATE_COMPACT% if "%~1" == "Wheels" ( if not "%CUDA_VERSION%" == "101" ( diff --git a/setup.py b/setup.py index c1c6514383c..9f895a03450 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ def get_dist(pkgname): return None -version = '0.5.0a0' +version = '0.6.0a0' sha = 'Unknown' package_name = 'torchvision' From e2b73e620110b4fcd1c21865c5a668129e68445c Mon Sep 17 00:00:00 2001 From: keith <1868690+wk5ovc@users.noreply.github.com> Date: Tue, 28 Jan 2020 05:41:24 -0800 Subject: [PATCH 030/357] Fix C++ API build work with libtorch (#1764) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1818 Reviewed By: thibautlavril Differential Revision: D19599196 Pulled By: fmassa fbshipit-source-id: 384b25622969827708881ed0e53b99141dead937 --- CMakeLists.txt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f78ec47a4a7..d5655ad7ef7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,28 @@ cmake_minimum_required(VERSION 2.8) project(torchvision) set(CMAKE_CXX_STANDARD 14) +enable_language(CUDA) + +add_definitions(-D__CUDA_NO_HALF_OPERATORS__) find_package(Torch REQUIRED) +find_package(pybind11 REQUIRED) + +include_directories(${PYTHON_INCLUDE_DIR}) -file(GLOB HEADERS torchvision/csrc/vision.h) +file(GLOB HEADERS torchvision/csrc/*.h) +file(GLOB CPU_HEADERS torchvision/csrc/cpu/vision_cpu.h) +file(GLOB CPU_SOURCES torchvision/csrc/cuda/*.h torchvision/csrc/cpu/*.cpp) +file(GLOB CUDA_HEADERS torchvision/csrc/cuda/vision_cuda.h) +file(GLOB CUDA_SOURCES torchvision/csrc/cuda/*.h torchvision/csrc/cuda/*.cu) file(GLOB MODELS_HEADERS torchvision/csrc/models/*.h) file(GLOB MODELS_SOURCES torchvision/csrc/models/*.h torchvision/csrc/models/*.cpp) -add_library (${PROJECT_NAME} SHARED ${MODELS_SOURCES}) +add_library (${PROJECT_NAME} SHARED ${MODELS_SOURCES} ${CPU_SOURCES} ${CUDA_SOURCES}) target_link_libraries(${PROJECT_NAME} PUBLIC "${TORCH_LIBRARIES}") install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}) +install(FILES ${CPU_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/cpu) +install(FILES ${CUDA_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/cuda) install(FILES ${MODELS_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/models) From 32e22ecb11d73a6ea7e86921d5b7a53073722d26 Mon Sep 17 00:00:00 2001 From: Jeremy Reizenstein Date: Tue, 28 Jan 2020 05:42:46 -0800 Subject: [PATCH 031/357] typing only needed for python 3.5 and previous (#1778) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1820 Reviewed By: thibautlavril Differential Revision: D19599200 Pulled By: fmassa fbshipit-source-id: 773b9858f4d3055c38382e65f429be39a7a3a954 --- packaging/conda/build_vision.sh | 6 ++++++ packaging/pkg_helpers.bash | 10 ++++++++++ packaging/torchvision/meta.yaml | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packaging/conda/build_vision.sh b/packaging/conda/build_vision.sh index 000f314670b..8c99fd57fc5 100755 --- a/packaging/conda/build_vision.sh +++ b/packaging/conda/build_vision.sh @@ -157,6 +157,12 @@ for py_ver in "${DESIRED_PYTHON[@]}"; do rm -rf "$output_folder" mkdir "$output_folder" + if [[ "$py_ver" == 3.5 ]]; then + export CONDA_TYPING_CONSTRAINT="- typing" + else + export CONDA_TYPING_CONSTRAINT="" + fi + export VSTOOLCHAIN_PACKAGE=vs2017 # We need to build the compiler activation scripts first on Windows diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index e082959f601..71fd6e736be 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -115,6 +115,15 @@ setup_macos() { fi } +# set variable to determine whether the typing library needs to be built in +setup_typing() { + if [[ "$PYTHON_VERSION" == 3.5 ]]; then + export CONDA_TYPING_CONSTRAINT="- typing" + else + export CONDA_TYPING_CONSTRAINT="" + fi +} + # Top-level entry point for things every package will need to do # # Usage: setup_env 0.2.0 @@ -122,6 +131,7 @@ setup_env() { setup_cuda setup_build_version "$1" setup_macos + setup_typing } # Function to retry functions that sometimes timeout or have flaky failures diff --git a/packaging/torchvision/meta.yaml b/packaging/torchvision/meta.yaml index da075ff03cb..1bc199e437b 100644 --- a/packaging/torchvision/meta.yaml +++ b/packaging/torchvision/meta.yaml @@ -47,7 +47,7 @@ test: - mock - av - ca-certificates - - typing + {{ environ.get('CONDA_TYPING_CONSTRAINT') }} commands: pytest . From 66482263b3524437844b2fcac214ac4eb4631662 Mon Sep 17 00:00:00 2001 From: Gokkulnath TS Date: Tue, 28 Jan 2020 05:43:39 -0800 Subject: [PATCH 032/357] Fixes EMNIST classes attribute is wrong #1716 (#1736) (#1812) Summary: * Fixes https://github.com/pytorch/vision/issues/1716 Fixes EMNIST classes attribute is wrong https://github.com/pytorch/vision/issues/1716 * Fixed the Classes for Letters Split * Update mnist.py * Move classes attribute inside init definition * Fix Linting errors Pull Request resolved: https://github.com/pytorch/vision/pull/1812 Reviewed By: javier-m Differential Revision: D19599110 Pulled By: fmassa fbshipit-source-id: 25c4cb6b9f509414a754dc74f7e402dc750c328a --- torchvision/datasets/mnist.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index 22c4c07ecaa..66299cd9418 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -7,6 +7,7 @@ import numpy as np import torch import codecs +import string from .utils import download_url, download_and_extract_archive, extract_archive, \ makedir_exist_ok, verify_str_arg @@ -239,12 +240,24 @@ class EMNIST(MNIST): url = 'http://www.itl.nist.gov/iaui/vip/cs_links/EMNIST/gzip.zip' md5 = "58c8d27c78d21e728a6bc7b3cc06412e" splits = ('byclass', 'bymerge', 'balanced', 'letters', 'digits', 'mnist') + # Merged Classes assumes Same structure for both uppercase and lowercase version + _merged_classes = set(['C', 'I', 'J', 'K', 'L', 'M', 'O', 'P', 'S', 'U', 'V', 'W', 'X', 'Y', 'Z']) + _all_classes = set(list(string.digits + string.ascii_letters)) + classes_split_dict = { + 'byclass': list(_all_classes), + 'bymerge': sorted(list(_all_classes - _merged_classes)), + 'balanced': sorted(list(_all_classes - _merged_classes)), + 'letters': list(string.ascii_lowercase), + 'digits': list(string.digits), + 'mnist': list(string.digits), + } def __init__(self, root, split, **kwargs): self.split = verify_str_arg(split, "split", self.splits) self.training_file = self._training_file(split) self.test_file = self._test_file(split) super(EMNIST, self).__init__(root, **kwargs) + self.classes = self.classes_split_dict[self.split] @staticmethod def _training_file(split): From ee261c67a6b3f236d6d0f829071ec22b294251ae Mon Sep 17 00:00:00 2001 From: Marco Martinelli Date: Tue, 28 Jan 2020 05:43:49 -0800 Subject: [PATCH 033/357] Changes in docstring example for RCNN based models. (#1763) (#1809) Summary: * Type of input featmap_names fixed in example. * Added missing imports. Pull Request resolved: https://github.com/pytorch/vision/pull/1809 Reviewed By: javier-m Differential Revision: D19599103 Pulled By: fmassa fbshipit-source-id: f80b3d77caa5dfbfea9c17925376e2d620aa5ae5 --- torchvision/models/detection/faster_rcnn.py | 4 ++-- torchvision/models/detection/keypoint_rcnn.py | 9 +++++---- torchvision/models/detection/mask_rcnn.py | 9 +++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/torchvision/models/detection/faster_rcnn.py b/torchvision/models/detection/faster_rcnn.py index dca61a53c2e..422989e694c 100644 --- a/torchvision/models/detection/faster_rcnn.py +++ b/torchvision/models/detection/faster_rcnn.py @@ -123,10 +123,10 @@ class FasterRCNN(GeneralizedRCNN): >>> # use to perform the region of interest cropping, as well as >>> # the size of the crop after rescaling. >>> # if your backbone returns a Tensor, featmap_names is expected to - >>> # be [0]. More generally, the backbone should return an + >>> # be ['0']. More generally, the backbone should return an >>> # OrderedDict[Tensor], and in featmap_names you can choose which >>> # feature maps to use. - >>> roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[0], + >>> roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'], >>> output_size=7, >>> sampling_ratio=2) >>> diff --git a/torchvision/models/detection/keypoint_rcnn.py b/torchvision/models/detection/keypoint_rcnn.py index f4076155335..7f280945ee4 100644 --- a/torchvision/models/detection/keypoint_rcnn.py +++ b/torchvision/models/detection/keypoint_rcnn.py @@ -101,6 +101,7 @@ class KeypointRCNN(FasterRCNN): Example:: + >>> import torch >>> import torchvision >>> from torchvision.models.detection import KeypointRCNN >>> from torchvision.models.detection.rpn import AnchorGenerator @@ -125,17 +126,17 @@ class KeypointRCNN(FasterRCNN): >>> # use to perform the region of interest cropping, as well as >>> # the size of the crop after rescaling. >>> # if your backbone returns a Tensor, featmap_names is expected to - >>> # be [0]. More generally, the backbone should return an + >>> # be ['0']. More generally, the backbone should return an >>> # OrderedDict[Tensor], and in featmap_names you can choose which >>> # feature maps to use. - >>> roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[0], + >>> roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'], >>> output_size=7, >>> sampling_ratio=2) >>> - >>> keypoint_roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[0], + >>> keypoint_roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'], >>> output_size=14, >>> sampling_ratio=2) - >>> # put the pieces together inside a FasterRCNN model + >>> # put the pieces together inside a KeypointRCNN model >>> model = KeypointRCNN(backbone, >>> num_classes=2, >>> rpn_anchor_generator=anchor_generator, diff --git a/torchvision/models/detection/mask_rcnn.py b/torchvision/models/detection/mask_rcnn.py index 4244f6fa1a1..51641966bbb 100644 --- a/torchvision/models/detection/mask_rcnn.py +++ b/torchvision/models/detection/mask_rcnn.py @@ -104,6 +104,7 @@ class MaskRCNN(FasterRCNN): Example:: + >>> import torch >>> import torchvision >>> from torchvision.models.detection import MaskRCNN >>> from torchvision.models.detection.rpn import AnchorGenerator @@ -128,17 +129,17 @@ class MaskRCNN(FasterRCNN): >>> # use to perform the region of interest cropping, as well as >>> # the size of the crop after rescaling. >>> # if your backbone returns a Tensor, featmap_names is expected to - >>> # be [0]. More generally, the backbone should return an + >>> # be ['0']. More generally, the backbone should return an >>> # OrderedDict[Tensor], and in featmap_names you can choose which >>> # feature maps to use. - >>> roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[0], + >>> roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'], >>> output_size=7, >>> sampling_ratio=2) >>> - >>> mask_roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=[0], + >>> mask_roi_pooler = torchvision.ops.MultiScaleRoIAlign(featmap_names=['0'], >>> output_size=14, >>> sampling_ratio=2) - >>> # put the pieces together inside a FasterRCNN model + >>> # put the pieces together inside a MaskRCNN model >>> model = MaskRCNN(backbone, >>> num_classes=2, >>> rpn_anchor_generator=anchor_generator, From 54de719b000556b6dabc8c4a43d61a7296998bed Mon Sep 17 00:00:00 2001 From: Richard Zou Date: Tue, 28 Jan 2020 05:44:26 -0800 Subject: [PATCH 034/357] Remove unintentional -O0 option in setup.py (#1770) (#1819) Summary: Previously, when doing a CUDA build, we would pass -O0 to build cpu bits. This PR removes that `-O0` (so we build in `-O3` instead. Pull Request resolved: https://github.com/pytorch/vision/pull/1819 Test Plan: - wait for CI Reviewed By: thibautlavril Differential Revision: D19599199 Pulled By: fmassa fbshipit-source-id: 2a31e12761be0bee48921a136ffde1b5ff47b18a --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9f895a03450..60b8a12c91b 100644 --- a/setup.py +++ b/setup.py @@ -113,7 +113,7 @@ def get_extensions(): else: nvcc_flags = nvcc_flags.split(' ') extra_compile_args = { - 'cxx': ['-O0'], + 'cxx': [], 'nvcc': nvcc_flags, } From 457a025cd96c9d0d8ef5cdf9d860ee17d27aabe4 Mon Sep 17 00:00:00 2001 From: Prajjwal Bhargava Date: Tue, 28 Jan 2020 05:44:45 -0800 Subject: [PATCH 035/357] Added Training Sample code for fasterrcnn_resnet50_fpn (#1695) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1807 Reviewed By: javier-m Differential Revision: D19599040 Pulled By: fmassa fbshipit-source-id: d40344c9b255b86f5876887afcd81d37ec6e24e5 --- torchvision/models/detection/faster_rcnn.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/torchvision/models/detection/faster_rcnn.py b/torchvision/models/detection/faster_rcnn.py index 422989e694c..82d56e40f13 100644 --- a/torchvision/models/detection/faster_rcnn.py +++ b/torchvision/models/detection/faster_rcnn.py @@ -318,7 +318,16 @@ def fasterrcnn_resnet50_fpn(pretrained=False, progress=True, Example:: >>> model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True) - >>> model.eval() + >>> images,boxes,labels = torch.rand(4,3,600,1200), torch.rand(4,11,4), torch.rand(4,11) # For Training + >>> images = list(image for image in images) + >>> targets = [] + >>> for i in range(len(images)): + >>> d = {} + >>> d['boxes'] = boxes[i] + >>> d['labels'] = labels[i].type(torch.int64) + >>> targets.append(d) + >>> output = model(images,targets) + >>> model.eval() # For inference >>> x = [torch.rand(3, 300, 400), torch.rand(3, 500, 400)] >>> predictions = model(x) From 2c7dcf05fc412336135a408c944bffbe3ea7a970 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 28 Jan 2020 05:44:51 -0800 Subject: [PATCH 036/357] Update quantized shufflenet weights (#1715) (#1814) Summary: Previous weights are not compatible with current PyTorch Pull Request resolved: https://github.com/pytorch/vision/pull/1814 Reviewed By: javier-m Differential Revision: D19599116 Pulled By: fmassa fbshipit-source-id: 5234990a0ba7fc95307ea09230462df4d6a941d0 --- torchvision/models/quantization/shufflenetv2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/quantization/shufflenetv2.py b/torchvision/models/quantization/shufflenetv2.py index 9826e61f679..ec888ec6a33 100644 --- a/torchvision/models/quantization/shufflenetv2.py +++ b/torchvision/models/quantization/shufflenetv2.py @@ -15,7 +15,7 @@ quant_model_urls = { 'shufflenetv2_x0.5_fbgemm': None, 'shufflenetv2_x1.0_fbgemm': - 'https://download.pytorch.org/models/quantized/shufflenetv2_x1_fbgemm-751f210b.pth', + 'https://download.pytorch.org/models/quantized/shufflenetv2_x1_fbgemm-db332c57.pth', 'shufflenetv2_x1.5_fbgemm': None, 'shufflenetv2_x2.0_fbgemm': None, } From 6ebcab0cf2d39f9443c2f5d87601172dd6e14799 Mon Sep 17 00:00:00 2001 From: Sergey Zagoruyko Date: Tue, 28 Jan 2020 05:45:54 -0800 Subject: [PATCH 037/357] fix for loading models with num_batches_tracked in frozen bn (#1728) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1815 Reviewed By: javier-m Differential Revision: D19599121 Pulled By: fmassa fbshipit-source-id: 9ecc14d232ad3c32fbbf847c4241d4a3c6cd4692 --- torchvision/ops/misc.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/torchvision/ops/misc.py b/torchvision/ops/misc.py index 8ca90e7e2bb..d06d702732e 100644 --- a/torchvision/ops/misc.py +++ b/torchvision/ops/misc.py @@ -145,6 +145,16 @@ def __init__(self, n): self.register_buffer("running_mean", torch.zeros(n)) self.register_buffer("running_var", torch.ones(n)) + def _load_from_state_dict(self, state_dict, prefix, local_metadata, strict, + missing_keys, unexpected_keys, error_msgs): + num_batches_tracked_key = prefix + 'num_batches_tracked' + if num_batches_tracked_key in state_dict: + del state_dict[num_batches_tracked_key] + + super(FrozenBatchNorm2d, self)._load_from_state_dict( + state_dict, prefix, local_metadata, strict, + missing_keys, unexpected_keys, error_msgs) + def forward(self, x): # move reshapes to the beginning # to make it fuser-friendly From b318f0926f17fa137a38437baa93a8474bc8006a Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 28 Jan 2020 05:47:49 -0800 Subject: [PATCH 038/357] Remove constants from DenseBlock (#1727) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1816 Reviewed By: javier-m Differential Revision: D19599122 Pulled By: fmassa fbshipit-source-id: b9be9caa0a0d9471cdd4267149e40e8a271bc1c8 --- torchvision/models/densenet.py | 1 - 1 file changed, 1 deletion(-) diff --git a/torchvision/models/densenet.py b/torchvision/models/densenet.py index d4dc283a5f5..b58e8b413e1 100644 --- a/torchvision/models/densenet.py +++ b/torchvision/models/densenet.py @@ -92,7 +92,6 @@ def forward(self, input): # noqa: F811 class _DenseBlock(nn.ModuleDict): _version = 2 - __constants__ = ['layers'] def __init__(self, num_layers, num_input_features, bn_size, growth_rate, drop_rate, memory_efficient=False): super(_DenseBlock, self).__init__() From db69d4f7b01cd6e8c0a4b4613d706d4134f31c3f Mon Sep 17 00:00:00 2001 From: Lara Haidar Date: Tue, 28 Jan 2020 05:49:16 -0800 Subject: [PATCH 039/357] UIpdate Doc with ONNX support (#1752) (#1808) Summary: * update doc * update doc Pull Request resolved: https://github.com/pytorch/vision/pull/1808 Reviewed By: javier-m Differential Revision: D19599099 Pulled By: fmassa fbshipit-source-id: 2071ceef51eed930c6da44374596389ab89cc501 --- torchvision/models/detection/faster_rcnn.py | 5 +++++ torchvision/models/detection/keypoint_rcnn.py | 5 +++++ torchvision/models/detection/mask_rcnn.py | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/torchvision/models/detection/faster_rcnn.py b/torchvision/models/detection/faster_rcnn.py index 82d56e40f13..f4d584b4139 100644 --- a/torchvision/models/detection/faster_rcnn.py +++ b/torchvision/models/detection/faster_rcnn.py @@ -315,6 +315,8 @@ def fasterrcnn_resnet50_fpn(pretrained=False, progress=True, - labels (``Int64Tensor[N]``): the predicted labels for each image - scores (``Tensor[N]``): the scores or each prediction + Faster R-CNN is exportable to ONNX for a fixed batch size with inputs images of fixed size. + Example:: >>> model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True) @@ -330,6 +332,9 @@ def fasterrcnn_resnet50_fpn(pretrained=False, progress=True, >>> model.eval() # For inference >>> x = [torch.rand(3, 300, 400), torch.rand(3, 500, 400)] >>> predictions = model(x) + >>> + >>> # optionally, if you want to export the model to ONNX: + >>> torch.onnx.export(model, x, "faster_rcnn.onnx", opset_version = 11) Arguments: pretrained (bool): If True, returns a model pre-trained on COCO train2017 diff --git a/torchvision/models/detection/keypoint_rcnn.py b/torchvision/models/detection/keypoint_rcnn.py index 7f280945ee4..937bccadf9d 100644 --- a/torchvision/models/detection/keypoint_rcnn.py +++ b/torchvision/models/detection/keypoint_rcnn.py @@ -295,12 +295,17 @@ def keypointrcnn_resnet50_fpn(pretrained=False, progress=True, - scores (``Tensor[N]``): the scores or each prediction - keypoints (``FloatTensor[N, K, 3]``): the locations of the predicted keypoints, in ``[x, y, v]`` format. + Keypoint R-CNN is exportable to ONNX for a fixed batch size with inputs images of fixed size. + Example:: >>> model = torchvision.models.detection.keypointrcnn_resnet50_fpn(pretrained=True) >>> model.eval() >>> x = [torch.rand(3, 300, 400), torch.rand(3, 500, 400)] >>> predictions = model(x) + >>> + >>> # optionally, if you want to export the model to ONNX: + >>> torch.onnx.export(model, x, "keypoint_rcnn.onnx", opset_version = 11) Arguments: pretrained (bool): If True, returns a model pre-trained on COCO train2017 diff --git a/torchvision/models/detection/mask_rcnn.py b/torchvision/models/detection/mask_rcnn.py index 51641966bbb..5b009ee6929 100644 --- a/torchvision/models/detection/mask_rcnn.py +++ b/torchvision/models/detection/mask_rcnn.py @@ -295,12 +295,17 @@ def maskrcnn_resnet50_fpn(pretrained=False, progress=True, obtain the final segmentation masks, the soft masks can be thresholded, generally with a value of 0.5 (``mask >= 0.5``) + Mask R-CNN is exportable to ONNX for a fixed batch size with inputs images of fixed size. + Example:: >>> model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True) >>> model.eval() >>> x = [torch.rand(3, 300, 400), torch.rand(3, 500, 400)] >>> predictions = model(x) + >>> + >>> # optionally, if you want to export the model to ONNX: + >>> torch.onnx.export(model, x, "mask_rcnn.onnx", opset_version = 11) Arguments: pretrained (bool): If True, returns a model pre-trained on COCO train2017 From 48fa44a3cc780d01d578ab5068fa618e36e2380d Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 28 Jan 2020 05:55:15 -0800 Subject: [PATCH 040/357] Update KeypointRCNN weights (#1609) (#1801) Summary: * Update KeypointRCNN weights with correct file * Fix model * Fix Pull Request resolved: https://github.com/pytorch/vision/pull/1801 Reviewed By: lerks Differential Revision: D19598576 Pulled By: fmassa fbshipit-source-id: ddd116b84d36cef7aace8d42397296f5a1dd5c78 --- torchvision/models/detection/keypoint_rcnn.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/torchvision/models/detection/keypoint_rcnn.py b/torchvision/models/detection/keypoint_rcnn.py index 937bccadf9d..2efdb1de03d 100644 --- a/torchvision/models/detection/keypoint_rcnn.py +++ b/torchvision/models/detection/keypoint_rcnn.py @@ -259,8 +259,11 @@ def forward(self, x): model_urls = { - 'keypointrcnn_resnet50_fpn_coco': + # legacy model for BC reasons, see https://github.com/pytorch/vision/issues/1606 + 'keypointrcnn_resnet50_fpn_coco_legacy': 'https://download.pytorch.org/models/keypointrcnn_resnet50_fpn_coco-9f466800.pth', + 'keypointrcnn_resnet50_fpn_coco': + 'https://download.pytorch.org/models/keypointrcnn_resnet50_fpn_coco-fc266e95.pth', } @@ -317,7 +320,10 @@ def keypointrcnn_resnet50_fpn(pretrained=False, progress=True, backbone = resnet_fpn_backbone('resnet50', pretrained_backbone) model = KeypointRCNN(backbone, num_classes, num_keypoints=num_keypoints, **kwargs) if pretrained: - state_dict = load_state_dict_from_url(model_urls['keypointrcnn_resnet50_fpn_coco'], + key = 'keypointrcnn_resnet50_fpn_coco' + if pretrained == 'legacy': + key += '_legacy' + state_dict = load_state_dict_from_url(model_urls[key], progress=progress) model.load_state_dict(state_dict) return model From c2cfe0252ca622cb849ac7b573b05b2b727c4ca6 Mon Sep 17 00:00:00 2001 From: peterjc123 Date: Tue, 28 Jan 2020 06:40:14 -0800 Subject: [PATCH 041/357] Fix Windows build by renaming Python init functions (#1779) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1821 Reviewed By: qasfb Differential Revision: D19599435 Pulled By: fmassa fbshipit-source-id: d4225e3c73686cfd8cf5846c38ac8e3691df1081 --- torchvision/csrc/vision.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/torchvision/csrc/vision.cpp b/torchvision/csrc/vision.cpp index c41c1b58e39..1ec4d669d4a 100644 --- a/torchvision/csrc/vision.cpp +++ b/torchvision/csrc/vision.cpp @@ -12,18 +12,18 @@ #include "nms.h" // If we are in a Windows environment, we need to define -// initialization functions for the _custom_ops extension +// initialization functions for the _C extension #ifdef _WIN32 #if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC init_custom_ops(void) { +PyMODINIT_FUNC init_C(void) { // No need to do anything. - // _custom_ops.py will run on load + // extension.py will run on load return NULL; } #else -PyMODINIT_FUNC PyInit__custom_ops(void) { +PyMODINIT_FUNC PyInit__C(void) { // No need to do anything. - // _custom_ops.py will run on load + // extension.py will run on load return NULL; } #endif From c7640911cdbfc40889cbdede9391e28739ccc692 Mon Sep 17 00:00:00 2001 From: Yuxin Wu Date: Tue, 28 Jan 2020 08:24:13 -0800 Subject: [PATCH 042/357] Speed up nms_cuda (#1704) (#1817) Summary: 1. Let the IOU function compare with threshold. This avoid a division. Similar strategy is also used in https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/kernels/non_max_suppression_op.cu.cc 2. Only compute the upper triangle of the mask. This speeds up the kernel about 20% (tested on GTX 1080Ti, with 20 input cases dumped from a Mask R-CNN inference job). Pull Request resolved: https://github.com/pytorch/vision/pull/1817 Reviewed By: javier-m Differential Revision: D19599124 Pulled By: fmassa fbshipit-source-id: f506be895e05d638749935a2fd4c2edfb1e0eb3d --- torchvision/csrc/cuda/nms_cuda.cu | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/torchvision/csrc/cuda/nms_cuda.cu b/torchvision/csrc/cuda/nms_cuda.cu index c5f6edb1b90..8487a4cbd7d 100644 --- a/torchvision/csrc/cuda/nms_cuda.cu +++ b/torchvision/csrc/cuda/nms_cuda.cu @@ -11,14 +11,14 @@ int const threadsPerBlock = sizeof(unsigned long long) * 8; template -__device__ inline float devIoU(T const* const a, T const* const b) { +__device__ inline bool devIoU(T const* const a, T const* const b, const float threshold) { T left = max(a[0], b[0]), right = min(a[2], b[2]); T top = max(a[1], b[1]), bottom = min(a[3], b[3]); T width = max(right - left, (T)0), height = max(bottom - top, (T)0); T interS = width * height; T Sa = (a[2] - a[0]) * (a[3] - a[1]); T Sb = (b[2] - b[0]) * (b[3] - b[1]); - return interS / (Sa + Sb - interS); + return interS > threshold * (Sa + Sb - interS); } template @@ -30,7 +30,7 @@ __global__ void nms_kernel( const int row_start = blockIdx.y; const int col_start = blockIdx.x; - // if (row_start > col_start) return; + if (row_start > col_start) return; const int row_size = min(n_boxes - row_start * threadsPerBlock, threadsPerBlock); @@ -60,7 +60,7 @@ __global__ void nms_kernel( start = threadIdx.x + 1; } for (i = start; i < col_size; i++) { - if (devIoU(cur_box, block_boxes + i * 4) > iou_threshold) { + if (devIoU(cur_box, block_boxes + i * 4, iou_threshold)) { t |= 1ULL << i; } } From 8860ec7aea7232506a911eacef9c28d900b773f5 Mon Sep 17 00:00:00 2001 From: peterjc123 Date: Tue, 28 Jan 2020 09:49:25 -0800 Subject: [PATCH 043/357] Add Python 3.8 binaries for Windows nightlies (#1789) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1823 Reviewed By: lerks Differential Revision: D19601709 Pulled By: fmassa fbshipit-source-id: ddaf713cd794df15908fd8e5013b2d8a17a6bf4c --- packaging/windows/templates/build_task.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packaging/windows/templates/build_task.yml b/packaging/windows/templates/build_task.yml index e595662d313..8e52749b338 100644 --- a/packaging/windows/templates/build_task.yml +++ b/packaging/windows/templates/build_task.yml @@ -55,6 +55,9 @@ jobs: PY3.7: DESIRED_PYTHON: 3.7 CUDA_VERSION: cpu + PY3.8: + DESIRED_PYTHON: 3.8 + CUDA_VERSION: cpu ${{ if ne(parameters.spec, 'CPU') }}: PY3.5_92: DESIRED_PYTHON: 3.5 @@ -65,6 +68,9 @@ jobs: PY3.7_92: DESIRED_PYTHON: 3.7 CUDA_VERSION: 92 + PY3.8_92: + DESIRED_PYTHON: 3.8 + CUDA_VERSION: 92 PY3.5_101: DESIRED_PYTHON: 3.5 CUDA_VERSION: 101 @@ -74,6 +80,9 @@ jobs: PY3.7_101: DESIRED_PYTHON: 3.7 CUDA_VERSION: 101 + PY3.8_101: + DESIRED_PYTHON: 3.8 + CUDA_VERSION: 101 pool: ${{ if eq(parameters.msagent, 'true') }}: From e44e1268087c0828dfec9ffbd566857e1b64fc42 Mon Sep 17 00:00:00 2001 From: Ebey Abraham Date: Tue, 28 Jan 2020 09:49:54 -0800 Subject: [PATCH 044/357] fixed function description (#1768) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1822 Reviewed By: lerks Differential Revision: D19601695 Pulled By: fmassa fbshipit-source-id: e6f2b239c807e9222d74e21b96d662351ea70bcb --- torchvision/models/detection/mask_rcnn.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/torchvision/models/detection/mask_rcnn.py b/torchvision/models/detection/mask_rcnn.py index 5b009ee6929..dba9d7eafd4 100644 --- a/torchvision/models/detection/mask_rcnn.py +++ b/torchvision/models/detection/mask_rcnn.py @@ -222,9 +222,9 @@ class MaskRCNNHeads(nn.Sequential): def __init__(self, in_channels, layers, dilation): """ Arguments: - num_classes (int): number of output classes - input_size (int): number of channels of the input once it's flattened - representation_size (int): size of the intermediate representation + in_channels (int): number of input channels + layers (list): feature dimensions of each FCN layer + dilation (int): dilation rate of kernel """ d = OrderedDict() next_feature = in_channels From 5024a2b2e3c2fccfea1fcd9f77bb02c44635e226 Mon Sep 17 00:00:00 2001 From: Tongzhou Wang Date: Tue, 28 Jan 2020 09:51:03 -0800 Subject: [PATCH 045/357] STL10: don't check integrity twice when download=True (#1787) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1826 Reviewed By: lerks Differential Revision: D19601737 Pulled By: fmassa fbshipit-source-id: 1789249cec0b6294aad9347e2341497447a70893 --- torchvision/datasets/stl10.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchvision/datasets/stl10.py b/torchvision/datasets/stl10.py index 0dbed6e06f2..e01d0b86c45 100644 --- a/torchvision/datasets/stl10.py +++ b/torchvision/datasets/stl10.py @@ -55,8 +55,7 @@ def __init__(self, root, split='train', folds=None, transform=None, if download: self.download() - - if not self._check_integrity(): + elif not self._check_integrity(): raise RuntimeError( 'Dataset not found or corrupted. ' 'You can use download=True to download it') @@ -161,6 +160,7 @@ def download(self): print('Files already downloaded and verified') return download_and_extract_archive(self.url, self.root, filename=self.filename, md5=self.tgz_md5) + self._check_integrity() def extra_repr(self): return "Split: {split}".format(**self.__dict__) From a4d347548f9c4936aab79802c19146f8f9883b9b Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Tue, 28 Jan 2020 09:51:59 -0800 Subject: [PATCH 046/357] Fix fill in rotate (#1760) (#1825) Summary: * initial fix * outsourced num bands lookup * fix doc * added pillow version requirement * simplify number of bands extraction * remove unrelated change * remove indirect dependency on pillow>=5.2.0 * extend docstring to transform * bug fix * added test Pull Request resolved: https://github.com/pytorch/vision/pull/1825 Reviewed By: lerks Differential Revision: D19601729 Pulled By: fmassa fbshipit-source-id: e0f073b052ea49b0c316f71ab5057641c92220e1 --- test/test_transforms.py | 21 +++++++++++++++++++ torchvision/transforms/functional.py | 31 ++++++++++++++++++++++------ torchvision/transforms/transforms.py | 7 ++++--- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/test/test_transforms.py b/test/test_transforms.py index a801360424c..3a76f3a1adb 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -1,5 +1,6 @@ from __future__ import division import os +import mock import torch import torchvision.transforms as transforms import torchvision.transforms.functional as F @@ -1074,6 +1075,26 @@ def test_rotate(self): self.assertTrue(np.all(np.array(result_a) == np.array(result_b))) + def test_rotate_fill(self): + img = F.to_pil_image(np.ones((100, 100, 3), dtype=np.uint8) * 255, "RGB") + + modes = ("L", "RGB") + nums_bands = [len(mode) for mode in modes] + fill = 127 + + for mode, num_bands in zip(modes, nums_bands): + img_conv = img.convert(mode) + img_rot = F.rotate(img_conv, 45.0, fill=fill) + pixel = img_rot.getpixel((0, 0)) + + if not isinstance(pixel, tuple): + pixel = (pixel,) + self.assertTupleEqual(pixel, tuple([fill] * num_bands)) + + for wrong_num_bands in set(nums_bands) - {num_bands}: + with self.assertRaises(ValueError): + F.rotate(img_conv, 45.0, fill=tuple([fill] * wrong_num_bands)) + def test_affine(self): input_img = np.zeros((40, 40, 3), dtype=np.uint8) pts = [] diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 8ae75f84c5b..299b0203944 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -696,7 +696,7 @@ def adjust_gamma(img, gamma, gain=1): return img -def rotate(img, angle, resample=False, expand=False, center=None, fill=0): +def rotate(img, angle, resample=False, expand=False, center=None, fill=None): """Rotate the image by angle. @@ -713,20 +713,39 @@ def rotate(img, angle, resample=False, expand=False, center=None, fill=0): center (2-tuple, optional): Optional center of rotation. Origin is the upper left corner. Default is the center of the image. - fill (3-tuple or int): RGB pixel fill value for area outside the rotated image. - If int, it is used for all channels respectively. + fill (n-tuple or int or float): Pixel fill value for area outside the rotated + image. If int or float, the value is used for all bands respectively. + Defaults to 0 for all bands. This option is only available for ``pillow>=5.2.0``. .. _filters: https://pillow.readthedocs.io/en/latest/handbook/concepts.html#filters """ + def parse_fill(fill, num_bands): + if PILLOW_VERSION < "5.2.0": + if fill is None: + return {} + else: + msg = ("The option to fill background area of the rotated image, " + "requires pillow>=5.2.0") + raise RuntimeError(msg) + + if fill is None: + fill = 0 + if isinstance(fill, (int, float)): + fill = tuple([fill] * num_bands) + if len(fill) != num_bands: + msg = ("The number of elements in 'fill' does not match the number of " + "bands of the image ({} != {})") + raise ValueError(msg.format(len(fill), num_bands)) + + return {"fillcolor": fill} if not _is_pil_image(img): raise TypeError('img should be PIL Image. Got {}'.format(type(img))) - if isinstance(fill, int): - fill = tuple([fill] * 3) + opts = parse_fill(fill, len(img.getbands())) - return img.rotate(angle, resample, expand, center, fillcolor=fill) + return img.rotate(angle, resample, expand, center, **opts) def _get_inverse_affine_matrix(center, angle, translate, scale, shear): diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 3ec84aae84c..393e3c2db33 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -956,14 +956,15 @@ class RandomRotation(object): center (2-tuple, optional): Optional center of rotation. Origin is the upper left corner. Default is the center of the image. - fill (3-tuple or int): RGB pixel fill value for area outside the rotated image. - If int, it is used for all channels respectively. + fill (n-tuple or int or float): Pixel fill value for area outside the rotated + image. If int or float, the value is used for all bands respectively. + Defaults to 0 for all bands. This option is only available for ``pillow>=5.2.0``. .. _filters: https://pillow.readthedocs.io/en/latest/handbook/concepts.html#filters """ - def __init__(self, degrees, resample=False, expand=False, center=None, fill=0): + def __init__(self, degrees, resample=False, expand=False, center=None, fill=None): if isinstance(degrees, numbers.Number): if degrees < 0: raise ValueError("If degrees is a single number, it must be positive.") From ccdc9f7ab64a52637a37c5ee2600f1ad1a317502 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 29 Jan 2020 10:39:59 -0800 Subject: [PATCH 047/357] Fix for rotate fill with Images of type F (#1828) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1829 Reviewed By: lerks Differential Revision: D19619779 Pulled By: fmassa fbshipit-source-id: 0a210f90d58102da59dfb8ab1b3f93c619d0507f --- test/test_transforms.py | 2 +- torchvision/transforms/functional.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_transforms.py b/test/test_transforms.py index 3a76f3a1adb..6eb295d63bf 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -1078,7 +1078,7 @@ def test_rotate(self): def test_rotate_fill(self): img = F.to_pil_image(np.ones((100, 100, 3), dtype=np.uint8) * 255, "RGB") - modes = ("L", "RGB") + modes = ("L", "RGB", "F") nums_bands = [len(mode) for mode in modes] fill = 127 diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 299b0203944..5eef861650e 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -731,9 +731,9 @@ def parse_fill(fill, num_bands): if fill is None: fill = 0 - if isinstance(fill, (int, float)): + if isinstance(fill, (int, float)) and num_bands > 1: fill = tuple([fill] * num_bands) - if len(fill) != num_bands: + if not isinstance(fill, (int, float)) and len(fill) != num_bands: msg = ("The number of elements in 'fill' does not match the number of " "bands of the image ({} != {})") raise ValueError(msg.format(len(fill), num_bands)) From f5628e06ec277de7f15cc6887818404c9708b1da Mon Sep 17 00:00:00 2001 From: Yuri Putivsky Date: Mon, 3 Feb 2020 14:56:24 -0800 Subject: [PATCH 048/357] Integrated base decoder into VideoReader class and video_utils.py (#1766) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1766 Replaced FfmpegDecoder (incompativle with VUE) by base decoder (compatible with VUE). Modified python utilities video_utils.py for internal simplification. Public interface got preserved. Reviewed By: fmassa Differential Revision: D19415903 fbshipit-source-id: 4d7a0158bd77bac0a18732fe4183fdd9a57f6402 --- setup.py | 32 +- .../csrc/cpu/decoder/audio_sampler.cpp | 40 +- torchvision/csrc/cpu/decoder/audio_sampler.h | 2 - torchvision/csrc/cpu/decoder/audio_stream.cpp | 53 +- torchvision/csrc/cpu/decoder/audio_stream.h | 5 - torchvision/csrc/cpu/decoder/cc_stream.cpp | 2 - torchvision/csrc/cpu/decoder/cc_stream.h | 2 - torchvision/csrc/cpu/decoder/decoder.cpp | 217 ++++--- torchvision/csrc/cpu/decoder/decoder.h | 20 +- torchvision/csrc/cpu/decoder/defs.h | 83 ++- .../csrc/cpu/decoder/memory_buffer.cpp | 75 +++ torchvision/csrc/cpu/decoder/memory_buffer.h | 25 + .../csrc/cpu/decoder/seekable_buffer.cpp | 159 +++-- .../csrc/cpu/decoder/seekable_buffer.h | 29 +- torchvision/csrc/cpu/decoder/stream.cpp | 201 +++++-- torchvision/csrc/cpu/decoder/stream.h | 38 +- .../csrc/cpu/decoder/subtitle_sampler.cpp | 2 - .../csrc/cpu/decoder/subtitle_sampler.h | 2 - .../csrc/cpu/decoder/subtitle_stream.cpp | 31 +- .../csrc/cpu/decoder/subtitle_stream.h | 8 +- torchvision/csrc/cpu/decoder/sync_decoder.cpp | 35 +- torchvision/csrc/cpu/decoder/sync_decoder.h | 7 +- .../csrc/cpu/decoder/sync_decoder_test.cpp | 139 ++++- torchvision/csrc/cpu/decoder/time_keeper.cpp | 12 +- torchvision/csrc/cpu/decoder/time_keeper.h | 8 +- torchvision/csrc/cpu/decoder/util.cpp | 2 - torchvision/csrc/cpu/decoder/util.h | 2 - .../csrc/cpu/decoder/video_sampler.cpp | 2 - torchvision/csrc/cpu/decoder/video_sampler.h | 2 - torchvision/csrc/cpu/decoder/video_stream.cpp | 58 +- torchvision/csrc/cpu/decoder/video_stream.h | 9 +- .../cpu/video_reader/FfmpegAudioSampler.cpp | 118 ---- .../cpu/video_reader/FfmpegAudioSampler.h | 32 - .../cpu/video_reader/FfmpegAudioStream.cpp | 103 ---- .../csrc/cpu/video_reader/FfmpegAudioStream.h | 54 -- .../csrc/cpu/video_reader/FfmpegDecoder.cpp | 412 ------------- .../csrc/cpu/video_reader/FfmpegDecoder.h | 127 ---- .../csrc/cpu/video_reader/FfmpegHeaders.h | 13 - .../csrc/cpu/video_reader/FfmpegSampler.h | 16 - .../csrc/cpu/video_reader/FfmpegStream.cpp | 188 ------ .../csrc/cpu/video_reader/FfmpegStream.h | 69 --- .../csrc/cpu/video_reader/FfmpegUtil.cpp | 111 ---- .../csrc/cpu/video_reader/FfmpegUtil.h | 27 - .../cpu/video_reader/FfmpegVideoSampler.cpp | 90 --- .../cpu/video_reader/FfmpegVideoSampler.h | 32 - .../cpu/video_reader/FfmpegVideoStream.cpp | 115 ---- .../csrc/cpu/video_reader/FfmpegVideoStream.h | 54 -- .../csrc/cpu/video_reader/Interface.cpp | 22 - torchvision/csrc/cpu/video_reader/Interface.h | 127 ---- .../csrc/cpu/video_reader/VideoReader.cpp | 547 ++++++++++++------ .../csrc/cpu/video_reader/VideoReader.h | 96 --- torchvision/csrc/cpu/video_reader/util.cpp | 60 -- torchvision/csrc/cpu/video_reader/util.h | 26 - 53 files changed, 1144 insertions(+), 2597 deletions(-) create mode 100644 torchvision/csrc/cpu/decoder/memory_buffer.cpp create mode 100644 torchvision/csrc/cpu/decoder/memory_buffer.h delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegAudioSampler.cpp delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegAudioSampler.h delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegAudioStream.cpp delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegAudioStream.h delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegDecoder.cpp delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegDecoder.h delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegHeaders.h delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegSampler.h delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegStream.cpp delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegStream.h delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegUtil.cpp delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegUtil.h delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegVideoSampler.cpp delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegVideoSampler.h delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegVideoStream.cpp delete mode 100644 torchvision/csrc/cpu/video_reader/FfmpegVideoStream.h delete mode 100644 torchvision/csrc/cpu/video_reader/Interface.cpp delete mode 100644 torchvision/csrc/cpu/video_reader/Interface.h delete mode 100644 torchvision/csrc/cpu/video_reader/util.cpp delete mode 100644 torchvision/csrc/cpu/video_reader/util.h diff --git a/setup.py b/setup.py index 60b8a12c91b..f763bd2c42c 100644 --- a/setup.py +++ b/setup.py @@ -155,41 +155,21 @@ def get_extensions(): ffmpeg_root = os.path.dirname(ffmpeg_bin) ffmpeg_include_dir = os.path.join(ffmpeg_root, 'include') - # TorchVision video reader + # TorchVision base decoder + video reader video_reader_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'video_reader') video_reader_src = glob.glob(os.path.join(video_reader_src_dir, "*.cpp")) - - ext_modules.append( - CppExtension( - 'torchvision.video_reader', - video_reader_src, - include_dirs=[ - video_reader_src_dir, - ffmpeg_include_dir, - extensions_dir, - ], - libraries=[ - 'avcodec', - 'avformat', - 'avutil', - 'swresample', - 'swscale', - ], - extra_compile_args=["-std=c++14"], - extra_link_args=["-std=c++14"], - ) - ) - - # TorchVision base decoder base_decoder_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'decoder') base_decoder_src = glob.glob(os.path.join(base_decoder_src_dir, "[!sync_decoder_test]*.cpp")) + combined_src = video_reader_src + base_decoder_src + ext_modules.append( CppExtension( - 'torchvision.base_decoder', - base_decoder_src, + 'torchvision.video_reader', + combined_src, include_dirs=[ base_decoder_src_dir, + video_reader_src_dir, ffmpeg_include_dir, extensions_dir, ], diff --git a/torchvision/csrc/cpu/decoder/audio_sampler.cpp b/torchvision/csrc/cpu/decoder/audio_sampler.cpp index c10fceb852d..4092df98359 100644 --- a/torchvision/csrc/cpu/decoder/audio_sampler.cpp +++ b/torchvision/csrc/cpu/decoder/audio_sampler.cpp @@ -1,15 +1,10 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "audio_sampler.h" #include #include "util.h" -// www.ffmpeg.org/doxygen/1.1/doc_2examples_2resampling_audio_8c-example.html#a24 - -#ifndef SWR_CH_MAX -#define SWR_CH_MAX 32 -#endif +#define AVRESAMPLE_MAX_CHANNELS 32 +// www.ffmpeg.org/doxygen/1.1/doc_2examples_2resampling_audio_8c-example.html#a24 namespace ffmpeg { namespace { @@ -94,9 +89,12 @@ int AudioSampler::numOutputSamples(int inSamples) const { } int AudioSampler::getSamplesBytes(AVFrame* frame) const { - return av_get_bytes_per_sample((AVSampleFormat)params_.out.audio.format) * - numOutputSamples(frame ? frame->nb_samples : 0) * - params_.out.audio.channels; + return av_samples_get_buffer_size( + nullptr, + params_.out.audio.channels, + numOutputSamples(frame ? frame->nb_samples : 0), + (AVSampleFormat)params_.out.audio.format, + 1); } int AudioSampler::sample( @@ -104,7 +102,7 @@ int AudioSampler::sample( int inNumSamples, ByteStorage* out, int outNumSamples) { - uint8_t* outPlanes[SWR_CH_MAX] = {nullptr}; + uint8_t* outPlanes[AVRESAMPLE_MAX_CHANNELS] = {nullptr}; int result; if ((result = preparePlanes( params_.out.audio, out->writableTail(), outNumSamples, outPlanes)) < @@ -140,9 +138,12 @@ int AudioSampler::sample(AVFrame* frame, ByteStorage* out) { return 0; } - const auto samplesBytes = - av_get_bytes_per_sample((AVSampleFormat)params_.out.audio.format) * - outNumSamples * params_.out.audio.channels; + const auto samplesBytes = av_samples_get_buffer_size( + nullptr, + params_.out.audio.channels, + outNumSamples, + (AVSampleFormat)params_.out.audio.format, + 1); // bytes must be allocated CHECK_LE(samplesBytes, out->tail()); @@ -167,14 +168,17 @@ int AudioSampler::sample(const ByteStorage* in, ByteStorage* out) { return 0; } - const auto samplesBytes = - av_get_bytes_per_sample((AVSampleFormat)params_.out.audio.format) * - outNumSamples * params_.out.audio.channels; + const auto samplesBytes = av_samples_get_buffer_size( + nullptr, + params_.out.audio.channels, + outNumSamples, + (AVSampleFormat)params_.out.audio.format, + 1); out->clear(); out->ensure(samplesBytes); - uint8_t* inPlanes[SWR_CH_MAX] = {nullptr}; + uint8_t* inPlanes[AVRESAMPLE_MAX_CHANNELS] = {nullptr}; int result; if (in && (result = preparePlanes( diff --git a/torchvision/csrc/cpu/decoder/audio_sampler.h b/torchvision/csrc/cpu/decoder/audio_sampler.h index d68a21ea20e..c6a021d2084 100644 --- a/torchvision/csrc/cpu/decoder/audio_sampler.h +++ b/torchvision/csrc/cpu/decoder/audio_sampler.h @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include "defs.h" diff --git a/torchvision/csrc/cpu/decoder/audio_stream.cpp b/torchvision/csrc/cpu/decoder/audio_stream.cpp index 17ab9fceb7b..ed4d6622ecd 100644 --- a/torchvision/csrc/cpu/decoder/audio_stream.cpp +++ b/torchvision/csrc/cpu/decoder/audio_stream.cpp @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "audio_stream.h" #include #include @@ -8,11 +6,23 @@ namespace ffmpeg { namespace { +bool operator==(const AudioFormat& x, const AVFrame& y) { + return x.samples == y.sample_rate && x.channels == y.channels && + x.format == y.format; +} + bool operator==(const AudioFormat& x, const AVCodecContext& y) { return x.samples == y.sample_rate && x.channels == y.channels && x.format == y.sample_fmt; } +AudioFormat& toAudioFormat(AudioFormat& x, const AVFrame& y) { + x.samples = y.sample_rate; + x.channels = y.channels; + x.format = y.format; + return x; +} + AudioFormat& toAudioFormat(AudioFormat& x, const AVCodecContext& y) { x.samples = y.sample_rate; x.channels = y.channels; @@ -29,7 +39,8 @@ AudioStream::AudioStream( : Stream( inputCtx, MediaFormat::makeMediaFormat(format, index), - convertPtsToWallTime) {} + convertPtsToWallTime, + 0) {} AudioStream::~AudioStream() { if (sampler_) { @@ -65,12 +76,15 @@ int AudioStream::initFormat() { int AudioStream::estimateBytes(bool flush) { ensureSampler(); - if (!(sampler_->getInputFormat().audio == *codecCtx_)) { + // check if input format gets changed + if (flush ? !(sampler_->getInputFormat().audio == *codecCtx_) + : !(sampler_->getInputFormat().audio == *frame_)) { // - reinit sampler SamplerParameters params; params.type = format_.type; params.out = format_.format; - toAudioFormat(params.in.audio, *codecCtx_); + flush ? toAudioFormat(params.in.audio, *codecCtx_) + : toAudioFormat(params.in.audio, *frame_); if (flush || !sampler_->init(params)) { return -1; } @@ -84,7 +98,7 @@ int AudioStream::estimateBytes(bool flush) { << ", channels: " << format_.format.audio.channels << ", format: " << format_.format.audio.format; } - return sampler_->getSamplesBytes(frame_); + return sampler_->getSamplesBytes(flush ? nullptr : frame_); } int AudioStream::copyFrameBytes(ByteStorage* out, bool flush) { @@ -92,31 +106,4 @@ int AudioStream::copyFrameBytes(ByteStorage* out, bool flush) { return sampler_->sample(flush ? nullptr : frame_, out); } -void AudioStream::setHeader(DecoderHeader* header) { - header->seqno = numGenerator_++; - - if (codecCtx_->time_base.num != 0) { - header->pts = av_rescale_q( - av_frame_get_best_effort_timestamp(frame_), - codecCtx_->time_base, - AV_TIME_BASE_Q); - } else { - // If the codec time_base is missing then we would've skipped the - // rescalePackage step to rescale to codec time_base, so here we can - // rescale straight from the stream time_base into AV_TIME_BASE_Q. - header->pts = av_rescale_q( - av_frame_get_best_effort_timestamp(frame_), - inputCtx_->streams[format_.stream]->time_base, - AV_TIME_BASE_Q); - } - - if (convertPtsToWallTime_) { - keeper_.adjust(header->pts); - } - - header->keyFrame = 1; - header->fps = std::numeric_limits::quiet_NaN(); - header->format = format_; -} - } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/audio_stream.h b/torchvision/csrc/cpu/decoder/audio_stream.h index c7708a3356d..4d200114e4a 100644 --- a/torchvision/csrc/cpu/decoder/audio_stream.h +++ b/torchvision/csrc/cpu/decoder/audio_stream.h @@ -1,10 +1,7 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include "audio_sampler.h" #include "stream.h" -#include "time_keeper.h" namespace ffmpeg { @@ -25,13 +22,11 @@ class AudioStream : public Stream { int initFormat() override; int estimateBytes(bool flush) override; int copyFrameBytes(ByteStorage* out, bool flush) override; - void setHeader(DecoderHeader* header) override; void ensureSampler(); private: std::unique_ptr sampler_; - TimeKeeper keeper_; }; } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/cc_stream.cpp b/torchvision/csrc/cpu/decoder/cc_stream.cpp index 47de485b100..7b443146289 100644 --- a/torchvision/csrc/cpu/decoder/cc_stream.cpp +++ b/torchvision/csrc/cpu/decoder/cc_stream.cpp @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "cc_stream.h" namespace ffmpeg { diff --git a/torchvision/csrc/cpu/decoder/cc_stream.h b/torchvision/csrc/cpu/decoder/cc_stream.h index 34506d3259f..d8c98f7be23 100644 --- a/torchvision/csrc/cpu/decoder/cc_stream.h +++ b/torchvision/csrc/cpu/decoder/cc_stream.h @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include "subtitle_stream.h" diff --git a/torchvision/csrc/cpu/decoder/decoder.cpp b/torchvision/csrc/cpu/decoder/decoder.cpp index d8f324863e4..b78c1e47214 100644 --- a/torchvision/csrc/cpu/decoder/decoder.cpp +++ b/torchvision/csrc/cpu/decoder/decoder.cpp @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "decoder.h" #include #include @@ -15,9 +13,8 @@ namespace ffmpeg { namespace { -constexpr ssize_t kMinSeekBufferSize = 1024; -constexpr ssize_t kMaxSeekBufferSize = 4 * 1024; -constexpr size_t kIoBufferSize = 4 * 1024; +constexpr size_t kIoBufferSize = 96 * 1024; +constexpr size_t kIoPaddingSize = AV_INPUT_BUFFER_PADDING_SIZE; constexpr size_t kLogBufferSize = 1024; int ffmpeg_lock(void** mutex, enum AVLockOp op) { @@ -205,7 +202,7 @@ void Decoder::initOnce() { av_lockmgr_register(&ffmpeg_lock); av_log_set_callback(Decoder::logFunction); av_log_set_level(AV_LOG_ERROR); - LOG(INFO) << "Registered ffmpeg libs"; + VLOG(1) << "Registered ffmpeg libs"; }); } @@ -213,10 +210,6 @@ Decoder::Decoder() { initOnce(); } -Decoder::~Decoder() { - cleanUp(); -} - bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { cleanUp(); @@ -229,42 +222,28 @@ bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { // set callback and params params_ = params; - auto tmpCtx = avformat_alloc_context(); - - if (!tmpCtx) { + if (!(inputCtx_ = avformat_alloc_context())) { LOG(ERROR) << "Cannot allocate format context"; return false; } AVInputFormat* fmt = nullptr; + int result = 0; if (in) { - const size_t avioCtxBufferSize = kIoBufferSize; - uint8_t* avioCtxBuffer = (uint8_t*)av_malloc(avioCtxBufferSize); - if (!avioCtxBuffer) { - LOG(ERROR) << "av_malloc cannot allocate " << avioCtxBufferSize - << " bytes"; - avformat_close_input(&tmpCtx); - cleanUp(); - return false; - } - - bool canSeek = in(nullptr, 0, 0) == 0; - - if (!seekableBuffer_.init( - std::forward(in), - kMinSeekBufferSize, - kMaxSeekBufferSize, - params_.timeoutMs)) { - LOG(ERROR) << "seekable buffer initialization failed"; - av_free(avioCtxBuffer); - avformat_close_input(&tmpCtx); + ImageType type = ImageType::UNKNOWN; + if ((result = seekableBuffer_.init( + std::forward(in), + params_.timeoutMs, + params_.maxSeekableBytes, + params_.isImage ? &type : nullptr)) < 0) { + LOG(ERROR) << "can't initiate seekable buffer"; cleanUp(); return false; } if (params_.isImage) { const char* fmtName = "image2"; - switch (seekableBuffer_.getImageType()) { + switch (type) { case ImageType::JPEG: fmtName = "jpeg_pipe"; break; @@ -281,6 +260,16 @@ bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { fmt = av_find_input_format(fmtName); } + const size_t avioCtxBufferSize = kIoBufferSize; + uint8_t* avioCtxBuffer = + (uint8_t*)av_malloc(avioCtxBufferSize + kIoPaddingSize); + if (!avioCtxBuffer) { + LOG(ERROR) << "av_malloc cannot allocate " << avioCtxBufferSize + << " bytes"; + cleanUp(); + return false; + } + if (!(avioCtx_ = avio_alloc_context( avioCtxBuffer, avioCtxBufferSize, @@ -288,36 +277,23 @@ bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { reinterpret_cast(this), &Decoder::readFunction, nullptr, - canSeek ? &Decoder::seekFunction : nullptr))) { + result == 1 ? &Decoder::seekFunction : nullptr))) { LOG(ERROR) << "avio_alloc_context failed"; av_free(avioCtxBuffer); - avformat_close_input(&tmpCtx); cleanUp(); return false; } - tmpCtx->pb = avioCtx_; + inputCtx_->pb = avioCtx_; + inputCtx_->flags |= AVFMT_FLAG_CUSTOM_IO; } - interrupted_ = false; - // ffmpeg avformat_open_input call can hang if media source doesn't respond - // set a guard for handle such situations - std::promise p; - std::future f = p.get_future(); - std::thread guard([&f, this]() { - auto timeout = std::chrono::milliseconds(params_.timeoutMs); - if (std::future_status::timeout == f.wait_for(timeout)) { - LOG(ERROR) << "Cannot open stream within " << params_.timeoutMs << " ms"; - interrupted_ = true; - } - }); - - tmpCtx->opaque = reinterpret_cast(this); - tmpCtx->interrupt_callback.callback = Decoder::shutdownFunction; - tmpCtx->interrupt_callback.opaque = reinterpret_cast(this); + inputCtx_->opaque = reinterpret_cast(this); + inputCtx_->interrupt_callback.callback = Decoder::shutdownFunction; + inputCtx_->interrupt_callback.opaque = reinterpret_cast(this); // add network timeout - tmpCtx->flags |= AVFMT_FLAG_NONBLOCK; + inputCtx_->flags |= AVFMT_FLAG_NONBLOCK; AVDictionary* options = nullptr; av_dict_set_int(&options, "analyzeduration", params_.timeoutMs * 1000, 0); @@ -326,19 +302,38 @@ bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { av_dict_set_int(&options, "listen", 1, 0); } - int result = 0; + interrupted_ = false; + + // ffmpeg avformat_open_input call can hang if media source doesn't respond + // set a guard for handle such situations, if requested + std::promise p; + std::future f = p.get_future(); + std::unique_ptr guard; + if (params_.preventStaleness) { + guard = std::make_unique([&f, this]() { + auto timeout = std::chrono::milliseconds(params_.timeoutMs); + if (std::future_status::timeout == f.wait_for(timeout)) { + LOG(ERROR) << "Cannot open stream within " << params_.timeoutMs + << " ms"; + interrupted_ = true; + } + }); + } + if (fmt) { - result = avformat_open_input(&tmpCtx, nullptr, fmt, &options); + result = avformat_open_input(&inputCtx_, nullptr, fmt, &options); } else { result = - avformat_open_input(&tmpCtx, params_.uri.c_str(), nullptr, &options); + avformat_open_input(&inputCtx_, params_.uri.c_str(), nullptr, &options); } - av_dict_free(&options); - p.set_value(true); - guard.join(); + av_dict_free(&options); - inputCtx_ = tmpCtx; + if (guard) { + p.set_value(true); + guard->join(); + guard.reset(); + } if (result < 0 || interrupted_) { LOG(ERROR) << "avformat_open_input failed, error: " @@ -356,7 +351,7 @@ bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { return false; } - if (!activateStreams()) { + if (!openStreams()) { LOG(ERROR) << "Cannot activate streams"; cleanUp(); return false; @@ -364,20 +359,19 @@ bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { onInit(); - if (params.startOffsetMs != 0) { - av_seek_frame( - inputCtx_, - -1, - params.startOffsetMs * AV_TIME_BASE / 1000, - AVSEEK_FLAG_FRAME | AVSEEK_FLAG_ANY); + if (params.startOffset != 0) { + auto offset = params.startOffset <= params.seekAccuracy + ? 0 + : params.startOffset - params.seekAccuracy; + + av_seek_frame(inputCtx_, -1, offset, AVSEEK_FLAG_BACKWARD); } - LOG(INFO) << "Decoder initialized, log level: " << params_.logLevel; - outOfRange_ = false; + VLOG(1) << "Decoder initialized, log level: " << params_.logLevel; return true; } -bool Decoder::activateStreams() { +bool Decoder::openStreams() { for (int i = 0; i < inputCtx_->nb_streams; i++) { // - find the corespondent format at params_.formats set MediaFormat format; @@ -418,6 +412,7 @@ bool Decoder::activateStreams() { return false; } streams_.emplace(i, std::move(stream)); + inRange_.set(i, true); } } @@ -458,8 +453,8 @@ void Decoder::cleanUp() { seekableBuffer_.shutdown(); } -int Decoder::getBytes(size_t workingTimeInMs) { - if (outOfRange_) { +int Decoder::getFrame(size_t workingTimeInMs) { + if (inRange_.none()) { return ENODATA; } // decode frames until cache is full and leave thread @@ -478,14 +473,16 @@ int Decoder::getBytes(size_t workingTimeInMs) { return std::chrono::steady_clock::now() <= end; }; - int result = ETIMEDOUT; + int result = 0; size_t decodingErrors = 0; - while (!interrupted_ && watcher()) { + bool decodedFrame = false; + while (!interrupted_ && inRange_.any() && !decodedFrame && watcher()) { result = av_read_frame(inputCtx_, &avPacket); if (result == AVERROR(EAGAIN)) { VLOG(4) << "Decoder is busy..."; + std::this_thread::yield(); result = 0; // reset error, EAGAIN is not an error at all - break; + continue; } else if (result == AVERROR_EOF) { flushStreams(); VLOG(1) << "End of stream"; @@ -499,24 +496,24 @@ int Decoder::getBytes(size_t workingTimeInMs) { // get stream auto stream = findByIndex(avPacket.stream_index); - if (stream == nullptr) { + if (stream == nullptr || !inRange_.test(stream->getIndex())) { av_packet_unref(&avPacket); continue; } - stream->rescalePackage(&avPacket); - - AVPacket copyPacket = avPacket; - size_t numConsecutiveNoBytes = 0; // it can be only partial decoding of the package bytes do { // decode package - if ((result = processPacket(stream, ©Packet)) < 0) { + bool gotFrame = false; + bool hasMsg = false; + // packet either got consumed completely or not at all + if ((result = processPacket(stream, &avPacket, &gotFrame, &hasMsg)) < 0) { + LOG(ERROR) << "processPacket failed with code: " << result; break; } - if (result == 0 && params_.maxProcessNoBytes != 0 && + if (!gotFrame && params_.maxProcessNoBytes != 0 && ++numConsecutiveNoBytes > params_.maxProcessNoBytes) { LOG(ERROR) << "Exceeding max amount of consecutive no bytes"; break; @@ -525,14 +522,14 @@ int Decoder::getBytes(size_t workingTimeInMs) { numConsecutiveNoBytes = 0; } - copyPacket.size -= result; - copyPacket.data += result; - } while (copyPacket.size > 0); + decodedFrame |= hasMsg; + } while (result == 0); // post loop check if (result < 0) { if (params_.maxPackageErrors != 0 && // check errors ++decodingErrors >= params_.maxPackageErrors) { // reached the limit + LOG(ERROR) << "Exceeding max amount of consecutive package errors"; break; } } else { @@ -546,7 +543,27 @@ int Decoder::getBytes(size_t workingTimeInMs) { av_packet_unref(&avPacket); - return result; + VLOG(2) << "Interrupted loop" + << ", interrupted_ " << interrupted_ << ", inRange_.any() " + << inRange_.any() << ", decodedFrame " << decodedFrame << ", result " + << result; + + // loop can be terminated, either by: + // 1. explcitly iterrupted + // 2. terminated by workable timeout + // 3. unrecoverable error or ENODATA (end of stream) + // 4. decoded frames pts are out of the specified range + // 5. success decoded frame + if (interrupted_) { + return EINTR; + } + if (result != 0) { + return result; + } + if (inRange_.none()) { + return ENODATA; + } + return 0; } Stream* Decoder::findByIndex(int streamIndex) const { @@ -563,17 +580,23 @@ Stream* Decoder::findByType(const MediaFormat& format) const { return nullptr; } -int Decoder::processPacket(Stream* stream, AVPacket* packet) { +int Decoder::processPacket(Stream* stream, + AVPacket* packet, + bool* gotFrame, + bool* hasMsg) { // decode package - int gotFrame = 0; int result; DecoderOutputMessage msg; msg.payload = createByteStorage(0); - if ((result = stream->decodeFrame(packet, &gotFrame)) >= 0 && gotFrame && - stream->getFrameBytes(&msg, params_.headerOnly) > 0) { + *hasMsg = false; + if ((result = stream->decodePacket( + packet, &msg, params_.headerOnly, gotFrame)) >= 0 && *gotFrame) { // check end offset - if (params_.endOffsetMs <= 0 || - !(outOfRange_ = msg.header.pts > params_.endOffsetMs * 1000)) { + bool endInRange = + params_.endOffset <= 0 || msg.header.pts <= params_.endOffset; + inRange_.set(stream->getIndex(), endInRange); + if (endInRange && msg.header.pts >= params_.startOffset) { + *hasMsg = true; push(std::move(msg)); } } @@ -587,9 +610,13 @@ void Decoder::flushStreams() { while (msg.payload = createByteStorage(0), stream.second->flush(&msg, params_.headerOnly) > 0) { // check end offset - if (params_.endOffsetMs <= 0 || - !(outOfRange_ = msg.header.pts > params_.endOffsetMs * 1000)) { + bool endInRange = + params_.endOffset <= 0 || msg.header.pts <= params_.endOffset; + inRange_.set(stream.second->getIndex(), endInRange); + if (endInRange && msg.header.pts >= params_.startOffset) { push(std::move(msg)); + } else { + msg.payload.reset(); } } } diff --git a/torchvision/csrc/cpu/decoder/decoder.h b/torchvision/csrc/cpu/decoder/decoder.h index 971eec10aa4..11894fabb74 100644 --- a/torchvision/csrc/cpu/decoder/decoder.h +++ b/torchvision/csrc/cpu/decoder/decoder.h @@ -1,7 +1,7 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once +#include +#include #include "seekable_buffer.h" #include "stream.h" @@ -15,7 +15,6 @@ namespace ffmpeg { class Decoder : public MediaDecoder { public: Decoder(); - ~Decoder() override; // MediaDecoder overrides bool init(const DecoderParameters& params, DecoderInCallback&& in) override; @@ -25,9 +24,10 @@ class Decoder : public MediaDecoder { protected: // function does actual work, derived class calls it in working thread - // periodically. On success method returns 0, ENOADATA on EOF and error on + // periodically. On success method returns 0, ENOADATA on EOF, ETIMEDOUT if + // no frames got decoded in the specified timeout time, and error on // unrecoverable error. - int getBytes(size_t workingTimeInMs = 100); + int getFrame(size_t workingTimeInMs = 100); // Derived class must override method and consume the provided message virtual void push(DecoderOutputMessage&& buffer) = 0; @@ -56,13 +56,15 @@ class Decoder : public MediaDecoder { virtual int64_t seekCallback(int64_t offset, int whence); virtual int shutdownCallback(); - bool activateStreams(); + bool openStreams(); Stream* findByIndex(int streamIndex) const; Stream* findByType(const MediaFormat& format) const; - int processPacket(Stream* stream, AVPacket* packet); + int processPacket(Stream* stream, + AVPacket* packet, + bool* gotFrame, + bool* hasMsg); void flushStreams(); void cleanUp(); - private: DecoderParameters params_; SeekableBuffer seekableBuffer_; @@ -72,6 +74,6 @@ class Decoder : public MediaDecoder { AVFormatContext* inputCtx_{nullptr}; AVIOContext* avioCtx_{nullptr}; std::unordered_map> streams_; - bool outOfRange_{false}; + std::bitset<64> inRange_; }; } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/defs.h b/torchvision/csrc/cpu/decoder/defs.h index 62854668b90..2e282bb59c6 100644 --- a/torchvision/csrc/cpu/decoder/defs.h +++ b/torchvision/csrc/cpu/decoder/defs.h @@ -27,7 +27,7 @@ struct AudioFormat { size_t samples{0}; // number samples per second (frequency) size_t channels{0}; // number of channels - ssize_t format{-1}; // AVSampleFormat, auto AV_SAMPLE_FMT_NONE + long format{-1}; // AVSampleFormat, auto AV_SAMPLE_FMT_NONE size_t padding[2]; // -- alignment 40 bytes }; @@ -42,7 +42,7 @@ struct VideoFormat { size_t width{0}; // width in pixels size_t height{0}; // height in pixels - ssize_t format{-1}; // AVPixelFormat, auto AV_PIX_FMT_NONE + long format{-1}; // AVPixelFormat, auto AV_PIX_FMT_NONE size_t minDimension{0}; // choose min dimension and rescale accordingly size_t cropImage{0}; // request image crop // -- alignment 40 bytes @@ -50,7 +50,7 @@ struct VideoFormat { // subtitle/cc struct SubtitleFormat { - ssize_t type{0}; // AVSubtitleType, auto SUBTITLE_NONE + long type{0}; // AVSubtitleType, auto SUBTITLE_NONE size_t padding[4]; // -- alignment 40 bytes }; @@ -94,28 +94,27 @@ struct MediaFormat { } } - explicit MediaFormat(ssize_t s = -1) - : type(TYPE_AUDIO), stream(s), format() {} - explicit MediaFormat(int x, ssize_t s = -1) + explicit MediaFormat(long s = -1) : type(TYPE_AUDIO), stream(s), format() {} + explicit MediaFormat(int x, long s = -1) : type(TYPE_VIDEO), stream(s), format(x) {} - explicit MediaFormat(char x, ssize_t s = -1) + explicit MediaFormat(char x, long s = -1) : type(TYPE_SUBTITLE), stream(s), format(x) {} - explicit MediaFormat(double x, ssize_t s = -1) + explicit MediaFormat(double x, long s = -1) : type(TYPE_CC), stream(s), format(x) {} - static MediaFormat makeMediaFormat(AudioFormat format, ssize_t stream) { + static MediaFormat makeMediaFormat(AudioFormat format, long stream) { MediaFormat result(stream); result.format.audio = format; return result; } - static MediaFormat makeMediaFormat(VideoFormat format, ssize_t stream) { + static MediaFormat makeMediaFormat(VideoFormat format, long stream) { MediaFormat result(0, stream); result.format.video = format; return result; } - static MediaFormat makeMediaFormat(SubtitleFormat format, ssize_t stream) { + static MediaFormat makeMediaFormat(SubtitleFormat format, long stream) { MediaFormat result('0', stream); result.format.subtitle = format; return result; @@ -126,17 +125,17 @@ struct MediaFormat { // stream index: // set -1 for one stream auto detection, -2 for all streams auto detection, // >= 0, specified stream, if caller knows the stream index (unlikely) - ssize_t stream; + long stream; // union keeps one of the possible formats, defined by MediaType FormatUnion format; // output parameters, ignored while initialization // time base numerator - ssize_t num{0}; + long num{0}; // time base denominator - ssize_t den{1}; - // duration of the stream, in stream time base, if available - ssize_t duration{-1}; + long den{1}; + // duration of the stream, in miscroseconds, if available + long duration{-1}; }; struct DecoderParameters { @@ -146,29 +145,33 @@ struct DecoderParameters { // timeout on getting bytes for decoding size_t timeoutMs{1000}; // logging level, default AV_LOG_PANIC - ssize_t logLevel{0}; + long logLevel{0}; // when decoder would give up, 0 means never size_t maxPackageErrors{0}; // max allowed consecutive times no bytes are processed. 0 means for infinite. size_t maxProcessNoBytes{0}; - // start offset - ssize_t startOffsetMs{0}; - // end offset - ssize_t endOffsetMs{-1}; + // start offset (us) + long startOffset{0}; + // end offset (us) + long endOffset{-1}; // logging id int64_t loggingUuid{0}; + // internal max seekable buffer size + size_t maxSeekableBytes{0}; // adjust header pts to the epoch time bool convertPtsToWallTime{false}; // indicate if input stream is an encoded image bool isImage{false}; - // what media types should be processed, default none - std::set formats; // listen and wait for new rtmp stream bool listen{false}; // don't copy frame body, only header bool headerOnly{false}; - // seek tolerated accuracy - double seekAccuracySec{1.0}; + // interrupt init method on timeout + bool preventStaleness{true}; + // seek tolerated accuracy (us) + double seekAccuracy{1000000.0}; + // what media types should be processed, default none + std::set formats; }; struct DecoderHeader { @@ -176,7 +179,7 @@ struct DecoderHeader { size_t seqno{0}; // decoded timestamp in microseconds from either beginning of the stream or // from epoch time, see DecoderParameters::convertPtsToWallTime - ssize_t pts{0}; + long pts{0}; // decoded key frame size_t keyFrame{0}; // frames per second, valid only for video streams @@ -219,27 +222,21 @@ struct DecoderOutputMessage { * Normally input/output parameter @out set to valid, not null buffer pointer, * which indicates "read" call, however there are "seek" modes as well. - * @out != nullptr, @size != 0, @timeoutMs != 0 => read from the current offset - * @size bytes => return number bytes read, 0 if no more bytes available, < 0 - * on error. - - * @out == nullptr, @size == 0, @timeoutMs == 0 => does provider support "seek" - * capability in a first place? return 0 on success, < 0 if "seek" mode is not - * supported. - - * @out == nullptr, @size > 0 => seek the absolute offset == @size, return - * 0 on success and < 0 on error. + * @out != nullptr => read from the current offset, @whence got ignored, + * @size bytes to read => return number bytes got read, 0 if no more bytes + * available, < 0 on error. - * @out == nullptr, @size < 0 => seek the end of the media, return 0 on success - * and < 0 on failure. Provider might support seek doesn't know the media size. + * @out == nullptr, @timeoutMs == 0 => does provider support "seek" + * capability in a first place? @size & @whence got ignored, return 0 on + * success, < 0 if "seek" mode is not supported. - * Additionally if @out is set to null AND @size is set to zero AND - * @timeoutMs is set to zero, caller requests the seek capability of the - * provider, i.e. returns 0 on success and error if provider is not supporting - * seek. + * @out == nullptr, @timeoutMs != 0 => normal seek call + * offset == @size, i.e. @whence = [SEEK_SET, SEEK_CUR, SEEK_END, AVSEEK_SIZE) + * return < 0 on error, position if @whence = [SEEK_SET, SEEK_CUR, SEEK_END], + * length of buffer if @whence = [AVSEEK_SIZE]. */ using DecoderInCallback = - std::function; + std::function; using DecoderOutCallback = std::function; diff --git a/torchvision/csrc/cpu/decoder/memory_buffer.cpp b/torchvision/csrc/cpu/decoder/memory_buffer.cpp new file mode 100644 index 00000000000..d91213fdcbb --- /dev/null +++ b/torchvision/csrc/cpu/decoder/memory_buffer.cpp @@ -0,0 +1,75 @@ +#include "memory_buffer.h" +#include + +extern "C" { +#include +} + +namespace ffmpeg { + +MemoryBuffer::MemoryBuffer(const uint8_t* buffer, size_t size) + : buffer_(buffer), len_(size) {} + +int MemoryBuffer::read(uint8_t* buf, int size) { + if (pos_ < len_) { + auto available = std::min(int(len_ - pos_), size); + memcpy(buf, buffer_ + pos_, available); + pos_ += available; + return available; + } + + return 0; +} + +int64_t MemoryBuffer::seek(int64_t offset, int whence) { + if (whence & AVSEEK_SIZE) { + return len_; + } + + // remove force flag + whence &= ~AVSEEK_FORCE; + + switch (whence) { + case SEEK_SET: + if (offset >= 0 && offset <= len_) { + pos_ = offset; + } + break; + case SEEK_END: + if (len_ + offset >= 0 && len_ + offset <= len_) { + pos_ = len_ + offset; + } + break; + case SEEK_CUR: + if (pos_ + offset > 0 && pos_ + offset <= len_) { + pos_ += offset; + } + break; + default: + LOG(ERROR) << "Unknown whence flag gets provided: " << whence; + } + return pos_; +} + +/* static */ +DecoderInCallback MemoryBuffer::getCallback( + const uint8_t* buffer, + size_t size) { + MemoryBuffer object(buffer, size); + return + [object](uint8_t* out, int size, int whence, uint64_t timeoutMs) mutable + -> int { + if (out) { // see defs.h file + // read mode + return object.read(out, size); + } + // seek mode + if (!timeoutMs) { + // seek capabilty, yes - supported + return 0; + } + return object.seek(size, whence); + }; +} + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/memory_buffer.h b/torchvision/csrc/cpu/decoder/memory_buffer.h new file mode 100644 index 00000000000..909626d3cae --- /dev/null +++ b/torchvision/csrc/cpu/decoder/memory_buffer.h @@ -0,0 +1,25 @@ +#pragma once + +#include "defs.h" + +namespace ffmpeg { + +/** + * Class uses external memory buffer and implements a seekable interface. + */ +class MemoryBuffer { + public: + explicit MemoryBuffer(const uint8_t* buffer, size_t size); + int64_t seek(int64_t offset, int whence); + int read(uint8_t* buf, int size); + + // static constructor for decoder callback. + static DecoderInCallback getCallback(const uint8_t* buffer, size_t size); + + private: + const uint8_t* buffer_; // set at construction time + long pos_{0}; // current position + long len_{0}; // bytes in buffer +}; + +} // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp index 8d159b789bf..2e6732a2f50 100644 --- a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp +++ b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp @@ -1,8 +1,7 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "seekable_buffer.h" #include #include +#include "memory_buffer.h" extern "C" { #include @@ -10,17 +9,59 @@ extern "C" { namespace ffmpeg { -bool SeekableBuffer::init( +int SeekableBuffer::init( DecoderInCallback&& in, - ssize_t minSize, - ssize_t maxSize, - uint64_t timeoutMs) { + uint64_t timeoutMs, + size_t maxSeekableBytes, + ImageType* type) { + shutdown(); + isSeekable_ = in(nullptr, 0, 0, 0) == 0; + if (isSeekable_) { // seekable + if (type) { + if (!readBytes(in, 8, timeoutMs)) { + return -1; + } + setImageType(type); + end_ = 0; + eof_ = false; + std::vector().swap(buffer_); + // reset callback + if (in(nullptr, 0, SEEK_SET, timeoutMs)) { + return -1; + } + } + inCallback_ = std::forward(in); + return 1; + } + + if (!readBytes(in, maxSeekableBytes, timeoutMs)) { + return -1; + } + + if (type) { + setImageType(type); + } + + if (eof_) { + end_ = 0; + eof_ = false; + // reuse MemoryBuffer functionality + inCallback_ = MemoryBuffer::getCallback(buffer_.data(), buffer_.size()); + isSeekable_ = true; + return 1; + } inCallback_ = std::forward(in); - len_ = minSize; - buffer_.resize(len_); - pos_ = 0; + return 0; +} + +bool SeekableBuffer::readBytes( + DecoderInCallback& in, + size_t maxBytes, + uint64_t timeoutMs) { + // Resize to th minimum 4K page or less + buffer_.resize(std::min(maxBytes, 4 * 1024UL)); end_ = 0; - eof_ = 0; + eof_ = false; auto end = std::chrono::steady_clock::now() + std::chrono::milliseconds(timeoutMs); @@ -28,62 +69,58 @@ bool SeekableBuffer::init( return std::chrono::steady_clock::now() <= end; }; - bool hasTime = false; - while (!eof_ && end_ < maxSize && (hasTime = watcher())) { + bool hasTime = true; + while (!eof_ && end_ < maxBytes && (hasTime = watcher())) { // lets read all bytes into available buffer - auto res = inCallback_(buffer_.data() + end_, len_ - end_, timeoutMs); + auto res = in(buffer_.data() + end_, buffer_.size() - end_, 0, timeoutMs); if (res > 0) { end_ += res; - if (end_ == len_) { - len_ = std::min(len_ * 4, maxSize); - buffer_.resize(len_); + if (end_ == buffer_.size()) { + buffer_.resize(std::min(end_ * 4UL, maxBytes)); } } else if (res == 0) { - eof_ = 1; + eof_ = true; } else { // error return false; } } - if (!hasTime) { - return false; - } + return hasTime; +} +void SeekableBuffer::setImageType(ImageType* type) { if (buffer_.size() > 2 && buffer_[0] == 0xFF && buffer_[1] == 0xD8 && buffer_[2] == 0xFF) { - imageType_ = ImageType::JPEG; + *type = ImageType::JPEG; } else if ( buffer_.size() > 3 && buffer_[1] == 'P' && buffer_[2] == 'N' && buffer_[3] == 'G') { - imageType_ = ImageType::PNG; + *type = ImageType::PNG; } else if ( buffer_.size() > 1 && ((buffer_[0] == 0x49 && buffer_[1] == 0x49) || (buffer_[0] == 0x4D && buffer_[1] == 0x4D))) { - imageType_ = ImageType::TIFF; + *type = ImageType::TIFF; + } else { + *type = ImageType::UNKNOWN; } - - return true; } int SeekableBuffer::read(uint8_t* buf, int size, uint64_t timeoutMs) { - // 1. pos_ < end_ + if (isSeekable_) { + return inCallback_(buf, size, 0, timeoutMs); + } if (pos_ < end_) { + // read cached bytes for non-seekable callback auto available = std::min(int(end_ - pos_), size); memcpy(buf, buffer_.data() + pos_, available); pos_ += available; return available; } else if (!eof_) { - auto res = inCallback_(buf, size, timeoutMs); // read through - if (res > 0) { - pos_ += res; - if (pos_ > end_ && !buffer_.empty()) { - std::vector().swap(buffer_); - } - } else if (res == 0) { - eof_ = 1; - } + // normal sequential read (see defs.h file), i.e. @buf != null + auto res = inCallback_(buf, size, 0, timeoutMs); // read through + eof_ = res == 0; return res; } else { return 0; @@ -91,57 +128,13 @@ int SeekableBuffer::read(uint8_t* buf, int size, uint64_t timeoutMs) { } int64_t SeekableBuffer::seek(int64_t offset, int whence, uint64_t timeoutMs) { - // remove force flag - whence &= ~AVSEEK_FORCE; - // get size request - int size = whence & AVSEEK_SIZE; - // remove size flag - whence &= ~AVSEEK_SIZE; - - if (size) { - return eof_ ? end_ : AVERROR(EINVAL); - } else { - switch (whence) { - case SEEK_SET: - if (offset < 0) { - return AVERROR(EINVAL); - } - if (offset <= end_) { - pos_ = offset; - return pos_; - } - if (!inCallback_(0, offset, timeoutMs)) { - pos_ = offset; - return 0; - } - break; - case SEEK_END: - if (eof_ && pos_ <= end_ && offset < 0 && end_ + offset >= 0) { - pos_ = end_ + offset; - return 0; - } - break; - case SEEK_CUR: - if (pos_ + offset < 0) { - return AVERROR(EINVAL); - } - if (pos_ + offset <= end_) { - pos_ += offset; - return 0; - } - if (!inCallback_(0, pos_ + offset, timeoutMs)) { - pos_ += offset; - return 0; - } - break; - default: - LOG(ERROR) << "Unknown whence flag gets provided: " << whence; - } - } - return AVERROR(EINVAL); // we have no idea what the media size is + return inCallback_(nullptr, offset, whence, timeoutMs); } void SeekableBuffer::shutdown() { + pos_ = end_ = 0; + eof_ = false; + std::vector().swap(buffer_); inCallback_ = nullptr; } diff --git a/torchvision/csrc/cpu/decoder/seekable_buffer.h b/torchvision/csrc/cpu/decoder/seekable_buffer.h index e8ba327e4ea..9d5729f5306 100644 --- a/torchvision/csrc/cpu/decoder/seekable_buffer.h +++ b/torchvision/csrc/cpu/decoder/seekable_buffer.h @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include "defs.h" @@ -20,27 +18,28 @@ enum class ImageType { class SeekableBuffer { public: - // try to fill out buffer, returns true if EOF detected (seek will supported) - bool init( + // @type is optional, not nullptr only is image detection required + // \returns 1 is buffer seekable, 0 - if not seekable, < 0 on error + int init( DecoderInCallback&& in, - ssize_t minSize, - ssize_t maxSize, - uint64_t timeoutMs); + uint64_t timeoutMs, + size_t maxSeekableBytes, + ImageType* type); int read(uint8_t* buf, int size, uint64_t timeoutMs); int64_t seek(int64_t offset, int whence, uint64_t timeoutMs); void shutdown(); - ImageType getImageType() const { - return imageType_; - } + + private: + bool readBytes(DecoderInCallback& in, size_t maxBytes, uint64_t timeoutMs); + void setImageType(ImageType* type); private: DecoderInCallback inCallback_; std::vector buffer_; // resized at init time - ssize_t len_{0}; // current buffer size - ssize_t pos_{0}; // current position (SEEK_CUR iff pos_ < end_) - ssize_t end_{0}; // bytes in buffer [0, buffer_.size()] - ssize_t eof_{0}; // indicates the EOF - ImageType imageType_{ImageType::UNKNOWN}; + long pos_{0}; // current position (SEEK_CUR iff pos_ < end_) + long end_{0}; // current buffer size + bool eof_{0}; // indicates the EOF + bool isSeekable_{false}; // is callback seekable }; } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/stream.cpp b/torchvision/csrc/cpu/decoder/stream.cpp index 767136657b6..ce13ca05a83 100644 --- a/torchvision/csrc/cpu/decoder/stream.cpp +++ b/torchvision/csrc/cpu/decoder/stream.cpp @@ -1,22 +1,18 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "stream.h" #include #include "util.h" namespace ffmpeg { -namespace { -const size_t kDecoderHeaderSize = sizeof(DecoderHeader); -} - Stream::Stream( AVFormatContext* inputCtx, MediaFormat format, - bool convertPtsToWallTime) + bool convertPtsToWallTime, + int64_t loggingUuid) : inputCtx_(inputCtx), format_(format), - convertPtsToWallTime_(convertPtsToWallTime) {} + convertPtsToWallTime_(convertPtsToWallTime), + loggingUuid_(loggingUuid) {} Stream::~Stream() { if (frame_) { @@ -36,25 +32,30 @@ int Stream::openCodec() { auto codec_id = steam->codecpar->codec_id; AVCodec* codec = avcodec_find_decoder(codec_id); if (!codec) { - LOG(ERROR) << "avcodec_find_decoder failed for codec_id: " << int(codec_id); + LOG(ERROR) << "LoggingUuid #" << loggingUuid_ + << ", avcodec_find_decoder failed for codec_id: " + << int(codec_id); return AVERROR(EINVAL); } if (!(codecCtx_ = avcodec_alloc_context3(codec))) { - LOG(ERROR) << "avcodec_alloc_context3 fails"; + LOG(ERROR) << "LoggingUuid #" << loggingUuid_ + << ", avcodec_alloc_context3 failed"; return AVERROR(ENOMEM); } int ret; // Copy codec parameters from input stream to output codec context if ((ret = avcodec_parameters_to_context(codecCtx_, steam->codecpar)) < 0) { - LOG(ERROR) << "Failed to copy codec parameters to decoder context"; + LOG(ERROR) << "LoggingUuid #" << loggingUuid_ + << ", avcodec_parameters_to_context failed"; return ret; } // after avcodec_open2, value of codecCtx_->time_base is NOT meaningful if ((ret = avcodec_open2(codecCtx_, codec, nullptr)) < 0) { - LOG(ERROR) << "avcodec_open2 failed. " << Util::generateErrorDesc(ret); + LOG(ERROR) << "LoggingUuid #" << loggingUuid_ + << ", avcodec_open2 failed: " << Util::generateErrorDesc(ret); avcodec_free_context(&codecCtx_); codecCtx_ = nullptr; return ret; @@ -62,30 +63,41 @@ int Stream::openCodec() { frame_ = av_frame_alloc(); + // always convert to us format_.num = inputCtx_->streams[format_.stream]->time_base.num; format_.den = inputCtx_->streams[format_.stream]->time_base.den; - format_.duration = inputCtx_->streams[format_.stream]->duration; - return initFormat(); -} + switch (format_.type) { + case TYPE_VIDEO: + fps_ = av_q2d(av_guess_frame_rate( + inputCtx_, inputCtx_->streams[format_.stream], nullptr)); + break; + case TYPE_AUDIO: + fps_ = codecCtx_->sample_rate; + break; + default: + fps_ = 30.0; + } + + format_.duration = av_rescale_q( + inputCtx_->streams[format_.stream]->duration, + inputCtx_->streams[format_.stream]->time_base, + AV_TIME_BASE_Q); -// rescale package -void Stream::rescalePackage(AVPacket* packet) { - if (codecCtx_->time_base.num != 0) { - av_packet_rescale_ts( - packet, - inputCtx_->streams[format_.stream]->time_base, - codecCtx_->time_base); + if ((ret = initFormat())) { + LOG(ERROR) << "initFormat failed, type: " << format_.type; } + + return ret; } -int Stream::analyzePacket(const AVPacket* packet, int* gotFramePtr) { +int Stream::analyzePacket(const AVPacket* packet, bool* gotFrame) { int consumed = 0; int result = avcodec_send_packet(codecCtx_, packet); if (result == AVERROR(EAGAIN)) { - *gotFramePtr = 0; // no bytes get consumed, fetch frame + *gotFrame = false; // no bytes get consumed, fetch frame } else if (result == AVERROR_EOF) { - *gotFramePtr = 0; // more than one flush packet + *gotFrame = false; // more than one flush packet if (packet) { // got packet after flush, this is an error return result; @@ -95,23 +107,23 @@ int Stream::analyzePacket(const AVPacket* packet, int* gotFramePtr) { << Util::generateErrorDesc(result); return result; // error } else { - consumed = packet ? packet->size : 0; // all bytes get consumed + consumed = 1; // all bytes get consumed } result = avcodec_receive_frame(codecCtx_, frame_); if (result >= 0) { - *gotFramePtr = 1; // frame is available + *gotFrame = true; // frame is available } else if (result == AVERROR(EAGAIN)) { - *gotFramePtr = 0; // no frames at this time, needs more packets + *gotFrame = false; // no frames at this time, needs more packets if (!consumed) { // precaution, if no packages got consumed and no frames are available return result; } } else if (result == AVERROR_EOF) { - *gotFramePtr = 0; // the last frame has been flushed + *gotFrame = false; // the last frame has been flushed // precaution, if no more frames are available assume we consume all bytes - consumed = packet ? packet->size : 0; + consumed = 0; } else { // error LOG(ERROR) << "avcodec_receive_frame failed, err: " << Util::generateErrorDesc(result); @@ -120,46 +132,121 @@ int Stream::analyzePacket(const AVPacket* packet, int* gotFramePtr) { return consumed; } -int Stream::decodeFrame(const AVPacket* packet, int* gotFramePtr) { - return analyzePacket(packet, gotFramePtr); -} - -int Stream::getFrameBytes(DecoderOutputMessage* out, bool headerOnly) { - return fillBuffer(out, false, headerOnly); +int Stream::decodePacket( + const AVPacket* packet, + DecoderOutputMessage* out, + bool headerOnly, + bool* hasMsg) { + int consumed; + bool gotFrame = false; + *hasMsg = false; + if ((consumed = analyzePacket(packet, &gotFrame)) >= 0 && + (packet == nullptr || gotFrame)) { + int result; + if ((result = getMessage(out, !gotFrame, headerOnly)) < 0) { + return result; // report error + } + *hasMsg = result > 0; + } + return consumed; } int Stream::flush(DecoderOutputMessage* out, bool headerOnly) { - int gotFramePtr = 0; - int result; - if (analyzePacket(nullptr, &gotFramePtr) >= 0 && gotFramePtr && - (result = fillBuffer(out, false, headerOnly)) > 0) { - return result; - } else if ((result = fillBuffer(out, true, headerOnly)) > 0) { + bool hasMsg = false; + int result = decodePacket(nullptr, out, headerOnly, &hasMsg); + if (result < 0) { + avcodec_flush_buffers(codecCtx_); return result; } - return result; + if (!hasMsg) { + avcodec_flush_buffers(codecCtx_); + return 0; + } + return 1; } -int Stream::fillBuffer(DecoderOutputMessage* out, bool flush, bool headerOnly) { - int result = -1; - if (!codecCtx_) { - LOG(INFO) << "Codec is not initialized"; - return result; +int Stream::getMessage(DecoderOutputMessage* out, bool flush, bool headerOnly) { + if (flush) { + // only flush of audio frames makes sense + if (format_.type == TYPE_AUDIO) { + int bytes = 0; + if ((bytes = estimateBytes(true)) < 0) { + return bytes; + } + int processed = 0; + // grab all audio bytes by chunks + do { + out->payload->ensure(out->payload->length() + bytes); + if ((processed = copyFrameBytes(out->payload.get(), true)) < 0) { + return processed; + } + } while (processed); + + if (out->payload->length()) { + // set header first + setHeader(&out->header, flush); + return 1; + } + } + return 0; + } else { + // set header first + setHeader(&out->header, flush); + + if (headerOnly) { + // Only header is requisted + return 1; + } + + // decoded frame is available + int bytes; + if ((bytes = estimateBytes(false)) < 0) { + return bytes; + } + out->payload->ensure(bytes); + return copyFrameBytes(out->payload.get(), false); } +} + +void Stream::setHeader(DecoderHeader* header, bool flush) { + header->seqno = numGenerator_++; - // assign message - setHeader(&out->header); + setFramePts(header, flush); - if (headerOnly) { - return sizeof(out->header); + if (convertPtsToWallTime_) { + keeper_.adjust(header->pts); } - // init sampler, if any and return required bytes - if ((result = estimateBytes(flush)) < 0) { - return result; + header->format = format_; + header->keyFrame = 0; + header->fps = std::numeric_limits::quiet_NaN(); +} + +void Stream::setFramePts(DecoderHeader* header, bool flush) { + if (flush) { + header->pts = nextPts_; // already in us + } else { + header->pts = av_frame_get_best_effort_timestamp(frame_); + if (header->pts == AV_NOPTS_VALUE) { + header->pts = nextPts_; + } else { + header->pts = av_rescale_q( + header->pts, + inputCtx_->streams[format_.stream]->time_base, + AV_TIME_BASE_Q); + } + + switch (format_.type) { + case TYPE_AUDIO: + nextPts_ = header->pts + frame_->nb_samples * AV_TIME_BASE / fps_; + break; + case TYPE_VIDEO: + nextPts_ = header->pts + AV_TIME_BASE / fps_; + break; + default: + nextPts_ = header->pts; + } } - out->payload->ensure(result); - return copyFrameBytes(out->payload.get(), flush); } } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/stream.h b/torchvision/csrc/cpu/decoder/stream.h index fd83b90428c..3473a2a0fd3 100644 --- a/torchvision/csrc/cpu/decoder/stream.h +++ b/torchvision/csrc/cpu/decoder/stream.h @@ -1,9 +1,8 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include #include "defs.h" +#include "time_keeper.h" extern "C" { #include @@ -22,23 +21,24 @@ class Stream { Stream( AVFormatContext* inputCtx, MediaFormat format, - bool convertPtsToWallTime); + bool convertPtsToWallTime, + int64_t loggingUuid); virtual ~Stream(); // returns 0 - on success or negative error int openCodec(); - // returns number processed bytes from packet, or negative error - int decodeFrame(const AVPacket* packet, int* gotFramePtr); + // returns 1 - if packet got consumed, 0 - if it's not, and < 0 on error + int decodePacket( + const AVPacket* packet, + DecoderOutputMessage* out, + bool headerOnly, + bool* hasMsg); // returns stream index int getIndex() const { return format_.stream; } - // returns number decoded/sampled bytes - int getFrameBytes(DecoderOutputMessage* out, bool headerOnly); - // returns number decoded/sampled bytes + // returns 1 - if message got a payload, 0 - if it's not, and < 0 on error int flush(DecoderOutputMessage* out, bool headerOnly); - // rescale package - void rescalePackage(AVPacket* packet); // return media format MediaFormat getMediaFormat() const { return format_; @@ -46,29 +46,37 @@ class Stream { protected: virtual int initFormat() = 0; + // returns 1 - if packet got consumed, 0 - if it's not, and < 0 on error + virtual int analyzePacket(const AVPacket* packet, bool* gotFrame); // returns number processed bytes from packet, or negative error - virtual int analyzePacket(const AVPacket* packet, int* gotFramePtr); - // returns number decoded/sampled bytes, or negative error virtual int copyFrameBytes(ByteStorage* out, bool flush) = 0; - // initialize codec, returns output buffer size, or negative error + // estimates bytes in frame, returns output buffer size, or negative error virtual int estimateBytes(bool flush) = 0; // sets output format - virtual void setHeader(DecoderHeader* header) = 0; + virtual void setHeader(DecoderHeader* header, bool flush); + // set frame pts + virtual void setFramePts(DecoderHeader* header, bool flush); // finds codec virtual AVCodec* findCodec(AVCodecContext* ctx); private: - int fillBuffer(DecoderOutputMessage* out, bool flush, bool headerOnly); + // returns 1 - if message got a payload, 0 - if it's not, and < 0 on error + int getMessage(DecoderOutputMessage* out, bool flush, bool headerOnly); protected: AVFormatContext* const inputCtx_; MediaFormat format_; const bool convertPtsToWallTime_; + int64_t loggingUuid_; AVCodecContext* codecCtx_{nullptr}; AVFrame* frame_{nullptr}; std::atomic numGenerator_{0}; + TimeKeeper keeper_; + // estimated next frame pts for flushing the last frame + int64_t nextPts_{0}; + double fps_{30.}; }; } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp b/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp index 02859c19187..b89ef8f1b86 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp +++ b/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "subtitle_sampler.h" #include "util.h" diff --git a/torchvision/csrc/cpu/decoder/subtitle_sampler.h b/torchvision/csrc/cpu/decoder/subtitle_sampler.h index 4846fe4d7c5..298e48d591f 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_sampler.h +++ b/torchvision/csrc/cpu/decoder/subtitle_sampler.h @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include "defs.h" diff --git a/torchvision/csrc/cpu/decoder/subtitle_stream.cpp b/torchvision/csrc/cpu/decoder/subtitle_stream.cpp index b699a0507cf..4f83fad68f8 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_stream.cpp +++ b/torchvision/csrc/cpu/decoder/subtitle_stream.cpp @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "subtitle_stream.h" #include #include @@ -26,7 +24,8 @@ SubtitleStream::SubtitleStream( : Stream( inputCtx, MediaFormat::makeMediaFormat(format, index), - convertPtsToWallTime) { + convertPtsToWallTime, + 0) { memset(&sub_, 0, sizeof(sub_)); } @@ -51,16 +50,16 @@ int SubtitleStream::initFormat() { return 0; } -int SubtitleStream::analyzePacket(const AVPacket* packet, int* gotFramePtr) { +int SubtitleStream::analyzePacket(const AVPacket* packet, bool* gotFrame) { // clean-up releaseSubtitle(); // check flush packet AVPacket avPacket; av_init_packet(&avPacket); avPacket.data = nullptr; - auto pkt = packet ? *packet : avPacket; - int result = avcodec_decode_subtitle2(codecCtx_, &sub_, gotFramePtr, &pkt); + int gotFramePtr = 0; + int result = avcodec_decode_subtitle2(codecCtx_, &sub_, &gotFramePtr, &pkt); if (result < 0) { VLOG(1) << "avcodec_decode_subtitle2 failed, err: " @@ -69,17 +68,18 @@ int SubtitleStream::analyzePacket(const AVPacket* packet, int* gotFramePtr) { result = packet ? packet->size : 0; // discard the rest of the package } - sub_.release = *gotFramePtr; + sub_.release = gotFramePtr; + *gotFrame = gotFramePtr > 0; return result; } -int SubtitleStream::estimateBytes(bool flush) { +int SubtitleStream::estimateBytes(bool) { if (!(sampler_.getInputFormat().subtitle == *codecCtx_)) { // - reinit sampler SamplerParameters params; params.type = MediaType::TYPE_SUBTITLE; toSubtitleFormat(params.in.subtitle, *codecCtx_); - if (flush || !sampler_.init(params)) { + if (!sampler_.init(params)) { return -1; } @@ -92,17 +92,8 @@ int SubtitleStream::copyFrameBytes(ByteStorage* out, bool flush) { return sampler_.sample(flush ? nullptr : &sub_, out); } -void SubtitleStream::setHeader(DecoderHeader* header) { - header->seqno = numGenerator_++; - +void SubtitleStream::setFramePts(DecoderHeader* header, bool) { header->pts = sub_.pts; // already in us - - if (convertPtsToWallTime_) { - keeper_.adjust(header->pts); - } - - header->keyFrame = 0; - header->fps = std::numeric_limits::quiet_NaN(); - header->format = format_; } + } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/subtitle_stream.h b/torchvision/csrc/cpu/decoder/subtitle_stream.h index 8669f15e0ce..4297cfa83f7 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_stream.h +++ b/torchvision/csrc/cpu/decoder/subtitle_stream.h @@ -1,10 +1,7 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include "stream.h" #include "subtitle_sampler.h" -#include "time_keeper.h" namespace ffmpeg { @@ -25,18 +22,17 @@ class SubtitleStream : public Stream { ~SubtitleStream() override; protected: - void setHeader(DecoderHeader* header) override; + void setFramePts(DecoderHeader* header, bool flush) override; private: int initFormat() override; - int analyzePacket(const AVPacket* packet, int* gotFramePtr) override; + int analyzePacket(const AVPacket* packet, bool* gotFrame) override; int estimateBytes(bool flush) override; int copyFrameBytes(ByteStorage* out, bool flush) override; void releaseSubtitle(); private: SubtitleSampler sampler_; - TimeKeeper keeper_; AVSubtitleKeeper sub_; }; diff --git a/torchvision/csrc/cpu/decoder/sync_decoder.cpp b/torchvision/csrc/cpu/decoder/sync_decoder.cpp index 6387837218e..5f3c38e08f8 100644 --- a/torchvision/csrc/cpu/decoder/sync_decoder.cpp +++ b/torchvision/csrc/cpu/decoder/sync_decoder.cpp @@ -1,23 +1,26 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "sync_decoder.h" #include namespace ffmpeg { SyncDecoder::VectorByteStorage::VectorByteStorage(size_t n) { - buffer_.resize(n); + ensure(n); +} + +SyncDecoder::VectorByteStorage::~VectorByteStorage() { + av_free(buffer_); } void SyncDecoder::VectorByteStorage::ensure(size_t n) { if (tail() < n) { - buffer_.resize(offset_ + length_ + n); + capacity_ = offset_ + length_ + n; + buffer_ = static_cast(av_realloc(buffer_, capacity_)); } } uint8_t* SyncDecoder::VectorByteStorage::writableTail() { - CHECK_LE(offset_ + length_, buffer_.size()); - return buffer_.data() + offset_ + length_; + CHECK_LE(offset_ + length_, capacity_); + return buffer_ + offset_ + length_; } void SyncDecoder::VectorByteStorage::append(size_t n) { @@ -32,7 +35,7 @@ void SyncDecoder::VectorByteStorage::trim(size_t n) { } const uint8_t* SyncDecoder::VectorByteStorage::data() const { - return buffer_.data() + offset_; + return buffer_ + offset_; } size_t SyncDecoder::VectorByteStorage::length() const { @@ -40,13 +43,11 @@ size_t SyncDecoder::VectorByteStorage::length() const { } size_t SyncDecoder::VectorByteStorage::tail() const { - auto size = buffer_.size(); - CHECK_LE(offset_ + length_, buffer_.size()); - return size - offset_ - length_; + CHECK_LE(offset_ + length_, capacity_); + return capacity_ - offset_ - length_; } void SyncDecoder::VectorByteStorage::clear() { - buffer_.clear(); offset_ = 0; length_ = 0; } @@ -66,16 +67,22 @@ int SyncDecoder::decode(DecoderOutputMessage* out, uint64_t timeoutMs) { } if (queue_.empty()) { - int result = getBytes(timeoutMs); + int result = getFrame(timeoutMs); + // assign EOF eof_ = result == ENODATA; - + // check unrecoverable error, any error but ENODATA if (result && result != ENODATA) { return result; } // still empty if (queue_.empty()) { - return ETIMEDOUT; + if (eof_) { + return ENODATA; + } else { + LOG(INFO) << "Queue is empty"; + return ETIMEDOUT; + } } } diff --git a/torchvision/csrc/cpu/decoder/sync_decoder.h b/torchvision/csrc/cpu/decoder/sync_decoder.h index 76c347fe707..192962acc0c 100644 --- a/torchvision/csrc/cpu/decoder/sync_decoder.h +++ b/torchvision/csrc/cpu/decoder/sync_decoder.h @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include @@ -13,9 +11,11 @@ namespace ffmpeg { * or fetched internally by FFMPEG library */ class SyncDecoder : public Decoder { + // Allocation of memory must be done with a proper alignment. class VectorByteStorage : public ByteStorage { public: VectorByteStorage(size_t n); + ~VectorByteStorage() override; void ensure(size_t n) override; uint8_t* writableTail() override; void append(size_t n) override; @@ -28,7 +28,8 @@ class SyncDecoder : public Decoder { private: size_t offset_{0}; size_t length_{0}; - std::vector buffer_; + size_t capacity_{0}; + uint8_t* buffer_{nullptr}; }; public: diff --git a/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp b/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp index ee0fe3fcf3c..379c24a0aa0 100644 --- a/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp +++ b/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp @@ -1,7 +1,6 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include #include +#include "memory_buffer.h" #include "sync_decoder.h" using namespace ffmpeg; @@ -10,7 +9,8 @@ TEST(SyncDecoder, Test) { SyncDecoder decoder; DecoderParameters params; params.timeoutMs = 10000; - params.startOffsetMs = 1000; + params.startOffset = 1000000; + params.seekAccuracy = 100000; params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; params.uri = "pytorch/vision/test/assets/videos/R6llTwEh07w.mp4"; CHECK(decoder.init(params, nullptr)); @@ -20,3 +20,136 @@ TEST(SyncDecoder, Test) { } decoder.shutdown(); } + +TEST(SyncDecoder, TestHeadersOnly) { + SyncDecoder decoder; + DecoderParameters params; + params.timeoutMs = 10000; + params.startOffset = 1000000; + params.seekAccuracy = 100000; + params.headerOnly = true; + params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; + params.uri = "pytorch/vision/test/assets/videos/R6llTwEh07w.mp4"; + CHECK(decoder.init(params, nullptr)); + DecoderOutputMessage out; + while (0 == decoder.decode(&out, 100)) { + LOG(INFO) << "Decoded frame, type: " << out.header.format.type + << ", timestamp(us): " << out.header.pts; + } + decoder.shutdown(); +} + +TEST(SyncDecoder, TestMemoryBuffer) { + SyncDecoder decoder; + DecoderParameters params; + params.timeoutMs = 10000; + params.startOffset = 1000000; + params.endOffset = 9000000; + params.seekAccuracy = 10000; + params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; + + FILE* f = fopen( + "pytorch/vision/test/assets/videos/RATRACE_wave_f_nm_np1_fr_goo_37.avi", + "rb"); + CHECK(f != nullptr); + fseek(f, 0, SEEK_END); + std::vector buffer(ftell(f)); + rewind(f); + CHECK_EQ(buffer.size(), fread(buffer.data(), 1, buffer.size(), f)); + fclose(f); + CHECK(decoder.init( + params, MemoryBuffer::getCallback(buffer.data(), buffer.size()))); + LOG(INFO) << "Decoding from memory bytes: " << buffer.size(); + DecoderOutputMessage out; + size_t audioFrames = 0, videoFrames = 0; + while (0 == decoder.decode(&out, 100)) { + if (out.header.format.type == TYPE_AUDIO) { + ++audioFrames; + } else if (out.header.format.type == TYPE_VIDEO) { + ++videoFrames; + } + } + LOG(INFO) << "Decoded audio frames: " << audioFrames + << ", video frames: " << videoFrames; + decoder.shutdown(); +} + +TEST(SyncDecoder, TestMemoryBufferNoSeekableWithFullRead) { + SyncDecoder decoder; + DecoderParameters params; + params.timeoutMs = 10000; + params.startOffset = 1000000; + params.endOffset = 9000000; + params.seekAccuracy = 10000; + params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; + + FILE* f = fopen("pytorch/vision/test/assets/videos/R6llTwEh07w.mp4", "rb"); + CHECK(f != nullptr); + fseek(f, 0, SEEK_END); + std::vector buffer(ftell(f)); + rewind(f); + CHECK_EQ(buffer.size(), fread(buffer.data(), 1, buffer.size(), f)); + fclose(f); + + params.maxSeekableBytes = buffer.size() + 1; + MemoryBuffer object(buffer.data(), buffer.size()); + CHECK(decoder.init( + params, + [object](uint8_t* out, int size, int whence, uint64_t timeoutMs) mutable + -> int { + if (out) { // see defs.h file + // read mode + return object.read(out, size); + } + // seek mode + if (!timeoutMs) { + // seek capabilty, yes - no + return -1; + } + return object.seek(size, whence); + })); + DecoderOutputMessage out; + while (0 == decoder.decode(&out, 100)) { + LOG(INFO) << "Decoded frame, timestamp(us): " << out.header.pts + << ", num: " << out.header.format.num + << ", den: " << out.header.format.den + << ", duration(us): " << out.header.format.duration; + } + decoder.shutdown(); +} + +TEST(SyncDecoder, TestMemoryBufferNoSeekableWithPartialRead) { + SyncDecoder decoder; + DecoderParameters params; + params.timeoutMs = 10000; + params.startOffset = 1000000; + params.endOffset = 9000000; + params.seekAccuracy = 10000; + params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; + + FILE* f = fopen("pytorch/vision/test/assets/videos/R6llTwEh07w.mp4", "rb"); + CHECK(f != nullptr); + fseek(f, 0, SEEK_END); + std::vector buffer(ftell(f)); + rewind(f); + CHECK_EQ(buffer.size(), fread(buffer.data(), 1, buffer.size(), f)); + fclose(f); + + params.maxSeekableBytes = buffer.size() / 2; + MemoryBuffer object(buffer.data(), buffer.size()); + CHECK(!decoder.init( + params, + [object](uint8_t* out, int size, int whence, uint64_t timeoutMs) mutable + -> int { + if (out) { // see defs.h file + // read mode + return object.read(out, size); + } + // seek mode + if (!timeoutMs) { + // seek capabilty, yes - no + return -1; + } + return object.seek(size, whence); + })); +} diff --git a/torchvision/csrc/cpu/decoder/time_keeper.cpp b/torchvision/csrc/cpu/decoder/time_keeper.cpp index a0da56a1f64..9cfc9457963 100644 --- a/torchvision/csrc/cpu/decoder/time_keeper.cpp +++ b/torchvision/csrc/cpu/decoder/time_keeper.cpp @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "time_keeper.h" extern "C" { @@ -9,13 +7,13 @@ extern "C" { namespace ffmpeg { namespace { -const ssize_t kMaxTimeBaseDiference = 10; +const long kMaxTimeBaseDiference = 10; } -ssize_t TimeKeeper::adjust(ssize_t& decoderTimestamp) { - const ssize_t now = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()) - .count(); +long TimeKeeper::adjust(long& decoderTimestamp) { + const long now = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count(); if (startTime_ == 0) { startTime_ = now; diff --git a/torchvision/csrc/cpu/decoder/time_keeper.h b/torchvision/csrc/cpu/decoder/time_keeper.h index c9d06025b2c..e4d4718c705 100644 --- a/torchvision/csrc/cpu/decoder/time_keeper.h +++ b/torchvision/csrc/cpu/decoder/time_keeper.h @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include @@ -17,11 +15,11 @@ class TimeKeeper { // adjust provided @timestamp to the corrected value // return advised sleep time before next frame processing in (us) - ssize_t adjust(ssize_t& decoderTimestamp); + long adjust(long& decoderTimestamp); private: - ssize_t startTime_{0}; - ssize_t streamTimestamp_{0}; + long startTime_{0}; + long streamTimestamp_{0}; }; } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/util.cpp b/torchvision/csrc/cpu/decoder/util.cpp index 6ae888838ea..ba19cf582b0 100644 --- a/torchvision/csrc/cpu/decoder/util.cpp +++ b/torchvision/csrc/cpu/decoder/util.cpp @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "util.h" #include diff --git a/torchvision/csrc/cpu/decoder/util.h b/torchvision/csrc/cpu/decoder/util.h index 6a985d78559..cc64d8944e4 100644 --- a/torchvision/csrc/cpu/decoder/util.h +++ b/torchvision/csrc/cpu/decoder/util.h @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include "defs.h" diff --git a/torchvision/csrc/cpu/decoder/video_sampler.cpp b/torchvision/csrc/cpu/decoder/video_sampler.cpp index 1a91c82a371..4b7d078ebd7 100644 --- a/torchvision/csrc/cpu/decoder/video_sampler.cpp +++ b/torchvision/csrc/cpu/decoder/video_sampler.cpp @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "video_sampler.h" #include #include "util.h" diff --git a/torchvision/csrc/cpu/decoder/video_sampler.h b/torchvision/csrc/cpu/decoder/video_sampler.h index 73997c213e1..85161307257 100644 --- a/torchvision/csrc/cpu/decoder/video_sampler.h +++ b/torchvision/csrc/cpu/decoder/video_sampler.h @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include "defs.h" diff --git a/torchvision/csrc/cpu/decoder/video_stream.cpp b/torchvision/csrc/cpu/decoder/video_stream.cpp index 9c6b77d0bfc..e464ed30cc9 100644 --- a/torchvision/csrc/cpu/decoder/video_stream.cpp +++ b/torchvision/csrc/cpu/decoder/video_stream.cpp @@ -1,5 +1,3 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #include "video_stream.h" #include #include "util.h" @@ -11,12 +9,23 @@ bool operator==(const VideoFormat& x, const AVFrame& y) { return x.width == y.width && x.height == y.height && x.format == y.format; } +bool operator==(const VideoFormat& x, const AVCodecContext& y) { + return x.width == y.width && x.height == y.height && x.format == y.pix_fmt; +} + VideoFormat& toVideoFormat(VideoFormat& x, const AVFrame& y) { x.width = y.width; x.height = y.height; x.format = y.format; return x; } + +VideoFormat& toVideoFormat(VideoFormat& x, const AVCodecContext& y) { + x.width = y.width; + x.height = y.height; + x.format = y.pix_fmt; + return x; +} } // namespace VideoStream::VideoStream( @@ -28,8 +37,8 @@ VideoStream::VideoStream( : Stream( inputCtx, MediaFormat::makeMediaFormat(format, index), - convertPtsToWallTime), - loggingUuid_(loggingUuid) {} + convertPtsToWallTime, + loggingUuid) {} VideoStream::~VideoStream() { if (sampler_) { @@ -79,12 +88,14 @@ int VideoStream::initFormat() { int VideoStream::estimateBytes(bool flush) { ensureSampler(); // check if input format gets changed - if (!flush && !(sampler_->getInputFormat().video == *frame_)) { + if (flush ? !(sampler_->getInputFormat().video == *codecCtx_) + : !(sampler_->getInputFormat().video == *frame_)) { // - reinit sampler SamplerParameters params; params.type = format_.type; params.out = format_.format; - toVideoFormat(params.in.video, *frame_); + flush ? toVideoFormat(params.in.video, *codecCtx_) + : toVideoFormat(params.in.video, *frame_); if (!sampler_->init(params)) { return -1; } @@ -108,36 +119,13 @@ int VideoStream::copyFrameBytes(ByteStorage* out, bool flush) { return sampler_->sample(flush ? nullptr : frame_, out); } -void VideoStream::setHeader(DecoderHeader* header) { - header->seqno = numGenerator_++; - - if (codecCtx_->time_base.num != 0) { - header->pts = av_rescale_q( - av_frame_get_best_effort_timestamp(frame_), - codecCtx_->time_base, - AV_TIME_BASE_Q); - } else { - // If the codec time_base is missing then we would've skipped the - // rescalePackage step to rescale to codec time_base, so here we can - // rescale straight from the stream time_base into AV_TIME_BASE_Q. - header->pts = av_rescale_q( - av_frame_get_best_effort_timestamp(frame_), - inputCtx_->streams[format_.stream]->time_base, - AV_TIME_BASE_Q); - } - - if (convertPtsToWallTime_) { - keeper_.adjust(header->pts); - } - - header->keyFrame = frame_->key_frame; - auto fpsRational = inputCtx_->streams[format_.stream]->avg_frame_rate; - if (fpsRational.den) { - header->fps = av_q2d(fpsRational); - } else { - header->fps = std::numeric_limits::quiet_NaN(); +void VideoStream::setHeader(DecoderHeader* header, bool flush) { + Stream::setHeader(header, flush); + if (!flush) { // no frames for video flush + header->keyFrame = frame_->key_frame; + header->fps = av_q2d(av_guess_frame_rate( + inputCtx_, inputCtx_->streams[format_.stream], nullptr)); } - header->format = format_; } } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/video_stream.h b/torchvision/csrc/cpu/decoder/video_stream.h index af1e3fb960f..8e73d099613 100644 --- a/torchvision/csrc/cpu/decoder/video_stream.h +++ b/torchvision/csrc/cpu/decoder/video_stream.h @@ -1,9 +1,6 @@ -// Copyright 2004-present Facebook. All Rights Reserved. - #pragma once #include "stream.h" -#include "time_keeper.h" #include "video_sampler.h" namespace ffmpeg { @@ -19,21 +16,19 @@ class VideoStream : public Stream { int index, bool convertPtsToWallTime, const VideoFormat& format, - int64_t loggingUuid = 0); + int64_t loggingUuid); ~VideoStream() override; private: int initFormat() override; int estimateBytes(bool flush) override; int copyFrameBytes(ByteStorage* out, bool flush) override; - void setHeader(DecoderHeader* header) override; + void setHeader(DecoderHeader* header, bool flush) override; void ensureSampler(); private: std::unique_ptr sampler_; - TimeKeeper keeper_; - int64_t loggingUuid_{0}; }; } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/video_reader/FfmpegAudioSampler.cpp b/torchvision/csrc/cpu/video_reader/FfmpegAudioSampler.cpp deleted file mode 100644 index 24aecacf946..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegAudioSampler.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "FfmpegAudioSampler.h" -#include -#include "FfmpegUtil.h" - -using namespace std; - -FfmpegAudioSampler::FfmpegAudioSampler( - const AudioFormat& in, - const AudioFormat& out) - : inFormat_(in), outFormat_(out) {} - -FfmpegAudioSampler::~FfmpegAudioSampler() { - if (swrContext_) { - swr_free(&swrContext_); - } -} - -int FfmpegAudioSampler::init() { - swrContext_ = swr_alloc_set_opts( - nullptr, // we're allocating a new context - av_get_default_channel_layout(outFormat_.channels), // out_ch_layout - static_cast(outFormat_.format), // out_sample_fmt - outFormat_.samples, // out_sample_rate - av_get_default_channel_layout(inFormat_.channels), // in_ch_layout - static_cast(inFormat_.format), // in_sample_fmt - inFormat_.samples, // in_sample_rate - 0, // log_offset - nullptr); // log_ctx - if (swrContext_ == nullptr) { - LOG(ERROR) << "swr_alloc_set_opts fails"; - return -1; - } - int result = 0; - if ((result = swr_init(swrContext_)) < 0) { - LOG(ERROR) << "swr_init failed, err: " << ffmpeg_util::getErrorDesc(result) - << ", in -> format: " << inFormat_.format - << ", channels: " << inFormat_.channels - << ", samples: " << inFormat_.samples - << ", out -> format: " << outFormat_.format - << ", channels: " << outFormat_.channels - << ", samples: " << outFormat_.samples; - return -1; - } - return 0; -} - -int64_t FfmpegAudioSampler::getSampleBytes(const AVFrame* frame) const { - auto outSamples = getOutNumSamples(frame->nb_samples); - - return av_samples_get_buffer_size( - nullptr, - outFormat_.channels, - outSamples, - static_cast(outFormat_.format), - 1); -} - -// https://www.ffmpeg.org/doxygen/3.2/group__lswr.html -unique_ptr FfmpegAudioSampler::sample(const AVFrame* frame) { - if (!frame) { - return nullptr; // no flush for videos - } - - auto inNumSamples = frame->nb_samples; - auto outNumSamples = getOutNumSamples(frame->nb_samples); - - auto outSampleSize = getSampleBytes(frame); - AvDataPtr frameData(static_cast(av_malloc(outSampleSize))); - - uint8_t* outPlanes[AVRESAMPLE_MAX_CHANNELS]; - int result = 0; - if ((result = av_samples_fill_arrays( - outPlanes, - nullptr, // linesize is not needed - frameData.get(), - outFormat_.channels, - outNumSamples, - static_cast(outFormat_.format), - 1)) < 0) { - LOG(ERROR) << "av_samples_fill_arrays failed, err: " - << ffmpeg_util::getErrorDesc(result) - << ", outNumSamples: " << outNumSamples - << ", format: " << outFormat_.format; - return nullptr; - } - - if ((result = swr_convert( - swrContext_, - &outPlanes[0], - outNumSamples, - (const uint8_t**)&frame->data[0], - inNumSamples)) < 0) { - LOG(ERROR) << "swr_convert faield, err: " - << ffmpeg_util::getErrorDesc(result); - return nullptr; - } - // result returned by swr_convert is the No. of actual output samples. - // So update the buffer size using av_samples_get_buffer_size - result = av_samples_get_buffer_size( - nullptr, - outFormat_.channels, - result, - static_cast(outFormat_.format), - 1); - - return make_unique(std::move(frameData), result, 0); -} -/* -Because of decoding delay, the returned value is an upper bound of No. of -output samples -*/ -int64_t FfmpegAudioSampler::getOutNumSamples(int inNumSamples) const { - return av_rescale_rnd( - swr_get_delay(swrContext_, inFormat_.samples) + inNumSamples, - outFormat_.samples, - inFormat_.samples, - AV_ROUND_UP); -} diff --git a/torchvision/csrc/cpu/video_reader/FfmpegAudioSampler.h b/torchvision/csrc/cpu/video_reader/FfmpegAudioSampler.h deleted file mode 100644 index 767a5ca6e4f..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegAudioSampler.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "FfmpegSampler.h" - -#define AVRESAMPLE_MAX_CHANNELS 32 - -/** - * Class transcode audio frames from one format into another - */ -class FfmpegAudioSampler : public FfmpegSampler { - public: - explicit FfmpegAudioSampler(const AudioFormat& in, const AudioFormat& out); - ~FfmpegAudioSampler() override; - - int init() override; - - int64_t getSampleBytes(const AVFrame* frame) const; - // FfmpegSampler overrides - // returns number of bytes of the sampled data - std::unique_ptr sample(const AVFrame* frame) override; - - const AudioFormat& getInFormat() const { - return inFormat_; - } - - private: - int64_t getOutNumSamples(int inNumSamples) const; - - AudioFormat inFormat_; - AudioFormat outFormat_; - SwrContext* swrContext_{nullptr}; -}; diff --git a/torchvision/csrc/cpu/video_reader/FfmpegAudioStream.cpp b/torchvision/csrc/cpu/video_reader/FfmpegAudioStream.cpp deleted file mode 100644 index b5b1e2fbda5..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegAudioStream.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include "FfmpegAudioStream.h" -#include "FfmpegUtil.h" - -using namespace std; - -namespace { - -bool operator==(const AudioFormat& x, const AVCodecContext& y) { - return x.samples == y.sample_rate && x.channels == y.channels && - x.format == y.sample_fmt; -} - -AudioFormat& toAudioFormat( - AudioFormat& audioFormat, - const AVCodecContext& codecCtx) { - audioFormat.samples = codecCtx.sample_rate; - audioFormat.channels = codecCtx.channels; - audioFormat.format = codecCtx.sample_fmt; - - return audioFormat; -} - -} // namespace - -FfmpegAudioStream::FfmpegAudioStream( - AVFormatContext* inputCtx, - int index, - enum AVMediaType avMediaType, - MediaFormat mediaFormat, - double seekFrameMargin) - : FfmpegStream(inputCtx, index, avMediaType, seekFrameMargin), - mediaFormat_(mediaFormat) {} - -FfmpegAudioStream::~FfmpegAudioStream() {} - -void FfmpegAudioStream::checkStreamDecodeParams() { - auto timeBase = getTimeBase(); - if (timeBase.first > 0) { - CHECK_EQ(timeBase.first, inputCtx_->streams[index_]->time_base.num); - CHECK_EQ(timeBase.second, inputCtx_->streams[index_]->time_base.den); - } -} - -void FfmpegAudioStream::updateStreamDecodeParams() { - auto timeBase = getTimeBase(); - if (timeBase.first == 0) { - mediaFormat_.format.audio.timeBaseNum = - inputCtx_->streams[index_]->time_base.num; - mediaFormat_.format.audio.timeBaseDen = - inputCtx_->streams[index_]->time_base.den; - } - mediaFormat_.format.audio.duration = inputCtx_->streams[index_]->duration; -} - -int FfmpegAudioStream::initFormat() { - AudioFormat& format = mediaFormat_.format.audio; - - if (format.samples == 0) { - format.samples = codecCtx_->sample_rate; - } - if (format.channels == 0) { - format.channels = codecCtx_->channels; - } - if (format.format == AV_SAMPLE_FMT_NONE) { - format.format = codecCtx_->sample_fmt; - VLOG(2) << "set stream format sample_fmt: " << format.format; - } - - checkStreamDecodeParams(); - - updateStreamDecodeParams(); - - if (format.samples > 0 && format.channels > 0 && - format.format != AV_SAMPLE_FMT_NONE) { - return 0; - } else { - return -1; - } -} - -unique_ptr FfmpegAudioStream::sampleFrameData() { - AudioFormat& audioFormat = mediaFormat_.format.audio; - - if (!sampler_ || !(sampler_->getInFormat() == *codecCtx_)) { - AudioFormat newInFormat; - newInFormat = toAudioFormat(newInFormat, *codecCtx_); - sampler_ = make_unique(newInFormat, audioFormat); - VLOG(1) << "Set sampler input audio format" - << ", samples: " << newInFormat.samples - << ", channels: " << newInFormat.channels - << ", format: " << newInFormat.format - << " : output audio sampler format" - << ", samples: " << audioFormat.samples - << ", channels: " << audioFormat.channels - << ", format: " << audioFormat.format; - int ret = sampler_->init(); - if (ret < 0) { - VLOG(1) << "Fail to initialize audio sampler"; - return nullptr; - } - } - return sampler_->sample(frame_); -} diff --git a/torchvision/csrc/cpu/video_reader/FfmpegAudioStream.h b/torchvision/csrc/cpu/video_reader/FfmpegAudioStream.h deleted file mode 100644 index 1d4f7a2f2ee..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegAudioStream.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include "FfmpegAudioSampler.h" -#include "FfmpegStream.h" - -/** - * Class uses FFMPEG library to decode one video stream. - */ -class FfmpegAudioStream : public FfmpegStream { - public: - explicit FfmpegAudioStream( - AVFormatContext* inputCtx, - int index, - enum AVMediaType avMediaType, - MediaFormat mediaFormat, - double seekFrameMargin); - - ~FfmpegAudioStream() override; - - // FfmpegStream overrides - MediaType getMediaType() const override { - return MediaType::TYPE_AUDIO; - } - - FormatUnion getMediaFormat() const override { - return mediaFormat_.format; - } - - int64_t getStartPts() const override { - return mediaFormat_.format.audio.startPts; - } - int64_t getEndPts() const override { - return mediaFormat_.format.audio.endPts; - } - // return numerator and denominator of time base - std::pair getTimeBase() const { - return std::make_pair( - mediaFormat_.format.audio.timeBaseNum, - mediaFormat_.format.audio.timeBaseDen); - } - - void checkStreamDecodeParams(); - - void updateStreamDecodeParams(); - - protected: - int initFormat() override; - std::unique_ptr sampleFrameData() override; - - private: - MediaFormat mediaFormat_; - std::unique_ptr sampler_{nullptr}; -}; diff --git a/torchvision/csrc/cpu/video_reader/FfmpegDecoder.cpp b/torchvision/csrc/cpu/video_reader/FfmpegDecoder.cpp deleted file mode 100644 index fb4d302cc03..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegDecoder.cpp +++ /dev/null @@ -1,412 +0,0 @@ -#include "FfmpegDecoder.h" -#include "FfmpegAudioStream.h" -#include "FfmpegUtil.h" -#include "FfmpegVideoStream.h" - -using namespace std; - -static AVPacket avPkt; - -namespace { - -unique_ptr createFfmpegStream( - MediaType type, - AVFormatContext* ctx, - int idx, - MediaFormat& mediaFormat, - double seekFrameMargin) { - enum AVMediaType avType; - CHECK(ffmpeg_util::mapMediaType(type, &avType)); - switch (type) { - case MediaType::TYPE_VIDEO: - return make_unique( - ctx, idx, avType, mediaFormat, seekFrameMargin); - case MediaType::TYPE_AUDIO: - return make_unique( - ctx, idx, avType, mediaFormat, seekFrameMargin); - default: - return nullptr; - } -} - -} // namespace - -FfmpegAvioContext::FfmpegAvioContext() - : workBuffersize_(VIO_BUFFER_SZ), - workBuffer_((uint8_t*)av_malloc(workBuffersize_)), - inputFile_(nullptr), - inputBuffer_(nullptr), - inputBufferSize_(0) {} - -int FfmpegAvioContext::initAVIOContext(const uint8_t* buffer, int64_t size) { - inputBuffer_ = buffer; - inputBufferSize_ = size; - avioCtx_ = avio_alloc_context( - workBuffer_, - workBuffersize_, - 0, - reinterpret_cast(this), - &FfmpegAvioContext::readMemory, - nullptr, // no write function - &FfmpegAvioContext::seekMemory); - return 0; -} - -FfmpegAvioContext::~FfmpegAvioContext() { - /* note: the internal buffer could have changed, and be != workBuffer_ */ - if (avioCtx_) { - av_freep(&avioCtx_->buffer); - av_freep(&avioCtx_); - } else { - av_freep(&workBuffer_); - } - if (inputFile_) { - fclose(inputFile_); - } -} - -int FfmpegAvioContext::read(uint8_t* buf, int buf_size) { - if (inputBuffer_) { - return readMemory(this, buf, buf_size); - } else { - return -1; - } -} - -int FfmpegAvioContext::readMemory(void* opaque, uint8_t* buf, int buf_size) { - FfmpegAvioContext* h = static_cast(opaque); - if (buf_size < 0) { - return -1; - } - - int reminder = h->inputBufferSize_ - h->offset_; - int r = buf_size < reminder ? buf_size : reminder; - if (r < 0) { - return AVERROR_EOF; - } - - memcpy(buf, h->inputBuffer_ + h->offset_, r); - h->offset_ += r; - return r; -} - -int64_t FfmpegAvioContext::seek(int64_t offset, int whence) { - if (inputBuffer_) { - return seekMemory(this, offset, whence); - } else { - return -1; - } -} - -int64_t FfmpegAvioContext::seekMemory( - void* opaque, - int64_t offset, - int whence) { - FfmpegAvioContext* h = static_cast(opaque); - switch (whence) { - case SEEK_CUR: // from current position - h->offset_ += offset; - break; - case SEEK_END: // from eof - h->offset_ = h->inputBufferSize_ + offset; - break; - case SEEK_SET: // from beginning of file - h->offset_ = offset; - break; - case AVSEEK_SIZE: - return h->inputBufferSize_; - } - return h->offset_; -} - -int FfmpegDecoder::init( - const std::string& filename, - bool isDecodeFile, - FfmpegAvioContext& ioctx, - DecoderOutput& decoderOutput) { - cleanUp(); - - int ret = 0; - if (!isDecodeFile) { - formatCtx_ = avformat_alloc_context(); - if (!formatCtx_) { - LOG(ERROR) << "avformat_alloc_context failed"; - return -1; - } - formatCtx_->pb = ioctx.get_avio(); - formatCtx_->flags |= AVFMT_FLAG_CUSTOM_IO; - - // Determining the input format: - int probeSz = AVPROBE_SIZE + AVPROBE_PADDING_SIZE; - uint8_t* probe((uint8_t*)av_malloc(probeSz)); - memset(probe, 0, probeSz); - int len = ioctx.read(probe, probeSz - AVPROBE_PADDING_SIZE); - if (len < probeSz - AVPROBE_PADDING_SIZE) { - LOG(ERROR) << "Insufficient data to determine video format"; - av_freep(&probe); - return -1; - } - // seek back to start of stream - ioctx.seek(0, SEEK_SET); - - unique_ptr probeData(new AVProbeData()); - probeData->buf = probe; - probeData->buf_size = len; - probeData->filename = ""; - // Determine the input-format: - formatCtx_->iformat = av_probe_input_format(probeData.get(), 1); - // this is to avoid the double-free error - if (formatCtx_->iformat == nullptr) { - LOG(ERROR) << "av_probe_input_format fails"; - return -1; - } - VLOG(1) << "av_probe_input_format succeeds"; - av_freep(&probe); - - ret = avformat_open_input(&formatCtx_, "", nullptr, nullptr); - } else { - ret = avformat_open_input(&formatCtx_, filename.c_str(), nullptr, nullptr); - } - - if (ret < 0) { - LOG(ERROR) << "avformat_open_input failed, error: " - << ffmpeg_util::getErrorDesc(ret); - cleanUp(); - return ret; - } - ret = avformat_find_stream_info(formatCtx_, nullptr); - if (ret < 0) { - LOG(ERROR) << "avformat_find_stream_info failed, error: " - << ffmpeg_util::getErrorDesc(ret); - cleanUp(); - return ret; - } - if (!initStreams()) { - LOG(ERROR) << "Cannot activate streams"; - cleanUp(); - return -1; - } - - for (auto& stream : streams_) { - MediaType mediaType = stream.second->getMediaType(); - decoderOutput.initMediaType(mediaType, stream.second->getMediaFormat()); - } - VLOG(1) << "FfmpegDecoder initialized"; - return 0; -} - -int FfmpegDecoder::decodeFile( - unique_ptr params, - const string& fileName, - DecoderOutput& decoderOutput) { - VLOG(1) << "decode file: " << fileName; - FfmpegAvioContext ioctx; - int ret = decodeLoop(std::move(params), fileName, true, ioctx, decoderOutput); - return ret; -} - -int FfmpegDecoder::decodeMemory( - unique_ptr params, - const uint8_t* buffer, - int64_t size, - DecoderOutput& decoderOutput) { - VLOG(1) << "decode video data in memory"; - FfmpegAvioContext ioctx; - int ret = ioctx.initAVIOContext(buffer, size); - if (ret == 0) { - ret = - decodeLoop(std::move(params), string(""), false, ioctx, decoderOutput); - } - return ret; -} - -int FfmpegDecoder::probeFile( - unique_ptr params, - const string& fileName, - DecoderOutput& decoderOutput) { - VLOG(1) << "probe file: " << fileName; - FfmpegAvioContext ioctx; - return probeVideo(std::move(params), fileName, true, ioctx, decoderOutput); -} - -int FfmpegDecoder::probeMemory( - unique_ptr params, - const uint8_t* buffer, - int64_t size, - DecoderOutput& decoderOutput) { - VLOG(1) << "probe video data in memory"; - FfmpegAvioContext ioctx; - int ret = ioctx.initAVIOContext(buffer, size); - if (ret == 0) { - ret = - probeVideo(std::move(params), string(""), false, ioctx, decoderOutput); - } - return ret; -} - -void FfmpegDecoder::cleanUp() { - if (formatCtx_) { - for (auto& stream : streams_) { - // Drain stream buffers. - DecoderOutput decoderOutput; - stream.second->flush(1, decoderOutput); - stream.second.reset(); - } - streams_.clear(); - avformat_close_input(&formatCtx_); - } -} - -FfmpegStream* FfmpegDecoder::findStreamByIndex(int streamIndex) const { - auto it = streams_.find(streamIndex); - return it != streams_.end() ? it->second.get() : nullptr; -} - -/* -Reference implementation: -https://ffmpeg.org/doxygen/3.4/demuxing_decoding_8c-example.html -*/ -int FfmpegDecoder::decodeLoop( - unique_ptr params, - const std::string& filename, - bool isDecodeFile, - FfmpegAvioContext& ioctx, - DecoderOutput& decoderOutput) { - params_ = std::move(params); - - int ret = init(filename, isDecodeFile, ioctx, decoderOutput); - if (ret < 0) { - return ret; - } - // init package - av_init_packet(&avPkt); - avPkt.data = nullptr; - avPkt.size = 0; - - int result = 0; - bool ptsInRange = true; - while (ptsInRange) { - result = av_read_frame(formatCtx_, &avPkt); - if (result == AVERROR(EAGAIN)) { - VLOG(1) << "Decoder is busy"; - ret = 0; - break; - } else if (result == AVERROR_EOF) { - VLOG(1) << "Stream decoding is completed"; - ret = 0; - break; - } else if (result < 0) { - VLOG(1) << "av_read_frame fails. Break decoder loop. Error: " - << ffmpeg_util::getErrorDesc(result); - ret = result; - break; - } - - ret = 0; - auto stream = findStreamByIndex(avPkt.stream_index); - if (stream == nullptr) { - // the packet is from a stream the caller is not interested. Ignore it - VLOG(2) << "avPkt ignored. stream index: " << avPkt.stream_index; - // Need to free the memory of AVPacket. Otherwise, memory leak happens - av_packet_unref(&avPkt); - continue; - } - - do { - result = stream->sendPacket(&avPkt); - if (result == AVERROR(EAGAIN)) { - VLOG(2) << "avcodec_send_packet returns AVERROR(EAGAIN)"; - // start to recevie available frames from internal buffer - stream->receiveAvailFrames(params_->getPtsOnly, decoderOutput); - if (isPtsExceedRange()) { - // exit the most-outer while loop - VLOG(1) << "In all streams, exceed the end pts. Exit decoding loop"; - ret = 0; - ptsInRange = false; - break; - } - } else if (result < 0) { - LOG(WARNING) << "avcodec_send_packet failed. Error: " - << ffmpeg_util::getErrorDesc(result); - ret = result; - break; - } else { - VLOG(2) << "avcodec_send_packet succeeds"; - // succeed. Read the next AVPacket and send out it - break; - } - } while (ptsInRange); - // Need to free the memory of AVPacket. Otherwise, memory leak happens - av_packet_unref(&avPkt); - } - /* flush cached frames */ - flushStreams(decoderOutput); - return ret; -} - -int FfmpegDecoder::probeVideo( - unique_ptr params, - const std::string& filename, - bool isDecodeFile, - FfmpegAvioContext& ioctx, - DecoderOutput& decoderOutput) { - params_ = std::move(params); - return init(filename, isDecodeFile, ioctx, decoderOutput); -} - -bool FfmpegDecoder::initStreams() { - for (auto it = params_->formats.begin(); it != params_->formats.end(); ++it) { - AVMediaType mediaType; - if (!ffmpeg_util::mapMediaType(it->first, &mediaType)) { - LOG(ERROR) << "Unknown media type: " << it->first; - return false; - } - int streamIdx = - av_find_best_stream(formatCtx_, mediaType, -1, -1, nullptr, 0); - - if (streamIdx >= 0) { - VLOG(2) << "find stream index: " << streamIdx; - auto stream = createFfmpegStream( - it->first, - formatCtx_, - streamIdx, - it->second, - params_->seekFrameMargin); - - CHECK(stream); - if (stream->openCodecContext() < 0) { - LOG(ERROR) << "Cannot open codec. Stream index: " << streamIdx; - return false; - } - streams_.emplace(streamIdx, move(stream)); - } else { - VLOG(1) << "Cannot open find stream of type " << it->first; - } - } - // Seek frames in each stream - int ret = 0; - for (auto& stream : streams_) { - auto startPts = stream.second->getStartPts(); - VLOG(1) << "stream: " << stream.first << " startPts: " << startPts; - if (startPts > 0 && (ret = stream.second->seekFrame(startPts)) < 0) { - LOG(WARNING) << "seekFrame in stream fails"; - return false; - } - } - VLOG(1) << "initStreams succeeds"; - return true; -} - -bool FfmpegDecoder::isPtsExceedRange() { - bool exceed = true; - for (auto& stream : streams_) { - exceed = exceed && stream.second->isFramePtsExceedRange(); - } - return exceed; -} - -void FfmpegDecoder::flushStreams(DecoderOutput& decoderOutput) { - for (auto& stream : streams_) { - stream.second->flush(params_->getPtsOnly, decoderOutput); - } -} diff --git a/torchvision/csrc/cpu/video_reader/FfmpegDecoder.h b/torchvision/csrc/cpu/video_reader/FfmpegDecoder.h deleted file mode 100644 index a0a564a4214..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegDecoder.h +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once - -#include -#include - -#include "FfmpegHeaders.h" -#include "FfmpegStream.h" -#include "Interface.h" - -#define VIO_BUFFER_SZ 81920 -#define AVPROBE_SIZE 8192 - -class DecoderParameters { - public: - std::unordered_map formats; - // av_seek_frame is imprecise so seek to a timestamp earlier by a margin - // The unit of margin is second - double seekFrameMargin{1.0}; - // When getPtsOnly is set to 1, we only get pts of each frame and don not - // output frame data. It will be much faster - int64_t getPtsOnly{0}; -}; - -class FfmpegAvioContext { - public: - FfmpegAvioContext(); - - int initAVIOContext(const uint8_t* buffer, int64_t size); - - ~FfmpegAvioContext(); - - int read(uint8_t* buf, int buf_size); - - static int readMemory(void* opaque, uint8_t* buf, int buf_size); - - int64_t seek(int64_t offset, int whence); - - static int64_t seekMemory(void* opaque, int64_t offset, int whence); - - AVIOContext* get_avio() { - return avioCtx_; - } - - private: - int workBuffersize_; - uint8_t* workBuffer_; - // for file mode - FILE* inputFile_; - // for memory mode - const uint8_t* inputBuffer_; - int inputBufferSize_; - int offset_ = 0; - - AVIOContext* avioCtx_{nullptr}; -}; - -class FfmpegDecoder { - public: - FfmpegDecoder() { - av_register_all(); - } - ~FfmpegDecoder() { - cleanUp(); - } - // return 0 on success - // return negative number on failure - int decodeFile( - std::unique_ptr params, - const std::string& filename, - DecoderOutput& decoderOutput); - // return 0 on success - // return negative number on failure - int decodeMemory( - std::unique_ptr params, - const uint8_t* buffer, - int64_t size, - DecoderOutput& decoderOutput); - // return 0 on success - // return negative number on failure - int probeFile( - std::unique_ptr params, - const std::string& filename, - DecoderOutput& decoderOutput); - // return 0 on success - // return negative number on failure - int probeMemory( - std::unique_ptr params, - const uint8_t* buffer, - int64_t size, - DecoderOutput& decoderOutput); - - void cleanUp(); - - private: - FfmpegStream* findStreamByIndex(int streamIndex) const; - - int init( - const std::string& filename, - bool isDecodeFile, - FfmpegAvioContext& ioctx, - DecoderOutput& decoderOutput); - // return 0 on success - // return negative number on failure - int decodeLoop( - std::unique_ptr params, - const std::string& filename, - bool isDecodeFile, - FfmpegAvioContext& ioctx, - DecoderOutput& decoderOutput); - - int probeVideo( - std::unique_ptr params, - const std::string& filename, - bool isDecodeFile, - FfmpegAvioContext& ioctx, - DecoderOutput& decoderOutput); - - bool initStreams(); - - void flushStreams(DecoderOutput& decoderOutput); - // whether in all streams, the pts of most recent frame exceeds range - bool isPtsExceedRange(); - - std::unordered_map> streams_; - AVFormatContext* formatCtx_{nullptr}; - std::unique_ptr params_{nullptr}; -}; diff --git a/torchvision/csrc/cpu/video_reader/FfmpegHeaders.h b/torchvision/csrc/cpu/video_reader/FfmpegHeaders.h deleted file mode 100644 index ff26aa30a8d..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegHeaders.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -#include -} diff --git a/torchvision/csrc/cpu/video_reader/FfmpegSampler.h b/torchvision/csrc/cpu/video_reader/FfmpegSampler.h deleted file mode 100644 index 3d00be3486f..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegSampler.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "FfmpegHeaders.h" -#include "Interface.h" - -/** - * Class sample data from AVFrame - */ -class FfmpegSampler { - public: - virtual ~FfmpegSampler() = default; - // return 0 on success and negative number on failure - virtual int init() = 0; - // sample from the given frame - virtual std::unique_ptr sample(const AVFrame* frame) = 0; -}; diff --git a/torchvision/csrc/cpu/video_reader/FfmpegStream.cpp b/torchvision/csrc/cpu/video_reader/FfmpegStream.cpp deleted file mode 100644 index b745170baf4..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegStream.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include "FfmpegStream.h" -#include "FfmpegUtil.h" - -using namespace std; - -// (TODO) Currently, disable the use of refCount -static int refCount = 0; - -FfmpegStream::FfmpegStream( - AVFormatContext* inputCtx, - int index, - enum AVMediaType avMediaType, - double seekFrameMargin) - : inputCtx_(inputCtx), - index_(index), - avMediaType_(avMediaType), - seekFrameMargin_(seekFrameMargin) {} - -FfmpegStream::~FfmpegStream() { - if (frame_) { - av_frame_free(&frame_); - } - avcodec_free_context(&codecCtx_); -} - -int FfmpegStream::openCodecContext() { - VLOG(2) << "stream start_time: " << inputCtx_->streams[index_]->start_time; - - auto typeString = av_get_media_type_string(avMediaType_); - AVStream* st = inputCtx_->streams[index_]; - auto codec_id = st->codecpar->codec_id; - VLOG(1) << "codec_id: " << codec_id; - AVCodec* codec = avcodec_find_decoder(codec_id); - if (!codec) { - LOG(ERROR) << "avcodec_find_decoder failed for codec_id: " << int(codec_id); - return AVERROR(EINVAL); - } - VLOG(1) << "Succeed to find decoder"; - - codecCtx_ = avcodec_alloc_context3(codec); - if (!codecCtx_) { - LOG(ERROR) << "avcodec_alloc_context3 fails"; - return AVERROR(ENOMEM); - } - - int ret; - /* Copy codec parameters from input stream to output codec context */ - if ((ret = avcodec_parameters_to_context(codecCtx_, st->codecpar)) < 0) { - LOG(ERROR) << "Failed to copy " << typeString - << " codec parameters to decoder context"; - return ret; - } - - AVDictionary* opts = nullptr; - av_dict_set(&opts, "refcounted_frames", refCount ? "1" : "0", 0); - - // after avcodec_open2, value of codecCtx_->time_base is NOT meaningful - // But inputCtx_->streams[index_]->time_base has meaningful values - if ((ret = avcodec_open2(codecCtx_, codec, &opts)) < 0) { - LOG(ERROR) << "avcodec_open2 failed. " << ffmpeg_util::getErrorDesc(ret); - return ret; - } - VLOG(1) << "Succeed to open codec"; - - frame_ = av_frame_alloc(); - return initFormat(); -} - -unique_ptr FfmpegStream::getFrameData(int getPtsOnly) { - if (!codecCtx_) { - LOG(ERROR) << "Codec is not initialized"; - return nullptr; - } - if (getPtsOnly) { - unique_ptr decodedFrame = make_unique(); - decodedFrame->pts_ = frame_->pts; - return decodedFrame; - } else { - unique_ptr decodedFrame = sampleFrameData(); - if (decodedFrame) { - decodedFrame->pts_ = frame_->pts; - } - return decodedFrame; - } -} - -void FfmpegStream::flush(int getPtsOnly, DecoderOutput& decoderOutput) { - VLOG(1) << "Media Type: " << getMediaType() << ", flush stream."; - // need to receive frames before entering draining mode - receiveAvailFrames(getPtsOnly, decoderOutput); - - VLOG(2) << "send nullptr packet"; - sendPacket(nullptr); - // receive remaining frames after entering draining mode - receiveAvailFrames(getPtsOnly, decoderOutput); - - avcodec_flush_buffers(codecCtx_); -} - -bool FfmpegStream::isFramePtsInRange() { - CHECK(frame_); - auto pts = frame_->pts; - auto startPts = this->getStartPts(); - auto endPts = this->getEndPts(); - VLOG(2) << "isPtsInRange. pts: " << pts << ", startPts: " << startPts - << ", endPts: " << endPts; - return (pts == AV_NOPTS_VALUE) || - (pts >= startPts && (endPts >= 0 ? pts <= endPts : true)); -} - -bool FfmpegStream::isFramePtsExceedRange() { - if (frame_) { - auto endPts = this->getEndPts(); - VLOG(2) << "isFramePtsExceedRange. last_pts_: " << last_pts_ - << ", endPts: " << endPts; - return endPts >= 0 ? last_pts_ >= endPts : false; - } else { - return true; - } -} - -// seek a frame -int FfmpegStream::seekFrame(int64_t seekPts) { - // translate margin from second to pts - int64_t margin = (int64_t)( - seekFrameMargin_ * (double)inputCtx_->streams[index_]->time_base.den / - (double)inputCtx_->streams[index_]->time_base.num); - int64_t real_seekPts = (seekPts - margin) > 0 ? (seekPts - margin) : 0; - VLOG(2) << "seek margin: " << margin; - VLOG(2) << "real seekPts: " << real_seekPts; - int ret = av_seek_frame( - inputCtx_, - index_, - (seekPts - margin) > 0 ? (seekPts - margin) : 0, - AVSEEK_FLAG_BACKWARD); - if (ret < 0) { - LOG(WARNING) << "av_seek_frame fails. Stream index: " << index_; - return ret; - } - return 0; -} - -// send/receive encoding and decoding API overview -// https://ffmpeg.org/doxygen/3.4/group__lavc__encdec.html -int FfmpegStream::sendPacket(const AVPacket* packet) { - return avcodec_send_packet(codecCtx_, packet); -} - -int FfmpegStream::receiveFrame() { - int ret = avcodec_receive_frame(codecCtx_, frame_); - if (ret >= 0) { - // succeed - frame_->pts = av_frame_get_best_effort_timestamp(frame_); - if (frame_->pts == AV_NOPTS_VALUE) { - // Trick: if we can not figure out pts, we just set it to be (last_pts + - // 1) - frame_->pts = last_pts_ + 1; - } - last_pts_ = frame_->pts; - - VLOG(2) << "avcodec_receive_frame succeed"; - } else if (ret == AVERROR(EAGAIN)) { - VLOG(2) << "avcodec_receive_frame fails and returns AVERROR(EAGAIN). "; - } else if (ret == AVERROR_EOF) { - // no more frame to read - VLOG(2) << "avcodec_receive_frame returns AVERROR_EOF"; - } else { - LOG(WARNING) << "avcodec_receive_frame failed. Error: " - << ffmpeg_util::getErrorDesc(ret); - } - return ret; -} - -void FfmpegStream::receiveAvailFrames( - int getPtsOnly, - DecoderOutput& decoderOutput) { - int result = 0; - while ((result = receiveFrame()) >= 0) { - unique_ptr decodedFrame = getFrameData(getPtsOnly); - - if (decodedFrame && - ((!getPtsOnly && decodedFrame->frameSize_ > 0) || getPtsOnly)) { - if (isFramePtsInRange()) { - decoderOutput.addMediaFrame(getMediaType(), std::move(decodedFrame)); - } - } // end-if - } // end-while -} diff --git a/torchvision/csrc/cpu/video_reader/FfmpegStream.h b/torchvision/csrc/cpu/video_reader/FfmpegStream.h deleted file mode 100644 index b66a36977ec..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegStream.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. -#pragma once - -#include -#include -#include -#include "FfmpegHeaders.h" -#include "Interface.h" - -/* -Class uses FFMPEG library to decode one media stream (audio or video). -*/ -class FfmpegStream { - public: - FfmpegStream( - AVFormatContext* inputCtx, - int index, - enum AVMediaType avMediaType, - double seekFrameMargin); - virtual ~FfmpegStream(); - - // returns 0 - on success or negative error - int openCodecContext(); - // returns stream index - int getIndex() const { - return index_; - } - // returns number decoded/sampled bytes - std::unique_ptr getFrameData(int getPtsOnly); - // flush the stream at the end of decoding. - // Return 0 on success and -1 when cache is drained - void flush(int getPtsOnly, DecoderOutput& decoderOutput); - // seek a frame - int seekFrame(int64_t ts); - // send an AVPacket - int sendPacket(const AVPacket* packet); - // receive AVFrame - int receiveFrame(); - // receive all available frames from the internal buffer - void receiveAvailFrames(int getPtsOnly, DecoderOutput& decoderOutput); - // return media type - virtual MediaType getMediaType() const = 0; - // return media format - virtual FormatUnion getMediaFormat() const = 0; - // return start presentation timestamp - virtual int64_t getStartPts() const = 0; - // return end presentation timestamp - virtual int64_t getEndPts() const = 0; - // is the pts of most recent frame within range? - bool isFramePtsInRange(); - // does the pts of most recent frame exceed range? - bool isFramePtsExceedRange(); - - protected: - virtual int initFormat() = 0; - // returns a decoded frame - virtual std::unique_ptr sampleFrameData() = 0; - - protected: - AVFormatContext* const inputCtx_; - const int index_; - enum AVMediaType avMediaType_; - - AVCodecContext* codecCtx_{nullptr}; - AVFrame* frame_{nullptr}; - // pts of last decoded frame - int64_t last_pts_{0}; - double seekFrameMargin_{1.0}; -}; diff --git a/torchvision/csrc/cpu/video_reader/FfmpegUtil.cpp b/torchvision/csrc/cpu/video_reader/FfmpegUtil.cpp deleted file mode 100644 index 9e804ee67c0..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegUtil.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "FfmpegUtil.h" - -using namespace std; - -namespace ffmpeg_util { - -bool mapFfmpegType(AVMediaType media, MediaType* type) { - switch (media) { - case AVMEDIA_TYPE_VIDEO: - *type = MediaType::TYPE_VIDEO; - return true; - case AVMEDIA_TYPE_AUDIO: - *type = MediaType::TYPE_AUDIO; - return true; - default: - return false; - } -} - -bool mapMediaType(MediaType type, AVMediaType* media) { - switch (type) { - case MediaType::TYPE_VIDEO: - *media = AVMEDIA_TYPE_VIDEO; - return true; - case MediaType::TYPE_AUDIO: - *media = AVMEDIA_TYPE_AUDIO; - return true; - default: - return false; - } -} - -void setFormatDimensions( - int& destW, - int& destH, - int userW, - int userH, - int srcW, - int srcH, - int minDimension) { - // rounding rules - // int -> double -> round - // round up if fraction is >= 0.5 or round down if fraction is < 0.5 - // int result = double(value) + 0.5 - // here we rounding double to int according to the above rule - if (userW == 0 && userH == 0) { - if (minDimension > 0) { // #2 - if (srcW > srcH) { - // landscape - destH = minDimension; - destW = round(double(srcW * minDimension) / srcH); - } else { - // portrait - destW = minDimension; - destH = round(double(srcH * minDimension) / srcW); - } - } else { // #1 - destW = srcW; - destH = srcH; - } - } else if (userW != 0 && userH == 0) { // #3 - destW = userW; - destH = round(double(srcH * userW) / srcW); - } else if (userW == 0 && userH != 0) { // #4 - destW = round(double(srcW * userH) / srcH); - destH = userH; - } else { - // userW != 0 && userH != 0. #5 - destW = userW; - destH = userH; - } - // prevent zeros - destW = std::max(destW, 1); - destH = std::max(destH, 1); -} - -bool validateVideoFormat(const VideoFormat& f) { - /* - Valid parameters values for decoder - ___________________________________________________ - | W | H | minDimension | algorithm | - |_________________________________________________| - | 0 | 0 | 0 | original | - |_________________________________________________| - | 0 | 0 | >0 |scale to min dimension| - |_____|_____|____________________________________ | - | >0 | 0 | 0 | scale keeping W | - |_________________________________________________| - | 0 | >0 | 0 | scale keeping H | - |_________________________________________________| - | >0 | >0 | 0 | stretch/scale | - |_________________________________________________| - - */ - return (f.width == 0 && f.height == 0) || // #1 and #2 - (f.width != 0 && f.height != 0 && f.minDimension == 0) || // # 5 - (((f.width != 0 && f.height == 0) || // #3 and #4 - (f.width == 0 && f.height != 0)) && - f.minDimension == 0); -} - -string getErrorDesc(int errnum) { - array buffer; - if (av_strerror(errnum, buffer.data(), buffer.size()) < 0) { - return string("Unknown error code"); - } - buffer.back() = 0; - return string(buffer.data()); -} - -} // namespace ffmpeg_util diff --git a/torchvision/csrc/cpu/video_reader/FfmpegUtil.h b/torchvision/csrc/cpu/video_reader/FfmpegUtil.h deleted file mode 100644 index 9f42eb53c97..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegUtil.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include -#include "FfmpegHeaders.h" -#include "Interface.h" - -namespace ffmpeg_util { - -bool mapFfmpegType(AVMediaType media, enum MediaType* type); - -bool mapMediaType(MediaType type, enum AVMediaType* media); - -void setFormatDimensions( - int& destW, - int& destH, - int userW, - int userH, - int srcW, - int srcH, - int minDimension); - -bool validateVideoFormat(const VideoFormat& f); - -std::string getErrorDesc(int errnum); - -} // namespace ffmpeg_util diff --git a/torchvision/csrc/cpu/video_reader/FfmpegVideoSampler.cpp b/torchvision/csrc/cpu/video_reader/FfmpegVideoSampler.cpp deleted file mode 100644 index d87b3104dd5..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegVideoSampler.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "FfmpegVideoSampler.h" -#include "FfmpegUtil.h" - -using namespace std; - -FfmpegVideoSampler::FfmpegVideoSampler( - const VideoFormat& in, - const VideoFormat& out, - int swsFlags) - : inFormat_(in), outFormat_(out), swsFlags_(swsFlags) {} - -FfmpegVideoSampler::~FfmpegVideoSampler() { - if (scaleContext_) { - sws_freeContext(scaleContext_); - scaleContext_ = nullptr; - } -} - -int FfmpegVideoSampler::init() { - VLOG(1) << "Input format: width " << inFormat_.width << ", height " - << inFormat_.height << ", format " << inFormat_.format - << ", minDimension " << inFormat_.minDimension; - VLOG(1) << "Scale format: width " << outFormat_.width << ", height " - << outFormat_.height << ", format " << outFormat_.format - << ", minDimension " << outFormat_.minDimension; - - scaleContext_ = sws_getContext( - inFormat_.width, - inFormat_.height, - (AVPixelFormat)inFormat_.format, - outFormat_.width, - outFormat_.height, - static_cast(outFormat_.format), - swsFlags_, - nullptr, - nullptr, - nullptr); - if (scaleContext_) { - return 0; - } else { - return -1; - } -} - -int32_t FfmpegVideoSampler::getImageBytes() const { - return av_image_get_buffer_size( - (AVPixelFormat)outFormat_.format, outFormat_.width, outFormat_.height, 1); -} - -// https://ffmpeg.org/doxygen/3.4/scaling_video_8c-example.html#a10 -unique_ptr FfmpegVideoSampler::sample(const AVFrame* frame) { - if (!frame) { - return nullptr; // no flush for videos - } - // scaled and cropped image - auto outImageSize = getImageBytes(); - AvDataPtr frameData(static_cast(av_malloc(outImageSize))); - - uint8_t* scalePlanes[4] = {nullptr}; - int scaleLines[4] = {0}; - - int result; - if ((result = av_image_fill_arrays( - scalePlanes, - scaleLines, - frameData.get(), - static_cast(outFormat_.format), - outFormat_.width, - outFormat_.height, - 1)) < 0) { - LOG(ERROR) << "av_image_fill_arrays failed, err: " - << ffmpeg_util::getErrorDesc(result); - return nullptr; - } - - if ((result = sws_scale( - scaleContext_, - frame->data, - frame->linesize, - 0, - inFormat_.height, - scalePlanes, - scaleLines)) < 0) { - LOG(ERROR) << "sws_scale failed, err: " - << ffmpeg_util::getErrorDesc(result); - return nullptr; - } - - return make_unique(std::move(frameData), outImageSize, 0); -} diff --git a/torchvision/csrc/cpu/video_reader/FfmpegVideoSampler.h b/torchvision/csrc/cpu/video_reader/FfmpegVideoSampler.h deleted file mode 100644 index 1fd6862f537..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegVideoSampler.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include "FfmpegSampler.h" - -/** - * Class transcode video frames from one format into another - */ - -class FfmpegVideoSampler : public FfmpegSampler { - public: - explicit FfmpegVideoSampler( - const VideoFormat& in, - const VideoFormat& out, - int swsFlags = SWS_AREA); - ~FfmpegVideoSampler() override; - - int init() override; - - int32_t getImageBytes() const; - // returns number of bytes of the sampled data - std::unique_ptr sample(const AVFrame* frame) override; - - const VideoFormat& getInFormat() const { - return inFormat_; - } - - private: - VideoFormat inFormat_; - VideoFormat outFormat_; - int swsFlags_; - SwsContext* scaleContext_{nullptr}; -}; diff --git a/torchvision/csrc/cpu/video_reader/FfmpegVideoStream.cpp b/torchvision/csrc/cpu/video_reader/FfmpegVideoStream.cpp deleted file mode 100644 index 7a429249a71..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegVideoStream.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "FfmpegVideoStream.h" -#include "FfmpegUtil.h" - -using namespace std; - -namespace { - -bool operator==(const VideoFormat& x, const AVFrame& y) { - return x.width == y.width && x.height == y.height && - x.format == static_cast(y.format); -} - -VideoFormat toVideoFormat(const AVFrame& frame) { - VideoFormat videoFormat; - videoFormat.width = frame.width; - videoFormat.height = frame.height; - videoFormat.format = static_cast(frame.format); - - return videoFormat; -} - -} // namespace - -FfmpegVideoStream::FfmpegVideoStream( - AVFormatContext* inputCtx, - int index, - enum AVMediaType avMediaType, - MediaFormat mediaFormat, - double seekFrameMargin) - : FfmpegStream(inputCtx, index, avMediaType, seekFrameMargin), - mediaFormat_(mediaFormat) {} - -FfmpegVideoStream::~FfmpegVideoStream() {} - -void FfmpegVideoStream::checkStreamDecodeParams() { - auto timeBase = getTimeBase(); - if (timeBase.first > 0) { - CHECK_EQ(timeBase.first, inputCtx_->streams[index_]->time_base.num); - CHECK_EQ(timeBase.second, inputCtx_->streams[index_]->time_base.den); - } -} - -void FfmpegVideoStream::updateStreamDecodeParams() { - auto timeBase = getTimeBase(); - if (timeBase.first == 0) { - mediaFormat_.format.video.timeBaseNum = - inputCtx_->streams[index_]->time_base.num; - mediaFormat_.format.video.timeBaseDen = - inputCtx_->streams[index_]->time_base.den; - } - mediaFormat_.format.video.duration = inputCtx_->streams[index_]->duration; -} - -int FfmpegVideoStream::initFormat() { - // set output format - VideoFormat& format = mediaFormat_.format.video; - if (!ffmpeg_util::validateVideoFormat(format)) { - LOG(ERROR) << "Invalid video format"; - return -1; - } - - format.fps = av_q2d( - av_guess_frame_rate(inputCtx_, inputCtx_->streams[index_], nullptr)); - - // keep aspect ratio - ffmpeg_util::setFormatDimensions( - format.width, - format.height, - format.width, - format.height, - codecCtx_->width, - codecCtx_->height, - format.minDimension); - - VLOG(1) << "After adjusting, video format" - << ", width: " << format.width << ", height: " << format.height - << ", format: " << format.format - << ", minDimension: " << format.minDimension; - - if (format.format == AV_PIX_FMT_NONE) { - format.format = codecCtx_->pix_fmt; - VLOG(1) << "Set pixel format: " << format.format; - } - - checkStreamDecodeParams(); - - updateStreamDecodeParams(); - - return format.width != 0 && format.height != 0 && - format.format != AV_PIX_FMT_NONE - ? 0 - : -1; -} - -unique_ptr FfmpegVideoStream::sampleFrameData() { - VideoFormat& format = mediaFormat_.format.video; - if (!sampler_ || !(sampler_->getInFormat() == *frame_)) { - VideoFormat newInFormat = toVideoFormat(*frame_); - sampler_ = make_unique(newInFormat, format, SWS_AREA); - VLOG(1) << "Set input video sampler format" - << ", width: " << newInFormat.width - << ", height: " << newInFormat.height - << ", format: " << newInFormat.format - << " : output video sampler format" - << ", width: " << format.width << ", height: " << format.height - << ", format: " << format.format - << ", minDimension: " << format.minDimension; - int ret = sampler_->init(); - if (ret < 0) { - VLOG(1) << "Fail to initialize video sampler"; - return nullptr; - } - } - return sampler_->sample(frame_); -} diff --git a/torchvision/csrc/cpu/video_reader/FfmpegVideoStream.h b/torchvision/csrc/cpu/video_reader/FfmpegVideoStream.h deleted file mode 100644 index 9bfbc9f665b..00000000000 --- a/torchvision/csrc/cpu/video_reader/FfmpegVideoStream.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include "FfmpegStream.h" -#include "FfmpegVideoSampler.h" - -/** - * Class uses FFMPEG library to decode one video stream. - */ -class FfmpegVideoStream : public FfmpegStream { - public: - explicit FfmpegVideoStream( - AVFormatContext* inputCtx, - int index, - enum AVMediaType avMediaType, - MediaFormat mediaFormat, - double seekFrameMargin); - - ~FfmpegVideoStream() override; - - // FfmpegStream overrides - MediaType getMediaType() const override { - return MediaType::TYPE_VIDEO; - } - - FormatUnion getMediaFormat() const override { - return mediaFormat_.format; - } - - int64_t getStartPts() const override { - return mediaFormat_.format.video.startPts; - } - int64_t getEndPts() const override { - return mediaFormat_.format.video.endPts; - } - // return numerator and denominator of time base - std::pair getTimeBase() const { - return std::make_pair( - mediaFormat_.format.video.timeBaseNum, - mediaFormat_.format.video.timeBaseDen); - } - - void checkStreamDecodeParams(); - - void updateStreamDecodeParams(); - - protected: - int initFormat() override; - std::unique_ptr sampleFrameData() override; - - private: - MediaFormat mediaFormat_; - std::unique_ptr sampler_{nullptr}; -}; diff --git a/torchvision/csrc/cpu/video_reader/Interface.cpp b/torchvision/csrc/cpu/video_reader/Interface.cpp deleted file mode 100644 index 0ec9f155821..00000000000 --- a/torchvision/csrc/cpu/video_reader/Interface.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "Interface.h" - -void DecoderOutput::initMediaType(MediaType mediaType, FormatUnion format) { - MediaData mediaData(format); - media_data_.emplace(mediaType, std::move(mediaData)); -} - -void DecoderOutput::addMediaFrame( - MediaType mediaType, - std::unique_ptr frame) { - if (media_data_.find(mediaType) != media_data_.end()) { - VLOG(1) << "media type: " << mediaType - << " add frame with pts: " << frame->pts_; - media_data_[mediaType].frames_.push_back(std::move(frame)); - } else { - VLOG(1) << "media type: " << mediaType << " not found. Skip the frame."; - } -} - -void DecoderOutput::clear() { - media_data_.clear(); -} diff --git a/torchvision/csrc/cpu/video_reader/Interface.h b/torchvision/csrc/cpu/video_reader/Interface.h deleted file mode 100644 index e137008ce7b..00000000000 --- a/torchvision/csrc/cpu/video_reader/Interface.h +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -extern "C" { - -#include -#include -void av_free(void* ptr); -} - -struct avDeleter { - void operator()(uint8_t* p) const { - av_free(p); - } -}; - -const AVPixelFormat defaultVideoPixelFormat = AV_PIX_FMT_RGB24; -const AVSampleFormat defaultAudioSampleFormat = AV_SAMPLE_FMT_FLT; - -using AvDataPtr = std::unique_ptr; - -enum MediaType : uint32_t { - TYPE_VIDEO = 1, - TYPE_AUDIO = 2, -}; - -struct EnumClassHash { - template - uint32_t operator()(T t) const { - return static_cast(t); - } -}; - -struct VideoFormat { - // fields are initialized for the auto detection - // caller can specify some/all of field values if specific output is desirable - - int width{0}; // width in pixels - int height{0}; // height in pixels - int minDimension{0}; // choose min dimension and rescale accordingly - // Output image pixel format. data type AVPixelFormat - AVPixelFormat format{defaultVideoPixelFormat}; // type AVPixelFormat - int64_t startPts{0}, endPts{0}; // Start and end presentation timestamp - int timeBaseNum{0}; - int timeBaseDen{1}; // numerator and denominator of time base - float fps{0.0}; - int64_t duration{0}; // duration of the stream, in stream time base -}; - -struct AudioFormat { - // fields are initialized for the auto detection - // caller can specify some/all of field values if specific output is desirable - - int samples{0}; // number samples per second (frequency) - int channels{0}; // number of channels - AVSampleFormat format{defaultAudioSampleFormat}; // type AVSampleFormat - int64_t startPts{0}, endPts{0}; // Start and end presentation timestamp - int timeBaseNum{0}; - int timeBaseDen{1}; // numerator and denominator of time base - int64_t duration{0}; // duration of the stream, in stream time base -}; - -union FormatUnion { - FormatUnion() {} - VideoFormat video; - AudioFormat audio; -}; - -struct MediaFormat { - MediaFormat() {} - - MediaFormat(const MediaFormat& mediaFormat) : type(mediaFormat.type) { - if (type == MediaType::TYPE_VIDEO) { - format.video = mediaFormat.format.video; - } else if (type == MediaType::TYPE_AUDIO) { - format.audio = mediaFormat.format.audio; - } - } - - MediaFormat(MediaType mediaType) : type(mediaType) { - if (mediaType == MediaType::TYPE_VIDEO) { - format.video = VideoFormat(); - } else if (mediaType == MediaType::TYPE_AUDIO) { - format.audio = AudioFormat(); - } - } - // media type - MediaType type; - // format data - FormatUnion format; -}; - -class DecodedFrame { - public: - explicit DecodedFrame() : frame_(nullptr), frameSize_(0), pts_(0) {} - explicit DecodedFrame(AvDataPtr frame, int frameSize, int64_t pts) - : frame_(std::move(frame)), frameSize_(frameSize), pts_(pts) {} - AvDataPtr frame_{nullptr}; - int frameSize_{0}; - int64_t pts_{0}; -}; - -struct MediaData { - MediaData() {} - MediaData(FormatUnion format) : format_(format) {} - FormatUnion format_; - std::vector> frames_; -}; - -class DecoderOutput { - public: - explicit DecoderOutput() {} - - ~DecoderOutput() {} - - void initMediaType(MediaType mediaType, FormatUnion format); - - void addMediaFrame(MediaType mediaType, std::unique_ptr frame); - - void clear(); - - std::unordered_map media_data_; -}; diff --git a/torchvision/csrc/cpu/video_reader/VideoReader.cpp b/torchvision/csrc/cpu/video_reader/VideoReader.cpp index dfe7f46bf39..7578927f1b5 100644 --- a/torchvision/csrc/cpu/video_reader/VideoReader.cpp +++ b/torchvision/csrc/cpu/video_reader/VideoReader.cpp @@ -3,11 +3,11 @@ #include #include #include -#include "FfmpegDecoder.h" -#include "FfmpegHeaders.h" -#include "util.h" +#include "memory_buffer.h" +#include "sync_decoder.h" using namespace std; +using namespace ffmpeg; // If we are in a Windows environment, we need to define // initialization functions for the _custom_ops extension @@ -27,121 +27,157 @@ PyMODINIT_FUNC PyInit_video_reader(void) { namespace video_reader { -class UnknownPixelFormatException : public exception { - const char* what() const throw() override { - return "Unknown pixel format"; - } -}; - -int getChannels(AVPixelFormat format) { - int numChannels = 0; - switch (format) { - case AV_PIX_FMT_BGR24: - case AV_PIX_FMT_RGB24: - numChannels = 3; - break; - default: - LOG(ERROR) << "Unknown format: " << format; - throw UnknownPixelFormatException(); - } - return numChannels; -} +const AVPixelFormat defaultVideoPixelFormat = AV_PIX_FMT_RGB24; +const AVSampleFormat defaultAudioSampleFormat = AV_SAMPLE_FMT_FLT; +const size_t decoderTimeoutMs = 600000; +// A jitter can be added to the end of the range to avoid conversion/rounding +// error, small value 100us won't be enough to select the next frame, but enough +// to compensate rounding error due to the multiple conversions. +const size_t timeBaseJitterUs = 100; + +DecoderParameters getDecoderParams( + int64_t videoStartUs, + int64_t videoEndUs, + double seekFrameMarginUs, + int64_t getPtsOnly, + int64_t readVideoStream, + int videoWidth, + int videoHeight, + int videoMinDimension, + int64_t readAudioStream, + int audioSamples, + int audioChannels) { + DecoderParameters params; + params.headerOnly = getPtsOnly != 0; + params.seekAccuracy = seekFrameMarginUs; + params.startOffset = videoStartUs; + params.endOffset = videoEndUs; + params.timeoutMs = decoderTimeoutMs; + params.preventStaleness = false; -void fillVideoTensor( - std::vector>& frames, - torch::Tensor& videoFrame, - torch::Tensor& videoFramePts) { - int frameSize = 0; - if (videoFrame.numel() > 0) { - frameSize = videoFrame.numel() / frames.size(); + if (readVideoStream == 1) { + MediaFormat videoFormat(0); + videoFormat.type = TYPE_VIDEO; + videoFormat.format.video.format = defaultVideoPixelFormat; + videoFormat.format.video.width = videoWidth; + videoFormat.format.video.height = videoHeight; + videoFormat.format.video.minDimension = videoMinDimension; + params.formats.insert(videoFormat); } - int frameCount = 0; + if (readAudioStream == 1) { + MediaFormat audioFormat; + audioFormat.type = TYPE_AUDIO; + audioFormat.format.audio.format = defaultAudioSampleFormat; + audioFormat.format.audio.samples = audioSamples; + audioFormat.format.audio.channels = audioChannels; + params.formats.insert(audioFormat); + } - uint8_t* videoFrameData = - videoFrame.numel() > 0 ? videoFrame.data_ptr() : nullptr; - int64_t* videoFramePtsData = videoFramePts.data_ptr(); + return params; +} - for (size_t i = 0; i < frames.size(); ++i) { - const auto& frame = frames[i]; - if (videoFrameData) { - memcpy( - videoFrameData + (size_t)(frameCount++) * (size_t)frameSize, - frame->frame_.get(), - frameSize * sizeof(uint8_t)); +// returns number of written bytes +template +size_t fillTensor( + std::vector& msgs, + torch::Tensor& frame, + torch::Tensor& framePts, + int64_t num, + int64_t den) { + if (msgs.empty()) { + return 0; + } + T* frameData = frame.numel() > 0 ? frame.data_ptr() : nullptr; + int64_t* framePtsData = framePts.data_ptr(); + CHECK_EQ(framePts.size(0), msgs.size()); + size_t avgElementsInFrame = frame.numel() / msgs.size(); + + size_t offset = 0; + for (size_t i = 0; i < msgs.size(); ++i) { + const auto& msg = msgs[i]; + // convert pts into original time_base + AVRational avr = {(int)num, (int)den}; + framePtsData[i] = av_rescale_q(msg.header.pts, AV_TIME_BASE_Q, avr); + VLOG(2) << "PTS type: " << sizeof(T) << ", us: " << msg.header.pts + << ", original: " << framePtsData[i]; + + if (frameData) { + auto sizeInBytes = msg.payload->length(); + memcpy(frameData + offset, msg.payload->data(), sizeInBytes); + if (sizeof(T) == sizeof(uint8_t)) { + // Video - move by allocated frame size + offset += avgElementsInFrame / sizeof(T); + } else { + // Audio - move by number of samples + offset += sizeInBytes / sizeof(T); + } } - videoFramePtsData[i] = frame->pts_; } + return offset * sizeof(T); } -void getVideoMeta( - DecoderOutput& decoderOutput, - int& numFrames, - int& height, - int& width, - int& numChannels) { - auto& videoFrames = decoderOutput.media_data_[TYPE_VIDEO].frames_; - numFrames = videoFrames.size(); - - FormatUnion& videoFormat = decoderOutput.media_data_[TYPE_VIDEO].format_; - height = videoFormat.video.height; - width = videoFormat.video.width; - numChannels = getChannels(videoFormat.video.format); +size_t fillVideoTensor( + std::vector& msgs, + torch::Tensor& videoFrame, + torch::Tensor& videoFramePts, + int64_t num, + int64_t den) { + return fillTensor(msgs, videoFrame, videoFramePts, num, den); } -void fillAudioTensor( - std::vector>& frames, +size_t fillAudioTensor( + std::vector& msgs, torch::Tensor& audioFrame, - torch::Tensor& audioFramePts) { - if (frames.size() == 0) { - return; - } - - float* audioFrameData = - audioFrame.numel() > 0 ? audioFrame.data_ptr() : nullptr; - CHECK_EQ(audioFramePts.size(0), frames.size()); - int64_t* audioFramePtsData = audioFramePts.data_ptr(); - - int bytesPerSample = av_get_bytes_per_sample(defaultAudioSampleFormat); - - int64_t frameDataOffset = 0; - for (size_t i = 0; i < frames.size(); ++i) { - audioFramePtsData[i] = frames[i]->pts_; - if (audioFrameData) { - memcpy( - audioFrameData + frameDataOffset, - frames[i]->frame_.get(), - frames[i]->frameSize_); - frameDataOffset += (frames[i]->frameSize_ / bytesPerSample); - } - } + torch::Tensor& audioFramePts, + int64_t num, + int64_t den) { + return fillTensor(msgs, audioFrame, audioFramePts, num, den); } -void getAudioMeta( - DecoderOutput& decoderOutput, - int64_t& numSamples, - int64_t& channels, - int64_t& numFrames) { - FormatUnion& audioFormat = decoderOutput.media_data_[TYPE_AUDIO].format_; - - channels = audioFormat.audio.channels; - CHECK_EQ(audioFormat.audio.format, AV_SAMPLE_FMT_FLT); - int bytesPerSample = av_get_bytes_per_sample( - static_cast(audioFormat.audio.format)); - - // auto& audioFrames = decoderOutput.media_frames_[TYPE_AUDIO]; - auto& audioFrames = decoderOutput.media_data_[TYPE_AUDIO].frames_; - numFrames = audioFrames.size(); - int64_t frameSizeTotal = 0; - for (auto const& decodedFrame : audioFrames) { - frameSizeTotal += static_cast(decodedFrame->frameSize_); +void offsetsToUs( + double& seekFrameMargin, + int64_t readVideoStream, + int64_t videoStartPts, + int64_t videoEndPts, + int64_t videoTimeBaseNum, + int64_t videoTimeBaseDen, + int64_t readAudioStream, + int64_t audioStartPts, + int64_t audioEndPts, + int64_t audioTimeBaseNum, + int64_t audioTimeBaseDen, + int64_t& videoStartUs, + int64_t& videoEndUs) { + seekFrameMargin *= AV_TIME_BASE; + videoStartUs = 0; + videoEndUs = -1; + + if (readVideoStream) { + AVRational vr = {(int)videoTimeBaseNum, (int)videoTimeBaseDen}; + if (videoStartPts > 0) { + videoStartUs = av_rescale_q(videoStartPts, vr, AV_TIME_BASE_Q); + } + if (videoEndPts > 0) { + // Add jitter to the end of the range to avoid conversion/rounding error. + // Small value 100us won't be enough to select the next frame, but enough + // to compensate rounding error due to the multiple conversions. + videoEndUs = + timeBaseJitterUs + av_rescale_q(videoEndPts, vr, AV_TIME_BASE_Q); + } + } else if (readAudioStream) { + AVRational ar = {(int)audioTimeBaseNum, (int)audioTimeBaseDen}; + if (audioStartPts > 0) { + videoStartUs = av_rescale_q(audioStartPts, ar, AV_TIME_BASE_Q); + } + if (audioEndPts > 0) { + // Add jitter to the end of the range to avoid conversion/rounding error. + // Small value 100us won't be enough to select the next frame, but enough + // to compensate rounding error due to the multiple conversions. + videoEndUs = + timeBaseJitterUs + av_rescale_q(audioEndPts, ar, AV_TIME_BASE_Q); + } } - VLOG(2) << "numFrames: " << numFrames; - VLOG(2) << "frameSizeTotal: " << frameSizeTotal; - VLOG(2) << "channels: " << channels; - VLOG(2) << "bytesPerSample: " << bytesPerSample; - CHECK_EQ(frameSizeTotal % (channels * bytesPerSample), 0); - numSamples = frameSizeTotal / (channels * bytesPerSample); } torch::List readVideo( @@ -165,38 +201,83 @@ torch::List readVideo( int64_t audioEndPts, int64_t audioTimeBaseNum, int64_t audioTimeBaseDen) { - unique_ptr params = util::getDecoderParams( + int64_t videoStartUs, videoEndUs; + + offsetsToUs( seekFrameMargin, - getPtsOnly, readVideoStream, - width, - height, - minDimension, videoStartPts, videoEndPts, videoTimeBaseNum, videoTimeBaseDen, readAudioStream, - audioSamples, - audioChannels, audioStartPts, audioEndPts, audioTimeBaseNum, - audioTimeBaseDen); - - FfmpegDecoder decoder; - DecoderOutput decoderOutput; + audioTimeBaseDen, + videoStartUs, + videoEndUs); + + DecoderParameters params = getDecoderParams( + videoStartUs, // videoStartPts + videoEndUs, // videoEndPts + seekFrameMargin, // seekFrameMargin + getPtsOnly, // getPtsOnly + readVideoStream, // readVideoStream + width, // width + height, // height + minDimension, // minDimension + readAudioStream, // readAudioStream + audioSamples, // audioSamples + audioChannels // audioChannels + ); + SyncDecoder decoder; + std::vector audioMessages, videoMessages; + DecoderInCallback callback = nullptr; + std::string logMessage, logType; if (isReadFile) { - decoder.decodeFile(std::move(params), videoPath, decoderOutput); + params.uri = videoPath; + logType = "file"; + logMessage = videoPath; } else { - decoder.decodeMemory( - std::move(params), - input_video.data_ptr(), - input_video.size(0), - decoderOutput); + callback = MemoryBuffer::getCallback( + input_video.data_ptr(), input_video.size(0)); + logType = "memory"; + logMessage = std::to_string(input_video.size(0)); } + VLOG(1) << "Video decoding from " << logType << " [" << logMessage + << "] has started"; + + const auto now = std::chrono::system_clock::now(); + + bool succeeded; + if ((succeeded = decoder.init(params, std::move(callback)))) { + int res; + DecoderOutputMessage msg; + while (0 == (res = decoder.decode(&msg, decoderTimeoutMs))) { + if (msg.header.format.type == TYPE_VIDEO) { + videoMessages.push_back(std::move(msg)); + } + if (msg.header.format.type == TYPE_AUDIO) { + audioMessages.push_back(std::move(msg)); + } + msg.payload.reset(); + } + + const auto then = std::chrono::system_clock::now(); + VLOG(1) << "Video decoding from " << logType << " [" << logMessage + << "] has finished, " + << std::chrono::duration_cast(then - now) + .count() + << " us"; + } else { + LOG(ERROR) << "Decoder initialization has failed"; + } + + decoder.shutdown(); + // video section torch::Tensor videoFrame = torch::zeros({0}, torch::kByte); torch::Tensor videoFramePts = torch::zeros({0}, torch::kLong); @@ -204,37 +285,50 @@ torch::List readVideo( torch::Tensor videoFps = torch::zeros({0}, torch::kFloat); torch::Tensor videoDuration = torch::zeros({0}, torch::kLong); - if (readVideoStream == 1) { - auto it = decoderOutput.media_data_.find(TYPE_VIDEO); - if (it != decoderOutput.media_data_.end()) { - int numVideoFrames, outHeight, outWidth, numChannels; - getVideoMeta( - decoderOutput, numVideoFrames, outHeight, outWidth, numChannels); - + if (succeeded && readVideoStream == 1) { + if (!videoMessages.empty()) { + const auto& header = videoMessages[0].header; + const auto& media = header.format; + const auto& format = media.format.video; + int numVideoFrames = videoMessages.size(); + int outHeight = format.height; + int outWidth = format.width; + int numChannels = 3; // decoder guarantees the default AV_PIX_FMT_RGB24 + + size_t expectedWrittenBytes = 0; if (getPtsOnly == 0) { videoFrame = torch::zeros( {numVideoFrames, outHeight, outWidth, numChannels}, torch::kByte); + expectedWrittenBytes = + numVideoFrames * outHeight * outWidth * numChannels; } videoFramePts = torch::zeros({numVideoFrames}, torch::kLong); - fillVideoTensor( - decoderOutput.media_data_[TYPE_VIDEO].frames_, - videoFrame, - videoFramePts); + VLOG(2) << "video duration: " << media.duration << ", fps: " << header.fps + << ", num: " << media.num << ", den: " << media.den + << ", num frames: " << numVideoFrames; + + auto numberWrittenBytes = fillVideoTensor( + videoMessages, videoFrame, videoFramePts, media.num, media.den); + + CHECK_EQ(numberWrittenBytes, expectedWrittenBytes); videoTimeBase = torch::zeros({2}, torch::kInt); int* videoTimeBaseData = videoTimeBase.data_ptr(); - videoTimeBaseData[0] = it->second.format_.video.timeBaseNum; - videoTimeBaseData[1] = it->second.format_.video.timeBaseDen; + videoTimeBaseData[0] = media.num; + videoTimeBaseData[1] = media.den; videoFps = torch::zeros({1}, torch::kFloat); float* videoFpsData = videoFps.data_ptr(); - videoFpsData[0] = it->second.format_.video.fps; + videoFpsData[0] = header.fps; videoDuration = torch::zeros({1}, torch::kLong); int64_t* videoDurationData = videoDuration.data_ptr(); - videoDurationData[0] = it->second.format_.video.duration; + AVRational avr = {(int)media.num, (int)media.den}; + videoDurationData[0] = av_rescale_q(media.duration, AV_TIME_BASE_Q, avr); + VLOG(1) << "Video decoding from " << logType << " [" << logMessage + << "] filled video tensors"; } else { VLOG(1) << "Miss video stream"; } @@ -246,39 +340,58 @@ torch::List readVideo( torch::Tensor audioTimeBase = torch::zeros({0}, torch::kInt); torch::Tensor audioSampleRate = torch::zeros({0}, torch::kInt); torch::Tensor audioDuration = torch::zeros({0}, torch::kLong); - if (readAudioStream == 1) { - auto it = decoderOutput.media_data_.find(TYPE_AUDIO); - if (it != decoderOutput.media_data_.end()) { - VLOG(1) << "Find audio stream"; - int64_t numAudioSamples = 0, outAudioChannels = 0, numAudioFrames = 0; - getAudioMeta( - decoderOutput, numAudioSamples, outAudioChannels, numAudioFrames); - VLOG(2) << "numAudioSamples: " << numAudioSamples; - VLOG(2) << "outAudioChannels: " << outAudioChannels; - VLOG(2) << "numAudioFrames: " << numAudioFrames; - + if (succeeded && readAudioStream == 1) { + if (!audioMessages.empty()) { + const auto& header = audioMessages[0].header; + const auto& media = header.format; + const auto& format = media.format.audio; + + int64_t outAudioChannels = format.channels; + int bytesPerSample = + av_get_bytes_per_sample(static_cast(format.format)); + + int numAudioFrames = audioMessages.size(); + int64_t numAudioSamples = 0; if (getPtsOnly == 0) { + int64_t frameSizeTotal = 0; + for (auto const& audioMessage : audioMessages) { + frameSizeTotal += audioMessage.payload->length(); + } + + CHECK_EQ(frameSizeTotal % (outAudioChannels * bytesPerSample), 0); + numAudioSamples = frameSizeTotal / (outAudioChannels * bytesPerSample); + audioFrame = torch::zeros({numAudioSamples, outAudioChannels}, torch::kFloat); } audioFramePts = torch::zeros({numAudioFrames}, torch::kLong); - fillAudioTensor( - decoderOutput.media_data_[TYPE_AUDIO].frames_, - audioFrame, - audioFramePts); + + VLOG(2) << "audio duration: " << media.duration + << ", channels: " << format.channels + << ", sample rate: " << format.samples << ", num: " << media.num + << ", den: " << media.den; + + auto numberWrittenBytes = fillAudioTensor( + audioMessages, audioFrame, audioFramePts, media.num, media.den); + CHECK_EQ( + numberWrittenBytes, + numAudioSamples * outAudioChannels * sizeof(float)); audioTimeBase = torch::zeros({2}, torch::kInt); int* audioTimeBaseData = audioTimeBase.data_ptr(); - audioTimeBaseData[0] = it->second.format_.audio.timeBaseNum; - audioTimeBaseData[1] = it->second.format_.audio.timeBaseDen; + audioTimeBaseData[0] = media.num; + audioTimeBaseData[1] = media.den; audioSampleRate = torch::zeros({1}, torch::kInt); int* audioSampleRateData = audioSampleRate.data_ptr(); - audioSampleRateData[0] = it->second.format_.audio.samples; + audioSampleRateData[0] = format.samples; audioDuration = torch::zeros({1}, torch::kLong); int64_t* audioDurationData = audioDuration.data_ptr(); - audioDurationData[0] = it->second.format_.audio.duration; + AVRational avr = {(int)media.num, (int)media.den}; + audioDurationData[0] = av_rescale_q(media.duration, AV_TIME_BASE_Q, avr); + VLOG(1) << "Video decoding from " << logType << " [" << logMessage + << "] filled audio tensors"; } else { VLOG(1) << "Miss audio stream"; } @@ -296,6 +409,9 @@ torch::List readVideo( result.push_back(std::move(audioSampleRate)); result.push_back(std::move(audioDuration)); + VLOG(1) << "Video decoding from " << logType << " [" << logMessage + << "] about to return"; + return result; } @@ -388,59 +504,101 @@ torch::List probeVideo( bool isReadFile, const torch::Tensor& input_video, std::string videoPath) { - unique_ptr params = util::getDecoderParams( + DecoderParameters params = getDecoderParams( + 0, // videoStartUs + -1, // videoEndUs 0, // seekFrameMargin - 0, // getPtsOnly + 1, // getPtsOnly 1, // readVideoStream 0, // width 0, // height 0, // minDimension - 0, // videoStartPts - 0, // videoEndPts - 0, // videoTimeBaseNum - 1, // videoTimeBaseDen 1, // readAudioStream 0, // audioSamples - 0, // audioChannels - 0, // audioStartPts - 0, // audioEndPts - 0, // audioTimeBaseNum - 1 // audioTimeBaseDen + 0 // audioChannels ); - FfmpegDecoder decoder; - DecoderOutput decoderOutput; + SyncDecoder decoder; + DecoderOutputMessage audioMessage, videoMessage; + DecoderInCallback callback = nullptr; + std::string logMessage, logType; if (isReadFile) { - decoder.probeFile(std::move(params), videoPath, decoderOutput); + params.uri = videoPath; + logType = "file"; + logMessage = videoPath; + } else { + callback = MemoryBuffer::getCallback( + input_video.data_ptr(), input_video.size(0)); + logType = "memory"; + logMessage = std::to_string(input_video.size(0)); + } + + VLOG(1) << "Video probing from " << logType << " [" << logMessage + << "] has started"; + + const auto now = std::chrono::system_clock::now(); + + bool succeeded; + bool gotAudio = false, gotVideo = false; + if ((succeeded = decoder.init(params, std::move(callback)))) { + int res; + DecoderOutputMessage msg; + while (0 == (res = decoder.decode(&msg, decoderTimeoutMs)) && + (!gotAudio || !gotVideo)) { + if (msg.header.format.type == TYPE_VIDEO && !gotVideo) { + videoMessage = std::move(msg); + gotVideo = true; + } + if (msg.header.format.type == TYPE_AUDIO && !gotAudio) { + audioMessage = std::move(msg); + gotAudio = true; + } + msg.payload.reset(); + } + succeeded = (res == 0 || res == ENODATA); + + const auto then = std::chrono::system_clock::now(); + VLOG(1) << "Video probing from " << logType << " [" << logMessage + << "] has finished, " + << std::chrono::duration_cast(then - now) + .count() + << " us"; } else { - decoder.probeMemory( - std::move(params), - input_video.data_ptr(), - input_video.size(0), - decoderOutput); + LOG(ERROR) << "Decoder initialization has failed"; } + + decoder.shutdown(); + // video section torch::Tensor videoTimeBase = torch::zeros({0}, torch::kInt); torch::Tensor videoFps = torch::zeros({0}, torch::kFloat); torch::Tensor videoDuration = torch::zeros({0}, torch::kLong); - auto it = decoderOutput.media_data_.find(TYPE_VIDEO); - if (it != decoderOutput.media_data_.end()) { - VLOG(1) << "Find video stream"; + if (succeeded && gotVideo) { videoTimeBase = torch::zeros({2}, torch::kInt); int* videoTimeBaseData = videoTimeBase.data_ptr(); - videoTimeBaseData[0] = it->second.format_.video.timeBaseNum; - videoTimeBaseData[1] = it->second.format_.video.timeBaseDen; + const auto& header = videoMessage.header; + const auto& media = header.format; + + videoTimeBaseData[0] = media.num; + videoTimeBaseData[1] = media.den; videoFps = torch::zeros({1}, torch::kFloat); float* videoFpsData = videoFps.data_ptr(); - videoFpsData[0] = it->second.format_.video.fps; + videoFpsData[0] = header.fps; videoDuration = torch::zeros({1}, torch::kLong); int64_t* videoDurationData = videoDuration.data_ptr(); - videoDurationData[0] = it->second.format_.video.duration; + AVRational avr = {(int)media.num, (int)media.den}; + videoDurationData[0] = av_rescale_q(media.duration, AV_TIME_BASE_Q, avr); + + VLOG(2) << "Prob fps: " << header.fps << ", duration: " << media.duration + << ", num: " << media.num << ", den: " << media.den; + + VLOG(1) << "Video probing from " << logType << " [" << logMessage + << "] filled video tensors"; } else { - VLOG(1) << "Miss video stream"; + LOG(ERROR) << "Miss video stream"; } // audio section @@ -448,21 +606,31 @@ torch::List probeVideo( torch::Tensor audioSampleRate = torch::zeros({0}, torch::kInt); torch::Tensor audioDuration = torch::zeros({0}, torch::kLong); - it = decoderOutput.media_data_.find(TYPE_AUDIO); - if (it != decoderOutput.media_data_.end()) { - VLOG(1) << "Find audio stream"; + if (succeeded && gotAudio) { audioTimeBase = torch::zeros({2}, torch::kInt); int* audioTimeBaseData = audioTimeBase.data_ptr(); - audioTimeBaseData[0] = it->second.format_.audio.timeBaseNum; - audioTimeBaseData[1] = it->second.format_.audio.timeBaseDen; + const auto& header = audioMessage.header; + const auto& media = header.format; + const auto& format = media.format.audio; + + audioTimeBaseData[0] = media.num; + audioTimeBaseData[1] = media.den; audioSampleRate = torch::zeros({1}, torch::kInt); int* audioSampleRateData = audioSampleRate.data_ptr(); - audioSampleRateData[0] = it->second.format_.audio.samples; + audioSampleRateData[0] = format.samples; audioDuration = torch::zeros({1}, torch::kLong); int64_t* audioDurationData = audioDuration.data_ptr(); - audioDurationData[0] = it->second.format_.audio.duration; + AVRational avr = {(int)media.num, (int)media.den}; + audioDurationData[0] = av_rescale_q(media.duration, AV_TIME_BASE_Q, avr); + + VLOG(2) << "Prob sample rate: " << format.samples + << ", duration: " << media.duration << ", num: " << media.num + << ", den: " << media.den; + + VLOG(1) << "Video probing from " << logType << " [" << logMessage + << "] filled audio tensors"; } else { VLOG(1) << "Miss audio stream"; } @@ -475,6 +643,9 @@ torch::List probeVideo( result.push_back(std::move(audioSampleRate)); result.push_back(std::move(audioDuration)); + VLOG(1) << "Video probing from " << logType << " [" << logMessage + << "] is about to return"; + return result; } diff --git a/torchvision/csrc/cpu/video_reader/VideoReader.h b/torchvision/csrc/cpu/video_reader/VideoReader.h index efc2e4709a6..923a3190977 100644 --- a/torchvision/csrc/cpu/video_reader/VideoReader.h +++ b/torchvision/csrc/cpu/video_reader/VideoReader.h @@ -1,99 +1,3 @@ #pragma once #include - -// Interface for Python - -/* - return: - videoFrame: tensor (N, H, W, C) kByte - videoFramePts: tensor (N) kLong - videoTimeBase: tensor (2) kInt - videoFps: tensor (1) kFloat - audioFrame: tensor (N, C) kFloat - audioFramePts: tensor (N) kLong - audioTimeBase: tensor (2) kInt - audioSampleRate: tensor (1) kInt -*/ -torch::List readVideoFromMemory( - // 1D tensor of data type uint8, storing the comparessed video data - torch::Tensor input_video, - // seeking frame in the video/audio stream is imprecise so seek to a - // timestamp earlier by a margin The unit of margin is second - double seekFrameMargin, - // If only pts is needed and video/audio frames are not needed, set it - // to 1 - int64_t getPtsOnly, - // bool variable. Set it to 1 if video stream should be read. Otherwise, set - // it to 0 - int64_t readVideoStream, - /* - Valid parameters values for rescaling video frames - ___________________________________________________ - | width | height | min_dimension | algorithm | - |_________________________________________________| - | 0 | 0 | 0 | original | - |_________________________________________________| - | 0 | 0 | >0 |scale to min dimension| - |_____|_____|____________________________________ | - | >0 | 0 | 0 | scale keeping W | - |_________________________________________________| - | 0 | >0 | 0 | scale keeping H | - |_________________________________________________| - | >0 | >0 | 0 | stretch/scale | - |_________________________________________________| - */ - int64_t width, - int64_t height, - int64_t minDimension, - // video frames with pts in [videoStartPts, videoEndPts] will be decoded - // For decoding all video frames, use [0, -1] - int64_t videoStartPts, - int64_t videoEndPts, - // numerator and denominator of time base of video stream. - // For decoding all video frames, supply dummy 0 (numerator) and 1 - // (denominator). For decoding localized video frames, need to supply - // them which will be checked during decoding - int64_t videoTimeBaseNum, - int64_t videoTimeBaseDen, - // bool variable. Set it to 1 if audio stream should be read. Otherwise, set - // it to 0 - int64_t readAudioStream, - // audio stream sampling rate. - // If not resampling audio waveform, supply 0 - // Otherwise, supply a positive integer. - int64_t audioSamples, - // audio stream channels - // Supply 0 to use the same number of channels as in the original audio - // stream - int64_t audioChannels, - // audio frames with pts in [audioStartPts, audioEndPts] will be decoded - // For decoding all audio frames, use [0, -1] - int64_t audioStartPts, - int64_t audioEndPts, - // numerator and denominator of time base of audio stream. - // For decoding all audio frames, supply dummy 0 (numerator) and 1 - // (denominator). For decoding localized audio frames, need to supply - // them which will be checked during decoding - int64_t audioTimeBaseNum, - int64_t audioTimeBaseDen); - -torch::List readVideoFromFile( - std::string videoPath, - double seekFrameMargin, - int64_t getPtsOnly, - int64_t readVideoStream, - int64_t width, - int64_t height, - int64_t minDimension, - int64_t videoStartPts, - int64_t videoEndPts, - int64_t videoTimeBaseNum, - int64_t videoTimeBaseDen, - int64_t readAudioStream, - int64_t audioSamples, - int64_t audioChannels, - int64_t audioStartPts, - int64_t audioEndPts, - int64_t audioTimeBaseNum, - int64_t audioTimeBaseDen); diff --git a/torchvision/csrc/cpu/video_reader/util.cpp b/torchvision/csrc/cpu/video_reader/util.cpp deleted file mode 100644 index ae3c3df0f0a..00000000000 --- a/torchvision/csrc/cpu/video_reader/util.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "util.h" - -using namespace std; - -namespace util { - -unique_ptr getDecoderParams( - double seekFrameMargin, - int64_t getPtsOnly, - int64_t readVideoStream, - int videoWidth, - int videoHeight, - int videoMinDimension, - int64_t videoStartPts, - int64_t videoEndPts, - int videoTimeBaseNum, - int videoTimeBaseDen, - int64_t readAudioStream, - int audioSamples, - int audioChannels, - int64_t audioStartPts, - int64_t audioEndPts, - int audioTimeBaseNum, - int audioTimeBaseDen) { - unique_ptr params = make_unique(); - - if (readVideoStream == 1) { - params->formats.emplace( - MediaType::TYPE_VIDEO, MediaFormat(MediaType::TYPE_VIDEO)); - MediaFormat& videoFormat = params->formats[MediaType::TYPE_VIDEO]; - - videoFormat.format.video.width = videoWidth; - videoFormat.format.video.height = videoHeight; - videoFormat.format.video.minDimension = videoMinDimension; - videoFormat.format.video.startPts = videoStartPts; - videoFormat.format.video.endPts = videoEndPts; - videoFormat.format.video.timeBaseNum = videoTimeBaseNum; - videoFormat.format.video.timeBaseDen = videoTimeBaseDen; - } - - if (readAudioStream == 1) { - params->formats.emplace( - MediaType::TYPE_AUDIO, MediaFormat(MediaType::TYPE_AUDIO)); - MediaFormat& audioFormat = params->formats[MediaType::TYPE_AUDIO]; - - audioFormat.format.audio.samples = audioSamples; - audioFormat.format.audio.channels = audioChannels; - audioFormat.format.audio.startPts = audioStartPts; - audioFormat.format.audio.endPts = audioEndPts; - audioFormat.format.audio.timeBaseNum = audioTimeBaseNum; - audioFormat.format.audio.timeBaseDen = audioTimeBaseDen; - } - - params->seekFrameMargin = seekFrameMargin; - params->getPtsOnly = getPtsOnly; - - return params; -} - -} // namespace util diff --git a/torchvision/csrc/cpu/video_reader/util.h b/torchvision/csrc/cpu/video_reader/util.h deleted file mode 100644 index 6b5fd55388b..00000000000 --- a/torchvision/csrc/cpu/video_reader/util.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include "FfmpegDecoder.h" - -namespace util { - -std::unique_ptr getDecoderParams( - double seekFrameMargin, - int64_t getPtsOnly, - int64_t readVideoStream, - int videoWidth, - int videoHeight, - int videoMinDimension, - int64_t videoStartPts, - int64_t videoEndPts, - int videoTimeBaseNum, - int videoTimeBaseDen, - int64_t readAudioStream, - int audioSamples, - int audioChannels, - int64_t audioStartPts, - int64_t audioEndPts, - int audioTimeBaseNum, - int audioTimeBaseDen); - -} // namespace util From 64e52a11082a27ba0a46ed3bc5b99a40895fa571 Mon Sep 17 00:00:00 2001 From: Yuri Putivsky Date: Sat, 8 Feb 2020 18:15:45 -0800 Subject: [PATCH 049/357] Optimizating base decoder performance. (#1852) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1852 Changed base decoder internals for a faster clip processing. Reviewed By: stephenyan1231 Differential Revision: D19748379 fbshipit-source-id: 58a435f0a0b25545e7bd1a3edb0b1d558176a806 --- .../csrc/cpu/decoder/audio_sampler.cpp | 142 +++++--- torchvision/csrc/cpu/decoder/audio_sampler.h | 1 - torchvision/csrc/cpu/decoder/audio_stream.cpp | 19 +- torchvision/csrc/cpu/decoder/audio_stream.h | 3 - torchvision/csrc/cpu/decoder/cc_stream.cpp | 12 +- torchvision/csrc/cpu/decoder/cc_stream.h | 2 +- torchvision/csrc/cpu/decoder/decoder.cpp | 34 +- torchvision/csrc/cpu/decoder/decoder.h | 18 +- torchvision/csrc/cpu/decoder/defs.h | 31 +- .../csrc/cpu/decoder/seekable_buffer.cpp | 2 +- torchvision/csrc/cpu/decoder/stream.cpp | 81 ++--- torchvision/csrc/cpu/decoder/stream.h | 8 +- .../csrc/cpu/decoder/subtitle_sampler.cpp | 16 +- .../csrc/cpu/decoder/subtitle_sampler.h | 1 - .../csrc/cpu/decoder/subtitle_stream.cpp | 41 +-- .../csrc/cpu/decoder/subtitle_stream.h | 1 - torchvision/csrc/cpu/decoder/sync_decoder.cpp | 22 +- torchvision/csrc/cpu/decoder/sync_decoder.h | 7 +- .../csrc/cpu/decoder/sync_decoder_test.cpp | 321 ++++++++++++++++-- .../csrc/cpu/decoder/video_sampler.cpp | 28 +- torchvision/csrc/cpu/decoder/video_sampler.h | 3 +- torchvision/csrc/cpu/decoder/video_stream.cpp | 17 +- torchvision/csrc/cpu/decoder/video_stream.h | 3 - .../csrc/cpu/video_reader/VideoReader.cpp | 116 +++---- 24 files changed, 599 insertions(+), 330 deletions(-) diff --git a/torchvision/csrc/cpu/decoder/audio_sampler.cpp b/torchvision/csrc/cpu/decoder/audio_sampler.cpp index 4092df98359..421e503b2ce 100644 --- a/torchvision/csrc/cpu/decoder/audio_sampler.cpp +++ b/torchvision/csrc/cpu/decoder/audio_sampler.cpp @@ -81,20 +81,7 @@ bool AudioSampler::init(const SamplerParameters& params) { } int AudioSampler::numOutputSamples(int inSamples) const { - return av_rescale_rnd( - swr_get_delay(swrContext_, params_.in.audio.samples) + inSamples, - params_.out.audio.samples, - params_.in.audio.samples, - AV_ROUND_UP); -} - -int AudioSampler::getSamplesBytes(AVFrame* frame) const { - return av_samples_get_buffer_size( - nullptr, - params_.out.audio.channels, - numOutputSamples(frame ? frame->nb_samples : 0), - (AVSampleFormat)params_.out.audio.format, - 1); + return swr_get_out_samples(swrContext_, inSamples); } int AudioSampler::sample( @@ -102,32 +89,95 @@ int AudioSampler::sample( int inNumSamples, ByteStorage* out, int outNumSamples) { - uint8_t* outPlanes[AVRESAMPLE_MAX_CHANNELS] = {nullptr}; int result; - if ((result = preparePlanes( - params_.out.audio, out->writableTail(), outNumSamples, outPlanes)) < - 0) { - return result; - } + int outBufferBytes = av_samples_get_buffer_size( + nullptr, + params_.out.audio.channels, + outNumSamples, + (AVSampleFormat)params_.out.audio.format, + 1); - if ((result = swr_convert( - swrContext_, &outPlanes[0], outNumSamples, inPlanes, inNumSamples)) < - 0) { - LOG(ERROR) << "swr_convert faield, err: " - << Util::generateErrorDesc(result); - return result; + if (out) { + out->ensure(outBufferBytes); + + uint8_t* outPlanes[AVRESAMPLE_MAX_CHANNELS] = {nullptr}; + + if ((result = preparePlanes( + params_.out.audio, + out->writableTail(), + outNumSamples, + outPlanes)) < 0) { + return result; + } + + if ((result = swr_convert( + swrContext_, + &outPlanes[0], + outNumSamples, + inPlanes, + inNumSamples)) < 0) { + LOG(ERROR) << "swr_convert faield, err: " + << Util::generateErrorDesc(result); + return result; + } + + CHECK_LE(result, outNumSamples); + + if (result) { + if ((result = av_samples_get_buffer_size( + nullptr, + params_.out.audio.channels, + result, + (AVSampleFormat)params_.out.audio.format, + 1)) >= 0) { + out->append(result); + } else { + LOG(ERROR) << "av_samples_get_buffer_size faield, err: " + << Util::generateErrorDesc(result); + } + } + } else { + // allocate a temporary buffer + auto* tmpBuffer = static_cast(av_malloc(outBufferBytes)); + if (!tmpBuffer) { + LOG(ERROR) << "av_alloc faield, for size: " << outBufferBytes; + return -1; + } + + uint8_t* outPlanes[AVRESAMPLE_MAX_CHANNELS] = {nullptr}; + + if ((result = preparePlanes( + params_.out.audio, tmpBuffer, outNumSamples, outPlanes)) < 0) { + av_free(tmpBuffer); + return result; + } + + if ((result = swr_convert( + swrContext_, + &outPlanes[0], + outNumSamples, + inPlanes, + inNumSamples)) < 0) { + LOG(ERROR) << "swr_convert faield, err: " + << Util::generateErrorDesc(result); + av_free(tmpBuffer); + return result; + } + + av_free(tmpBuffer); + + CHECK_LE(result, outNumSamples); + + if (result) { + result = av_samples_get_buffer_size( + nullptr, + params_.out.audio.channels, + result, + (AVSampleFormat)params_.out.audio.format, + 1); + } } - CHECK_LE(result, outNumSamples); - - if ((result = av_samples_get_buffer_size( - nullptr, - params_.out.audio.channels, - result, - (AVSampleFormat)params_.out.audio.format, - 1)) > 0) { - out->append(result); - } return result; } @@ -138,16 +188,6 @@ int AudioSampler::sample(AVFrame* frame, ByteStorage* out) { return 0; } - const auto samplesBytes = av_samples_get_buffer_size( - nullptr, - params_.out.audio.channels, - outNumSamples, - (AVSampleFormat)params_.out.audio.format, - 1); - - // bytes must be allocated - CHECK_LE(samplesBytes, out->tail()); - return sample( frame ? (const uint8_t**)&frame->data[0] : nullptr, frame ? frame->nb_samples : 0, @@ -168,16 +208,6 @@ int AudioSampler::sample(const ByteStorage* in, ByteStorage* out) { return 0; } - const auto samplesBytes = av_samples_get_buffer_size( - nullptr, - params_.out.audio.channels, - outNumSamples, - (AVSampleFormat)params_.out.audio.format, - 1); - - out->clear(); - out->ensure(samplesBytes); - uint8_t* inPlanes[AVRESAMPLE_MAX_CHANNELS] = {nullptr}; int result; if (in && diff --git a/torchvision/csrc/cpu/decoder/audio_sampler.h b/torchvision/csrc/cpu/decoder/audio_sampler.h index c6a021d2084..d6d8402d971 100644 --- a/torchvision/csrc/cpu/decoder/audio_sampler.h +++ b/torchvision/csrc/cpu/decoder/audio_sampler.h @@ -22,7 +22,6 @@ class AudioSampler : public MediaSampler { int sample(const ByteStorage* in, ByteStorage* out) override; void shutdown() override; - int getSamplesBytes(AVFrame* frame) const; int sample(AVFrame* frame, ByteStorage* out); private: diff --git a/torchvision/csrc/cpu/decoder/audio_stream.cpp b/torchvision/csrc/cpu/decoder/audio_stream.cpp index ed4d6622ecd..513128a66ac 100644 --- a/torchvision/csrc/cpu/decoder/audio_stream.cpp +++ b/torchvision/csrc/cpu/decoder/audio_stream.cpp @@ -49,12 +49,6 @@ AudioStream::~AudioStream() { } } -void AudioStream::ensureSampler() { - if (!sampler_) { - sampler_ = std::make_unique(codecCtx_); - } -} - int AudioStream::initFormat() { // set output format if (format_.format.audio.samples == 0) { @@ -74,8 +68,10 @@ int AudioStream::initFormat() { : -1; } -int AudioStream::estimateBytes(bool flush) { - ensureSampler(); +int AudioStream::copyFrameBytes(ByteStorage* out, bool flush) { + if (!sampler_) { + sampler_ = std::make_unique(codecCtx_); + } // check if input format gets changed if (flush ? !(sampler_->getInputFormat().audio == *codecCtx_) : !(sampler_->getInputFormat().audio == *frame_)) { @@ -85,7 +81,7 @@ int AudioStream::estimateBytes(bool flush) { params.out = format_.format; flush ? toAudioFormat(params.in.audio, *codecCtx_) : toAudioFormat(params.in.audio, *frame_); - if (flush || !sampler_->init(params)) { + if (!sampler_->init(params)) { return -1; } @@ -98,11 +94,6 @@ int AudioStream::estimateBytes(bool flush) { << ", channels: " << format_.format.audio.channels << ", format: " << format_.format.audio.format; } - return sampler_->getSamplesBytes(flush ? nullptr : frame_); -} - -int AudioStream::copyFrameBytes(ByteStorage* out, bool flush) { - ensureSampler(); return sampler_->sample(flush ? nullptr : frame_, out); } diff --git a/torchvision/csrc/cpu/decoder/audio_stream.h b/torchvision/csrc/cpu/decoder/audio_stream.h index 4d200114e4a..2d6457b68f5 100644 --- a/torchvision/csrc/cpu/decoder/audio_stream.h +++ b/torchvision/csrc/cpu/decoder/audio_stream.h @@ -20,11 +20,8 @@ class AudioStream : public Stream { private: int initFormat() override; - int estimateBytes(bool flush) override; int copyFrameBytes(ByteStorage* out, bool flush) override; - void ensureSampler(); - private: std::unique_ptr sampler_; }; diff --git a/torchvision/csrc/cpu/decoder/cc_stream.cpp b/torchvision/csrc/cpu/decoder/cc_stream.cpp index 7b443146289..89174c396fd 100644 --- a/torchvision/csrc/cpu/decoder/cc_stream.cpp +++ b/torchvision/csrc/cpu/decoder/cc_stream.cpp @@ -11,14 +11,14 @@ CCStream::CCStream( format_.type = TYPE_CC; } -AVCodec* CCStream::findCodec(AVCodecContext* ctx) { - if (ctx->codec_id == AV_CODEC_ID_BIN_DATA && - ctx->codec_type == AVMEDIA_TYPE_DATA) { +AVCodec* CCStream::findCodec(AVCodecParameters* params) { + if (params->codec_id == AV_CODEC_ID_BIN_DATA && + params->codec_type == AVMEDIA_TYPE_DATA) { // obtain subtitles codec - ctx->codec_id = AV_CODEC_ID_MOV_TEXT; - ctx->codec_type = AVMEDIA_TYPE_SUBTITLE; + params->codec_id = AV_CODEC_ID_MOV_TEXT; + params->codec_type = AVMEDIA_TYPE_SUBTITLE; } - return Stream::findCodec(ctx); + return Stream::findCodec(params); } } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/cc_stream.h b/torchvision/csrc/cpu/decoder/cc_stream.h index d8c98f7be23..3a1d169f014 100644 --- a/torchvision/csrc/cpu/decoder/cc_stream.h +++ b/torchvision/csrc/cpu/decoder/cc_stream.h @@ -16,7 +16,7 @@ class CCStream : public SubtitleStream { const SubtitleFormat& format); private: - AVCodec* findCodec(AVCodecContext* ctx) override; + AVCodec* findCodec(AVCodecParameters* params) override; }; } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/decoder/decoder.cpp b/torchvision/csrc/cpu/decoder/decoder.cpp index b78c1e47214..e9d1acaa3e0 100644 --- a/torchvision/csrc/cpu/decoder/decoder.cpp +++ b/torchvision/csrc/cpu/decoder/decoder.cpp @@ -210,7 +210,14 @@ Decoder::Decoder() { initOnce(); } -bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { +Decoder::~Decoder() { + cleanUp(); +} + +bool Decoder::init( + const DecoderParameters& params, + DecoderInCallback&& in, + std::vector* metadata) { cleanUp(); if ((params.uri.empty() || in) && (!params.uri.empty() || !in)) { @@ -351,7 +358,7 @@ bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { return false; } - if (!openStreams()) { + if (!openStreams(metadata)) { LOG(ERROR) << "Cannot activate streams"; cleanUp(); return false; @@ -371,7 +378,7 @@ bool Decoder::init(const DecoderParameters& params, DecoderInCallback&& in) { return true; } -bool Decoder::openStreams() { +bool Decoder::openStreams(std::vector* metadata) { for (int i = 0; i < inputCtx_->nb_streams; i++) { // - find the corespondent format at params_.formats set MediaFormat format; @@ -407,7 +414,7 @@ bool Decoder::openStreams() { it->format, params_.loggingUuid); CHECK(stream); - if (stream->openCodec() < 0) { + if (stream->openCodec(metadata) < 0) { LOG(ERROR) << "Cannot open codec " << i; return false; } @@ -436,8 +443,7 @@ void Decoder::cleanUp() { for (auto& stream : streams_) { // Drain stream buffers. DecoderOutputMessage msg; - while (msg.payload = createByteStorage(0), - stream.second->flush(&msg, params_.headerOnly) > 0) { + while (msg.payload = nullptr, stream.second->flush(&msg, true) > 0) { } stream.second.reset(); } @@ -580,17 +586,19 @@ Stream* Decoder::findByType(const MediaFormat& format) const { return nullptr; } -int Decoder::processPacket(Stream* stream, - AVPacket* packet, - bool* gotFrame, - bool* hasMsg) { +int Decoder::processPacket( + Stream* stream, + AVPacket* packet, + bool* gotFrame, + bool* hasMsg) { // decode package int result; DecoderOutputMessage msg; - msg.payload = createByteStorage(0); + msg.payload = params_.headerOnly ? nullptr : createByteStorage(0); *hasMsg = false; if ((result = stream->decodePacket( - packet, &msg, params_.headerOnly, gotFrame)) >= 0 && *gotFrame) { + packet, &msg, params_.headerOnly, gotFrame)) >= 0 && + *gotFrame) { // check end offset bool endInRange = params_.endOffset <= 0 || msg.header.pts <= params_.endOffset; @@ -607,7 +615,7 @@ void Decoder::flushStreams() { VLOG(1) << "Flushing streams..."; for (auto& stream : streams_) { DecoderOutputMessage msg; - while (msg.payload = createByteStorage(0), + while (msg.payload = (params_.headerOnly ? nullptr : createByteStorage(0)), stream.second->flush(&msg, params_.headerOnly) > 0) { // check end offset bool endInRange = diff --git a/torchvision/csrc/cpu/decoder/decoder.h b/torchvision/csrc/cpu/decoder/decoder.h index 11894fabb74..dce42cfb59a 100644 --- a/torchvision/csrc/cpu/decoder/decoder.h +++ b/torchvision/csrc/cpu/decoder/decoder.h @@ -15,9 +15,13 @@ namespace ffmpeg { class Decoder : public MediaDecoder { public: Decoder(); + ~Decoder() override; // MediaDecoder overrides - bool init(const DecoderParameters& params, DecoderInCallback&& in) override; + bool init( + const DecoderParameters& params, + DecoderInCallback&& in, + std::vector* metadata) override; int decode_all(const DecoderOutCallback& callback) override; void shutdown() override; void interrupt() override; @@ -56,15 +60,17 @@ class Decoder : public MediaDecoder { virtual int64_t seekCallback(int64_t offset, int whence); virtual int shutdownCallback(); - bool openStreams(); + bool openStreams(std::vector* metadata); Stream* findByIndex(int streamIndex) const; Stream* findByType(const MediaFormat& format) const; - int processPacket(Stream* stream, - AVPacket* packet, - bool* gotFrame, - bool* hasMsg); + int processPacket( + Stream* stream, + AVPacket* packet, + bool* gotFrame, + bool* hasMsg); void flushStreams(); void cleanUp(); + private: DecoderParameters params_; SeekableBuffer seekableBuffer_; diff --git a/torchvision/csrc/cpu/decoder/defs.h b/torchvision/csrc/cpu/decoder/defs.h index 2e282bb59c6..bc9ca31a810 100644 --- a/torchvision/csrc/cpu/decoder/defs.h +++ b/torchvision/csrc/cpu/decoder/defs.h @@ -128,14 +128,6 @@ struct MediaFormat { long stream; // union keeps one of the possible formats, defined by MediaType FormatUnion format; - - // output parameters, ignored while initialization - // time base numerator - long num{0}; - // time base denominator - long den{1}; - // duration of the stream, in miscroseconds, if available - long duration{-1}; }; struct DecoderParameters { @@ -172,6 +164,12 @@ struct DecoderParameters { double seekAccuracy{1000000.0}; // what media types should be processed, default none std::set formats; + + // can be used for asynchronous decoders + size_t cacheSize{8192}; // mow many bytes to cache before stop reading bytes + size_t cacheTimeoutMs{1000}; // timeout on bytes writing + bool enforceCacheSize{false}; // drop output frames if cache is full + bool mergeAudioMessages{false}; // combine collocated audio messages together }; struct DecoderHeader { @@ -240,6 +238,18 @@ using DecoderInCallback = using DecoderOutCallback = std::function; +struct DecoderMetadata { + // time base numerator + long num{0}; + // time base denominator + long den{1}; + // duration of the stream, in miscroseconds, if available + long duration{-1}; + // frames per second, valid only for video streams + double fps{0}; + // format specifies what kind frame is in a payload + MediaFormat format; +}; /** * Abstract class for decoding media bytes * It has two diffrent modes. Internal media bytes retrieval for given uri and @@ -255,10 +265,13 @@ class MediaDecoder { * Media bytes get fetched internally from provided URI * or invokes provided input callback to get media bytes. * Input callback must be empty for the internal media provider + * Caller can provide non-null pointer for the input container + * if headers to obtain the streams metadata (optional) */ virtual bool init( const DecoderParameters& params, - DecoderInCallback&& in) = 0; + DecoderInCallback&& in, + std::vector* metadata) = 0; /** * Polls available decoded one frame from decoder diff --git a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp index 2e6732a2f50..26da3e5d7c1 100644 --- a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp +++ b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp @@ -34,7 +34,7 @@ int SeekableBuffer::init( return 1; } - if (!readBytes(in, maxSeekableBytes, timeoutMs)) { + if (!readBytes(in, maxSeekableBytes + (type ? 8 : 0), timeoutMs)) { return -1; } diff --git a/torchvision/csrc/cpu/decoder/stream.cpp b/torchvision/csrc/cpu/decoder/stream.cpp index ce13ca05a83..ec508639e7a 100644 --- a/torchvision/csrc/cpu/decoder/stream.cpp +++ b/torchvision/csrc/cpu/decoder/stream.cpp @@ -23,18 +23,18 @@ Stream::~Stream() { } } -AVCodec* Stream::findCodec(AVCodecContext* ctx) { - return avcodec_find_decoder(ctx->codec_id); +AVCodec* Stream::findCodec(AVCodecParameters* params) { + return avcodec_find_decoder(params->codec_id); } -int Stream::openCodec() { +int Stream::openCodec(std::vector* metadata) { AVStream* steam = inputCtx_->streams[format_.stream]; - auto codec_id = steam->codecpar->codec_id; - AVCodec* codec = avcodec_find_decoder(codec_id); + + AVCodec* codec = findCodec(steam->codecpar); if (!codec) { LOG(ERROR) << "LoggingUuid #" << loggingUuid_ << ", avcodec_find_decoder failed for codec_id: " - << int(codec_id); + << int(steam->codecpar->codec_id); return AVERROR(EINVAL); } @@ -63,14 +63,9 @@ int Stream::openCodec() { frame_ = av_frame_alloc(); - // always convert to us - format_.num = inputCtx_->streams[format_.stream]->time_base.num; - format_.den = inputCtx_->streams[format_.stream]->time_base.den; - switch (format_.type) { case TYPE_VIDEO: - fps_ = av_q2d(av_guess_frame_rate( - inputCtx_, inputCtx_->streams[format_.stream], nullptr)); + fps_ = av_q2d(av_guess_frame_rate(inputCtx_, steam, nullptr)); break; case TYPE_AUDIO: fps_ = codecCtx_->sample_rate; @@ -79,15 +74,21 @@ int Stream::openCodec() { fps_ = 30.0; } - format_.duration = av_rescale_q( - inputCtx_->streams[format_.stream]->duration, - inputCtx_->streams[format_.stream]->time_base, - AV_TIME_BASE_Q); - if ((ret = initFormat())) { LOG(ERROR) << "initFormat failed, type: " << format_.type; } + if (metadata) { + DecoderMetadata header; + header.format = format_; + header.fps = fps_; + header.num = steam->time_base.num; + header.den = steam->time_base.den; + header.duration = + av_rescale_q(steam->duration, steam->time_base, AV_TIME_BASE_Q); + metadata->push_back(header); + } + return ret; } @@ -107,7 +108,7 @@ int Stream::analyzePacket(const AVPacket* packet, bool* gotFrame) { << Util::generateErrorDesc(result); return result; // error } else { - consumed = 1; // all bytes get consumed + consumed = packet ? packet->size : 0; // all bytes get consumed } result = avcodec_receive_frame(codecCtx_, frame_); @@ -169,42 +170,46 @@ int Stream::getMessage(DecoderOutputMessage* out, bool flush, bool headerOnly) { if (flush) { // only flush of audio frames makes sense if (format_.type == TYPE_AUDIO) { - int bytes = 0; - if ((bytes = estimateBytes(true)) < 0) { - return bytes; - } int processed = 0; + size_t total = 0; // grab all audio bytes by chunks do { - out->payload->ensure(out->payload->length() + bytes); - if ((processed = copyFrameBytes(out->payload.get(), true)) < 0) { + if ((processed = copyFrameBytes(out->payload.get(), flush)) < 0) { return processed; } + total += processed; } while (processed); - if (out->payload->length()) { - // set header first + if (total) { + // set header if message bytes are available setHeader(&out->header, flush); return 1; } } return 0; } else { - // set header first - setHeader(&out->header, flush); + if (format_.type == TYPE_AUDIO) { + int processed = 0; + if ((processed = copyFrameBytes(out->payload.get(), flush)) < 0) { + return processed; + } + if (processed) { + // set header if message bytes are available + setHeader(&out->header, flush); + return 1; + } + return 0; + } else { + // set header + setHeader(&out->header, flush); - if (headerOnly) { - // Only header is requisted - return 1; - } + if (headerOnly) { + // Only header is requisted + return 1; + } - // decoded frame is available - int bytes; - if ((bytes = estimateBytes(false)) < 0) { - return bytes; + return copyFrameBytes(out->payload.get(), flush); } - out->payload->ensure(bytes); - return copyFrameBytes(out->payload.get(), false); } } diff --git a/torchvision/csrc/cpu/decoder/stream.h b/torchvision/csrc/cpu/decoder/stream.h index 3473a2a0fd3..6d03f1c2c1e 100644 --- a/torchvision/csrc/cpu/decoder/stream.h +++ b/torchvision/csrc/cpu/decoder/stream.h @@ -26,7 +26,7 @@ class Stream { virtual ~Stream(); // returns 0 - on success or negative error - int openCodec(); + int openCodec(std::vector* metadata); // returns 1 - if packet got consumed, 0 - if it's not, and < 0 on error int decodePacket( const AVPacket* packet, @@ -46,18 +46,16 @@ class Stream { protected: virtual int initFormat() = 0; - // returns 1 - if packet got consumed, 0 - if it's not, and < 0 on error + // returns number processed bytes from packet, or negative error virtual int analyzePacket(const AVPacket* packet, bool* gotFrame); // returns number processed bytes from packet, or negative error virtual int copyFrameBytes(ByteStorage* out, bool flush) = 0; - // estimates bytes in frame, returns output buffer size, or negative error - virtual int estimateBytes(bool flush) = 0; // sets output format virtual void setHeader(DecoderHeader* header, bool flush); // set frame pts virtual void setFramePts(DecoderHeader* header, bool flush); // finds codec - virtual AVCodec* findCodec(AVCodecContext* ctx); + virtual AVCodec* findCodec(AVCodecParameters* params); private: // returns 1 - if message got a payload, 0 - if it's not, and < 0 on error diff --git a/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp b/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp index b89ef8f1b86..d0df24d3e35 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp +++ b/torchvision/csrc/cpu/decoder/subtitle_sampler.cpp @@ -1,4 +1,5 @@ #include "subtitle_sampler.h" +#include #include "util.h" namespace ffmpeg { @@ -18,22 +19,23 @@ bool SubtitleSampler::init(const SamplerParameters& params) { return true; } -int SubtitleSampler::getSamplesBytes(AVSubtitle* sub) const { - return Util::size(*sub); -} - int SubtitleSampler::sample(AVSubtitle* sub, ByteStorage* out) { - if (!sub) { + if (!sub || !out) { return 0; // flush } + out->ensure(Util::size(*sub)); + return Util::serialize(*sub, out); } int SubtitleSampler::sample(const ByteStorage* in, ByteStorage* out) { - if (in) { + if (in && out) { // Get a writable copy - *out = *in; + if (size_t len = in->length()) { + out->ensure(len); + memcpy(out->writableTail(), in->data(), len); + } return out->length(); } return 0; diff --git a/torchvision/csrc/cpu/decoder/subtitle_sampler.h b/torchvision/csrc/cpu/decoder/subtitle_sampler.h index 298e48d591f..fb50b1c4682 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_sampler.h +++ b/torchvision/csrc/cpu/decoder/subtitle_sampler.h @@ -23,7 +23,6 @@ class SubtitleSampler : public MediaSampler { // returns number processed/scaling bytes int sample(AVSubtitle* sub, ByteStorage* out); - int getSamplesBytes(AVSubtitle* sub) const; // helper serialization/deserialization methods static void serialize(const AVSubtitle& sub, ByteStorage* out); diff --git a/torchvision/csrc/cpu/decoder/subtitle_stream.cpp b/torchvision/csrc/cpu/decoder/subtitle_stream.cpp index 4f83fad68f8..87906e78fe4 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_stream.cpp +++ b/torchvision/csrc/cpu/decoder/subtitle_stream.cpp @@ -5,17 +5,6 @@ namespace ffmpeg { -namespace { - -bool operator==(const SubtitleFormat&, const AVCodecContext&) { - return true; -} - -SubtitleFormat& toSubtitleFormat(SubtitleFormat& x, const AVCodecContext&) { - return x; -} -} // namespace - SubtitleStream::SubtitleStream( AVFormatContext* inputCtx, int index, @@ -45,7 +34,7 @@ int SubtitleStream::initFormat() { if (!codecCtx_->subtitle_header) { LOG(ERROR) << "No subtitle header found"; } else { - LOG(INFO) << "Subtitle header found!"; + VLOG(1) << "Subtitle header found!"; } return 0; } @@ -57,35 +46,29 @@ int SubtitleStream::analyzePacket(const AVPacket* packet, bool* gotFrame) { AVPacket avPacket; av_init_packet(&avPacket); avPacket.data = nullptr; + avPacket.size = 0; auto pkt = packet ? *packet : avPacket; int gotFramePtr = 0; int result = avcodec_decode_subtitle2(codecCtx_, &sub_, &gotFramePtr, &pkt); if (result < 0) { - VLOG(1) << "avcodec_decode_subtitle2 failed, err: " - << Util::generateErrorDesc(result); + LOG(ERROR) << "avcodec_decode_subtitle2 failed, err: " + << Util::generateErrorDesc(result); + return result; } else if (result == 0) { - result = packet ? packet->size : 0; // discard the rest of the package + result = pkt.size; // discard the rest of the package } sub_.release = gotFramePtr; *gotFrame = gotFramePtr > 0; - return result; -} - -int SubtitleStream::estimateBytes(bool) { - if (!(sampler_.getInputFormat().subtitle == *codecCtx_)) { - // - reinit sampler - SamplerParameters params; - params.type = MediaType::TYPE_SUBTITLE; - toSubtitleFormat(params.in.subtitle, *codecCtx_); - if (!sampler_.init(params)) { - return -1; - } - VLOG(1) << "Set input subtitle sampler format"; + // set proper pts in us + if (gotFramePtr) { + sub_.pts = av_rescale_q( + pkt.pts, inputCtx_->streams[format_.stream]->time_base, AV_TIME_BASE_Q); } - return sampler_.getSamplesBytes(&sub_); + + return result; } int SubtitleStream::copyFrameBytes(ByteStorage* out, bool flush) { diff --git a/torchvision/csrc/cpu/decoder/subtitle_stream.h b/torchvision/csrc/cpu/decoder/subtitle_stream.h index 4297cfa83f7..6c366e11f50 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_stream.h +++ b/torchvision/csrc/cpu/decoder/subtitle_stream.h @@ -27,7 +27,6 @@ class SubtitleStream : public Stream { private: int initFormat() override; int analyzePacket(const AVPacket* packet, bool* gotFrame) override; - int estimateBytes(bool flush) override; int copyFrameBytes(ByteStorage* out, bool flush) override; void releaseSubtitle(); diff --git a/torchvision/csrc/cpu/decoder/sync_decoder.cpp b/torchvision/csrc/cpu/decoder/sync_decoder.cpp index 5f3c38e08f8..374b40838ea 100644 --- a/torchvision/csrc/cpu/decoder/sync_decoder.cpp +++ b/torchvision/csrc/cpu/decoder/sync_decoder.cpp @@ -3,57 +3,57 @@ namespace ffmpeg { -SyncDecoder::VectorByteStorage::VectorByteStorage(size_t n) { +SyncDecoder::AVByteStorage::AVByteStorage(size_t n) { ensure(n); } -SyncDecoder::VectorByteStorage::~VectorByteStorage() { +SyncDecoder::AVByteStorage::~AVByteStorage() { av_free(buffer_); } -void SyncDecoder::VectorByteStorage::ensure(size_t n) { +void SyncDecoder::AVByteStorage::ensure(size_t n) { if (tail() < n) { capacity_ = offset_ + length_ + n; buffer_ = static_cast(av_realloc(buffer_, capacity_)); } } -uint8_t* SyncDecoder::VectorByteStorage::writableTail() { +uint8_t* SyncDecoder::AVByteStorage::writableTail() { CHECK_LE(offset_ + length_, capacity_); return buffer_ + offset_ + length_; } -void SyncDecoder::VectorByteStorage::append(size_t n) { +void SyncDecoder::AVByteStorage::append(size_t n) { CHECK_LE(n, tail()); length_ += n; } -void SyncDecoder::VectorByteStorage::trim(size_t n) { +void SyncDecoder::AVByteStorage::trim(size_t n) { CHECK_LE(n, length_); offset_ += n; length_ -= n; } -const uint8_t* SyncDecoder::VectorByteStorage::data() const { +const uint8_t* SyncDecoder::AVByteStorage::data() const { return buffer_ + offset_; } -size_t SyncDecoder::VectorByteStorage::length() const { +size_t SyncDecoder::AVByteStorage::length() const { return length_; } -size_t SyncDecoder::VectorByteStorage::tail() const { +size_t SyncDecoder::AVByteStorage::tail() const { CHECK_LE(offset_ + length_, capacity_); return capacity_ - offset_ - length_; } -void SyncDecoder::VectorByteStorage::clear() { +void SyncDecoder::AVByteStorage::clear() { offset_ = 0; length_ = 0; } std::unique_ptr SyncDecoder::createByteStorage(size_t n) { - return std::make_unique(n); + return std::make_unique(n); } void SyncDecoder::onInit() { diff --git a/torchvision/csrc/cpu/decoder/sync_decoder.h b/torchvision/csrc/cpu/decoder/sync_decoder.h index 192962acc0c..b7cf7b625ac 100644 --- a/torchvision/csrc/cpu/decoder/sync_decoder.h +++ b/torchvision/csrc/cpu/decoder/sync_decoder.h @@ -11,11 +11,12 @@ namespace ffmpeg { * or fetched internally by FFMPEG library */ class SyncDecoder : public Decoder { + public: // Allocation of memory must be done with a proper alignment. - class VectorByteStorage : public ByteStorage { + class AVByteStorage : public ByteStorage { public: - VectorByteStorage(size_t n); - ~VectorByteStorage() override; + explicit AVByteStorage(size_t n); + ~AVByteStorage() override; void ensure(size_t n) override; uint8_t* writableTail() override; void append(size_t n) override; diff --git a/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp b/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp index 379c24a0aa0..6109b12685e 100644 --- a/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp +++ b/torchvision/csrc/cpu/decoder/sync_decoder_test.cpp @@ -1,10 +1,218 @@ #include +#include #include #include "memory_buffer.h" #include "sync_decoder.h" +#include "util.h" using namespace ffmpeg; +namespace { +struct VideoFileStats { + std::string name; + size_t durationPts{0}; + int num{0}; + int den{0}; + int fps{0}; +}; + +void gotAllTestFiles( + const std::string& folder, + std::vector* stats) { + DIR* d = opendir(folder.c_str()); + CHECK(d); + struct dirent* dir; + while ((dir = readdir(d))) { + if (dir->d_type != DT_DIR && 0 != strcmp(dir->d_name, "README")) { + VideoFileStats item; + item.name = folder + '/' + dir->d_name; + LOG(INFO) << "Found video file: " << item.name; + stats->push_back(std::move(item)); + } + } + closedir(d); +} + +void gotFilesStats(std::vector& stats) { + DecoderParameters params; + params.timeoutMs = 10000; + params.startOffset = 1000000; + params.seekAccuracy = 100000; + params.formats = {MediaFormat(0)}; + params.headerOnly = true; + params.preventStaleness = false; + size_t avgProvUs = 0; + const size_t rounds = 100; + for (auto& item : stats) { + LOG(INFO) << "Decoding video file in memory: " << item.name; + FILE* f = fopen(item.name.c_str(), "rb"); + CHECK(f != nullptr); + fseek(f, 0, SEEK_END); + std::vector buffer(ftell(f)); + rewind(f); + CHECK_EQ(buffer.size(), fread(buffer.data(), 1, buffer.size(), f)); + fclose(f); + + for (size_t i = 0; i < rounds; ++i) { + SyncDecoder decoder; + std::vector metadata; + const auto now = std::chrono::steady_clock::now(); + CHECK(decoder.init( + params, + MemoryBuffer::getCallback(buffer.data(), buffer.size()), + &metadata)); + const auto then = std::chrono::steady_clock::now(); + decoder.shutdown(); + avgProvUs += + std::chrono::duration_cast(then - now) + .count(); + CHECK_EQ(metadata.size(), 1); + item.num = metadata[0].num; + item.den = metadata[0].den; + item.fps = metadata[0].fps; + item.durationPts = + av_rescale_q(metadata[0].duration, AV_TIME_BASE_Q, {1, item.fps}); + } + } + LOG(INFO) << "Probing (us) " << avgProvUs / stats.size() / rounds; +} + +size_t measurePerformanceUs( + const std::vector& stats, + size_t rounds, + size_t num, + size_t stride) { + size_t avgClipDecodingUs = 0; + std::srand(time(nullptr)); + for (const auto& item : stats) { + FILE* f = fopen(item.name.c_str(), "rb"); + CHECK(f != nullptr); + fseek(f, 0, SEEK_END); + std::vector buffer(ftell(f)); + rewind(f); + CHECK_EQ(buffer.size(), fread(buffer.data(), 1, buffer.size(), f)); + fclose(f); + + for (size_t i = 0; i < rounds; ++i) { + // randomy select clip + size_t rOffset = std::rand(); + size_t fOffset = rOffset % item.durationPts; + size_t clipFrames = num + (num - 1) * stride; + if (fOffset + clipFrames > item.durationPts) { + fOffset = item.durationPts - clipFrames; + } + + DecoderParameters params; + params.timeoutMs = 10000; + params.startOffset = 1000000; + params.seekAccuracy = 100000; + params.preventStaleness = false; + + for (size_t n = 0; n < num; ++n) { + std::list msgs; + + params.startOffset = + av_rescale_q(fOffset, {1, item.fps}, AV_TIME_BASE_Q); + params.endOffset = params.startOffset + 100; + + auto now = std::chrono::steady_clock::now(); + SyncDecoder decoder; + CHECK(decoder.init( + params, + MemoryBuffer::getCallback(buffer.data(), buffer.size()), + nullptr)); + DecoderOutputMessage out; + while (0 == decoder.decode(&out, params.timeoutMs)) { + msgs.push_back(std::move(out)); + } + + decoder.shutdown(); + + const auto then = std::chrono::steady_clock::now(); + + fOffset += 1 + stride; + + avgClipDecodingUs += + std::chrono::duration_cast(then - now) + .count(); + } + } + } + + return avgClipDecodingUs / rounds / num / stats.size(); +} + +void runDecoder(SyncDecoder& decoder) { + DecoderOutputMessage out; + size_t audioFrames = 0, videoFrames = 0, totalBytes = 0; + while (0 == decoder.decode(&out, 10000)) { + if (out.header.format.type == TYPE_AUDIO) { + ++audioFrames; + } else if (out.header.format.type == TYPE_VIDEO) { + ++videoFrames; + } else if (out.header.format.type == TYPE_SUBTITLE && out.payload) { + // deserialize + LOG(INFO) << "Deserializing subtitle"; + AVSubtitle sub; + memset(&sub, 0, sizeof(sub)); + EXPECT_TRUE(Util::deserialize(*out.payload, &sub)); + LOG(INFO) << "Found subtitles" + << ", num rects: " << sub.num_rects; + for (int i = 0; i < sub.num_rects; ++i) { + std::string text = "picture"; + if (sub.rects[i]->type == SUBTITLE_TEXT) { + text = sub.rects[i]->text; + } else if (sub.rects[i]->type == SUBTITLE_ASS) { + text = sub.rects[i]->ass; + } + + LOG(INFO) << "Rect num: " << i << ", type:" << sub.rects[i]->type + << ", text: " << text; + } + + avsubtitle_free(&sub); + } + if (out.payload) { + totalBytes += out.payload->length(); + } + } + LOG(INFO) << "Decoded audio frames: " << audioFrames + << ", video frames: " << videoFrames + << ", total bytes: " << totalBytes; +} +} // namespace + +TEST(SyncDecoder, TestSyncDecoderPerformance) { + // Measure the average time of decoding per clip + // 1. list of the videos in testing directory + // 2. for each video got number of frames with timestamps + // 3. randomly select frame offset + // 4. adjust offset for number frames and strides, + // if it's out out upper boundary + // 5. repeat multiple times, measuring and accumulating decoding time + // per clip. + /* + 1) 4 x 2 + 2) 8 x 8 + 3) 16 x 8 + 4) 32 x 4 + */ + const std::string kFolder = "pytorch/vision/test/assets/videos"; + std::vector stats; + gotAllTestFiles(kFolder, &stats); + gotFilesStats(stats); + + const size_t kRounds = 10; + + auto new4x2 = measurePerformanceUs(stats, kRounds, 4, 2); + auto new8x8 = measurePerformanceUs(stats, kRounds, 8, 8); + auto new16x8 = measurePerformanceUs(stats, kRounds, 16, 8); + auto new32x4 = measurePerformanceUs(stats, kRounds, 32, 4); + LOG(INFO) << "Clip decoding (us)" + << ", new(4x2): " << new4x2 << ", new(8x8): " << new8x8 + << ", new(16x8): " << new16x8 << ", new(32x4): " << new32x4; +} + TEST(SyncDecoder, Test) { SyncDecoder decoder; DecoderParameters params; @@ -13,11 +221,19 @@ TEST(SyncDecoder, Test) { params.seekAccuracy = 100000; params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; params.uri = "pytorch/vision/test/assets/videos/R6llTwEh07w.mp4"; - CHECK(decoder.init(params, nullptr)); - DecoderOutputMessage out; - while (0 == decoder.decode(&out, 100)) { - LOG(INFO) << "Decoded frame, timestamp(us): " << out.header.pts; - } + CHECK(decoder.init(params, nullptr, nullptr)); + runDecoder(decoder); + decoder.shutdown(); +} + +TEST(SyncDecoder, TestSubtitles) { + SyncDecoder decoder; + DecoderParameters params; + params.timeoutMs = 10000; + params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; + params.uri = "vue/synergy/data/robotsub.mp4"; + CHECK(decoder.init(params, nullptr, nullptr)); + runDecoder(decoder); decoder.shutdown(); } @@ -29,16 +245,69 @@ TEST(SyncDecoder, TestHeadersOnly) { params.seekAccuracy = 100000; params.headerOnly = true; params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; + params.uri = "pytorch/vision/test/assets/videos/R6llTwEh07w.mp4"; - CHECK(decoder.init(params, nullptr)); - DecoderOutputMessage out; - while (0 == decoder.decode(&out, 100)) { - LOG(INFO) << "Decoded frame, type: " << out.header.format.type - << ", timestamp(us): " << out.header.pts; - } + CHECK(decoder.init(params, nullptr, nullptr)); + runDecoder(decoder); + decoder.shutdown(); + + params.uri = "pytorch/vision/test/assets/videos/SOX5yA1l24A.mp4"; + CHECK(decoder.init(params, nullptr, nullptr)); + runDecoder(decoder); + decoder.shutdown(); + + params.uri = "pytorch/vision/test/assets/videos/WUzgd7C1pWA.mp4"; + CHECK(decoder.init(params, nullptr, nullptr)); + runDecoder(decoder); + decoder.shutdown(); +} + +TEST(SyncDecoder, TestHeadersOnlyDownSampling) { + SyncDecoder decoder; + DecoderParameters params; + params.timeoutMs = 10000; + params.startOffset = 1000000; + params.seekAccuracy = 100000; + params.headerOnly = true; + MediaFormat format; + format.type = TYPE_AUDIO; + format.format.audio.samples = 8000; + params.formats.insert(format); + + format.type = TYPE_VIDEO; + format.format.video.width = 224; + format.format.video.height = 224; + params.formats.insert(format); + + params.uri = "pytorch/vision/test/assets/videos/R6llTwEh07w.mp4"; + CHECK(decoder.init(params, nullptr, nullptr)); + runDecoder(decoder); + decoder.shutdown(); + + params.uri = "pytorch/vision/test/assets/videos/SOX5yA1l24A.mp4"; + CHECK(decoder.init(params, nullptr, nullptr)); + runDecoder(decoder); + decoder.shutdown(); + + params.uri = "pytorch/vision/test/assets/videos/WUzgd7C1pWA.mp4"; + CHECK(decoder.init(params, nullptr, nullptr)); + runDecoder(decoder); decoder.shutdown(); } +TEST(SyncDecoder, TestInitOnlyNoShutdown) { + SyncDecoder decoder; + DecoderParameters params; + params.timeoutMs = 10000; + params.startOffset = 1000000; + params.seekAccuracy = 100000; + params.headerOnly = false; + params.formats = {MediaFormat(), MediaFormat(0), MediaFormat('0')}; + params.uri = "pytorch/vision/test/assets/videos/R6llTwEh07w.mp4"; + std::vector metadata; + CHECK(decoder.init(params, nullptr, &metadata)); +} + TEST(SyncDecoder, TestMemoryBuffer) { SyncDecoder decoder; DecoderParameters params; @@ -58,19 +327,11 @@ TEST(SyncDecoder, TestMemoryBuffer) { CHECK_EQ(buffer.size(), fread(buffer.data(), 1, buffer.size(), f)); fclose(f); CHECK(decoder.init( - params, MemoryBuffer::getCallback(buffer.data(), buffer.size()))); + params, + MemoryBuffer::getCallback(buffer.data(), buffer.size()), + nullptr)); LOG(INFO) << "Decoding from memory bytes: " << buffer.size(); - DecoderOutputMessage out; - size_t audioFrames = 0, videoFrames = 0; - while (0 == decoder.decode(&out, 100)) { - if (out.header.format.type == TYPE_AUDIO) { - ++audioFrames; - } else if (out.header.format.type == TYPE_VIDEO) { - ++videoFrames; - } - } - LOG(INFO) << "Decoded audio frames: " << audioFrames - << ", video frames: " << videoFrames; + runDecoder(decoder); decoder.shutdown(); } @@ -107,14 +368,9 @@ TEST(SyncDecoder, TestMemoryBufferNoSeekableWithFullRead) { return -1; } return object.seek(size, whence); - })); - DecoderOutputMessage out; - while (0 == decoder.decode(&out, 100)) { - LOG(INFO) << "Decoded frame, timestamp(us): " << out.header.pts - << ", num: " << out.header.format.num - << ", den: " << out.header.format.den - << ", duration(us): " << out.header.format.duration; - } + }, + nullptr)); + runDecoder(decoder); decoder.shutdown(); } @@ -151,5 +407,6 @@ TEST(SyncDecoder, TestMemoryBufferNoSeekableWithPartialRead) { return -1; } return object.seek(size, whence); - })); + }, + nullptr)); } diff --git a/torchvision/csrc/cpu/decoder/video_sampler.cpp b/torchvision/csrc/cpu/decoder/video_sampler.cpp index 4b7d078ebd7..b839dcf557a 100644 --- a/torchvision/csrc/cpu/decoder/video_sampler.cpp +++ b/torchvision/csrc/cpu/decoder/video_sampler.cpp @@ -156,27 +156,19 @@ bool VideoSampler::init(const SamplerParameters& params) { return scaleContext_ != nullptr; } -int VideoSampler::getImageBytes() const { - return av_image_get_buffer_size( - (AVPixelFormat)params_.out.video.format, - params_.out.video.width, - params_.out.video.height, - 1); -} - int VideoSampler::sample( const uint8_t* const srcSlice[], int srcStride[], - ByteStorage* out, - bool allocateBuffer) { + ByteStorage* out) { int result; // scaled and cropped image - const auto outImageSize = getImageBytes(); - if (allocateBuffer) { - out->clear(); - out->ensure(outImageSize); - } - CHECK_LE(outImageSize, out->tail()); + int outImageSize = av_image_get_buffer_size( + (AVPixelFormat)params_.out.video.format, + params_.out.video.width, + params_.out.video.height, + 1); + + out->ensure(outImageSize); uint8_t* scalePlanes[4] = {nullptr}; int scaleLines[4] = {0}; @@ -237,7 +229,7 @@ int VideoSampler::sample(AVFrame* frame, ByteStorage* out) { return 0; // no flush for videos } - return sample(frame->data, frame->linesize, out, false); + return sample(frame->data, frame->linesize, out); } int VideoSampler::sample(const ByteStorage* in, ByteStorage* out) { @@ -254,7 +246,7 @@ int VideoSampler::sample(const ByteStorage* in, ByteStorage* out) { return result; } - return sample(inPlanes, inLineSize, out, true); + return sample(inPlanes, inLineSize, out); } void VideoSampler::cleanUp() { diff --git a/torchvision/csrc/cpu/decoder/video_sampler.h b/torchvision/csrc/cpu/decoder/video_sampler.h index 85161307257..66318af5962 100644 --- a/torchvision/csrc/cpu/decoder/video_sampler.h +++ b/torchvision/csrc/cpu/decoder/video_sampler.h @@ -35,8 +35,7 @@ class VideoSampler : public MediaSampler { int sample( const uint8_t* const srcSlice[], int srcStride[], - ByteStorage* out, - bool allocateBuffer); + ByteStorage* out); private: VideoFormat scaleFormat_; diff --git a/torchvision/csrc/cpu/decoder/video_stream.cpp b/torchvision/csrc/cpu/decoder/video_stream.cpp index e464ed30cc9..947b4a6214b 100644 --- a/torchvision/csrc/cpu/decoder/video_stream.cpp +++ b/torchvision/csrc/cpu/decoder/video_stream.cpp @@ -47,12 +47,6 @@ VideoStream::~VideoStream() { } } -void VideoStream::ensureSampler() { - if (!sampler_) { - sampler_ = std::make_unique(SWS_AREA, loggingUuid_); - } -} - int VideoStream::initFormat() { // set output format if (!Util::validateVideoFormat(format_.format.video)) { @@ -85,8 +79,11 @@ int VideoStream::initFormat() { : -1; } -int VideoStream::estimateBytes(bool flush) { - ensureSampler(); +int VideoStream::copyFrameBytes(ByteStorage* out, bool flush) { + if (!sampler_) { + sampler_ = std::make_unique(SWS_AREA, loggingUuid_); + } + // check if input format gets changed if (flush ? !(sampler_->getInputFormat().video == *codecCtx_) : !(sampler_->getInputFormat().video == *frame_)) { @@ -111,11 +108,7 @@ int VideoStream::estimateBytes(bool flush) { << ", minDimension: " << format_.format.video.minDimension << ", crop: " << format_.format.video.cropImage; } - return sampler_->getImageBytes(); -} -int VideoStream::copyFrameBytes(ByteStorage* out, bool flush) { - ensureSampler(); return sampler_->sample(flush ? nullptr : frame_, out); } diff --git a/torchvision/csrc/cpu/decoder/video_stream.h b/torchvision/csrc/cpu/decoder/video_stream.h index 8e73d099613..e6a8bf02b65 100644 --- a/torchvision/csrc/cpu/decoder/video_stream.h +++ b/torchvision/csrc/cpu/decoder/video_stream.h @@ -21,12 +21,9 @@ class VideoStream : public Stream { private: int initFormat() override; - int estimateBytes(bool flush) override; int copyFrameBytes(ByteStorage* out, bool flush) override; void setHeader(DecoderHeader* header, bool flush) override; - void ensureSampler(); - private: std::unique_ptr sampler_; }; diff --git a/torchvision/csrc/cpu/video_reader/VideoReader.cpp b/torchvision/csrc/cpu/video_reader/VideoReader.cpp index 7578927f1b5..08b3f8c14a3 100644 --- a/torchvision/csrc/cpu/video_reader/VideoReader.cpp +++ b/torchvision/csrc/cpu/video_reader/VideoReader.cpp @@ -253,7 +253,16 @@ torch::List readVideo( const auto now = std::chrono::system_clock::now(); bool succeeded; - if ((succeeded = decoder.init(params, std::move(callback)))) { + DecoderMetadata audioMetadata, videoMetadata; + std::vector metadata; + if ((succeeded = decoder.init(params, std::move(callback), &metadata))) { + for (const auto& header : metadata) { + if (header.format.type == TYPE_VIDEO) { + videoMetadata = header; + } else if (header.format.type == TYPE_AUDIO) { + audioMetadata = header; + } + } int res; DecoderOutputMessage msg; while (0 == (res = decoder.decode(&msg, decoderTimeoutMs))) { @@ -265,16 +274,15 @@ torch::List readVideo( } msg.payload.reset(); } - - const auto then = std::chrono::system_clock::now(); - VLOG(1) << "Video decoding from " << logType << " [" << logMessage - << "] has finished, " - << std::chrono::duration_cast(then - now) - .count() - << " us"; } else { LOG(ERROR) << "Decoder initialization has failed"; } + const auto then = std::chrono::system_clock::now(); + VLOG(1) << "Video decoding from " << logType << " [" << logMessage + << "] has finished, " + << std::chrono::duration_cast(then - now) + .count() + << " us"; decoder.shutdown(); @@ -287,9 +295,8 @@ torch::List readVideo( if (succeeded && readVideoStream == 1) { if (!videoMessages.empty()) { - const auto& header = videoMessages[0].header; - const auto& media = header.format; - const auto& format = media.format.video; + const auto& header = videoMetadata; + const auto& format = header.format.format.video; int numVideoFrames = videoMessages.size(); int outHeight = format.height; int outWidth = format.width; @@ -305,19 +312,19 @@ torch::List readVideo( videoFramePts = torch::zeros({numVideoFrames}, torch::kLong); - VLOG(2) << "video duration: " << media.duration << ", fps: " << header.fps - << ", num: " << media.num << ", den: " << media.den - << ", num frames: " << numVideoFrames; + VLOG(2) << "video duration: " << header.duration + << ", fps: " << header.fps << ", num: " << header.num + << ", den: " << header.den << ", num frames: " << numVideoFrames; auto numberWrittenBytes = fillVideoTensor( - videoMessages, videoFrame, videoFramePts, media.num, media.den); + videoMessages, videoFrame, videoFramePts, header.num, header.den); CHECK_EQ(numberWrittenBytes, expectedWrittenBytes); videoTimeBase = torch::zeros({2}, torch::kInt); int* videoTimeBaseData = videoTimeBase.data_ptr(); - videoTimeBaseData[0] = media.num; - videoTimeBaseData[1] = media.den; + videoTimeBaseData[0] = header.num; + videoTimeBaseData[1] = header.den; videoFps = torch::zeros({1}, torch::kFloat); float* videoFpsData = videoFps.data_ptr(); @@ -325,8 +332,8 @@ torch::List readVideo( videoDuration = torch::zeros({1}, torch::kLong); int64_t* videoDurationData = videoDuration.data_ptr(); - AVRational avr = {(int)media.num, (int)media.den}; - videoDurationData[0] = av_rescale_q(media.duration, AV_TIME_BASE_Q, avr); + AVRational vr = {(int)header.num, (int)header.den}; + videoDurationData[0] = av_rescale_q(header.duration, AV_TIME_BASE_Q, vr); VLOG(1) << "Video decoding from " << logType << " [" << logMessage << "] filled video tensors"; } else { @@ -342,9 +349,8 @@ torch::List readVideo( torch::Tensor audioDuration = torch::zeros({0}, torch::kLong); if (succeeded && readAudioStream == 1) { if (!audioMessages.empty()) { - const auto& header = audioMessages[0].header; - const auto& media = header.format; - const auto& format = media.format.audio; + const auto& header = audioMetadata; + const auto& format = header.format.format.audio; int64_t outAudioChannels = format.channels; int bytesPerSample = @@ -366,21 +372,21 @@ torch::List readVideo( } audioFramePts = torch::zeros({numAudioFrames}, torch::kLong); - VLOG(2) << "audio duration: " << media.duration + VLOG(2) << "audio duration: " << header.duration << ", channels: " << format.channels - << ", sample rate: " << format.samples << ", num: " << media.num - << ", den: " << media.den; + << ", sample rate: " << format.samples << ", num: " << header.num + << ", den: " << header.den; auto numberWrittenBytes = fillAudioTensor( - audioMessages, audioFrame, audioFramePts, media.num, media.den); + audioMessages, audioFrame, audioFramePts, header.num, header.den); CHECK_EQ( numberWrittenBytes, numAudioSamples * outAudioChannels * sizeof(float)); audioTimeBase = torch::zeros({2}, torch::kInt); int* audioTimeBaseData = audioTimeBase.data_ptr(); - audioTimeBaseData[0] = media.num; - audioTimeBaseData[1] = media.den; + audioTimeBaseData[0] = header.num; + audioTimeBaseData[1] = header.den; audioSampleRate = torch::zeros({1}, torch::kInt); int* audioSampleRateData = audioSampleRate.data_ptr(); @@ -388,8 +394,8 @@ torch::List readVideo( audioDuration = torch::zeros({1}, torch::kLong); int64_t* audioDurationData = audioDuration.data_ptr(); - AVRational avr = {(int)media.num, (int)media.den}; - audioDurationData[0] = av_rescale_q(media.duration, AV_TIME_BASE_Q, avr); + AVRational ar = {(int)header.num, (int)header.den}; + audioDurationData[0] = av_rescale_q(header.duration, AV_TIME_BASE_Q, ar); VLOG(1) << "Video decoding from " << logType << " [" << logMessage << "] filled audio tensors"; } else { @@ -519,7 +525,6 @@ torch::List probeVideo( ); SyncDecoder decoder; - DecoderOutputMessage audioMessage, videoMessage; DecoderInCallback callback = nullptr; std::string logMessage, logType; if (isReadFile) { @@ -540,23 +545,18 @@ torch::List probeVideo( bool succeeded; bool gotAudio = false, gotVideo = false; - if ((succeeded = decoder.init(params, std::move(callback)))) { - int res; - DecoderOutputMessage msg; - while (0 == (res = decoder.decode(&msg, decoderTimeoutMs)) && - (!gotAudio || !gotVideo)) { - if (msg.header.format.type == TYPE_VIDEO && !gotVideo) { - videoMessage = std::move(msg); + DecoderMetadata audioMetadata, videoMetadata; + std::vector metadata; + if ((succeeded = decoder.init(params, std::move(callback), &metadata))) { + for (const auto& header : metadata) { + if (header.format.type == TYPE_VIDEO) { gotVideo = true; - } - if (msg.header.format.type == TYPE_AUDIO && !gotAudio) { - audioMessage = std::move(msg); + videoMetadata = header; + } else if (header.format.type == TYPE_AUDIO) { gotAudio = true; + audioMetadata = header; } - msg.payload.reset(); } - succeeded = (res == 0 || res == ENODATA); - const auto then = std::chrono::system_clock::now(); VLOG(1) << "Video probing from " << logType << " [" << logMessage << "] has finished, " @@ -577,11 +577,11 @@ torch::List probeVideo( if (succeeded && gotVideo) { videoTimeBase = torch::zeros({2}, torch::kInt); int* videoTimeBaseData = videoTimeBase.data_ptr(); - const auto& header = videoMessage.header; + const auto& header = videoMetadata; const auto& media = header.format; - videoTimeBaseData[0] = media.num; - videoTimeBaseData[1] = media.den; + videoTimeBaseData[0] = header.num; + videoTimeBaseData[1] = header.den; videoFps = torch::zeros({1}, torch::kFloat); float* videoFpsData = videoFps.data_ptr(); @@ -589,11 +589,11 @@ torch::List probeVideo( videoDuration = torch::zeros({1}, torch::kLong); int64_t* videoDurationData = videoDuration.data_ptr(); - AVRational avr = {(int)media.num, (int)media.den}; - videoDurationData[0] = av_rescale_q(media.duration, AV_TIME_BASE_Q, avr); + AVRational avr = {(int)header.num, (int)header.den}; + videoDurationData[0] = av_rescale_q(header.duration, AV_TIME_BASE_Q, avr); - VLOG(2) << "Prob fps: " << header.fps << ", duration: " << media.duration - << ", num: " << media.num << ", den: " << media.den; + VLOG(2) << "Prob fps: " << header.fps << ", duration: " << header.duration + << ", num: " << header.num << ", den: " << header.den; VLOG(1) << "Video probing from " << logType << " [" << logMessage << "] filled video tensors"; @@ -609,12 +609,12 @@ torch::List probeVideo( if (succeeded && gotAudio) { audioTimeBase = torch::zeros({2}, torch::kInt); int* audioTimeBaseData = audioTimeBase.data_ptr(); - const auto& header = audioMessage.header; + const auto& header = audioMetadata; const auto& media = header.format; const auto& format = media.format.audio; - audioTimeBaseData[0] = media.num; - audioTimeBaseData[1] = media.den; + audioTimeBaseData[0] = header.num; + audioTimeBaseData[1] = header.den; audioSampleRate = torch::zeros({1}, torch::kInt); int* audioSampleRateData = audioSampleRate.data_ptr(); @@ -622,12 +622,12 @@ torch::List probeVideo( audioDuration = torch::zeros({1}, torch::kLong); int64_t* audioDurationData = audioDuration.data_ptr(); - AVRational avr = {(int)media.num, (int)media.den}; - audioDurationData[0] = av_rescale_q(media.duration, AV_TIME_BASE_Q, avr); + AVRational avr = {(int)header.num, (int)header.den}; + audioDurationData[0] = av_rescale_q(header.duration, AV_TIME_BASE_Q, avr); VLOG(2) << "Prob sample rate: " << format.samples - << ", duration: " << media.duration << ", num: " << media.num - << ", den: " << media.den; + << ", duration: " << header.duration << ", num: " << header.num + << ", den: " << header.den; VLOG(1) << "Video probing from " << logType << " [" << logMessage << "] filled audio tensors"; From d8f7a0eb856621321e8301e0b44d1714b8f58148 Mon Sep 17 00:00:00 2001 From: Yuri Putivsky Date: Fri, 14 Feb 2020 09:11:09 -0800 Subject: [PATCH 050/357] Minor fix and decoder class members access. Summary: Found and fix a bug in cropping algorithm (simple mistyping). Also derived classes need access to some decoder class members, like initialization parameters - make it protected. Reviewed By: stephenyan1231, fmassa Differential Revision: D19895076 fbshipit-source-id: 691336c8e18526b085ae5792ac3546bc387a6db9 --- torchvision/csrc/cpu/decoder/decoder.h | 4 +++- torchvision/csrc/cpu/decoder/video_sampler.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/torchvision/csrc/cpu/decoder/decoder.h b/torchvision/csrc/cpu/decoder/decoder.h index dce42cfb59a..69b69721226 100644 --- a/torchvision/csrc/cpu/decoder/decoder.h +++ b/torchvision/csrc/cpu/decoder/decoder.h @@ -71,8 +71,10 @@ class Decoder : public MediaDecoder { void flushStreams(); void cleanUp(); - private: + protected: DecoderParameters params_; + + private: SeekableBuffer seekableBuffer_; int printPrefix{1}; diff --git a/torchvision/csrc/cpu/decoder/video_sampler.cpp b/torchvision/csrc/cpu/decoder/video_sampler.cpp index b839dcf557a..59385a78fdc 100644 --- a/torchvision/csrc/cpu/decoder/video_sampler.cpp +++ b/torchvision/csrc/cpu/decoder/video_sampler.cpp @@ -97,7 +97,7 @@ bool VideoSampler::init(const SamplerParameters& params) { cropContext_ = sws_getContext( params.out.video.width, params.out.video.height, - (AVPixelFormat)params_.out.video.format, + (AVPixelFormat)params.out.video.format, params.out.video.width, params.out.video.height, (AVPixelFormat)params.out.video.format, From d4f383fe8c99fd3a6ff7d4bb204170538655b638 Mon Sep 17 00:00:00 2001 From: Yuri Putivsky Date: Tue, 18 Feb 2020 09:54:03 -0800 Subject: [PATCH 051/357] Added missing header for less dependencies. (#1898) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1898 Include streams/samplers shouldn't depend on decoder headers. Add dependencies directly to the place where they are required. Reviewed By: stephenyan1231 Differential Revision: D19911404 fbshipit-source-id: ef322a053708405c02cee4562b456b1602fb12fc --- torchvision/csrc/cpu/decoder/audio_sampler.h | 4 ---- torchvision/csrc/cpu/decoder/defs.h | 10 ++++++++++ torchvision/csrc/cpu/decoder/memory_buffer.cpp | 4 ---- torchvision/csrc/cpu/decoder/seekable_buffer.cpp | 4 ---- torchvision/csrc/cpu/decoder/stream.h | 6 ------ torchvision/csrc/cpu/decoder/subtitle_sampler.h | 4 ---- torchvision/csrc/cpu/decoder/time_keeper.cpp | 5 +---- torchvision/csrc/cpu/decoder/util.h | 4 ---- torchvision/csrc/cpu/decoder/video_sampler.cpp | 4 ---- torchvision/csrc/cpu/decoder/video_sampler.h | 5 ----- 10 files changed, 11 insertions(+), 39 deletions(-) diff --git a/torchvision/csrc/cpu/decoder/audio_sampler.h b/torchvision/csrc/cpu/decoder/audio_sampler.h index d6d8402d971..e105bbe4de2 100644 --- a/torchvision/csrc/cpu/decoder/audio_sampler.h +++ b/torchvision/csrc/cpu/decoder/audio_sampler.h @@ -2,10 +2,6 @@ #include "defs.h" -extern "C" { -#include -} - namespace ffmpeg { /** diff --git a/torchvision/csrc/cpu/decoder/defs.h b/torchvision/csrc/cpu/decoder/defs.h index bc9ca31a810..a62afd2729d 100644 --- a/torchvision/csrc/cpu/decoder/defs.h +++ b/torchvision/csrc/cpu/decoder/defs.h @@ -7,6 +7,16 @@ #include #include +extern "C" { +#include +#include +#include +#include +#include +#include +#include "libswscale/swscale.h" +} + namespace ffmpeg { // bit mask of formats, keep them in form 2^n diff --git a/torchvision/csrc/cpu/decoder/memory_buffer.cpp b/torchvision/csrc/cpu/decoder/memory_buffer.cpp index d91213fdcbb..a7b0128e3ed 100644 --- a/torchvision/csrc/cpu/decoder/memory_buffer.cpp +++ b/torchvision/csrc/cpu/decoder/memory_buffer.cpp @@ -1,10 +1,6 @@ #include "memory_buffer.h" #include -extern "C" { -#include -} - namespace ffmpeg { MemoryBuffer::MemoryBuffer(const uint8_t* buffer, size_t size) diff --git a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp index 26da3e5d7c1..118548db01c 100644 --- a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp +++ b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp @@ -3,10 +3,6 @@ #include #include "memory_buffer.h" -extern "C" { -#include -} - namespace ffmpeg { int SeekableBuffer::init( diff --git a/torchvision/csrc/cpu/decoder/stream.h b/torchvision/csrc/cpu/decoder/stream.h index 6d03f1c2c1e..97dfa8b5761 100644 --- a/torchvision/csrc/cpu/decoder/stream.h +++ b/torchvision/csrc/cpu/decoder/stream.h @@ -4,12 +4,6 @@ #include "defs.h" #include "time_keeper.h" -extern "C" { -#include -#include -#include -} - namespace ffmpeg { /** diff --git a/torchvision/csrc/cpu/decoder/subtitle_sampler.h b/torchvision/csrc/cpu/decoder/subtitle_sampler.h index fb50b1c4682..4aee811ed56 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_sampler.h +++ b/torchvision/csrc/cpu/decoder/subtitle_sampler.h @@ -2,10 +2,6 @@ #include "defs.h" -extern "C" { -#include -} - namespace ffmpeg { /** diff --git a/torchvision/csrc/cpu/decoder/time_keeper.cpp b/torchvision/csrc/cpu/decoder/time_keeper.cpp index 9cfc9457963..845c76cddc8 100644 --- a/torchvision/csrc/cpu/decoder/time_keeper.cpp +++ b/torchvision/csrc/cpu/decoder/time_keeper.cpp @@ -1,8 +1,5 @@ #include "time_keeper.h" - -extern "C" { -#include -} +#include "defs.h" namespace ffmpeg { diff --git a/torchvision/csrc/cpu/decoder/util.h b/torchvision/csrc/cpu/decoder/util.h index cc64d8944e4..dbbfa33a091 100644 --- a/torchvision/csrc/cpu/decoder/util.h +++ b/torchvision/csrc/cpu/decoder/util.h @@ -2,10 +2,6 @@ #include "defs.h" -extern "C" { -#include -} - namespace ffmpeg { /** diff --git a/torchvision/csrc/cpu/decoder/video_sampler.cpp b/torchvision/csrc/cpu/decoder/video_sampler.cpp index 59385a78fdc..0c28fd9bb4e 100644 --- a/torchvision/csrc/cpu/decoder/video_sampler.cpp +++ b/torchvision/csrc/cpu/decoder/video_sampler.cpp @@ -2,10 +2,6 @@ #include #include "util.h" -extern "C" { -#include -} - // www.ffmpeg.org/doxygen/0.5/swscale-example_8c-source.html namespace ffmpeg { diff --git a/torchvision/csrc/cpu/decoder/video_sampler.h b/torchvision/csrc/cpu/decoder/video_sampler.h index 66318af5962..47247f2c0c5 100644 --- a/torchvision/csrc/cpu/decoder/video_sampler.h +++ b/torchvision/csrc/cpu/decoder/video_sampler.h @@ -2,11 +2,6 @@ #include "defs.h" -extern "C" { -#include -#include "libswscale/swscale.h" -} - namespace ffmpeg { /** From 2c79a6cf3aaeb563924071c27e29e00f92501725 Mon Sep 17 00:00:00 2001 From: Yuri Putivsky Date: Wed, 26 Feb 2020 08:48:50 -0800 Subject: [PATCH 052/357] Implemented VUE Asynchronous Decoder Summary: For Mothership we have found that asynchronous decoder provides a better performance. Differential Revision: D20026194 fbshipit-source-id: 627b91844b4e3f917002031dd32cb19c239f4ba8 --- torchvision/csrc/cpu/decoder/seekable_buffer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp index 118548db01c..0d7ec7236a2 100644 --- a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp +++ b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp @@ -82,6 +82,8 @@ bool SeekableBuffer::readBytes( } } + buffer_.resize(end_); + return hasTime; } From 80b2c767749b6d126796237ffc0f389d3e99be62 Mon Sep 17 00:00:00 2001 From: Zhicheng Yan Date: Wed, 4 Mar 2020 22:47:23 -0800 Subject: [PATCH 053/357] fix a bug in API read_video_from_memory (#1942) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1942 In D18720474, it introduces a bug in `read_video_from_memory` API. Thank weiyaowang for reporting it. Reviewed By: weiyaowang Differential Revision: D20270179 fbshipit-source-id: 66348c99a5ad1f9129b90e934524ddfaad59de03 --- torchvision/io/video.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/io/video.py b/torchvision/io/video.py index fc56c015473..96cf7feeb79 100644 --- a/torchvision/io/video.py +++ b/torchvision/io/video.py @@ -375,7 +375,7 @@ def read_video_from_memory( return _video_opt._read_video_from_memory( video_data, seek_frame_margin, - read_audio_stream, + read_video_stream, video_width, video_height, video_min_dimension, From 2757caf6d332269791fa30982daaab778a44397c Mon Sep 17 00:00:00 2001 From: Zhicheng Yan Date: Thu, 5 Mar 2020 12:30:13 -0800 Subject: [PATCH 054/357] extend decoder to support new video_max_dimension argument (#1924) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1924 Extend `video reader` decoder python API in Torchvision to support a new argument `video_max_dimension`. This enables the new video decoding use cases. When setting `video_width=0`, `video_height=0`, `video_min_dimension != 0`, and `video_max_dimension != 0`, we can rescale the video clips so that its spatial resolution (height, width) becomes - (video_min_dimension, video_max_dimension) if original height < original width - (video_max_dimension, video_min_dimension) if original height >= original width This is useful at video model testing stage, where we perform fully convolution evaluation and take entire video frames without cropping as input. Previously, for instance we can only set `video_width=0`, `video_height=0`, `video_min_dimension = 128`, which will preserve aspect ratio. In production dataset, there are a small number of videos where aspect ratio is either extremely large or small, and when the shorter edge is rescaled to 128, the longer edge is still large. This will easily cause GPU memory OOM when we sample multiple video clips, and put them in a single minibatch. Now, we can set (for instance) `video_width=0`, `video_height=0`, `video_min_dimension = 128` and `video_max_dimension = 171` so that the rescale resolution is either (128, 171) or (171, 128) depending on whether original height is larger than original width. Thus, we are less likely to have gpu OOM because the spatial size of video clips is determined. Reviewed By: putivsky Differential Revision: D20182529 fbshipit-source-id: f9c40afb7590e7c45e6908946597141efa35f57c --- test/test_video_reader.py | 129 ++++++++++++++++-- torchvision/csrc/cpu/decoder/defs.h | 20 ++- torchvision/csrc/cpu/decoder/util.cpp | 79 +++++++---- torchvision/csrc/cpu/decoder/util.h | 1 + torchvision/csrc/cpu/decoder/util_test.cpp | 33 +++++ .../csrc/cpu/decoder/video_sampler.cpp | 1 + torchvision/csrc/cpu/decoder/video_stream.cpp | 1 + .../csrc/cpu/video_reader/VideoReader.cpp | 9 ++ torchvision/datasets/video_utils.py | 8 ++ torchvision/io/_video_opt.py | 76 ++++++++--- torchvision/io/video.py | 2 + 11 files changed, 299 insertions(+), 60 deletions(-) create mode 100644 torchvision/csrc/cpu/decoder/util_test.cpp diff --git a/test/test_video_reader.py b/test/test_video_reader.py index ec0fa75da1d..70112427b85 100644 --- a/test/test_video_reader.py +++ b/test/test_video_reader.py @@ -395,7 +395,7 @@ def compare_decoding_result(self, tv_result, ref_result, config=all_check_config def test_stress_test_read_video_from_file(self): num_iter = 10000 # video related - width, height, min_dimension = 0, 0, 0 + width, height, min_dimension, max_dimension = 0, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -416,6 +416,7 @@ def test_stress_test_read_video_from_file(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -434,7 +435,7 @@ def test_read_video_from_file(self): Test the case when decoder starts with a video file to decode frames. """ # video related - width, height, min_dimension = 0, 0, 0 + width, height, min_dimension, max_dimension = 0, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -454,6 +455,7 @@ def test_read_video_from_file(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -479,7 +481,7 @@ def test_read_video_from_file_read_single_stream_only(self): only reads video stream and ignores audio stream """ # video related - width, height, min_dimension = 0, 0, 0 + width, height, min_dimension, max_dimension = 0, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -499,6 +501,7 @@ def test_read_video_from_file_read_single_stream_only(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -536,7 +539,7 @@ def test_read_video_from_file_rescale_min_dimension(self): video min dimension between height and width is set. """ # video related - width, height, min_dimension = 0, 0, 128 + width, height, min_dimension, max_dimension = 0, 0, 128, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -555,6 +558,7 @@ def test_read_video_from_file_rescale_min_dimension(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -571,13 +575,100 @@ def test_read_video_from_file_rescale_min_dimension(self): min_dimension, min(tv_result[0].size(1), tv_result[0].size(2)) ) + def test_read_video_from_file_rescale_max_dimension(self): + """ + Test the case when decoder starts with a video file to decode frames, and + video min dimension between height and width is set. + """ + # video related + width, height, min_dimension, max_dimension = 0, 0, 0, 85 + video_start_pts, video_end_pts = 0, -1 + video_timebase_num, video_timebase_den = 0, 1 + # audio related + samples, channels = 0, 0 + audio_start_pts, audio_end_pts = 0, -1 + audio_timebase_num, audio_timebase_den = 0, 1 + + for test_video, _config in test_videos.items(): + full_path = os.path.join(VIDEO_DIR, test_video) + + tv_result = torch.ops.video_reader.read_video_from_file( + full_path, + seek_frame_margin, + 0, # getPtsOnly + 1, # readVideoStream + width, + height, + min_dimension, + max_dimension, + video_start_pts, + video_end_pts, + video_timebase_num, + video_timebase_den, + 1, # readAudioStream + samples, + channels, + audio_start_pts, + audio_end_pts, + audio_timebase_num, + audio_timebase_den, + ) + self.assertEqual( + max_dimension, max(tv_result[0].size(1), tv_result[0].size(2)) + ) + + def test_read_video_from_file_rescale_both_min_max_dimension(self): + """ + Test the case when decoder starts with a video file to decode frames, and + video min dimension between height and width is set. + """ + # video related + width, height, min_dimension, max_dimension = 0, 0, 64, 85 + video_start_pts, video_end_pts = 0, -1 + video_timebase_num, video_timebase_den = 0, 1 + # audio related + samples, channels = 0, 0 + audio_start_pts, audio_end_pts = 0, -1 + audio_timebase_num, audio_timebase_den = 0, 1 + + for test_video, _config in test_videos.items(): + full_path = os.path.join(VIDEO_DIR, test_video) + + tv_result = torch.ops.video_reader.read_video_from_file( + full_path, + seek_frame_margin, + 0, # getPtsOnly + 1, # readVideoStream + width, + height, + min_dimension, + max_dimension, + video_start_pts, + video_end_pts, + video_timebase_num, + video_timebase_den, + 1, # readAudioStream + samples, + channels, + audio_start_pts, + audio_end_pts, + audio_timebase_num, + audio_timebase_den, + ) + self.assertEqual( + min_dimension, min(tv_result[0].size(1), tv_result[0].size(2)) + ) + self.assertEqual( + max_dimension, max(tv_result[0].size(1), tv_result[0].size(2)) + ) + def test_read_video_from_file_rescale_width(self): """ Test the case when decoder starts with a video file to decode frames, and video width is set. """ # video related - width, height, min_dimension = 256, 0, 0 + width, height, min_dimension, max_dimension = 256, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -596,6 +687,7 @@ def test_read_video_from_file_rescale_width(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -616,7 +708,7 @@ def test_read_video_from_file_rescale_height(self): video height is set. """ # video related - width, height, min_dimension = 0, 224, 0 + width, height, min_dimension, max_dimension = 0, 224, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -635,6 +727,7 @@ def test_read_video_from_file_rescale_height(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -655,7 +748,7 @@ def test_read_video_from_file_rescale_width_and_height(self): both video height and width are set. """ # video related - width, height, min_dimension = 320, 240, 0 + width, height, min_dimension, max_dimension = 320, 240, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -674,6 +767,7 @@ def test_read_video_from_file_rescale_width_and_height(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -697,7 +791,7 @@ def test_read_video_from_file_audio_resampling(self): for samples in [9600, 96000]: # downsampling # upsampling # video related - width, height, min_dimension = 0, 0, 0 + width, height, min_dimension, max_dimension = 0, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -716,6 +810,7 @@ def test_read_video_from_file_audio_resampling(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -752,7 +847,7 @@ def test_compare_read_video_from_memory_and_file(self): Test the case when video is already in memory, and decoder reads data in memory """ # video related - width, height, min_dimension = 0, 0, 0 + width, height, min_dimension, max_dimension = 0, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -772,6 +867,7 @@ def test_compare_read_video_from_memory_and_file(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -794,6 +890,7 @@ def test_compare_read_video_from_memory_and_file(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -816,7 +913,7 @@ def test_read_video_from_memory(self): Test the case when video is already in memory, and decoder reads data in memory """ # video related - width, height, min_dimension = 0, 0, 0 + width, height, min_dimension, max_dimension = 0, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -836,6 +933,7 @@ def test_read_video_from_memory(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -861,7 +959,7 @@ def test_read_video_from_memory_get_pts_only(self): for both pts and frame data """ # video related - width, height, min_dimension = 0, 0, 0 + width, height, min_dimension, max_dimension = 0, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -881,6 +979,7 @@ def test_read_video_from_memory_get_pts_only(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -904,6 +1003,7 @@ def test_read_video_from_memory_get_pts_only(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -930,7 +1030,7 @@ def test_read_video_in_range_from_memory(self): for test_video, config in test_videos.items(): full_path, video_tensor = _get_video_tensor(VIDEO_DIR, test_video) # video related - width, height, min_dimension = 0, 0, 0 + width, height, min_dimension, max_dimension = 0, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -946,6 +1046,7 @@ def test_read_video_in_range_from_memory(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -1000,6 +1101,7 @@ def test_read_video_in_range_from_memory(self): width, height, min_dimension, + max_dimension, video_start_pts, video_end_pts, video_timebase_num, @@ -1099,7 +1201,7 @@ def test_read_video_from_memory_scripted(self): Test the case when video is already in memory, and decoder reads data in memory """ # video related - width, height, min_dimension = 0, 0, 0 + width, height, min_dimension, max_dimension = 0, 0, 0, 0 video_start_pts, video_end_pts = 0, -1 video_timebase_num, video_timebase_den = 0, 1 # audio related @@ -1130,6 +1232,7 @@ def test_read_video_from_memory_scripted(self): [audio_start_pts, audio_end_pts], audio_timebase_num, audio_timebase_den, + max_dimension, ) # FUTURE: check value of video / audio frames diff --git a/torchvision/csrc/cpu/decoder/defs.h b/torchvision/csrc/cpu/decoder/defs.h index a62afd2729d..a53f2aeb2b0 100644 --- a/torchvision/csrc/cpu/decoder/defs.h +++ b/torchvision/csrc/cpu/decoder/defs.h @@ -49,11 +49,29 @@ struct VideoFormat { bool operator==(const VideoFormat& x) const { return x.format == format && x.width == width && x.height == height; } - + /* + When width = 0, height = 0, minDimension = 0, and maxDimension = 0, + keep the orignal frame resolution + When width = 0, height = 0, minDimension != 0, and maxDimension = 0, + keep the aspect ratio and resize the frame so that shorter edge size is minDimension + When width = 0, height = 0, minDimension = 0, and maxDimension != 0, + keep the aspect ratio and resize the frame so that longer edge size is maxDimension + When width = 0, height = 0, minDimension != 0, and maxDimension != 0, + resize the frame so that shorter edge size is minDimension, and + longer edge size is maxDimension. The aspect ratio may not be preserved + When width = 0, height != 0, minDimension = 0, and maxDimension = 0, + keep the aspect ratio and resize the frame so that frame height is $height + When width != 0, height = 0, minDimension = 0, and maxDimension = 0, + keep the aspect ratio and resize the frame so that frame width is $width + When width != 0, height != 0, minDimension = 0, and maxDimension = 0, + resize the frame so that frame width and height are set to $width and $height, + respectively + */ size_t width{0}; // width in pixels size_t height{0}; // height in pixels long format{-1}; // AVPixelFormat, auto AV_PIX_FMT_NONE size_t minDimension{0}; // choose min dimension and rescale accordingly + size_t maxDimension{0}; // choose max dimension and rescale accordingly size_t cropImage{0}; // request image crop // -- alignment 40 bytes }; diff --git a/torchvision/csrc/cpu/decoder/util.cpp b/torchvision/csrc/cpu/decoder/util.cpp index ba19cf582b0..9ca7246bbaf 100644 --- a/torchvision/csrc/cpu/decoder/util.cpp +++ b/torchvision/csrc/cpu/decoder/util.cpp @@ -286,31 +286,36 @@ size_t size(const AVSubtitle& sub) { bool validateVideoFormat(const VideoFormat& f) { /* Valid parameters values for decoder - ______________________________________________________________ - | W | H | minDimension | cropImage | algorithm | - |_____________________________________________________________| - | 0 | 0 | 0 | N/A | original | - |_____________________________________________________________| - | >0 | 0 | N/A | N/A | scale keeping W | - |_____________________________________________________________| - | 0 | >0 | N/A | N/A | scale keeping H | - |_____________________________________________________________| - | >0 | >0 | N/A | 0 | stretch/scale | - |_____________________________________________________________| - | >0 | >0 | N/A | >0 | scale/crop | - |_____________________________________________________________| - | 0 | 0 | >0 | N/A |scale to min dimension| - |_____|_____|______________|___________|______________________| + ____________________________________________________________________________________ + | W | H | minDimension | maxDimension | cropImage | algorithm | + |__________________________________________________________________________________| + | 0 | 0 | 0 | 0 | N/A | original | + |__________________________________________________________________________________| + | >0 | 0 | N/A | N/A | N/A | scale keeping W | + |__________________________________________________________________________________| + | 0 | >0 | N/A | N/A | N/A | scale keeping H | + |__________________________________________________________________________________| + | >0 | >0 | N/A | N/A | 0 | stretch/scale | + |__________________________________________________________________________________| + | >0 | >0 | N/A | N/A | >0 | scale/crop | + |__________________________________________________________________________________| + | 0 | 0 | >0 | 0 | N/A |scale to min dimension | + |__________________________________________________________________________________| + | 0 | 0 | 0 | >0 | N/A |scale to max dimension | + |__________________________________________________________________________________| + | 0 | 0 | >0 | >0 | N/A |stretch to min/max dimension| + |_____|_____|______________|______________|___________|____________________________| + */ - return (f.width == 0 && // #1 and #6 + return (f.width == 0 && // #1, #6, #7 and #8 f.height == 0 && f.cropImage == 0) || (f.width != 0 && // #4 and #5 - f.height != 0 && f.minDimension == 0) || + f.height != 0 && f.minDimension == 0 && f.maxDimension == 0) || (((f.width != 0 && // #2 f.height == 0) || (f.width == 0 && // #3 f.height != 0)) && - f.minDimension == 0 && f.cropImage == 0); + f.minDimension == 0 && f.maxDimension == 0 && f.cropImage == 0); } void setFormatDimensions( @@ -321,14 +326,17 @@ void setFormatDimensions( size_t srcW, size_t srcH, size_t minDimension, + size_t maxDimension, size_t cropImage) { // rounding rules // int -> double -> round up // if fraction is >= 0.5 or round down if fraction is < 0.5 // int result = double(value) + 0.5 // here we rounding double to int according to the above rule + + // #1, #6, #7 and #8 if (userW == 0 && userH == 0) { - if (minDimension > 0) { + if (minDimension > 0 && maxDimension == 0) { // #6 if (srcW > srcH) { // landscape destH = minDimension; @@ -338,21 +346,44 @@ void setFormatDimensions( destW = minDimension; destH = round(double(srcH * minDimension) / srcW); } - } else { + } + else if (minDimension == 0 && maxDimension > 0) { // #7 + if (srcW > srcH) { + // landscape + destW = maxDimension; + destH = round(double(srcH * maxDimension) / srcW); + } else { + // portrait + destH = maxDimension; + destW = round(double(srcW * maxDimension) / srcH); + } + } + else if (minDimension > 0 && maxDimension > 0) { // #8 + if (srcW > srcH) { + // landscape + destW = maxDimension; + destH = minDimension; + } else { + // portrait + destW = minDimension; + destH = maxDimension; + } + } + else { // #1 destW = srcW; destH = srcH; } - } else if (userW != 0 && userH == 0) { + } else if (userW != 0 && userH == 0) { // #2 destW = userW; destH = round(double(srcH * userW) / srcW); - } else if (userW == 0 && userH != 0) { + } else if (userW == 0 && userH != 0) { // #3 destW = round(double(srcW * userH) / srcH); destH = userH; } else { // userW != 0 && userH != 0 - if (cropImage == 0) { + if (cropImage == 0) { // #4 destW = userW; destH = userH; - } else { + } else { // #5 double userSlope = double(userH) / userW; double srcSlope = double(srcH) / srcW; if (srcSlope < userSlope) { diff --git a/torchvision/csrc/cpu/decoder/util.h b/torchvision/csrc/cpu/decoder/util.h index dbbfa33a091..01b550e5bbc 100644 --- a/torchvision/csrc/cpu/decoder/util.h +++ b/torchvision/csrc/cpu/decoder/util.h @@ -21,6 +21,7 @@ void setFormatDimensions( size_t srcW, size_t srcH, size_t minDimension, + size_t maxDimension, size_t cropImage); bool validateVideoFormat(const VideoFormat& format); } // namespace Util diff --git a/torchvision/csrc/cpu/decoder/util_test.cpp b/torchvision/csrc/cpu/decoder/util_test.cpp new file mode 100644 index 00000000000..80a316af5c9 --- /dev/null +++ b/torchvision/csrc/cpu/decoder/util_test.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include "util.h" + +TEST(Util, TestSetFormatDimensions) { + const size_t test_cases[][9] = { + // (userW, userH, srcW, srcH, minDimension, maxDimension, cropImage, destW, destH) + {0, 0, 172, 128, 0, 0, 0, 172, 128}, // #1 + {86, 0, 172, 128, 0, 0, 0, 86, 64}, // #2 + {64, 0, 128, 172, 0, 0, 0, 64, 86}, // #2 + {0, 32, 172, 128, 0, 0, 0, 43, 32}, // #3 + {32, 0, 128, 172, 0, 0, 0, 32, 43}, // #3 + {60, 50, 172, 128, 0, 0, 0, 60, 50}, // #4 + {50, 60, 128, 172, 0, 0, 0, 50, 60}, // #4 + {86, 40, 172, 128, 0, 0, 1, 86, 64}, // #5 + {86, 92, 172, 128, 0, 0, 1, 124, 92}, // #5 + {0, 0, 172, 128, 256, 0, 0, 344, 256}, // #6 + {0, 0, 128, 172, 256, 0, 0, 256, 344}, // #6 + {0, 0, 128, 172, 0, 344, 0, 256, 344}, // #7 + {0, 0, 172, 128, 0, 344, 0, 344, 256}, // #7 + {0, 0, 172, 128, 100, 344, 0, 344, 100},// #8 + {0, 0, 128, 172, 100, 344, 0, 100, 344} // #8 + }; + + for (const auto& tc : test_cases) { + size_t destW = 0; + size_t destH = 0; + ffmpeg::Util::setFormatDimensions(destW, destH, tc[0], tc[1], tc[2], tc[3], tc[4], tc[5], tc[6]); + CHECK(destW == tc[7]); + CHECK(destH == tc[8]); + } +} diff --git a/torchvision/csrc/cpu/decoder/video_sampler.cpp b/torchvision/csrc/cpu/decoder/video_sampler.cpp index 0c28fd9bb4e..5b9726b7c6c 100644 --- a/torchvision/csrc/cpu/decoder/video_sampler.cpp +++ b/torchvision/csrc/cpu/decoder/video_sampler.cpp @@ -87,6 +87,7 @@ bool VideoSampler::init(const SamplerParameters& params) { params.in.video.width, params.in.video.height, 0, + 0, 1); if (!(scaleFormat_ == params_.out.video)) { // crop required diff --git a/torchvision/csrc/cpu/decoder/video_stream.cpp b/torchvision/csrc/cpu/decoder/video_stream.cpp index 947b4a6214b..e18dbc2dbc6 100644 --- a/torchvision/csrc/cpu/decoder/video_stream.cpp +++ b/torchvision/csrc/cpu/decoder/video_stream.cpp @@ -68,6 +68,7 @@ int VideoStream::initFormat() { codecCtx_->width, codecCtx_->height, format_.format.video.minDimension, + format_.format.video.maxDimension, 0); if (format_.format.video.format == AV_PIX_FMT_NONE) { diff --git a/torchvision/csrc/cpu/video_reader/VideoReader.cpp b/torchvision/csrc/cpu/video_reader/VideoReader.cpp index 08b3f8c14a3..57801930926 100644 --- a/torchvision/csrc/cpu/video_reader/VideoReader.cpp +++ b/torchvision/csrc/cpu/video_reader/VideoReader.cpp @@ -44,6 +44,7 @@ DecoderParameters getDecoderParams( int videoWidth, int videoHeight, int videoMinDimension, + int videoMaxDimension, int64_t readAudioStream, int audioSamples, int audioChannels) { @@ -62,6 +63,7 @@ DecoderParameters getDecoderParams( videoFormat.format.video.width = videoWidth; videoFormat.format.video.height = videoHeight; videoFormat.format.video.minDimension = videoMinDimension; + videoFormat.format.video.maxDimension = videoMaxDimension; params.formats.insert(videoFormat); } @@ -190,6 +192,7 @@ torch::List readVideo( int64_t width, int64_t height, int64_t minDimension, + int64_t maxDimension, int64_t videoStartPts, int64_t videoEndPts, int64_t videoTimeBaseNum, @@ -227,6 +230,7 @@ torch::List readVideo( width, // width height, // height minDimension, // minDimension + maxDimension, // maxDimension readAudioStream, // readAudioStream audioSamples, // audioSamples audioChannels // audioChannels @@ -429,6 +433,7 @@ torch::List readVideoFromMemory( int64_t width, int64_t height, int64_t minDimension, + int64_t maxDimension, int64_t videoStartPts, int64_t videoEndPts, int64_t videoTimeBaseNum, @@ -450,6 +455,7 @@ torch::List readVideoFromMemory( width, height, minDimension, + maxDimension, videoStartPts, videoEndPts, videoTimeBaseNum, @@ -471,6 +477,7 @@ torch::List readVideoFromFile( int64_t width, int64_t height, int64_t minDimension, + int64_t maxDimension, int64_t videoStartPts, int64_t videoEndPts, int64_t videoTimeBaseNum, @@ -493,6 +500,7 @@ torch::List readVideoFromFile( width, height, minDimension, + maxDimension, videoStartPts, videoEndPts, videoTimeBaseNum, @@ -519,6 +527,7 @@ torch::List probeVideo( 0, // width 0, // height 0, // minDimension + 0, // maxDimension 1, // readAudioStream 0, // audioSamples 0 // audioChannels diff --git a/torchvision/datasets/video_utils.py b/torchvision/datasets/video_utils.py index 303a3375953..d743cc49b13 100644 --- a/torchvision/datasets/video_utils.py +++ b/torchvision/datasets/video_utils.py @@ -98,6 +98,7 @@ def __init__( _video_width=0, _video_height=0, _video_min_dimension=0, + _video_max_dimension=0, _audio_samples=0, _audio_channels=0, ): @@ -109,6 +110,7 @@ def __init__( self._video_width = _video_width self._video_height = _video_height self._video_min_dimension = _video_min_dimension + self._video_max_dimension = _video_max_dimension self._audio_samples = _audio_samples self._audio_channels = _audio_channels @@ -182,6 +184,7 @@ def subset(self, indices): _video_width=self._video_width, _video_height=self._video_height, _video_min_dimension=self._video_min_dimension, + _video_max_dimension=self._video_max_dimension, _audio_samples=self._audio_samples, _audio_channels=self._audio_channels, ) @@ -302,6 +305,10 @@ def get_clip(self, idx): raise ValueError( "pyav backend doesn't support _video_min_dimension != 0" ) + if self._video_max_dimension != 0: + raise ValueError( + "pyav backend doesn't support _video_max_dimension != 0" + ) if self._audio_samples != 0: raise ValueError("pyav backend doesn't support _audio_samples != 0") @@ -338,6 +345,7 @@ def get_clip(self, idx): video_width=self._video_width, video_height=self._video_height, video_min_dimension=self._video_min_dimension, + video_max_dimension=self._video_max_dimension, video_pts_range=(video_start_pts, video_end_pts), video_timebase=video_timebase, audio_samples=self._audio_samples, diff --git a/torchvision/io/_video_opt.py b/torchvision/io/_video_opt.py index aa4b4244962..4c39529b950 100644 --- a/torchvision/io/_video_opt.py +++ b/torchvision/io/_video_opt.py @@ -138,6 +138,7 @@ def _read_video_from_file( video_width=0, video_height=0, video_min_dimension=0, + video_max_dimension=0, video_pts_range=(0, -1), video_timebase=default_timebase, read_audio_stream=True, @@ -155,21 +156,34 @@ def _read_video_from_file( filename : str path to the video file seek_frame_margin: double, optional - seeking frame in the stream is imprecise. Thus, when video_start_pts is specified, - we seek the pts earlier by seek_frame_margin seconds + seeking frame in the stream is imprecise. Thus, when video_start_pts + is specified, we seek the pts earlier by seek_frame_margin seconds read_video_stream: int, optional whether read video stream. If yes, set to 1. Otherwise, 0 - video_width/video_height/video_min_dimension: int + video_width/video_height/video_min_dimension/video_max_dimension: int together decide the size of decoded frames - - when video_width = 0, video_height = 0, and video_min_dimension = 0, keep the orignal frame resolution - - when video_width = 0, video_height = 0, and video_min_dimension != 0, keep the aspect ratio and resize - the frame so that shorter edge size is video_min_dimension - - When video_width = 0, and video_height != 0, keep the aspect ratio and resize the frame - so that frame video_height is $video_height - - When video_width != 0, and video_height == 0, keep the aspect ratio and resize the frame - so that frame video_height is $video_width - - When video_width != 0, and video_height != 0, resize the frame so that frame video_width and video_height - are set to $video_width and $video_height, respectively + - When video_width = 0, video_height = 0, video_min_dimension = 0, + and video_max_dimension = 0, keep the orignal frame resolution + - When video_width = 0, video_height = 0, video_min_dimension != 0, + and video_max_dimension = 0, keep the aspect ratio and resize the + frame so that shorter edge size is video_min_dimension + - When video_width = 0, video_height = 0, video_min_dimension = 0, + and video_max_dimension != 0, keep the aspect ratio and resize + the frame so that longer edge size is video_max_dimension + - When video_width = 0, video_height = 0, video_min_dimension != 0, + and video_max_dimension != 0, resize the frame so that shorter + edge size is video_min_dimension, and longer edge size is + video_max_dimension. The aspect ratio may not be preserved + - When video_width = 0, video_height != 0, video_min_dimension = 0, + and video_max_dimension = 0, keep the aspect ratio and resize + the frame so that frame video_height is $video_height + - When video_width != 0, video_height == 0, video_min_dimension = 0, + and video_max_dimension = 0, keep the aspect ratio and resize + the frame so that frame video_width is $video_width + - When video_width != 0, video_height != 0, video_min_dimension = 0, + and video_max_dimension = 0, resize the frame so that frame + video_width and video_height are set to $video_width and + $video_height, respectively video_pts_range : list(int), optional the start and end presentation timestamp of video stream video_timebase: Fraction, optional @@ -207,6 +221,7 @@ def _read_video_from_file( video_width, video_height, video_min_dimension, + video_max_dimension, video_pts_range[0], video_pts_range[1], video_timebase.numerator, @@ -244,6 +259,7 @@ def _read_video_timestamps_from_file(filename): 0, # video_width 0, # video_height 0, # video_min_dimension + 0, # video_max_dimension 0, # video_start_pts -1, # video_end_pts 0, # video_timebase_num @@ -282,6 +298,7 @@ def _read_video_from_memory( video_width=0, # type: int video_height=0, # type: int video_min_dimension=0, # type: int + video_max_dimension=0, # type: int video_pts_range=(0, -1), # type: List[int] video_timebase_numerator=0, # type: int video_timebase_denominator=1, # type: int @@ -307,17 +324,30 @@ def _read_video_from_memory( we seek the pts earlier by seek_frame_margin seconds read_video_stream: int, optional whether read video stream. If yes, set to 1. Otherwise, 0 - video_width/video_height/video_min_dimension: int + video_width/video_height/video_min_dimension/video_max_dimension: int together decide the size of decoded frames - - when video_width = 0, video_height = 0, and video_min_dimension = 0, keep the orignal frame resolution - - when video_width = 0, video_height = 0, and video_min_dimension != 0, keep the aspect ratio and resize - the frame so that shorter edge size is video_min_dimension - - When video_width = 0, and video_height != 0, keep the aspect ratio and resize the frame - so that frame video_height is $video_height - - When video_width != 0, and video_height == 0, keep the aspect ratio and resize the frame - so that frame video_height is $video_width - - When video_width != 0, and video_height != 0, resize the frame so that frame video_width and video_height - are set to $video_width and $video_height, respectively + - When video_width = 0, video_height = 0, video_min_dimension = 0, + and video_max_dimension = 0, keep the orignal frame resolution + - When video_width = 0, video_height = 0, video_min_dimension != 0, + and video_max_dimension = 0, keep the aspect ratio and resize the + frame so that shorter edge size is video_min_dimension + - When video_width = 0, video_height = 0, video_min_dimension = 0, + and video_max_dimension != 0, keep the aspect ratio and resize + the frame so that longer edge size is video_max_dimension + - When video_width = 0, video_height = 0, video_min_dimension != 0, + and video_max_dimension != 0, resize the frame so that shorter + edge size is video_min_dimension, and longer edge size is + video_max_dimension. The aspect ratio may not be preserved + - When video_width = 0, video_height != 0, video_min_dimension = 0, + and video_max_dimension = 0, keep the aspect ratio and resize + the frame so that frame video_height is $video_height + - When video_width != 0, video_height == 0, video_min_dimension = 0, + and video_max_dimension = 0, keep the aspect ratio and resize + the frame so that frame video_width is $video_width + - When video_width != 0, video_height != 0, video_min_dimension = 0, + and video_max_dimension = 0, resize the frame so that frame + video_width and video_height are set to $video_width and + $video_height, respectively video_pts_range : list(int), optional the start and end presentation timestamp of video stream video_timebase_numerator / video_timebase_denominator: optional @@ -353,6 +383,7 @@ def _read_video_from_memory( video_width, video_height, video_min_dimension, + video_max_dimension, video_pts_range[0], video_pts_range[1], video_timebase_numerator, @@ -394,6 +425,7 @@ def _read_video_timestamps_from_memory(video_data): 0, # video_width 0, # video_height 0, # video_min_dimension + 0, # video_max_dimension 0, # video_start_pts -1, # video_end_pts 0, # video_timebase_num diff --git a/torchvision/io/video.py b/torchvision/io/video.py index 96cf7feeb79..5729f1b54dd 100644 --- a/torchvision/io/video.py +++ b/torchvision/io/video.py @@ -370,6 +370,7 @@ def read_video_from_memory( audio_pts_range=(0, -1), # type: List[int] audio_timebase_numerator=0, # type: int audio_timebase_denominator=1, # type: int + video_max_dimension=0, # type: int ): # type: (...) -> Tuple[torch.Tensor, torch.Tensor] return _video_opt._read_video_from_memory( @@ -379,6 +380,7 @@ def read_video_from_memory( video_width, video_height, video_min_dimension, + video_max_dimension, video_pts_range, video_timebase_numerator, video_timebase_denominator, From 7bc93032d246a1cfc206118351b3915d7dc17833 Mon Sep 17 00:00:00 2001 From: Yuri Putivsky Date: Wed, 11 Mar 2020 17:37:54 -0700 Subject: [PATCH 055/357] Fixing samplers initialization (#1967) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1967 No-ops for torchvision diff, which fixes samplers. Differential Revision: D20397218 fbshipit-source-id: 6dc4d04364f305fbda7ca4f67a25ceecd73d0f20 --- torchvision/csrc/cpu/decoder/audio_stream.cpp | 1 + torchvision/csrc/cpu/decoder/video_stream.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/torchvision/csrc/cpu/decoder/audio_stream.cpp b/torchvision/csrc/cpu/decoder/audio_stream.cpp index 513128a66ac..9d66e589bf3 100644 --- a/torchvision/csrc/cpu/decoder/audio_stream.cpp +++ b/torchvision/csrc/cpu/decoder/audio_stream.cpp @@ -79,6 +79,7 @@ int AudioStream::copyFrameBytes(ByteStorage* out, bool flush) { SamplerParameters params; params.type = format_.type; params.out = format_.format; + params.in = FormatUnion(); flush ? toAudioFormat(params.in.audio, *codecCtx_) : toAudioFormat(params.in.audio, *frame_); if (!sampler_->init(params)) { diff --git a/torchvision/csrc/cpu/decoder/video_stream.cpp b/torchvision/csrc/cpu/decoder/video_stream.cpp index e18dbc2dbc6..a9e20434fe0 100644 --- a/torchvision/csrc/cpu/decoder/video_stream.cpp +++ b/torchvision/csrc/cpu/decoder/video_stream.cpp @@ -92,6 +92,7 @@ int VideoStream::copyFrameBytes(ByteStorage* out, bool flush) { SamplerParameters params; params.type = format_.type; params.out = format_.format; + params.in = FormatUnion(0); flush ? toVideoFormat(params.in.video, *codecCtx_) : toVideoFormat(params.in.video, *frame_); if (!sampler_->init(params)) { From 7d2e56a149b3456f326663dcc4e084048ff81642 Mon Sep 17 00:00:00 2001 From: Eli Uriegas Date: Fri, 20 Mar 2020 08:45:34 -0700 Subject: [PATCH 056/357] Import 1731 1885 1960 1980 (#2000) Summary: Imports CircleCI improvements Pull Request resolved: https://github.com/pytorch/vision/pull/2000 Reviewed By: zhangguanheng66 Differential Revision: D20556382 Pulled By: fmassa fbshipit-source-id: 068bd43cc036c886f4c1fa02944325aafde5dc3a --- .circleci/config.yml | 447 ++++++++++++++++++++++------- .circleci/config.yml.in | 16 +- .circleci/regenerate.py | 23 +- packaging/build_conda.sh | 1 + packaging/pkg_helpers.bash | 23 +- packaging/torchvision/meta.yaml | 2 +- packaging/wheel/linux_manywheel.sh | 4 +- test/test_quantized_models.py | 5 +- 8 files changed, 402 insertions(+), 119 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b16fae311aa..02a24180bc4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -105,6 +105,8 @@ jobs: root: /opt/conda/conda-bld/linux-64 paths: - "*" + - store_test_results: + path: build_results/ binary_linux_conda_cuda: <<: *binary_common @@ -190,6 +192,8 @@ jobs: conda install -yq conda-build "conda-package-handling!=1.5.0" bash packaging/build_conda.sh shell: powershell.exe + - store_test_results: + path: build_results/ binary_win_conda_cuda: <<: *binary_common @@ -246,6 +250,8 @@ jobs: root: /Users/distiller/miniconda3/conda-bld/osx-64 paths: - "*" + - store_test_results: + path: build_results/ # Requires org-member context binary_conda_upload: @@ -258,12 +264,8 @@ jobs: command: | # Prevent credential from leaking conda install -yq anaconda-client - set +x - anaconda login \ - --username "$PYTORCH_BINARY_PJH5_CONDA_USERNAME" \ - --password "$PYTORCH_BINARY_PJH5_CONDA_PASSWORD" set -x - anaconda upload ~/workspace/*.tar.bz2 -u pytorch-nightly --label main --no-progress --force + anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u pytorch-nightly --label main --no-progress --force # Requires org-member context binary_wheel_upload: @@ -299,138 +301,202 @@ workflows: cu_version: cpu name: binary_linux_wheel_py3.5_cpu python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: cu_version: cu92 name: binary_linux_wheel_py3.5_cu92 python_version: '3.5' wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_wheel: - cu_version: cu100 - name: binary_linux_wheel_py3.5_cu100 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_wheel: cu_version: cu101 name: binary_linux_wheel_py3.5_cu101 python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_linux_wheel: + cu_version: cu102 + name: binary_linux_wheel_py3.5_cu102 + python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: cu_version: cpu name: binary_linux_wheel_py3.6_cpu python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: cu_version: cu92 name: binary_linux_wheel_py3.6_cu92 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_wheel: - cu_version: cu100 - name: binary_linux_wheel_py3.6_cu100 - python_version: '3.6' - wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_wheel: cu_version: cu101 name: binary_linux_wheel_py3.6_cu101 python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_linux_wheel: + cu_version: cu102 + name: binary_linux_wheel_py3.6_cu102 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: cu_version: cpu name: binary_linux_wheel_py3.7_cpu python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: cu_version: cu92 name: binary_linux_wheel_py3.7_cu92 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_wheel: - cu_version: cu100 - name: binary_linux_wheel_py3.7_cu100 - python_version: '3.7' - wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_wheel: cu_version: cu101 name: binary_linux_wheel_py3.7_cu101 python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_linux_wheel: + cu_version: cu102 + name: binary_linux_wheel_py3.7_cu102 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_wheel: + cu_version: cpu + name: binary_linux_wheel_py3.8_cpu + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_wheel: + cu_version: cu92 + name: binary_linux_wheel_py3.8_cu92 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda92 + - binary_linux_wheel: + cu_version: cu101 + name: binary_linux_wheel_py3.8_cu101 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_linux_wheel: + cu_version: cu102 + name: binary_linux_wheel_py3.8_cu102 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_macos_wheel: cu_version: cpu name: binary_macos_wheel_py3.5_cpu python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_macos_wheel: cu_version: cpu name: binary_macos_wheel_py3.6_cpu python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_macos_wheel: cu_version: cpu name: binary_macos_wheel_py3.7_cpu python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_macos_wheel: + cu_version: cpu + name: binary_macos_wheel_py3.8_cpu + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: cu_version: cpu name: binary_linux_conda_py3.5_cpu python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: cu_version: cu92 name: binary_linux_conda_py3.5_cu92 python_version: '3.5' wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_conda: - cu_version: cu100 - name: binary_linux_conda_py3.5_cu100 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_conda: cu_version: cu101 name: binary_linux_conda_py3.5_cu101 python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_linux_conda: + cu_version: cu102 + name: binary_linux_conda_py3.5_cu102 + python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: cu_version: cpu name: binary_linux_conda_py3.6_cpu python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: cu_version: cu92 name: binary_linux_conda_py3.6_cu92 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_conda: - cu_version: cu100 - name: binary_linux_conda_py3.6_cu100 - python_version: '3.6' - wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_conda: cu_version: cu101 name: binary_linux_conda_py3.6_cu101 python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_linux_conda: + cu_version: cu102 + name: binary_linux_conda_py3.6_cu102 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: cu_version: cpu name: binary_linux_conda_py3.7_cpu python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: cu_version: cu92 name: binary_linux_conda_py3.7_cu92 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_conda: - cu_version: cu100 - name: binary_linux_conda_py3.7_cu100 - python_version: '3.7' - wheel_docker_image: pytorch/manylinux-cuda100 - binary_linux_conda: cu_version: cu101 name: binary_linux_conda_py3.7_cu101 python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_linux_conda: + cu_version: cu102 + name: binary_linux_conda_py3.7_cu102 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_conda: + cu_version: cpu + name: binary_linux_conda_py3.8_cpu + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_conda: + cu_version: cu92 + name: binary_linux_conda_py3.8_cu92 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda92 + - binary_linux_conda: + cu_version: cu101 + name: binary_linux_conda_py3.8_cu101 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_linux_conda: + cu_version: cu102 + name: binary_linux_conda_py3.8_cu102 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_macos_conda: cu_version: cpu name: binary_macos_conda_py3.5_cpu python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_macos_conda: cu_version: cpu name: binary_macos_conda_py3.6_cpu python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_macos_conda: cu_version: cpu name: binary_macos_conda_py3.7_cpu python_version: '3.7' - - binary_linux_conda_cuda: - name: torchvision_linux_py3.7_cu100 - python_version: "3.7" - cu_version: "cu100" + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_macos_conda: + cu_version: cpu + name: binary_macos_conda_py3.8_cpu + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_win_conda: name: torchvision_win_py3.6_cpu python_version: "3.6" @@ -450,6 +516,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py3.5_cpu python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: @@ -477,38 +544,39 @@ workflows: - nightly_binary_linux_wheel_py3.5_cu92 subfolder: cu92/ - binary_linux_wheel: - cu_version: cu100 + cu_version: cu101 filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.5_cu100 + name: nightly_binary_linux_wheel_py3.5_cu101 python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda101 - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.5_cu100_upload + name: nightly_binary_linux_wheel_py3.5_cu101_upload requires: - - nightly_binary_linux_wheel_py3.5_cu100 - subfolder: cu100/ + - nightly_binary_linux_wheel_py3.5_cu101 + subfolder: cu101/ - binary_linux_wheel: - cu_version: cu101 + cu_version: cu102 filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.5_cu101 + name: nightly_binary_linux_wheel_py3.5_cu102 python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.5_cu101_upload + name: nightly_binary_linux_wheel_py3.5_cu102_upload requires: - - nightly_binary_linux_wheel_py3.5_cu101 - subfolder: cu101/ + - nightly_binary_linux_wheel_py3.5_cu102 + subfolder: cu102/ - binary_linux_wheel: cu_version: cpu filters: @@ -516,6 +584,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py3.6_cpu python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: @@ -543,38 +612,39 @@ workflows: - nightly_binary_linux_wheel_py3.6_cu92 subfolder: cu92/ - binary_linux_wheel: - cu_version: cu100 + cu_version: cu101 filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.6_cu100 + name: nightly_binary_linux_wheel_py3.6_cu101 python_version: '3.6' - wheel_docker_image: pytorch/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda101 - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.6_cu100_upload + name: nightly_binary_linux_wheel_py3.6_cu101_upload requires: - - nightly_binary_linux_wheel_py3.6_cu100 - subfolder: cu100/ + - nightly_binary_linux_wheel_py3.6_cu101 + subfolder: cu101/ - binary_linux_wheel: - cu_version: cu101 + cu_version: cu102 filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.6_cu101 + name: nightly_binary_linux_wheel_py3.6_cu102 python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.6_cu101_upload + name: nightly_binary_linux_wheel_py3.6_cu102_upload requires: - - nightly_binary_linux_wheel_py3.6_cu101 - subfolder: cu101/ + - nightly_binary_linux_wheel_py3.6_cu102 + subfolder: cu102/ - binary_linux_wheel: cu_version: cpu filters: @@ -582,6 +652,7 @@ workflows: only: nightly name: nightly_binary_linux_wheel_py3.7_cpu python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: @@ -609,38 +680,107 @@ workflows: - nightly_binary_linux_wheel_py3.7_cu92 subfolder: cu92/ - binary_linux_wheel: - cu_version: cu100 + cu_version: cu101 filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.7_cu100 + name: nightly_binary_linux_wheel_py3.7_cu101 python_version: '3.7' - wheel_docker_image: pytorch/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda101 - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.7_cu100_upload + name: nightly_binary_linux_wheel_py3.7_cu101_upload requires: - - nightly_binary_linux_wheel_py3.7_cu100 - subfolder: cu100/ + - nightly_binary_linux_wheel_py3.7_cu101 + subfolder: cu101/ - binary_linux_wheel: - cu_version: cu101 + cu_version: cu102 filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.7_cu101 + name: nightly_binary_linux_wheel_py3.7_cu102 python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_wheel_py3.7_cu101_upload + name: nightly_binary_linux_wheel_py3.7_cu102_upload requires: - - nightly_binary_linux_wheel_py3.7_cu101 + - nightly_binary_linux_wheel_py3.7_cu102 + subfolder: cu102/ + - binary_linux_wheel: + cu_version: cpu + filters: + branches: + only: nightly + name: nightly_binary_linux_wheel_py3.8_cpu + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_linux_wheel_py3.8_cpu_upload + requires: + - nightly_binary_linux_wheel_py3.8_cpu + subfolder: cpu/ + - binary_linux_wheel: + cu_version: cu92 + filters: + branches: + only: nightly + name: nightly_binary_linux_wheel_py3.8_cu92 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda92 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_linux_wheel_py3.8_cu92_upload + requires: + - nightly_binary_linux_wheel_py3.8_cu92 + subfolder: cu92/ + - binary_linux_wheel: + cu_version: cu101 + filters: + branches: + only: nightly + name: nightly_binary_linux_wheel_py3.8_cu101 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_linux_wheel_py3.8_cu101_upload + requires: + - nightly_binary_linux_wheel_py3.8_cu101 subfolder: cu101/ + - binary_linux_wheel: + cu_version: cu102 + filters: + branches: + only: nightly + name: nightly_binary_linux_wheel_py3.8_cu102 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_linux_wheel_py3.8_cu102_upload + requires: + - nightly_binary_linux_wheel_py3.8_cu102 + subfolder: cu102/ - binary_macos_wheel: cu_version: cpu filters: @@ -648,6 +788,7 @@ workflows: only: nightly name: nightly_binary_macos_wheel_py3.5_cpu python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: @@ -664,6 +805,7 @@ workflows: only: nightly name: nightly_binary_macos_wheel_py3.6_cpu python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: @@ -680,6 +822,7 @@ workflows: only: nightly name: nightly_binary_macos_wheel_py3.7_cpu python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_wheel_upload: context: org-member filters: @@ -689,6 +832,23 @@ workflows: requires: - nightly_binary_macos_wheel_py3.7_cpu subfolder: '' + - binary_macos_wheel: + cu_version: cpu + filters: + branches: + only: nightly + name: nightly_binary_macos_wheel_py3.8_cpu + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_macos_wheel_py3.8_cpu_upload + requires: + - nightly_binary_macos_wheel_py3.8_cpu + subfolder: '' - binary_linux_conda: cu_version: cpu filters: @@ -696,6 +856,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py3.5_cpu python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_conda_upload: context: org-member filters: @@ -721,36 +882,37 @@ workflows: requires: - nightly_binary_linux_conda_py3.5_cu92 - binary_linux_conda: - cu_version: cu100 + cu_version: cu101 filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu100 + name: nightly_binary_linux_conda_py3.5_cu101 python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda101 - binary_conda_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu100_upload + name: nightly_binary_linux_conda_py3.5_cu101_upload requires: - - nightly_binary_linux_conda_py3.5_cu100 + - nightly_binary_linux_conda_py3.5_cu101 - binary_linux_conda: - cu_version: cu101 + cu_version: cu102 filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu101 + name: nightly_binary_linux_conda_py3.5_cu102 python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_conda_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu101_upload + name: nightly_binary_linux_conda_py3.5_cu102_upload requires: - - nightly_binary_linux_conda_py3.5_cu101 + - nightly_binary_linux_conda_py3.5_cu102 - binary_linux_conda: cu_version: cpu filters: @@ -758,6 +920,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py3.6_cpu python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_conda_upload: context: org-member filters: @@ -783,36 +946,37 @@ workflows: requires: - nightly_binary_linux_conda_py3.6_cu92 - binary_linux_conda: - cu_version: cu100 + cu_version: cu101 filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.6_cu100 + name: nightly_binary_linux_conda_py3.6_cu101 python_version: '3.6' - wheel_docker_image: pytorch/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda101 - binary_conda_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.6_cu100_upload + name: nightly_binary_linux_conda_py3.6_cu101_upload requires: - - nightly_binary_linux_conda_py3.6_cu100 + - nightly_binary_linux_conda_py3.6_cu101 - binary_linux_conda: - cu_version: cu101 + cu_version: cu102 filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.6_cu101 + name: nightly_binary_linux_conda_py3.6_cu102 python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_conda_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.6_cu101_upload + name: nightly_binary_linux_conda_py3.6_cu102_upload requires: - - nightly_binary_linux_conda_py3.6_cu101 + - nightly_binary_linux_conda_py3.6_cu102 - binary_linux_conda: cu_version: cpu filters: @@ -820,6 +984,7 @@ workflows: only: nightly name: nightly_binary_linux_conda_py3.7_cpu python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_conda_upload: context: org-member filters: @@ -845,36 +1010,101 @@ workflows: requires: - nightly_binary_linux_conda_py3.7_cu92 - binary_linux_conda: - cu_version: cu100 + cu_version: cu101 filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.7_cu100 + name: nightly_binary_linux_conda_py3.7_cu101 python_version: '3.7' - wheel_docker_image: pytorch/manylinux-cuda100 + wheel_docker_image: pytorch/manylinux-cuda101 - binary_conda_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.7_cu100_upload + name: nightly_binary_linux_conda_py3.7_cu101_upload requires: - - nightly_binary_linux_conda_py3.7_cu100 + - nightly_binary_linux_conda_py3.7_cu101 - binary_linux_conda: - cu_version: cu101 + cu_version: cu102 filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.7_cu101 + name: nightly_binary_linux_conda_py3.7_cu102 python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_conda_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.7_cu101_upload + name: nightly_binary_linux_conda_py3.7_cu102_upload requires: - - nightly_binary_linux_conda_py3.7_cu101 + - nightly_binary_linux_conda_py3.7_cu102 + - binary_linux_conda: + cu_version: cpu + filters: + branches: + only: nightly + name: nightly_binary_linux_conda_py3.8_cpu + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_linux_conda_py3.8_cpu_upload + requires: + - nightly_binary_linux_conda_py3.8_cpu + - binary_linux_conda: + cu_version: cu92 + filters: + branches: + only: nightly + name: nightly_binary_linux_conda_py3.8_cu92 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda92 + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_linux_conda_py3.8_cu92_upload + requires: + - nightly_binary_linux_conda_py3.8_cu92 + - binary_linux_conda: + cu_version: cu101 + filters: + branches: + only: nightly + name: nightly_binary_linux_conda_py3.8_cu101 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda101 + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_linux_conda_py3.8_cu101_upload + requires: + - nightly_binary_linux_conda_py3.8_cu101 + - binary_linux_conda: + cu_version: cu102 + filters: + branches: + only: nightly + name: nightly_binary_linux_conda_py3.8_cu102 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_linux_conda_py3.8_cu102_upload + requires: + - nightly_binary_linux_conda_py3.8_cu102 - binary_macos_conda: cu_version: cpu filters: @@ -882,6 +1112,7 @@ workflows: only: nightly name: nightly_binary_macos_conda_py3.5_cpu python_version: '3.5' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_conda_upload: context: org-member filters: @@ -897,6 +1128,7 @@ workflows: only: nightly name: nightly_binary_macos_conda_py3.6_cpu python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_conda_upload: context: org-member filters: @@ -912,6 +1144,7 @@ workflows: only: nightly name: nightly_binary_macos_conda_py3.7_cpu python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda102 - binary_conda_upload: context: org-member filters: @@ -919,4 +1152,20 @@ workflows: only: nightly name: nightly_binary_macos_conda_py3.7_cpu_upload requires: - - nightly_binary_macos_conda_py3.7_cpu \ No newline at end of file + - nightly_binary_macos_conda_py3.7_cpu + - binary_macos_conda: + cu_version: cpu + filters: + branches: + only: nightly + name: nightly_binary_macos_conda_py3.8_cpu + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda102 + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + name: nightly_binary_macos_conda_py3.8_cpu_upload + requires: + - nightly_binary_macos_conda_py3.8_cpu \ No newline at end of file diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index e3747134c6f..62d411ce4b8 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -105,6 +105,8 @@ jobs: root: /opt/conda/conda-bld/linux-64 paths: - "*" + - store_test_results: + path: build_results/ binary_linux_conda_cuda: <<: *binary_common @@ -190,6 +192,8 @@ jobs: conda install -yq conda-build "conda-package-handling!=1.5.0" bash packaging/build_conda.sh shell: powershell.exe + - store_test_results: + path: build_results/ binary_win_conda_cuda: <<: *binary_common @@ -246,6 +250,8 @@ jobs: root: /Users/distiller/miniconda3/conda-bld/osx-64 paths: - "*" + - store_test_results: + path: build_results/ # Requires org-member context binary_conda_upload: @@ -258,12 +264,8 @@ jobs: command: | # Prevent credential from leaking conda install -yq anaconda-client - set +x - anaconda login \ - --username "$PYTORCH_BINARY_PJH5_CONDA_USERNAME" \ - --password "$PYTORCH_BINARY_PJH5_CONDA_PASSWORD" set -x - anaconda upload ~/workspace/*.tar.bz2 -u pytorch-nightly --label main --no-progress --force + anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u pytorch-nightly --label main --no-progress --force # Requires org-member context binary_wheel_upload: @@ -297,10 +299,6 @@ workflows: jobs: - circleci_consistency {{ workflows() }} - - binary_linux_conda_cuda: - name: torchvision_linux_py3.7_cu100 - python_version: "3.7" - cu_version: "cu100" - binary_win_conda: name: torchvision_win_py3.6_cpu python_version: "3.6" diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index f47533d0016..24c40506417 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -23,8 +23,8 @@ def workflows(prefix='', filter_branch=None, upload=False, indentation=6): w = [] for btype in ["wheel", "conda"]: for os_type in ["linux", "macos"]: - for python_version in ["3.5", "3.6", "3.7"]: - for cu_version in (["cpu", "cu92", "cu100", "cu101"] if os_type == "linux" else ["cpu"]): + for python_version in ["3.5", "3.6", "3.7", "3.8"]: + for cu_version in (["cpu", "cu92", "cu101", "cu102"] if os_type == "linux" else ["cpu"]): for unicode in ([False, True] if btype == "wheel" and python_version == "2.7" else [False]): w += workflow_pair( btype, os_type, python_version, cu_version, @@ -49,6 +49,20 @@ def workflow_pair(btype, os_type, python_version, cu_version, unicode, prefix='' return w +manylinux_images = { + "cu92": "pytorch/manylinux-cuda92", + "cu101": "pytorch/manylinux-cuda101", + "cu102": "pytorch/manylinux-cuda102", +} + + +def get_manylinux_image(cu_version): + cu_suffix = "102" + if cu_version.startswith('cu'): + cu_suffix = cu_version[len('cu'):] + return f"pytorch/manylinux-cuda{cu_suffix}" + + def generate_base_workflow(base_workflow_name, python_version, cu_version, unicode, os_type, btype, *, filter_branch=None): @@ -61,10 +75,7 @@ def generate_base_workflow(base_workflow_name, python_version, cu_version, if unicode: d["unicode_abi"] = '1' - if cu_version == "cu92": - d["wheel_docker_image"] = "pytorch/manylinux-cuda92" - elif cu_version == "cu100": - d["wheel_docker_image"] = "pytorch/manylinux-cuda100" + d["wheel_docker_image"] = get_manylinux_image(cu_version) if filter_branch is not None: d["filters"] = {"branches": {"only": filter_branch}} diff --git a/packaging/build_conda.sh b/packaging/build_conda.sh index 61022f3c5fa..9ec011d7d75 100755 --- a/packaging/build_conda.sh +++ b/packaging/build_conda.sh @@ -10,4 +10,5 @@ export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint setup_conda_cudatoolkit_constraint setup_visual_studio_constraint +setup_junit_results_folder conda build $CONDA_CHANNEL_FLAGS -c defaults -c conda-forge --no-anaconda-upload --python "$PYTHON_VERSION" packaging/torchvision diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 71fd6e736be..9e87fcfe8a1 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -36,7 +36,7 @@ setup_cuda() { # Wheel builds need suffixes (but not if they're on OS X, which never has suffix) if [[ "$BUILD_TYPE" == "wheel" ]] && [[ "$(uname)" != Darwin ]]; then # The default CUDA has no suffix - if [[ "$CU_VERSION" != "cu101" ]]; then + if [[ "$CU_VERSION" != "cu102" ]]; then export PYTORCH_VERSION_SUFFIX="+$CU_VERSION" fi # Match the suffix scheme of pytorch, unless this package does not have @@ -49,6 +49,17 @@ setup_cuda() { # Now work out the CUDA settings case "$CU_VERSION" in + cu102) + if [[ "$OSTYPE" == "msys" ]]; then + export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2" + else + export CUDA_HOME=/usr/local/cuda-10.2/ + fi + export FORCE_CUDA=1 + # Hard-coding gencode flags is temporary situation until + # https://github.com/pytorch/pytorch/pull/23408 lands + export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_50,code=compute_50" + ;; cu101) if [[ "$OSTYPE" == "msys" ]]; then export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.1" @@ -165,6 +176,7 @@ setup_wheel_python() { 3.5) python_abi=cp35-cp35m ;; 3.6) python_abi=cp36-cp36m ;; 3.7) python_abi=cp37-cp37m ;; + 3.8) python_abi=cp38-cp38 ;; *) echo "Unrecognized PYTHON_VERSION=$PYTHON_VERSION" exit 1 @@ -239,6 +251,9 @@ setup_conda_cudatoolkit_constraint() { export CONDA_CUDATOOLKIT_CONSTRAINT="" else case "$CU_VERSION" in + cu102) + export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=10.2,<10.3 # [not osx]" + ;; cu101) export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=10.1,<10.2 # [not osx]" ;; @@ -269,3 +284,9 @@ setup_visual_studio_constraint() { cp packaging/$VSTOOLCHAIN_PACKAGE/conda_build_config.yaml packaging/torchvision/conda_build_config.yaml fi } + +setup_junit_results_folder() { + if [[ "$CI" == "true" ]]; then + export CONDA_PYTORCH_BUILD_RESULTS_DIRECTORY="${SOURCE_ROOT_DIR}/build_results/results.xml" + fi +} diff --git a/packaging/torchvision/meta.yaml b/packaging/torchvision/meta.yaml index 1bc199e437b..a97bc429e32 100644 --- a/packaging/torchvision/meta.yaml +++ b/packaging/torchvision/meta.yaml @@ -49,7 +49,7 @@ test: - ca-certificates {{ environ.get('CONDA_TYPING_CONSTRAINT') }} commands: - pytest . + pytest . --verbose --junitxml={{ environ.get("CONDA_PYTORCH_BUILD_RESULTS_DIRECTORY", "build/test_results.xml" )}} about: diff --git a/packaging/wheel/linux_manywheel.sh b/packaging/wheel/linux_manywheel.sh index d04e334d237..19e7d1a7500 100644 --- a/packaging/wheel/linux_manywheel.sh +++ b/packaging/wheel/linux_manywheel.sh @@ -6,9 +6,9 @@ if [ "$#" -ne 1 ]; then echo "CUDA version should be cu92, cu100 or cpu" exit 1 fi -export CUVER="$1" # cu92 cu100 cpu +export CUVER="$1" # cu[0-9]* cpu -if [[ "$CUVER" == "cu101" ]]; then +if [[ "$CUVER" == "cu102" ]]; then cu_suffix="" else cu_suffix="+$CUVER" diff --git a/test/test_quantized_models.py b/test/test_quantized_models.py index f20cc369276..d8fd5325755 100644 --- a/test/test_quantized_models.py +++ b/test/test_quantized_models.py @@ -83,7 +83,10 @@ def do_test(self, model_name=model_name): input_shape = (1, 3, 299, 299) self._test_classification_model(model_name, input_shape) - setattr(ModelTester, "test_" + model_name, do_test) + # inception_v3 was causing timeouts on circleci + # See https://github.com/pytorch/vision/issues/1857 + if model_name not in ['inception_v3']: + setattr(ModelTester, "test_" + model_name, do_test) if __name__ == '__main__': From 00d4933a75d7239cc930cf7342b4420f9e7c90bd Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Fri, 20 Mar 2020 08:47:02 -0700 Subject: [PATCH 057/357] Exclude C++ test files (#1990) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/1990 Reviewed By: zhangguanheng66 Differential Revision: D20487850 Pulled By: fmassa fbshipit-source-id: 222a4cd92c3bfa01a47d85096912417814408788 --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f763bd2c42c..0e5dfc3a18e 100644 --- a/setup.py +++ b/setup.py @@ -159,7 +159,8 @@ def get_extensions(): video_reader_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'video_reader') video_reader_src = glob.glob(os.path.join(video_reader_src_dir, "*.cpp")) base_decoder_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'decoder') - base_decoder_src = glob.glob(os.path.join(base_decoder_src_dir, "[!sync_decoder_test]*.cpp")) + base_decoder_src = glob.glob( + os.path.join(base_decoder_src_dir, "[!sync_decoder_test,!utils_test]*.cpp")) combined_src = video_reader_src + base_decoder_src From 4ac09e7454be6cc0eb82f96ef407a22b776a706a Mon Sep 17 00:00:00 2001 From: Yu Mao Date: Sun, 22 Mar 2020 21:31:53 -0700 Subject: [PATCH 058/357] Allow passing list to the input argument 'scale' of RandomResizedCrop (#1997) Summary: Currently the scale argument can only be of type tuple or integer, this diff allows feeding the input argument `scale` with a list. Pull Request resolved: https://github.com/pytorch/vision/pull/1997 Test Plan: Without this diff, launching the following classy vision task causes error: https://our.intern.facebook.com/intern/fblearner/details/175876950/ With this diff, everything works fine: https://our.intern.facebook.com/intern/fblearner/details/175913768/ Reviewed By: resonatevision Differential Revision: D20544904 Pulled By: ymao1993 fbshipit-source-id: a95a2e9ceadec77fffe234756fb3b38b1b9c9cb1 --- torchvision/transforms/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 393e3c2db33..38472a1b05d 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -620,7 +620,7 @@ class RandomResizedCrop(object): """ def __init__(self, size, scale=(0.08, 1.0), ratio=(3. / 4., 4. / 3.), interpolation=Image.BILINEAR): - if isinstance(size, tuple): + if isinstance(size, (tuple, list)): self.size = size else: self.size = (size, size) From 274e1da1539a309e9716b388a56c9065a87ad831 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 24 Mar 2020 13:24:57 -0700 Subject: [PATCH 059/357] Fix C++ lint (#2009) (#2010) Summary: * Fix C++ lint * More fixes Pull Request resolved: https://github.com/pytorch/vision/pull/2010 Reviewed By: zhangguanheng66 Differential Revision: D20624423 Pulled By: fmassa fbshipit-source-id: 48b08e04eaa201f6f0c16a2448096cb81675c9b1 --- torchvision/csrc/cpu/decoder/defs.h | 9 ++-- torchvision/csrc/cpu/decoder/util.cpp | 11 +++-- torchvision/csrc/cpu/decoder/util_test.cpp | 52 +++++++++++----------- 3 files changed, 38 insertions(+), 34 deletions(-) diff --git a/torchvision/csrc/cpu/decoder/defs.h b/torchvision/csrc/cpu/decoder/defs.h index a53f2aeb2b0..5db17b3e92c 100644 --- a/torchvision/csrc/cpu/decoder/defs.h +++ b/torchvision/csrc/cpu/decoder/defs.h @@ -53,9 +53,11 @@ struct VideoFormat { When width = 0, height = 0, minDimension = 0, and maxDimension = 0, keep the orignal frame resolution When width = 0, height = 0, minDimension != 0, and maxDimension = 0, - keep the aspect ratio and resize the frame so that shorter edge size is minDimension + keep the aspect ratio and resize the frame so that shorter edge size is + minDimension When width = 0, height = 0, minDimension = 0, and maxDimension != 0, - keep the aspect ratio and resize the frame so that longer edge size is maxDimension + keep the aspect ratio and resize the frame so that longer edge size is + maxDimension When width = 0, height = 0, minDimension != 0, and maxDimension != 0, resize the frame so that shorter edge size is minDimension, and longer edge size is maxDimension. The aspect ratio may not be preserved @@ -64,7 +66,8 @@ struct VideoFormat { When width != 0, height = 0, minDimension = 0, and maxDimension = 0, keep the aspect ratio and resize the frame so that frame width is $width When width != 0, height != 0, minDimension = 0, and maxDimension = 0, - resize the frame so that frame width and height are set to $width and $height, + resize the frame so that frame width and height are set to $width and + $height, respectively */ size_t width{0}; // width in pixels diff --git a/torchvision/csrc/cpu/decoder/util.cpp b/torchvision/csrc/cpu/decoder/util.cpp index 9ca7246bbaf..0dbcf885cf5 100644 --- a/torchvision/csrc/cpu/decoder/util.cpp +++ b/torchvision/csrc/cpu/decoder/util.cpp @@ -284,6 +284,7 @@ size_t size(const AVSubtitle& sub) { } bool validateVideoFormat(const VideoFormat& f) { + // clang-format off /* Valid parameters values for decoder ____________________________________________________________________________________ @@ -307,6 +308,7 @@ bool validateVideoFormat(const VideoFormat& f) { |_____|_____|______________|______________|___________|____________________________| */ + // clang-format on return (f.width == 0 && // #1, #6, #7 and #8 f.height == 0 && f.cropImage == 0) || (f.width != 0 && // #4 and #5 @@ -346,8 +348,7 @@ void setFormatDimensions( destW = minDimension; destH = round(double(srcH * minDimension) / srcW); } - } - else if (minDimension == 0 && maxDimension > 0) { // #7 + } else if (minDimension == 0 && maxDimension > 0) { // #7 if (srcW > srcH) { // landscape destW = maxDimension; @@ -357,8 +358,7 @@ void setFormatDimensions( destH = maxDimension; destW = round(double(srcW * maxDimension) / srcH); } - } - else if (minDimension > 0 && maxDimension > 0) { // #8 + } else if (minDimension > 0 && maxDimension > 0) { // #8 if (srcW > srcH) { // landscape destW = maxDimension; @@ -368,8 +368,7 @@ void setFormatDimensions( destW = minDimension; destH = maxDimension; } - } - else { // #1 + } else { // #1 destW = srcW; destH = srcH; } diff --git a/torchvision/csrc/cpu/decoder/util_test.cpp b/torchvision/csrc/cpu/decoder/util_test.cpp index 80a316af5c9..78de08b7139 100644 --- a/torchvision/csrc/cpu/decoder/util_test.cpp +++ b/torchvision/csrc/cpu/decoder/util_test.cpp @@ -4,30 +4,32 @@ #include "util.h" TEST(Util, TestSetFormatDimensions) { - const size_t test_cases[][9] = { - // (userW, userH, srcW, srcH, minDimension, maxDimension, cropImage, destW, destH) - {0, 0, 172, 128, 0, 0, 0, 172, 128}, // #1 - {86, 0, 172, 128, 0, 0, 0, 86, 64}, // #2 - {64, 0, 128, 172, 0, 0, 0, 64, 86}, // #2 - {0, 32, 172, 128, 0, 0, 0, 43, 32}, // #3 - {32, 0, 128, 172, 0, 0, 0, 32, 43}, // #3 - {60, 50, 172, 128, 0, 0, 0, 60, 50}, // #4 - {50, 60, 128, 172, 0, 0, 0, 50, 60}, // #4 - {86, 40, 172, 128, 0, 0, 1, 86, 64}, // #5 - {86, 92, 172, 128, 0, 0, 1, 124, 92}, // #5 - {0, 0, 172, 128, 256, 0, 0, 344, 256}, // #6 - {0, 0, 128, 172, 256, 0, 0, 256, 344}, // #6 - {0, 0, 128, 172, 0, 344, 0, 256, 344}, // #7 - {0, 0, 172, 128, 0, 344, 0, 344, 256}, // #7 - {0, 0, 172, 128, 100, 344, 0, 344, 100},// #8 - {0, 0, 128, 172, 100, 344, 0, 100, 344} // #8 - }; + // clang-format off + const size_t test_cases[][9] = { + // (userW, userH, srcW, srcH, minDimension, maxDimension, cropImage, destW, destH) + {0, 0, 172, 128, 0, 0, 0, 172, 128}, // #1 + {86, 0, 172, 128, 0, 0, 0, 86, 64}, // #2 + {64, 0, 128, 172, 0, 0, 0, 64, 86}, // #2 + {0, 32, 172, 128, 0, 0, 0, 43, 32}, // #3 + {32, 0, 128, 172, 0, 0, 0, 32, 43}, // #3 + {60, 50, 172, 128, 0, 0, 0, 60, 50}, // #4 + {50, 60, 128, 172, 0, 0, 0, 50, 60}, // #4 + {86, 40, 172, 128, 0, 0, 1, 86, 64}, // #5 + {86, 92, 172, 128, 0, 0, 1, 124, 92}, // #5 + {0, 0, 172, 128, 256, 0, 0, 344, 256}, // #6 + {0, 0, 128, 172, 256, 0, 0, 256, 344}, // #6 + {0, 0, 128, 172, 0, 344, 0, 256, 344}, // #7 + {0, 0, 172, 128, 0, 344, 0, 344, 256}, // #7 + {0, 0, 172, 128, 100, 344, 0, 344, 100},// #8 + {0, 0, 128, 172, 100, 344, 0, 100, 344} // #8 + }; + // clang-format onn - for (const auto& tc : test_cases) { - size_t destW = 0; - size_t destH = 0; - ffmpeg::Util::setFormatDimensions(destW, destH, tc[0], tc[1], tc[2], tc[3], tc[4], tc[5], tc[6]); - CHECK(destW == tc[7]); - CHECK(destH == tc[8]); - } + for (const auto& tc : test_cases) { + size_t destW = 0; + size_t destH = 0; + ffmpeg::Util::setFormatDimensions(destW, destH, tc[0], tc[1], tc[2], tc[3], tc[4], tc[5], tc[6]); + CHECK(destW == tc[7]); + CHECK(destH == tc[8]); + } } From a20e9bfc61f255f48e5bba8ca62850689e9117ee Mon Sep 17 00:00:00 2001 From: Patrick Labatut Date: Wed, 1 Apr 2020 08:50:51 -0700 Subject: [PATCH 060/357] Fix docstring formatting issues Summary: Fix docstring formatting issues Reviewed By: fmassa Differential Revision: D20736644 fbshipit-source-id: 78f66045cfd4c84cb35ca84a1e1fa6aadcd50642 --- torchvision/__init__.py | 8 +++---- torchvision/transforms/functional.py | 31 +++++++++++++++------------- torchvision/transforms/transforms.py | 21 ++++++++++--------- torchvision/utils.py | 2 +- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/torchvision/__init__.py b/torchvision/__init__.py index ca155712671..084c8468fa3 100644 --- a/torchvision/__init__.py +++ b/torchvision/__init__.py @@ -49,10 +49,10 @@ def set_video_backend(backend): Args: backend (string): Name of the video backend. one of {'pyav', 'video_reader'}. The :mod:`pyav` package uses the 3rd party PyAv library. It is a Pythonic - binding for the FFmpeg libraries. - The :mod:`video_reader` package includes a native c++ implementation on - top of FFMPEG libraries, and a python API of TorchScript custom operator. - It is generally decoding faster than pyav, but perhaps is less robust. + binding for the FFmpeg libraries. + The :mod:`video_reader` package includes a native C++ implementation on + top of FFMPEG libraries, and a python API of TorchScript custom operator. + It is generally decoding faster than :mod:`pyav`, but perhaps is less robust. """ global _video_backend if backend not in ["pyav", "video_reader"]: diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 5eef861650e..f6b4161869b 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -352,12 +352,14 @@ def pad(img, padding, fill=0, padding_mode='constant'): def crop(img, top, left, height, width): """Crop the given PIL Image. + Args: img (PIL Image): Image to be cropped. (0,0) denotes the top left corner of the image. top (int): Vertical component of the top left corner of the crop box. left (int): Horizontal component of the top left corner of the crop box. height (int): Height of the crop box. width (int): Width of the crop box. + Returns: PIL Image: Cropped image. """ @@ -370,13 +372,13 @@ def crop(img, top, left, height, width): def center_crop(img, output_size): """Crop the given PIL Image and resize it to desired size. - Args: - img (PIL Image): Image to be cropped. (0,0) denotes the top left corner of the image. - output_size (sequence or int): (height, width) of the crop box. If int, - it is used for both directions - Returns: - PIL Image: Cropped image. - """ + Args: + img (PIL Image): Image to be cropped. (0,0) denotes the top left corner of the image. + output_size (sequence or int): (height, width) of the crop box. If int, + it is used for both directions + Returns: + PIL Image: Cropped image. + """ if isinstance(output_size, numbers.Number): output_size = (int(output_size), int(output_size)) image_width, image_height = img.size @@ -519,23 +521,24 @@ def five_crop(img, size): def ten_crop(img, size, vertical_flip=False): - r"""Crop the given PIL Image into four corners and the central crop plus the - flipped version of these (horizontal flipping is used by default). + """Generate ten cropped images from the given PIL Image. + Crop the given PIL Image into four corners and the central crop plus the + flipped version of these (horizontal flipping is used by default). .. Note:: This transform returns a tuple of images and there may be a mismatch in the number of inputs and targets your ``Dataset`` returns. Args: - size (sequence or int): Desired output size of the crop. If size is an + size (sequence or int): Desired output size of the crop. If size is an int instead of sequence like (h, w), a square crop (size, size) is made. - vertical_flip (bool): Use vertical flipping instead of horizontal + vertical_flip (bool): Use vertical flipping instead of horizontal Returns: - tuple: tuple (tl, tr, bl, br, center, tl_flip, tr_flip, bl_flip, br_flip, center_flip) - Corresponding top left, top right, bottom left, bottom right and center crop - and same for the flipped image. + tuple: tuple (tl, tr, bl, br, center, tl_flip, tr_flip, bl_flip, br_flip, center_flip) + Corresponding top left, top right, bottom left, bottom right and + center crop and same for the flipped image. """ if isinstance(size, numbers.Number): size = (int(size), int(size)) diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 38472a1b05d..0e72d391508 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -647,7 +647,7 @@ def get_params(img, scale, ratio): width, height = _get_image_size(img) area = height * width - for attempt in range(10): + for _ in range(10): target_area = random.uniform(*scale) * area log_ratio = (math.log(ratio[0]), math.log(ratio[1])) aspect_ratio = math.exp(random.uniform(*log_ratio)) @@ -1156,8 +1156,8 @@ class Grayscale(object): Returns: PIL Image: Grayscale version of the input. - - If num_output_channels == 1 : returned image is single channel - - If num_output_channels == 3 : returned image is 3 channel with r == g == b + - If ``num_output_channels == 1`` : returned image is single channel + - If ``num_output_channels == 3`` : returned image is 3 channel with r == g == b """ @@ -1214,8 +1214,8 @@ def __repr__(self): class RandomErasing(object): """ Randomly selects a rectangle region in an image and erases its pixels. - 'Random Erasing Data Augmentation' by Zhong et al. - See https://arxiv.org/pdf/1708.04896.pdf + 'Random Erasing Data Augmentation' by Zhong et al. See https://arxiv.org/pdf/1708.04896.pdf + Args: p: probability that the random erasing operation will be performed. scale: range of proportion of erased area against input image. @@ -1228,12 +1228,13 @@ class RandomErasing(object): Returns: Erased Image. + # Examples: >>> transform = transforms.Compose([ - >>> transforms.RandomHorizontalFlip(), - >>> transforms.ToTensor(), - >>> transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)), - >>> transforms.RandomErasing(), + >>> transforms.RandomHorizontalFlip(), + >>> transforms.ToTensor(), + >>> transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)), + >>> transforms.RandomErasing(), >>> ]) """ @@ -1267,7 +1268,7 @@ def get_params(img, scale, ratio, value=0): img_c, img_h, img_w = img.shape area = img_h * img_w - for attempt in range(10): + for _ in range(10): erase_area = random.uniform(scale[0], scale[1]) * area aspect_ratio = random.uniform(ratio[0], ratio[1]) diff --git a/torchvision/utils.py b/torchvision/utils.py index 9658328a704..1a773b3fd2e 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -95,7 +95,7 @@ def save_image(tensor, fp, nrow=8, padding=2, Args: tensor (Tensor or list): Image to be saved. If given a mini-batch tensor, saves the tensor as a grid of images by calling ``make_grid``. - fp - A filename(string) or file object + fp (string or file object): A filename or a file object format(Optional): If omitted, the format to use is determined from the filename extension. If a file object was used instead of a filename, this parameter should always be used. **kwargs: Other arguments are documented in ``make_grid``. From 2860aecea1bc2f3977bf3dce93bc9db148dca6bc Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 8 Apr 2020 11:28:49 -0700 Subject: [PATCH 061/357] Make read_video_meta_data_from_memory and read_video_from_memory private (#2077) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2077 Pull Request resolved: https://github.com/facebookresearch/SlowFast/pull/164 This is a follow-up diff from D18720474 We will be releasing a new version of torchvision soon and the signature of those functions is not ready yet, following my comment in https://our.intern.facebook.com/intern/diff/D18720474/?transaction_id=561239541337402 Reviewed By: stephenyan1231 Differential Revision: D20914571 fbshipit-source-id: 1a7560b8f8e46ab42ef376c50b494a4f73923e94 --- test/test_video_reader.py | 8 +++---- torchvision/io/__init__.py | 4 ---- torchvision/io/video.py | 44 -------------------------------------- 3 files changed, 4 insertions(+), 52 deletions(-) diff --git a/test/test_video_reader.py b/test/test_video_reader.py index 70112427b85..70cd9c64843 100644 --- a/test/test_video_reader.py +++ b/test/test_video_reader.py @@ -1187,8 +1187,8 @@ def test_probe_video_from_memory(self): probe_result = torch.ops.video_reader.probe_video_from_memory(video_tensor) self.check_probe_result(probe_result, config) - def test_read_video_meta_data_from_memory_script(self): - scripted_fun = torch.jit.script(io.read_video_meta_data_from_memory) + def test_probe_video_from_memory_script(self): + scripted_fun = torch.jit.script(io._probe_video_from_memory) self.assertIsNotNone(scripted_fun) for test_video, config in test_videos.items(): @@ -1209,7 +1209,7 @@ def test_read_video_from_memory_scripted(self): audio_start_pts, audio_end_pts = 0, -1 audio_timebase_num, audio_timebase_den = 0, 1 - scripted_fun = torch.jit.script(io.read_video_from_memory) + scripted_fun = torch.jit.script(io._read_video_from_memory) self.assertIsNotNone(scripted_fun) for test_video, _config in test_videos.items(): @@ -1223,6 +1223,7 @@ def test_read_video_from_memory_scripted(self): width, height, min_dimension, + max_dimension, [video_start_pts, video_end_pts], video_timebase_num, video_timebase_den, @@ -1232,7 +1233,6 @@ def test_read_video_from_memory_scripted(self): [audio_start_pts, audio_end_pts], audio_timebase_num, audio_timebase_den, - max_dimension, ) # FUTURE: check value of video / audio frames diff --git a/torchvision/io/__init__.py b/torchvision/io/__init__.py index 713113a0ae1..cbbf560412e 100644 --- a/torchvision/io/__init__.py +++ b/torchvision/io/__init__.py @@ -11,8 +11,6 @@ ) from .video import ( read_video, - read_video_from_memory, - read_video_meta_data_from_memory, read_video_timestamps, write_video, ) @@ -22,8 +20,6 @@ "write_video", "read_video", "read_video_timestamps", - "read_video_meta_data_from_memory", - "read_video_from_memory", "_read_video_from_file", "_read_video_timestamps_from_file", "_probe_video_from_file", diff --git a/torchvision/io/video.py b/torchvision/io/video.py index 5729f1b54dd..40d1cfeed85 100644 --- a/torchvision/io/video.py +++ b/torchvision/io/video.py @@ -347,47 +347,3 @@ def read_video_timestamps(filename, pts_unit="pts"): pts = [x * video_time_base for x in pts] return pts, video_fps - - -def read_video_meta_data_from_memory(video_data): - # type: (torch.Tensor) -> VideoMetaData - return _video_opt._probe_video_from_memory(video_data) - - -def read_video_from_memory( - video_data, # type: torch.Tensor - seek_frame_margin=0.25, # type: float - read_video_stream=1, # type: int - video_width=0, # type: int - video_height=0, # type: int - video_min_dimension=0, # type: int - video_pts_range=(0, -1), # type: List[int] - video_timebase_numerator=0, # type: int - video_timebase_denominator=1, # type: int - read_audio_stream=1, # type: int - audio_samples=0, # type: int - audio_channels=0, # type: int - audio_pts_range=(0, -1), # type: List[int] - audio_timebase_numerator=0, # type: int - audio_timebase_denominator=1, # type: int - video_max_dimension=0, # type: int -): - # type: (...) -> Tuple[torch.Tensor, torch.Tensor] - return _video_opt._read_video_from_memory( - video_data, - seek_frame_margin, - read_video_stream, - video_width, - video_height, - video_min_dimension, - video_max_dimension, - video_pts_range, - video_timebase_numerator, - video_timebase_denominator, - read_audio_stream, - audio_samples, - audio_channels, - audio_pts_range, - audio_timebase_numerator, - audio_timebase_denominator, - ) From 521ddb56d6166b33c0e6e058ad67e1c5611ad8cf Mon Sep 17 00:00:00 2001 From: Tilak Sharma Date: Mon, 27 Apr 2020 15:53:06 -0700 Subject: [PATCH 062/357] Fix overflow error for large buffers. Summary: Allow writes of >= 2^32 bytes. High-res video can cross this threshold sometimes. LHS is `size_t`, but RHS is all `int32`, and will overflow for output tensors >2Gb. Reviewed By: jsawruk Differential Revision: D21255664 fbshipit-source-id: 7b4c5da989777297a89e73615aaeee8c7a13186a --- torchvision/csrc/cpu/video_reader/VideoReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/csrc/cpu/video_reader/VideoReader.cpp b/torchvision/csrc/cpu/video_reader/VideoReader.cpp index 57801930926..3a184716b4d 100644 --- a/torchvision/csrc/cpu/video_reader/VideoReader.cpp +++ b/torchvision/csrc/cpu/video_reader/VideoReader.cpp @@ -311,7 +311,7 @@ torch::List readVideo( videoFrame = torch::zeros( {numVideoFrames, outHeight, outWidth, numChannels}, torch::kByte); expectedWrittenBytes = - numVideoFrames * outHeight * outWidth * numChannels; + (size_t)numVideoFrames * outHeight * outWidth * numChannels; } videoFramePts = torch::zeros({numVideoFrames}, torch::kLong); From 5768ca55901265eb8af527183af9cfa5fa28b38c Mon Sep 17 00:00:00 2001 From: Joanna Bitton Date: Wed, 3 Jun 2020 14:04:09 -0700 Subject: [PATCH 063/357] Add option to write audio to video file Summary: I was trying to use torchvision's `write_video` function and realized there was no option to add in the audio. Thus, this diff contains the changes necessary such that this is possible. This is my first time trying to contribute to this project, so be as harsh as you need! Reviewed By: fmassa Differential Revision: D21480083 fbshipit-source-id: 2e11f2c8728d42f86c94068f75b843793d5a94aa --- test/test_io.py | 35 +++++++++++++++++++++++ torchvision/io/video.py | 62 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/test/test_io.py b/test/test_io.py index 4c01f9ecb32..23f496d13c4 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -24,6 +24,9 @@ av = None +VIDEO_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "videos") + + def _create_video_frames(num_frames, height, width): y, x = torch.meshgrid(torch.linspace(-2, 2, height), torch.linspace(-2, 2, width)) data = [] @@ -262,6 +265,38 @@ def test_read_video_partially_corrupted_file(self): # and the last few frames are wrong self.assertFalse(video.equal(data)) + def test_write_video_with_audio(self): + f_name = os.path.join(VIDEO_DIR, "R6llTwEh07w.mp4") + video_tensor, audio_tensor, info = io.read_video(f_name, pts_unit="sec") + + with tempfile.TemporaryDirectory() as tmpdir: + out_f_name = os.path.join(tmpdir, "testing.mp4") + io.video.write_video( + out_f_name, + video_tensor, + round(info["video_fps"]), + video_codec="libx264rgb", + options={'crf': '0'}, + audio_array=audio_tensor, + audio_fps=info["audio_fps"], + audio_codec="aac", + ) + + out_video_tensor, out_audio_tensor, out_info = io.read_video( + out_f_name, pts_unit="sec" + ) + + self.assertEqual(info["video_fps"], out_info["video_fps"]) + self.assertTrue(video_tensor.equal(out_video_tensor)) + + audio_stream = av.open(f_name).streams.audio[0] + out_audio_stream = av.open(out_f_name).streams.audio[0] + + self.assertEqual(info["audio_fps"], out_info["audio_fps"]) + self.assertEqual(audio_stream.rate, out_audio_stream.rate) + self.assertAlmostEqual(audio_stream.frames, out_audio_stream.frames, delta=1) + self.assertEqual(audio_stream.frame_size, out_audio_stream.frame_size) + # TODO add tests for audio diff --git a/torchvision/io/video.py b/torchvision/io/video.py index 40d1cfeed85..e9be826bc03 100644 --- a/torchvision/io/video.py +++ b/torchvision/io/video.py @@ -49,7 +49,17 @@ def _av_available(): _GC_COLLECTION_INTERVAL = 10 -def write_video(filename, video_array, fps, video_codec="libx264", options=None): +def write_video( + filename, + video_array, + fps, + video_codec="libx264", + options=None, + audio_array=None, + audio_fps=None, + audio_codec=None, + audio_options=None, +): """ Writes a 4d tensor in [T, H, W, C] format in a video file @@ -60,7 +70,20 @@ def write_video(filename, video_array, fps, video_codec="libx264", options=None) video_array : Tensor[T, H, W, C] tensor containing the individual frames, as a uint8 tensor in [T, H, W, C] format fps : Number - frames per second + video frames per second + video_codec : str + the name of the video codec, i.e. "libx264", "h264", etc. + options : Dict + dictionary containing options to be passed into the PyAV video stream + audio_array : Tensor[C, N] + tensor containing the audio, where C is the number of channels and N is the + number of samples + audio_fps : Number + audio sample rate, typically 44100 or 48000 + audio_codec : str + the name of the audio codec, i.e. "mp3", "aac", etc. + audio_options : Dict + dictionary containing options to be passed into the PyAV audio stream """ _check_av_available() video_array = torch.as_tensor(video_array, dtype=torch.uint8).numpy() @@ -73,6 +96,41 @@ def write_video(filename, video_array, fps, video_codec="libx264", options=None) stream.pix_fmt = "yuv420p" if video_codec != "libx264rgb" else "rgb24" stream.options = options or {} + if audio_array is not None: + audio_format_dtypes = { + 'dbl': ' 1 else "mono" + audio_sample_fmt = container.streams.audio[0].format.name + + format_dtype = np.dtype(audio_format_dtypes[audio_sample_fmt]) + audio_array = torch.as_tensor(audio_array).numpy().astype(format_dtype) + + frame = av.AudioFrame.from_ndarray( + audio_array, format=audio_sample_fmt, layout=audio_layout + ) + + frame.sample_rate = audio_fps + + for packet in a_stream.encode(frame): + container.mux(packet) + + for packet in a_stream.encode(): + container.mux(packet) + for img in video_array: frame = av.VideoFrame.from_ndarray(img, format="rgb24") frame.pict_type = "NONE" From 2104083163cca7ea70e19a8d481c7cf297fde82c Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 9 Jun 2020 10:43:24 -0700 Subject: [PATCH 064/357] Import torchscript changes for Faster R-CNN (#2305) Summary: This is a massive PR, but I tried to keep is as minimal as possible so that importing it should work. Just cherry-picks, no new content Pull Request resolved: https://github.com/pytorch/vision/pull/2305 Reviewed By: zhangguanheng66 Differential Revision: D21951002 Pulled By: fmassa fbshipit-source-id: 3302d1c2c2d5ad411e4f0f6d7a35fbdbf2d72b4d --- .travis.yml | 3 +- docs/source/conf.py | 2 +- references/detection/engine.py | 2 + references/similarity/test.py | 8 +- test/common_utils.py | 205 ++++++++++++++-- test/test_backbone_utils.py | 4 +- test/test_io.py | 25 +- test/test_models.py | 133 +++++++--- .../test_models_detection_negative_samples.py | 133 ++++++++++ test/test_models_detection_utils.py | 22 ++ test/test_onnx.py | 198 +++++++++++---- test/test_ops.py | 9 + torchvision/__init__.py | 5 +- torchvision/csrc/empty_tensor_op.h | 37 +++ torchvision/csrc/vision.cpp | 2 + torchvision/datasets/usps.py | 2 +- torchvision/io/_video_opt.py | 2 - torchvision/models/_utils.py | 3 +- torchvision/models/detection/_utils.py | 40 ++- .../models/detection/backbone_utils.py | 19 +- torchvision/models/detection/faster_rcnn.py | 4 +- .../models/detection/generalized_rcnn.py | 34 ++- torchvision/models/detection/image_list.py | 8 +- torchvision/models/detection/keypoint_rcnn.py | 11 +- torchvision/models/detection/mask_rcnn.py | 2 +- torchvision/models/detection/roi_heads.py | 231 ++++++++++++------ torchvision/models/detection/rpn.py | 151 ++++++++---- torchvision/models/detection/transform.py | 154 +++++++++--- torchvision/models/mobilenet.py | 8 +- torchvision/models/quantization/mobilenet.py | 2 +- torchvision/models/quantization/resnet.py | 2 +- .../models/quantization/shufflenetv2.py | 2 +- torchvision/models/resnet.py | 7 +- torchvision/models/shufflenetv2.py | 6 +- torchvision/ops/__init__.py | 3 +- torchvision/ops/_register_onnx_ops.py | 20 +- torchvision/ops/boxes.py | 36 ++- torchvision/ops/feature_pyramid_network.py | 62 ++++- torchvision/ops/misc.py | 158 ++++++------ torchvision/ops/new_empty_tensor.py | 16 ++ torchvision/ops/poolers.py | 92 +++++-- torchvision/ops/roi_align.py | 4 +- torchvision/ops/roi_pool.py | 4 +- torchvision/transforms/functional.py | 2 +- torchvision/transforms/transforms.py | 4 +- 45 files changed, 1423 insertions(+), 454 deletions(-) create mode 100644 test/test_models_detection_negative_samples.py create mode 100644 test/test_models_detection_utils.py create mode 100644 torchvision/csrc/empty_tensor_op.h create mode 100644 torchvision/ops/new_empty_tensor.py diff --git a/.travis.yml b/.travis.yml index eae4967d542..d08225c29bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,7 +46,8 @@ before_install: - pip install typing - | if [[ $TRAVIS_PYTHON_VERSION == 3.6 ]]; then - pip install onnxruntime + pip install -q --user typing-extensions==3.6.6 + pip install -q --user -i https://test.pypi.org/simple/ ort-nightly==1.2.0.dev202005021 fi - conda install av -c conda-forge diff --git a/docs/source/conf.py b/docs/source/conf.py index 3c277168a70..fdb36238ff9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -208,7 +208,7 @@ def patched_make_field(self, types, domain, items, **kw): # `kw` catches `env=None` needed for newer sphinx while maintaining # backwards compatibility when passed along further down! - # type: (list, unicode, tuple) -> nodes.field + # type: (list, unicode, tuple) -> nodes.field # noqa: F821 def handle_item(fieldarg, content): par = nodes.paragraph() par += addnodes.literal_strong('', fieldarg) # Patch: this line added diff --git a/references/detection/engine.py b/references/detection/engine.py index 68c39a4fc1b..86c25d9c486 100644 --- a/references/detection/engine.py +++ b/references/detection/engine.py @@ -52,6 +52,8 @@ def train_one_epoch(model, optimizer, data_loader, device, epoch, print_freq): metric_logger.update(loss=losses_reduced, **loss_dict_reduced) metric_logger.update(lr=optimizer.param_groups[0]["lr"]) + return metric_logger + def _get_iou_types(model): model_without_ddp = model diff --git a/references/similarity/test.py b/references/similarity/test.py index a1e646111c8..8381e02e740 100644 --- a/references/similarity/test.py +++ b/references/similarity/test.py @@ -27,15 +27,15 @@ def test_pksampler(self): for _, labels in loader: bins = defaultdict(int) - for l in labels.tolist(): - bins[l] += 1 + for label in labels.tolist(): + bins[label] += 1 # Ensure that each batch has samples from exactly p classes self.assertEqual(len(bins), p) # Ensure that there are k samples from each class - for l in bins: - self.assertEqual(bins[l], k) + for b in bins: + self.assertEqual(bins[b], k) if __name__ == '__main__': diff --git a/test/common_utils.py b/test/common_utils.py index 9c0c3175ef1..b0a8fbe1c97 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -5,10 +5,15 @@ import unittest import argparse import sys +import io import torch import errno import __main__ +from numbers import Number +from torch._six import string_classes, inf +from collections import OrderedDict + @contextlib.contextmanager def get_tmp_dir(src=None, **kwargs): @@ -23,6 +28,9 @@ def get_tmp_dir(src=None, **kwargs): ACCEPT = os.getenv('EXPECTTEST_ACCEPT') +TEST_WITH_SLOW = os.getenv('PYTORCH_TEST_WITH_SLOW', '0') == '1' +# TEST_WITH_SLOW = True # TODO: Delete this line once there is a PYTORCH_TEST_WITH_SLOW aware CI job + parser = argparse.ArgumentParser(add_help=False) parser.add_argument('--accept', action='store_true') @@ -64,10 +72,20 @@ def map_nested_tensor_object(object, tensor_map_fn): return impl(object) +def is_iterable(obj): + try: + iter(obj) + return True + except TypeError: + return False + + # adapted from TestCase in torch/test/common_utils to accept non-string # inputs and set maximum binary size class TestCase(unittest.TestCase): - def assertExpected(self, output, subname=None, rtol=None, atol=None): + precision = 1e-5 + + def assertExpected(self, output, subname=None, prec=None): r""" Test that a python value matches the recorded contents of a file derived from the name of this test and subname. The value must be @@ -123,31 +141,182 @@ def accept_output(update_type): if ACCEPT: equal = False try: - equal = self.assertNestedTensorObjectsEqual(output, expected, rtol=rtol, atol=atol) + equal = self.assertEqual(output, expected, prec=prec) except Exception: equal = False if not equal: return accept_output("updated output") else: - self.assertNestedTensorObjectsEqual(output, expected, rtol=rtol, atol=atol) + self.assertEqual(output, expected, prec=prec) - def assertNestedTensorObjectsEqual(self, a, b, rtol=None, atol=None): - self.assertEqual(type(a), type(b)) + def assertEqual(self, x, y, prec=None, message='', allow_inf=False): + """ + This is copied from pytorch/test/common_utils.py's TestCase.assertEqual + """ + if isinstance(prec, str) and message == '': + message = prec + prec = None + if prec is None: + prec = self.precision - if isinstance(a, torch.Tensor): - torch.testing.assert_allclose(a, b, rtol=rtol, atol=atol) + if isinstance(x, torch.Tensor) and isinstance(y, Number): + self.assertEqual(x.item(), y, prec=prec, message=message, + allow_inf=allow_inf) + elif isinstance(y, torch.Tensor) and isinstance(x, Number): + self.assertEqual(x, y.item(), prec=prec, message=message, + allow_inf=allow_inf) + elif isinstance(x, torch.Tensor) and isinstance(y, torch.Tensor): + def assertTensorsEqual(a, b): + super(TestCase, self).assertEqual(a.size(), b.size(), message) + if a.numel() > 0: + if (a.device.type == 'cpu' and (a.dtype == torch.float16 or a.dtype == torch.bfloat16)): + # CPU half and bfloat16 tensors don't have the methods we need below + a = a.to(torch.float32) + b = b.to(a) - elif isinstance(a, dict): - self.assertEqual(len(a), len(b)) - for key, value in a.items(): - self.assertTrue(key in b, "key: " + str(key)) + if (a.dtype == torch.bool) != (b.dtype == torch.bool): + raise TypeError("Was expecting both tensors to be bool type.") + else: + if a.dtype == torch.bool and b.dtype == torch.bool: + # we want to respect precision but as bool doesn't support substraction, + # boolean tensor has to be converted to int + a = a.to(torch.int) + b = b.to(torch.int) - self.assertNestedTensorObjectsEqual(value, b[key], rtol=rtol, atol=atol) - elif isinstance(a, (list, tuple)): - self.assertEqual(len(a), len(b)) + diff = a - b + if a.is_floating_point(): + # check that NaNs are in the same locations + nan_mask = torch.isnan(a) + self.assertTrue(torch.equal(nan_mask, torch.isnan(b)), message) + diff[nan_mask] = 0 + # inf check if allow_inf=True + if allow_inf: + inf_mask = torch.isinf(a) + inf_sign = inf_mask.sign() + self.assertTrue(torch.equal(inf_sign, torch.isinf(b).sign()), message) + diff[inf_mask] = 0 + # TODO: implement abs on CharTensor (int8) + if diff.is_signed() and diff.dtype != torch.int8: + diff = diff.abs() + max_err = diff.max() + tolerance = prec + prec * abs(a.max()) + self.assertLessEqual(max_err, tolerance, message) + super(TestCase, self).assertEqual(x.is_sparse, y.is_sparse, message) + super(TestCase, self).assertEqual(x.is_quantized, y.is_quantized, message) + if x.is_sparse: + x = self.safeCoalesce(x) + y = self.safeCoalesce(y) + assertTensorsEqual(x._indices(), y._indices()) + assertTensorsEqual(x._values(), y._values()) + elif x.is_quantized and y.is_quantized: + self.assertEqual(x.qscheme(), y.qscheme(), prec=prec, + message=message, allow_inf=allow_inf) + if x.qscheme() == torch.per_tensor_affine: + self.assertEqual(x.q_scale(), y.q_scale(), prec=prec, + message=message, allow_inf=allow_inf) + self.assertEqual(x.q_zero_point(), y.q_zero_point(), + prec=prec, message=message, + allow_inf=allow_inf) + elif x.qscheme() == torch.per_channel_affine: + self.assertEqual(x.q_per_channel_scales(), y.q_per_channel_scales(), prec=prec, + message=message, allow_inf=allow_inf) + self.assertEqual(x.q_per_channel_zero_points(), y.q_per_channel_zero_points(), + prec=prec, message=message, + allow_inf=allow_inf) + self.assertEqual(x.q_per_channel_axis(), y.q_per_channel_axis(), + prec=prec, message=message) + self.assertEqual(x.dtype, y.dtype) + self.assertEqual(x.int_repr().to(torch.int32), + y.int_repr().to(torch.int32), prec=prec, + message=message, allow_inf=allow_inf) + else: + assertTensorsEqual(x, y) + elif isinstance(x, string_classes) and isinstance(y, string_classes): + super(TestCase, self).assertEqual(x, y, message) + elif type(x) == set and type(y) == set: + super(TestCase, self).assertEqual(x, y, message) + elif isinstance(x, dict) and isinstance(y, dict): + if isinstance(x, OrderedDict) and isinstance(y, OrderedDict): + self.assertEqual(x.items(), y.items(), prec=prec, + message=message, allow_inf=allow_inf) + else: + self.assertEqual(set(x.keys()), set(y.keys()), prec=prec, + message=message, allow_inf=allow_inf) + key_list = list(x.keys()) + self.assertEqual([x[k] for k in key_list], + [y[k] for k in key_list], + prec=prec, message=message, + allow_inf=allow_inf) + elif is_iterable(x) and is_iterable(y): + super(TestCase, self).assertEqual(len(x), len(y), message) + for x_, y_ in zip(x, y): + self.assertEqual(x_, y_, prec=prec, message=message, + allow_inf=allow_inf) + elif isinstance(x, bool) and isinstance(y, bool): + super(TestCase, self).assertEqual(x, y, message) + elif isinstance(x, Number) and isinstance(y, Number): + if abs(x) == inf or abs(y) == inf: + if allow_inf: + super(TestCase, self).assertEqual(x, y, message) + else: + self.fail("Expected finite numeric values - x={}, y={}".format(x, y)) + return + super(TestCase, self).assertLessEqual(abs(x - y), prec, message) + else: + super(TestCase, self).assertEqual(x, y, message) - for val1, val2 in zip(a, b): - self.assertNestedTensorObjectsEqual(val1, val2, rtol=rtol, atol=atol) + def checkModule(self, nn_module, args, unwrapper=None, skip=False): + """ + Check that a nn.Module's results in TorchScript match eager and that it + can be exported + """ + if not TEST_WITH_SLOW or skip: + # TorchScript is not enabled, skip these tests + return - else: - self.assertEqual(a, b) + sm = torch.jit.script(nn_module) + + with freeze_rng_state(): + eager_out = nn_module(*args) + + with freeze_rng_state(): + script_out = sm(*args) + if unwrapper: + script_out = unwrapper(script_out) + + self.assertEqual(eager_out, script_out) + self.assertExportImportModule(sm, args) + + return sm + + def getExportImportCopy(self, m): + """ + Save and load a TorchScript model + """ + buffer = io.BytesIO() + torch.jit.save(m, buffer) + buffer.seek(0) + imported = torch.jit.load(buffer) + return imported + + def assertExportImportModule(self, m, args): + """ + Check that the results of a model are the same after saving and loading + """ + m_import = self.getExportImportCopy(m) + with freeze_rng_state(): + results = m(*args) + with freeze_rng_state(): + results_from_imported = m_import(*args) + self.assertEqual(results, results_from_imported) + + +@contextlib.contextmanager +def freeze_rng_state(): + rng_state = torch.get_rng_state() + if torch.cuda.is_available(): + cuda_rng_state = torch.cuda.get_rng_state() + yield + if torch.cuda.is_available(): + torch.cuda.set_rng_state(cuda_rng_state) + torch.set_rng_state(rng_state) diff --git a/test/test_backbone_utils.py b/test/test_backbone_utils.py index 41d54514568..7ee1aed1459 100644 --- a/test/test_backbone_utils.py +++ b/test/test_backbone_utils.py @@ -15,11 +15,11 @@ def test_resnet18_fpn_backbone(self): x = torch.rand(1, 3, 300, 300, dtype=self.dtype, device=device) resnet18_fpn = resnet_fpn_backbone(backbone_name='resnet18', pretrained=False) y = resnet18_fpn(x) - self.assertEqual(list(y.keys()), [0, 1, 2, 3, 'pool']) + self.assertEqual(list(y.keys()), ['0', '1', '2', '3', 'pool']) def test_resnet50_fpn_backbone(self): device = torch.device('cpu') x = torch.rand(1, 3, 300, 300, dtype=self.dtype, device=device) resnet50_fpn = resnet_fpn_backbone(backbone_name='resnet50', pretrained=False) y = resnet50_fpn(x) - self.assertEqual(list(y.keys()), [0, 1, 2, 3, 'pool']) + self.assertEqual(list(y.keys()), ['0', '1', '2', '3', 'pool']) diff --git a/test/test_io.py b/test/test_io.py index 23f496d13c4..4b122461a2c 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -66,6 +66,7 @@ def temp_video(num_frames, height, width, fps, lossless=False, video_codec=None, yield f.name, data os.unlink(f.name) + @unittest.skipIf(get_video_backend() != "pyav" and not io._HAS_VIDEO_OPT, "video_reader backend not available") @unittest.skipIf(av is None, "PyAV unavailable") @@ -115,10 +116,10 @@ def test_read_partial_video(self): with temp_video(10, 300, 300, 5, lossless=True) as (f_name, data): pts, _ = io.read_video_timestamps(f_name) for start in range(5): - for l in range(1, 4): - lv, _, _ = io.read_video(f_name, pts[start], pts[start + l - 1]) - s_data = data[start:(start + l)] - self.assertEqual(len(lv), l) + for offset in range(1, 4): + lv, _, _ = io.read_video(f_name, pts[start], pts[start + offset - 1]) + s_data = data[start:(start + offset)] + self.assertEqual(len(lv), offset) self.assertTrue(s_data.equal(lv)) if get_video_backend() == "pyav": @@ -134,10 +135,10 @@ def test_read_partial_video_bframes(self): with temp_video(100, 300, 300, 5, options=options) as (f_name, data): pts, _ = io.read_video_timestamps(f_name) for start in range(0, 80, 20): - for l in range(1, 4): - lv, _, _ = io.read_video(f_name, pts[start], pts[start + l - 1]) - s_data = data[start:(start + l)] - self.assertEqual(len(lv), l) + for offset in range(1, 4): + lv, _, _ = io.read_video(f_name, pts[start], pts[start + offset - 1]) + s_data = data[start:(start + offset)] + self.assertEqual(len(lv), offset) self.assertTrue((s_data.float() - lv.float()).abs().max() < self.TOLERANCE) lv, _, _ = io.read_video(f_name, pts[4] + 1, pts[7]) @@ -208,10 +209,10 @@ def test_read_partial_video_pts_unit_sec(self): pts, _ = io.read_video_timestamps(f_name, pts_unit='sec') for start in range(5): - for l in range(1, 4): - lv, _, _ = io.read_video(f_name, pts[start], pts[start + l - 1], pts_unit='sec') - s_data = data[start:(start + l)] - self.assertEqual(len(lv), l) + for offset in range(1, 4): + lv, _, _ = io.read_video(f_name, pts[start], pts[start + offset - 1], pts_unit='sec') + s_data = data[start:(start + offset)] + self.assertEqual(len(lv), offset) self.assertTrue(s_data.equal(lv)) container = av.open(f_name) diff --git a/test/test_models.py b/test/test_models.py index c70ef6830bf..24b5a8b6b66 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -1,4 +1,4 @@ -from common_utils import TestCase, map_nested_tensor_object +from common_utils import TestCase, map_nested_tensor_object, freeze_rng_state from collections import OrderedDict from itertools import product import torch @@ -38,64 +38,72 @@ def get_available_video_models(): # models that are in torch hub, as well as r3d_18. we tried testing all models # but the test was too slow. not included are detection models, because # they are not yet supported in JIT. -script_test_models = [ - "deeplabv3_resnet101", - "mobilenet_v2", - "resnext50_32x4d", - "fcn_resnet101", - "googlenet", - "densenet121", - "resnet18", - "alexnet", - "shufflenet_v2_x1_0", - "squeezenet1_0", - "vgg11", - "inception_v3", - 'r3d_18', -] +# If 'unwrapper' is provided it will be called with the script model outputs +# before they are compared to the eager model outputs. This is useful if the +# model outputs are different between TorchScript / Eager mode +script_test_models = { + 'deeplabv3_resnet101': {}, + 'mobilenet_v2': {}, + 'resnext50_32x4d': {}, + 'fcn_resnet101': {}, + 'googlenet': { + 'unwrapper': lambda x: x.logits + }, + 'densenet121': {}, + 'resnet18': {}, + 'alexnet': {}, + 'shufflenet_v2_x1_0': {}, + 'squeezenet1_0': {}, + 'vgg11': {}, + 'inception_v3': { + 'unwrapper': lambda x: x.logits + }, + 'r3d_18': {}, + "fasterrcnn_resnet50_fpn": { + 'unwrapper': lambda x: x[1] + }, + "maskrcnn_resnet50_fpn": { + 'unwrapper': lambda x: x[1] + }, + "keypointrcnn_resnet50_fpn": { + 'unwrapper': lambda x: x[1] + }, +} class ModelTester(TestCase): - def check_script(self, model, name): + def checkModule(self, model, name, args): if name not in script_test_models: return - scriptable = True - msg = "" - try: - torch.jit.script(model) - except Exception as e: - tb = traceback.format_exc() - scriptable = False - msg = str(e) + str(tb) - self.assertTrue(scriptable, msg) + unwrapper = script_test_models[name].get('unwrapper', None) + return super(ModelTester, self).checkModule(model, args, unwrapper=unwrapper, skip=False) def _test_classification_model(self, name, input_shape): + set_rng_seed(0) # passing num_class equal to a number other than 1000 helps in making the test # more enforcing in nature - set_rng_seed(0) model = models.__dict__[name](num_classes=50) - self.check_script(model, name) model.eval() x = torch.rand(input_shape) out = model(x) - self.assertExpected(out, rtol=1e-2, atol=0.) + self.assertExpected(out, prec=0.1) self.assertEqual(out.shape[-1], 50) + self.checkModule(model, name, (x,)) def _test_segmentation_model(self, name): # passing num_class equal to a number other than 1000 helps in making the test # more enforcing in nature model = models.segmentation.__dict__[name](num_classes=50, pretrained_backbone=False) - self.check_script(model, name) model.eval() input_shape = (1, 3, 300, 300) x = torch.rand(input_shape) out = model(x) self.assertEqual(tuple(out["out"].shape), (1, 50, 300, 300)) + self.checkModule(model, name, (x,)) def _test_detection_model(self, name): set_rng_seed(0) model = models.detection.__dict__[name](num_classes=50, pretrained_backbone=False) - self.check_script(model, name) model.eval() input_shape = (3, 300, 300) x = torch.rand(input_shape) @@ -125,14 +133,25 @@ def compute_mean_std(tensor): # compare results with mean and std if name == "maskrcnn_resnet50_fpn": test_value = map_nested_tensor_object(out, tensor_map_fn=compute_mean_std) - # mean values are small, use large rtol - self.assertExpected(test_value, rtol=.01, atol=.01) + # mean values are small, use large prec + self.assertExpected(test_value, prec=.01) else: - self.assertExpected(map_nested_tensor_object(out, tensor_map_fn=subsample_tensor)) - + self.assertExpected(map_nested_tensor_object(out, tensor_map_fn=subsample_tensor), prec=0.01) + + scripted_model = torch.jit.script(model) + scripted_model.eval() + scripted_out = scripted_model(model_input)[1] + self.assertEqual(scripted_out[0]["boxes"], out[0]["boxes"]) + self.assertEqual(scripted_out[0]["scores"], out[0]["scores"]) + # labels currently float in script: need to investigate (though same result) + self.assertEqual(scripted_out[0]["labels"].to(dtype=torch.long), out[0]["labels"]) self.assertTrue("boxes" in out[0]) self.assertTrue("scores" in out[0]) self.assertTrue("labels" in out[0]) + # don't check script because we are compiling it here: + # TODO: refactor tests + # self.check_script(model, name) + self.checkModule(model, name, ([x],)) def _test_video_model(self, name): # the default input shape is @@ -140,9 +159,10 @@ def _test_video_model(self, name): input_shape = (1, 3, 4, 112, 112) # test both basicblock and Bottleneck model = models.video.__dict__[name](num_classes=50) - self.check_script(model, name) + model.eval() x = torch.rand(input_shape) out = model(x) + self.checkModule(model, name, (x,)) self.assertEqual(out.shape[-1], 50) def _make_sliced_model(self, model, stop_layer): @@ -206,6 +226,47 @@ def test_fasterrcnn_double(self): self.assertTrue("scores" in out[0]) self.assertTrue("labels" in out[0]) + @unittest.skipIf(not torch.cuda.is_available(), 'needs GPU') + def test_fasterrcnn_switch_devices(self): + model = models.detection.fasterrcnn_resnet50_fpn(num_classes=50, pretrained_backbone=False) + model.cuda() + model.eval() + input_shape = (3, 300, 300) + x = torch.rand(input_shape, device='cuda') + model_input = [x] + out = model(model_input) + self.assertIs(model_input[0], x) + self.assertEqual(len(out), 1) + self.assertTrue("boxes" in out[0]) + self.assertTrue("scores" in out[0]) + self.assertTrue("labels" in out[0]) + # now switch to cpu and make sure it works + model.cpu() + x = x.cpu() + out_cpu = model([x]) + self.assertTrue("boxes" in out_cpu[0]) + self.assertTrue("scores" in out_cpu[0]) + self.assertTrue("labels" in out_cpu[0]) + + def test_generalizedrcnn_transform_repr(self): + + min_size, max_size = 224, 299 + image_mean = [0.485, 0.456, 0.406] + image_std = [0.229, 0.224, 0.225] + + t = models.detection.transform.GeneralizedRCNNTransform(min_size=min_size, + max_size=max_size, + image_mean=image_mean, + image_std=image_std) + + # Check integrity of object __repr__ attribute + expected_string = 'GeneralizedRCNNTransform(' + _indent = '\n ' + expected_string += '{0}Normalize(mean={1}, std={2})'.format(_indent, image_mean, image_std) + expected_string += '{0}Resize(min_size=({1},), max_size={2}, '.format(_indent, min_size, max_size) + expected_string += "mode='bilinear')\n)" + self.assertEqual(t.__repr__(), expected_string) + for model_name in get_available_classification_models(): # for-loop bodies don't define scopes, so we have to save the variables diff --git a/test/test_models_detection_negative_samples.py b/test/test_models_detection_negative_samples.py new file mode 100644 index 00000000000..ed0cc515940 --- /dev/null +++ b/test/test_models_detection_negative_samples.py @@ -0,0 +1,133 @@ +import torch + +import torchvision.models +from torchvision.ops import MultiScaleRoIAlign +from torchvision.models.detection.rpn import AnchorGenerator, RPNHead, RegionProposalNetwork +from torchvision.models.detection.roi_heads import RoIHeads +from torchvision.models.detection.faster_rcnn import FastRCNNPredictor, TwoMLPHead + +import unittest + + +class Tester(unittest.TestCase): + + def _make_empty_sample(self, add_masks=False, add_keypoints=False): + images = [torch.rand((3, 100, 100), dtype=torch.float32)] + boxes = torch.zeros((0, 4), dtype=torch.float32) + negative_target = {"boxes": boxes, + "labels": torch.zeros(0, dtype=torch.int64), + "image_id": 4, + "area": (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0]), + "iscrowd": torch.zeros((0,), dtype=torch.int64)} + + if add_masks: + negative_target["masks"] = torch.zeros(0, 100, 100, dtype=torch.uint8) + + if add_keypoints: + negative_target["keypoints"] = torch.zeros(17, 0, 3, dtype=torch.float32) + + targets = [negative_target] + return images, targets + + def test_targets_to_anchors(self): + _, targets = self._make_empty_sample() + anchors = [torch.randint(-50, 50, (3, 4), dtype=torch.float32)] + + anchor_sizes = ((32,), (64,), (128,), (256,), (512,)) + aspect_ratios = ((0.5, 1.0, 2.0),) * len(anchor_sizes) + rpn_anchor_generator = AnchorGenerator( + anchor_sizes, aspect_ratios + ) + rpn_head = RPNHead(4, rpn_anchor_generator.num_anchors_per_location()[0]) + + head = RegionProposalNetwork( + rpn_anchor_generator, rpn_head, + 0.5, 0.3, + 256, 0.5, + 2000, 2000, 0.7) + + labels, matched_gt_boxes = head.assign_targets_to_anchors(anchors, targets) + + self.assertEqual(labels[0].sum(), 0) + self.assertEqual(labels[0].shape, torch.Size([anchors[0].shape[0]])) + self.assertEqual(labels[0].dtype, torch.float32) + + self.assertEqual(matched_gt_boxes[0].sum(), 0) + self.assertEqual(matched_gt_boxes[0].shape, anchors[0].shape) + self.assertEqual(matched_gt_boxes[0].dtype, torch.float32) + + def test_assign_targets_to_proposals(self): + + proposals = [torch.randint(-50, 50, (20, 4), dtype=torch.float32)] + gt_boxes = [torch.zeros((0, 4), dtype=torch.float32)] + gt_labels = [torch.tensor([[0]], dtype=torch.int64)] + + box_roi_pool = MultiScaleRoIAlign( + featmap_names=['0', '1', '2', '3'], + output_size=7, + sampling_ratio=2) + + resolution = box_roi_pool.output_size[0] + representation_size = 1024 + box_head = TwoMLPHead( + 4 * resolution ** 2, + representation_size) + + representation_size = 1024 + box_predictor = FastRCNNPredictor( + representation_size, + 2) + + roi_heads = RoIHeads( + # Box + box_roi_pool, box_head, box_predictor, + 0.5, 0.5, + 512, 0.25, + None, + 0.05, 0.5, 100) + + matched_idxs, labels = roi_heads.assign_targets_to_proposals(proposals, gt_boxes, gt_labels) + + self.assertEqual(matched_idxs[0].sum(), 0) + self.assertEqual(matched_idxs[0].shape, torch.Size([proposals[0].shape[0]])) + self.assertEqual(matched_idxs[0].dtype, torch.int64) + + self.assertEqual(labels[0].sum(), 0) + self.assertEqual(labels[0].shape, torch.Size([proposals[0].shape[0]])) + self.assertEqual(labels[0].dtype, torch.int64) + + def test_forward_negative_sample_frcnn(self): + model = torchvision.models.detection.fasterrcnn_resnet50_fpn( + num_classes=2, min_size=100, max_size=100) + + images, targets = self._make_empty_sample() + loss_dict = model(images, targets) + + self.assertEqual(loss_dict["loss_box_reg"], torch.tensor(0.)) + self.assertEqual(loss_dict["loss_rpn_box_reg"], torch.tensor(0.)) + + def test_forward_negative_sample_mrcnn(self): + model = torchvision.models.detection.maskrcnn_resnet50_fpn( + num_classes=2, min_size=100, max_size=100) + + images, targets = self._make_empty_sample(add_masks=True) + loss_dict = model(images, targets) + + self.assertEqual(loss_dict["loss_box_reg"], torch.tensor(0.)) + self.assertEqual(loss_dict["loss_rpn_box_reg"], torch.tensor(0.)) + self.assertEqual(loss_dict["loss_mask"], torch.tensor(0.)) + + def test_forward_negative_sample_krcnn(self): + model = torchvision.models.detection.keypointrcnn_resnet50_fpn( + num_classes=2, min_size=100, max_size=100) + + images, targets = self._make_empty_sample(add_keypoints=True) + loss_dict = model(images, targets) + + self.assertEqual(loss_dict["loss_box_reg"], torch.tensor(0.)) + self.assertEqual(loss_dict["loss_rpn_box_reg"], torch.tensor(0.)) + self.assertEqual(loss_dict["loss_keypoint"], torch.tensor(0.)) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_models_detection_utils.py b/test/test_models_detection_utils.py new file mode 100644 index 00000000000..fb0b20678d8 --- /dev/null +++ b/test/test_models_detection_utils.py @@ -0,0 +1,22 @@ +import torch +from torchvision.models.detection import _utils +import unittest + + +class Tester(unittest.TestCase): + def test_balanced_positive_negative_sampler(self): + sampler = _utils.BalancedPositiveNegativeSampler(4, 0.25) + # keep all 6 negatives first, then add 3 positives, last two are ignore + matched_idxs = [torch.tensor([0, 0, 0, 0, 0, 0, 1, 1, 1, -1, -1])] + pos, neg = sampler(matched_idxs) + # we know the number of elements that should be sampled for the positive (1) + # and the negative (3), and their location. Let's make sure that they are + # there + self.assertEqual(pos[0].sum(), 1) + self.assertEqual(pos[0][6:9].sum(), 1) + self.assertEqual(neg[0].sum(), 3) + self.assertEqual(neg[0][0:6].sum(), 3) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_onnx.py b/test/test_onnx.py index 75af8a90b85..c34d48a682b 100644 --- a/test/test_onnx.py +++ b/test/test_onnx.py @@ -28,14 +28,15 @@ class ONNXExporterTester(unittest.TestCase): def setUpClass(cls): torch.manual_seed(123) - def run_model(self, model, inputs_list, tolerate_small_mismatch=False): + def run_model(self, model, inputs_list, tolerate_small_mismatch=False, do_constant_folding=True, dynamic_axes=None, + output_names=None, input_names=None): model.eval() onnx_io = io.BytesIO() # export to onnx with the first input torch.onnx.export(model, inputs_list[0], onnx_io, - do_constant_folding=True, opset_version=_onnx_opset_version) - + do_constant_folding=do_constant_folding, opset_version=_onnx_opset_version, + dynamic_axes=dynamic_axes, input_names=input_names, output_names=output_names) # validate the exported model with onnx runtime for test_inputs in inputs_list: with torch.no_grad(): @@ -74,6 +75,20 @@ def to_numpy(tensor): else: raise + @unittest.skip("Disable test until Split w/ zero sizes is implemented in ORT") + def test_new_empty_tensor(self): + class Module(torch.nn.Module): + def __init__(self): + super(Module, self).__init__() + self.conv2 = ops.misc.ConvTranspose2d(16, 33, (3, 5)) + + def forward(self, input2): + return self.conv2(input2) + + input = torch.rand(0, 16, 10, 10) + test_input = torch.rand(0, 16, 20, 20) + self.run_model(Module(), [(input, ), (test_input,)], do_constant_folding=False) + def test_nms(self): boxes = torch.rand(5, 4) boxes[:, 2:] += torch.rand(5, 2) @@ -85,6 +100,21 @@ def forward(self, boxes, scores): self.run_model(Module(), [(boxes, scores)]) + def test_clip_boxes_to_image(self): + boxes = torch.randn(5, 4) * 500 + boxes[:, 2:] += boxes[:, :2] + size = torch.randn(200, 300) + + size_2 = torch.randn(300, 400) + + class Module(torch.nn.Module): + def forward(self, boxes, size): + return ops.boxes.clip_boxes_to_image(boxes, size.shape) + + self.run_model(Module(), [(boxes, size), (boxes, size_2)], + input_names=["boxes", "size"], + dynamic_axes={"size": [0, 1]}) + def test_roi_align(self): x = torch.rand(1, 1, 10, 10, dtype=torch.float32) single_roi = torch.tensor([[0, 0, 0, 4, 4]], dtype=torch.float32) @@ -99,6 +129,20 @@ def test_roi_pool(self): model = ops.RoIPool((pool_h, pool_w), 2) self.run_model(model, [(x, rois)]) + def test_resize_images(self): + class TransformModule(torch.nn.Module): + def __init__(self_module): + super(TransformModule, self_module).__init__() + self_module.transform = self._init_test_generalized_rcnn_transform() + + def forward(self_module, images): + return self_module.transform.resize(images, None)[0] + + input = torch.rand(3, 10, 20) + input_test = torch.rand(3, 100, 150) + self.run_model(TransformModule(), [(input,), (input_test,)], + input_names=["input1"], dynamic_axes={"input1": [0, 1, 2, 3]}) + def test_transform_images(self): class TransformModule(torch.nn.Module): @@ -109,9 +153,9 @@ def __init__(self_module): def forward(self_module, images): return self_module.transform(images)[0].tensors - input = [torch.rand(3, 100, 200), torch.rand(3, 200, 200)] - input_test = [torch.rand(3, 100, 200), torch.rand(3, 200, 200)] - self.run_model(TransformModule(), [input, input_test]) + input = torch.rand(3, 100, 200), torch.rand(3, 200, 200) + input_test = torch.rand(3, 100, 200), torch.rand(3, 200, 200) + self.run_model(TransformModule(), [(input,), (input_test,)]) def _init_test_generalized_rcnn_transform(self): min_size = 100 @@ -193,22 +237,28 @@ def get_features(self, images): def test_rpn(self): class RPNModule(torch.nn.Module): - def __init__(self_module, images): + def __init__(self_module): super(RPNModule, self_module).__init__() self_module.rpn = self._init_test_rpn() - self_module.images = ImageList(images, [i.shape[-2:] for i in images]) - def forward(self_module, features): - return self_module.rpn(self_module.images, features) + def forward(self_module, images, features): + images = ImageList(images, [i.shape[-2:] for i in images]) + return self_module.rpn(images, features) - images = torch.rand(2, 3, 600, 600) + images = torch.rand(2, 3, 150, 150) features = self.get_features(images) - test_features = self.get_features(images) + images2 = torch.rand(2, 3, 80, 80) + test_features = self.get_features(images2) - model = RPNModule(images) + model = RPNModule() model.eval() - model(features) - self.run_model(model, [(features,), (test_features,)], tolerate_small_mismatch=True) + model(images, features) + + self.run_model(model, [(images, features), (images2, test_features)], tolerate_small_mismatch=True, + input_names=["input1", "input2", "input3", "input4", "input5", "input6"], + dynamic_axes={"input1": [0, 1, 2, 3], "input2": [0, 1, 2, 3], + "input3": [0, 1, 2, 3], "input4": [0, 1, 2, 3], + "input5": [0, 1, 2, 3], "input6": [0, 1, 2, 3]}) def test_multi_scale_roi_align(self): @@ -237,63 +287,79 @@ def forward(self, input, boxes): def test_roi_heads(self): class RoiHeadsModule(torch.nn.Module): - def __init__(self_module, images): + def __init__(self_module): super(RoiHeadsModule, self_module).__init__() self_module.transform = self._init_test_generalized_rcnn_transform() self_module.rpn = self._init_test_rpn() self_module.roi_heads = self._init_test_roi_heads_faster_rcnn() - self_module.original_image_sizes = [img.shape[-2:] for img in images] - self_module.images = ImageList(images, [i.shape[-2:] for i in images]) - def forward(self_module, features): - proposals, _ = self_module.rpn(self_module.images, features) - detections, _ = self_module.roi_heads(features, proposals, self_module.images.image_sizes) + def forward(self_module, images, features): + original_image_sizes = [img.shape[-2:] for img in images] + images = ImageList(images, [i.shape[-2:] for i in images]) + proposals, _ = self_module.rpn(images, features) + detections, _ = self_module.roi_heads(features, proposals, images.image_sizes) detections = self_module.transform.postprocess(detections, - self_module.images.image_sizes, - self_module.original_image_sizes) + images.image_sizes, + original_image_sizes) return detections - images = torch.rand(2, 3, 600, 600) + images = torch.rand(2, 3, 100, 100) features = self.get_features(images) - test_features = self.get_features(images) + images2 = torch.rand(2, 3, 150, 150) + test_features = self.get_features(images2) - model = RoiHeadsModule(images) + model = RoiHeadsModule() model.eval() - model(features) - self.run_model(model, [(features,), (test_features,)]) + model(images, features) + + self.run_model(model, [(images, features), (images2, test_features)], tolerate_small_mismatch=True, + input_names=["input1", "input2", "input3", "input4", "input5", "input6"], + dynamic_axes={"input1": [0, 1, 2, 3], "input2": [0, 1, 2, 3], "input3": [0, 1, 2, 3], + "input4": [0, 1, 2, 3], "input5": [0, 1, 2, 3], "input6": [0, 1, 2, 3]}) - def get_image_from_url(self, url): + def get_image_from_url(self, url, size=None): import requests - import numpy from PIL import Image from io import BytesIO from torchvision import transforms data = requests.get(url) image = Image.open(BytesIO(data.content)).convert("RGB") - image = image.resize((300, 200), Image.BILINEAR) + + if size is None: + size = (300, 200) + image = image.resize(size, Image.BILINEAR) to_tensor = transforms.ToTensor() return to_tensor(image) def get_test_images(self): image_url = "http://farm3.staticflickr.com/2469/3915380994_2e611b1779_z.jpg" - image = self.get_image_from_url(url=image_url) + image = self.get_image_from_url(url=image_url, size=(100, 320)) + image_url2 = "https://pytorch.org/tutorials/_static/img/tv_tutorial/tv_image05.png" - image2 = self.get_image_from_url(url=image_url2) + image2 = self.get_image_from_url(url=image_url2, size=(250, 380)) + images = [image] test_images = [image2] return images, test_images def test_faster_rcnn(self): images, test_images = self.get_test_images() - - model = models.detection.faster_rcnn.fasterrcnn_resnet50_fpn(pretrained=True, - min_size=200, - max_size=300) + dummy_image = [torch.ones(3, 100, 100) * 0.3] + model = models.detection.faster_rcnn.fasterrcnn_resnet50_fpn(pretrained=True, min_size=200, max_size=300) model.eval() model(images) - self.run_model(model, [(images,), (test_images,)]) + # Test exported model on images of different size, or dummy input + self.run_model(model, [(images,), (test_images,), (dummy_image,)], input_names=["images_tensors"], + output_names=["outputs"], + dynamic_axes={"images_tensors": [0, 1, 2, 3], "outputs": [0, 1, 2, 3]}, + tolerate_small_mismatch=True) + # Test exported model for an image with no detections on other images + self.run_model(model, [(dummy_image,), (images,)], input_names=["images_tensors"], + output_names=["outputs"], + dynamic_axes={"images_tensors": [0, 1, 2, 3], "outputs": [0, 1, 2, 3]}, + tolerate_small_mismatch=True) # Verify that paste_mask_in_image beahves the same in tracing. # This test also compares both paste_masks_in_image and _onnx_paste_masks_in_image @@ -329,14 +395,27 @@ def test_paste_mask_in_image(self): assert torch.all(out2.eq(out_trace2)) - @unittest.skip("Disable test until Resize opset 11 is implemented in ONNX Runtime") def test_mask_rcnn(self): images, test_images = self.get_test_images() - - model = models.detection.mask_rcnn.maskrcnn_resnet50_fpn(pretrained=True) + dummy_image = [torch.ones(3, 100, 320) * 0.3] + model = models.detection.mask_rcnn.maskrcnn_resnet50_fpn(pretrained=True, min_size=200, max_size=300) model.eval() model(images) - self.run_model(model, [(images,), (test_images,)]) + # Test exported model on images of different size, or dummy input + self.run_model(model, [(images,), (test_images,), (dummy_image,)], + input_names=["images_tensors"], + output_names=["boxes", "labels", "scores"], + dynamic_axes={"images_tensors": [0, 1, 2, 3], "boxes": [0, 1], "labels": [0], + "scores": [0], "masks": [0, 1, 2, 3]}, + tolerate_small_mismatch=True) + # TODO: enable this test once dynamic model export is fixed + # Test exported model for an image with no detections on other images + # self.run_model(model, [(images,),(test_images,)], + # input_names=["images_tensors"], + # output_names=["boxes", "labels", "scores"], + # dynamic_axes={"images_tensors": [0, 1, 2, 3], "boxes": [0, 1], "labels": [0], + # "scores": [0], "masks": [0, 1, 2, 3]}, + # tolerate_small_mismatch=True) # Verify that heatmaps_to_keypoints behaves the same in tracing. # This test also compares both heatmaps_to_keypoints and _onnx_heatmaps_to_keypoints @@ -366,14 +445,39 @@ def test_heatmaps_to_keypoints(self): assert torch.all(out2[0].eq(out_trace2[0])) assert torch.all(out2[1].eq(out_trace2[1])) - @unittest.skip("Disable test until Argmax is updated in ONNX") def test_keypoint_rcnn(self): - images, test_images = self.get_test_images() + class KeyPointRCNN(torch.nn.Module): + def __init__(self): + super(KeyPointRCNN, self).__init__() + self.model = models.detection.keypoint_rcnn.keypointrcnn_resnet50_fpn(pretrained=True, min_size=200, max_size=300) + + def forward(self, images): + output = self.model(images) + # TODO: The keypoints_scores require the use of Argmax that is updated in ONNX. + # For now we are testing all the output of KeypointRCNN except keypoints_scores. + # Enable When Argmax is updated in ONNX Runtime. + return output[0]['boxes'], output[0]['labels'], output[0]['scores'], output[0]['keypoints'] - model = models.detection.keypoint_rcnn.keypointrcnn_resnet50_fpn(pretrained=True, min_size=200, max_size=300) + images, test_images = self.get_test_images() + # TODO: + # Enable test for dummy_image (no detection) once issue is + # _onnx_heatmaps_to_keypoints_loop for empty heatmaps is fixed + # dummy_images = [torch.ones(3, 100, 100) * 0.3] + model = KeyPointRCNN() model.eval() - model(test_images) - self.run_model(model, [(images,), (test_images,)]) + model(images) + self.run_model(model, [(images,), (test_images,)], + input_names=["images_tensors"], + output_names=["outputs1", "outputs2", "outputs3", "outputs4"], + dynamic_axes={"images_tensors": [0, 1, 2, 3]}, + tolerate_small_mismatch=True) + # TODO: enable this test once dynamic model export is fixed + # Test exported model for an image with no detections on other images + # self.run_model(model, [(dummy_images,), (test_images,)], + # input_names=["images_tensors"], + # output_names=["outputs1", "outputs2", "outputs3", "outputs4"], + # dynamic_axes={"images_tensors": [0, 1, 2, 3]}, + # tolerate_small_mismatch=True) if __name__ == '__main__': diff --git a/test/test_ops.py b/test/test_ops.py index c4cc3fe0bd6..9d4916771ab 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -367,5 +367,14 @@ def test_nms_cuda(self): self.assertTrue(torch.allclose(r_cpu, r_cuda.cpu()), err_msg.format(iou)) +class NewEmptyTensorTester(unittest.TestCase): + def test_new_empty_tensor(self): + input = torch.tensor([2., 2.], requires_grad=True) + new_shape = [3, 3] + out = torch.ops.torchvision._new_empty_tensor_op(input, new_shape) + assert out.size() == torch.Size([3, 3]) + assert out.dtype == input.dtype + + if __name__ == '__main__': unittest.main() diff --git a/torchvision/__init__.py b/torchvision/__init__.py index 084c8468fa3..1f21d34865d 100644 --- a/torchvision/__init__.py +++ b/torchvision/__init__.py @@ -1,5 +1,7 @@ import warnings +from .extension import _HAS_OPS + from torchvision import models from torchvision import datasets from torchvision import ops @@ -7,7 +9,7 @@ from torchvision import utils from torchvision import io -from .extension import _HAS_OPS +import torch try: from .version import __version__ # noqa: F401 @@ -70,5 +72,4 @@ def get_video_backend(): def _is_tracing(): - import torch return torch._C._get_tracing_state() diff --git a/torchvision/csrc/empty_tensor_op.h b/torchvision/csrc/empty_tensor_op.h new file mode 100644 index 00000000000..435ed82133c --- /dev/null +++ b/torchvision/csrc/empty_tensor_op.h @@ -0,0 +1,37 @@ +#pragma once + +// All pure C++ headers for the C++ frontend. +#include +// Python bindings for the C++ frontend (includes Python.h). +#include + +using namespace at; +using torch::Tensor; +using torch::autograd::AutogradContext; +using torch::autograd::Variable; +using torch::autograd::variable_list; + +class NewEmptyTensorOp : public torch::autograd::Function { + public: + static variable_list forward( + AutogradContext* ctx, + Variable input, + c10::List new_shape) { + ctx->saved_data["shape"] = input.sizes(); + std::vector shape(new_shape.begin(), new_shape.end()); + return {input.new_empty(shape, TensorOptions())}; + } + + static variable_list backward( + AutogradContext* ctx, + variable_list grad_output) { + // Use data saved in forward + auto shape = ctx->saved_data["shape"].toIntList(); + auto out = forward(ctx, grad_output[0], shape); + return {out[0], at::Tensor()}; + } +}; + +Tensor new_empty_tensor(const Tensor& input, c10::List shape) { + return NewEmptyTensorOp::apply(input, shape)[0]; +} diff --git a/torchvision/csrc/vision.cpp b/torchvision/csrc/vision.cpp index 1ec4d669d4a..38dcdfc1cc0 100644 --- a/torchvision/csrc/vision.cpp +++ b/torchvision/csrc/vision.cpp @@ -9,6 +9,7 @@ #include "PSROIPool.h" #include "ROIAlign.h" #include "ROIPool.h" +#include "empty_tensor_op.h" #include "nms.h" // If we are in a Windows environment, we need to define @@ -43,6 +44,7 @@ static auto registry = .op("torchvision::roi_align(Tensor input, Tensor rois, float spatial_scale, int pooled_height, int pooled_width, int sampling_ratio) -> Tensor", &roi_align) .op("torchvision::roi_pool", &roi_pool) + .op("torchvision::_new_empty_tensor_op", &new_empty_tensor) .op("torchvision::ps_roi_align", &ps_roi_align) .op("torchvision::ps_roi_pool", &ps_roi_pool) .op("torchvision::_cuda_version", &_cuda_version); diff --git a/torchvision/datasets/usps.py b/torchvision/datasets/usps.py index 8a3cad0bd3d..371b2a85e83 100644 --- a/torchvision/datasets/usps.py +++ b/torchvision/datasets/usps.py @@ -50,7 +50,7 @@ def __init__(self, root, train=True, transform=None, target_transform=None, import bz2 with bz2.open(full_path) as fp: - raw_data = [l.decode().split() for l in fp.readlines()] + raw_data = [line.decode().split() for line in fp.readlines()] imgs = [[x.split(':')[-1] for x in data[1:]] for data in raw_data] imgs = np.asarray(imgs, dtype=np.float32).reshape((-1, 16, 16)) imgs = ((imgs + 1) / 2 * 255).astype(dtype=np.uint8) diff --git a/torchvision/io/_video_opt.py b/torchvision/io/_video_opt.py index 4c39529b950..e28c565bce7 100644 --- a/torchvision/io/_video_opt.py +++ b/torchvision/io/_video_opt.py @@ -26,7 +26,6 @@ # simple class for torch scripting # the complex Fraction class from fractions module is not scriptable -@torch.jit.script class Timebase(object): __annotations__ = {"numerator": int, "denominator": int} __slots__ = ["numerator", "denominator"] @@ -41,7 +40,6 @@ def __init__( self.denominator = denominator -@torch.jit.script class VideoMetaData(object): __annotations__ = { "has_video": bool, diff --git a/torchvision/models/_utils.py b/torchvision/models/_utils.py index 617778116b4..291041d7b5f 100644 --- a/torchvision/models/_utils.py +++ b/torchvision/models/_utils.py @@ -37,7 +37,6 @@ class IntermediateLayerGetter(nn.ModuleDict): >>> ('feat2', torch.Size([1, 256, 14, 14]))] """ _version = 2 - __constants__ = ['layers'] __annotations__ = { "return_layers": Dict[str, str], } @@ -46,7 +45,7 @@ def __init__(self, model, return_layers): if not set(return_layers).issubset([name for name, _ in model.named_children()]): raise ValueError("return_layers are not present in model") orig_return_layers = return_layers - return_layers = {k: v for k, v in return_layers.items()} + return_layers = {str(k): str(v) for k, v in return_layers.items()} layers = OrderedDict() for name, module in model.named_children(): layers[name] = module diff --git a/torchvision/models/detection/_utils.py b/torchvision/models/detection/_utils.py index 854fc6ae3d1..2d4e6284811 100644 --- a/torchvision/models/detection/_utils.py +++ b/torchvision/models/detection/_utils.py @@ -3,6 +3,8 @@ import math import torch +from torch.jit.annotations import List, Tuple +from torch import Tensor import torchvision @@ -12,6 +14,7 @@ class BalancedPositiveNegativeSampler(object): """ def __init__(self, batch_size_per_image, positive_fraction): + # type: (int, float) -> None """ Arguments: batch_size_per_image (int): number of elements to be selected per image @@ -21,6 +24,7 @@ def __init__(self, batch_size_per_image, positive_fraction): self.positive_fraction = positive_fraction def __call__(self, matched_idxs): + # type: (List[Tensor]) -> Tuple[List[Tensor], List[Tensor]] """ Arguments: matched idxs: list of tensors containing -1, 0 or positive values. @@ -63,6 +67,7 @@ def __call__(self, matched_idxs): neg_idx_per_image_mask = torch.zeros_like( matched_idxs_per_image, dtype=torch.uint8 ) + pos_idx_per_image_mask[pos_idx_per_image] = 1 neg_idx_per_image_mask[neg_idx_per_image] = 1 @@ -127,6 +132,7 @@ class BoxCoder(object): """ def __init__(self, weights, bbox_xform_clip=math.log(1000. / 16)): + # type: (Tuple[float, float, float, float], float) -> None """ Arguments: weights (4-element tuple) @@ -136,6 +142,7 @@ def __init__(self, weights, bbox_xform_clip=math.log(1000. / 16)): self.bbox_xform_clip = bbox_xform_clip def encode(self, reference_boxes, proposals): + # type: (List[Tensor], List[Tensor]) -> List[Tensor] boxes_per_image = [len(b) for b in reference_boxes] reference_boxes = torch.cat(reference_boxes, dim=0) proposals = torch.cat(proposals, dim=0) @@ -159,16 +166,18 @@ def encode_single(self, reference_boxes, proposals): return targets def decode(self, rel_codes, boxes): + # type: (Tensor, List[Tensor]) -> Tensor assert isinstance(boxes, (list, tuple)) - if isinstance(rel_codes, (list, tuple)): - rel_codes = torch.cat(rel_codes, dim=0) assert isinstance(rel_codes, torch.Tensor) boxes_per_image = [b.size(0) for b in boxes] concat_boxes = torch.cat(boxes, dim=0) + box_sum = 0 + for val in boxes_per_image: + box_sum += val pred_boxes = self.decode_single( - rel_codes.reshape(sum(boxes_per_image), -1), concat_boxes + rel_codes.reshape(box_sum, -1), concat_boxes ) - return pred_boxes.reshape(sum(boxes_per_image), -1, 4) + return pred_boxes.reshape(box_sum, -1, 4) def decode_single(self, rel_codes, boxes): """ @@ -202,10 +211,10 @@ def decode_single(self, rel_codes, boxes): pred_w = torch.exp(dw) * widths[:, None] pred_h = torch.exp(dh) * heights[:, None] - pred_boxes1 = pred_ctr_x - torch.tensor(0.5, dtype=pred_ctr_x.dtype) * pred_w - pred_boxes2 = pred_ctr_y - torch.tensor(0.5, dtype=pred_ctr_y.dtype) * pred_h - pred_boxes3 = pred_ctr_x + torch.tensor(0.5, dtype=pred_ctr_x.dtype) * pred_w - pred_boxes4 = pred_ctr_y + torch.tensor(0.5, dtype=pred_ctr_y.dtype) * pred_h + pred_boxes1 = pred_ctr_x - torch.tensor(0.5, dtype=pred_ctr_x.dtype, device=pred_w.device) * pred_w + pred_boxes2 = pred_ctr_y - torch.tensor(0.5, dtype=pred_ctr_y.dtype, device=pred_h.device) * pred_h + pred_boxes3 = pred_ctr_x + torch.tensor(0.5, dtype=pred_ctr_x.dtype, device=pred_w.device) * pred_w + pred_boxes4 = pred_ctr_y + torch.tensor(0.5, dtype=pred_ctr_y.dtype, device=pred_h.device) * pred_h pred_boxes = torch.stack((pred_boxes1, pred_boxes2, pred_boxes3, pred_boxes4), dim=2).flatten(1) return pred_boxes @@ -228,7 +237,13 @@ class Matcher(object): BELOW_LOW_THRESHOLD = -1 BETWEEN_THRESHOLDS = -2 + __annotations__ = { + 'BELOW_LOW_THRESHOLD': int, + 'BETWEEN_THRESHOLDS': int, + } + def __init__(self, high_threshold, low_threshold, allow_low_quality_matches=False): + # type: (float, float, bool) -> None """ Args: high_threshold (float): quality values greater than or equal to @@ -242,6 +257,8 @@ def __init__(self, high_threshold, low_threshold, allow_low_quality_matches=Fals for predictions that have only low-quality match candidates. See set_low_quality_matches_ for more details. """ + self.BELOW_LOW_THRESHOLD = -1 + self.BETWEEN_THRESHOLDS = -2 assert low_threshold <= high_threshold self.high_threshold = high_threshold self.low_threshold = low_threshold @@ -274,16 +291,19 @@ def __call__(self, match_quality_matrix): matched_vals, matches = match_quality_matrix.max(dim=0) if self.allow_low_quality_matches: all_matches = matches.clone() + else: + all_matches = None # Assign candidate matches with low quality to negative (unassigned) values below_low_threshold = matched_vals < self.low_threshold between_thresholds = (matched_vals >= self.low_threshold) & ( matched_vals < self.high_threshold ) - matches[below_low_threshold] = Matcher.BELOW_LOW_THRESHOLD - matches[between_thresholds] = Matcher.BETWEEN_THRESHOLDS + matches[below_low_threshold] = self.BELOW_LOW_THRESHOLD + matches[between_thresholds] = self.BETWEEN_THRESHOLDS if self.allow_low_quality_matches: + assert all_matches is not None self.set_low_quality_matches_(matches, all_matches, match_quality_matrix) return matches diff --git a/torchvision/models/detection/backbone_utils.py b/torchvision/models/detection/backbone_utils.py index bd2a791c4f0..f5335c451d9 100644 --- a/torchvision/models/detection/backbone_utils.py +++ b/torchvision/models/detection/backbone_utils.py @@ -7,14 +7,12 @@ from .. import resnet -class BackboneWithFPN(nn.Sequential): +class BackboneWithFPN(nn.Module): """ Adds a FPN on top of a model. - Internally, it uses torchvision.models._utils.IntermediateLayerGetter to extract a submodel that returns the feature maps specified in return_layers. The same limitations of IntermediatLayerGetter apply here. - Arguments: backbone (nn.Module) return_layers (Dict[name, new_name]): a dict containing the names @@ -24,21 +22,24 @@ class BackboneWithFPN(nn.Sequential): in_channels_list (List[int]): number of channels for each feature map that is returned, in the order they are present in the OrderedDict out_channels (int): number of channels in the FPN. - Attributes: out_channels (int): the number of channels in the FPN """ def __init__(self, backbone, return_layers, in_channels_list, out_channels): - body = IntermediateLayerGetter(backbone, return_layers=return_layers) - fpn = FeaturePyramidNetwork( + super(BackboneWithFPN, self).__init__() + self.body = IntermediateLayerGetter(backbone, return_layers=return_layers) + self.fpn = FeaturePyramidNetwork( in_channels_list=in_channels_list, out_channels=out_channels, extra_blocks=LastLevelMaxPool(), ) - super(BackboneWithFPN, self).__init__(OrderedDict( - [("body", body), ("fpn", fpn)])) self.out_channels = out_channels + def forward(self, x): + x = self.body(x) + x = self.fpn(x) + return x + def resnet_fpn_backbone(backbone_name, pretrained): backbone = resnet.__dict__[backbone_name]( @@ -49,7 +50,7 @@ def resnet_fpn_backbone(backbone_name, pretrained): if 'layer2' not in name and 'layer3' not in name and 'layer4' not in name: parameter.requires_grad_(False) - return_layers = {'layer1': 0, 'layer2': 1, 'layer3': 2, 'layer4': 3} + return_layers = {'layer1': '0', 'layer2': '1', 'layer3': '2', 'layer4': '3'} in_channels_stage2 = backbone.inplanes // 8 in_channels_list = [ diff --git a/torchvision/models/detection/faster_rcnn.py b/torchvision/models/detection/faster_rcnn.py index f4d584b4139..cb45f77df17 100644 --- a/torchvision/models/detection/faster_rcnn.py +++ b/torchvision/models/detection/faster_rcnn.py @@ -199,7 +199,7 @@ def __init__(self, backbone, num_classes=None, if box_roi_pool is None: box_roi_pool = MultiScaleRoIAlign( - featmap_names=[0, 1, 2, 3], + featmap_names=['0', '1', '2', '3'], output_size=7, sampling_ratio=2) @@ -273,7 +273,7 @@ def __init__(self, in_channels, num_classes): self.bbox_pred = nn.Linear(in_channels, num_classes * 4) def forward(self, x): - if x.ndimension() == 4: + if x.dim() == 4: assert list(x.shape[2:]) == [1, 1] x = x.flatten(start_dim=1) scores = self.cls_score(x) diff --git a/torchvision/models/detection/generalized_rcnn.py b/torchvision/models/detection/generalized_rcnn.py index 87ade2a6dfe..636772edeca 100644 --- a/torchvision/models/detection/generalized_rcnn.py +++ b/torchvision/models/detection/generalized_rcnn.py @@ -6,6 +6,9 @@ from collections import OrderedDict import torch from torch import nn +import warnings +from torch.jit.annotations import Tuple, List, Dict, Optional +from torch import Tensor class GeneralizedRCNN(nn.Module): @@ -27,8 +30,19 @@ def __init__(self, backbone, rpn, roi_heads, transform): self.backbone = backbone self.rpn = rpn self.roi_heads = roi_heads + # used only on torchscript mode + self._has_warned = False + + @torch.jit.unused + def eager_outputs(self, losses, detections): + # type: (Dict[str, Tensor], List[Dict[str, Tensor]]) -> Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]] + if self.training: + return losses + + return detections def forward(self, images, targets=None): + # type: (List[Tensor], Optional[List[Dict[str, Tensor]]]) -> Tuple[Dict[str, Tensor], List[Dict[str, Tensor]]] """ Arguments: images (list[Tensor]): images to be processed @@ -43,11 +57,16 @@ def forward(self, images, targets=None): """ if self.training and targets is None: raise ValueError("In training mode, targets should be passed") - original_image_sizes = [img.shape[-2:] for img in images] + original_image_sizes = torch.jit.annotate(List[Tuple[int, int]], []) + for img in images: + val = img.shape[-2:] + assert len(val) == 2 + original_image_sizes.append((val[0], val[1])) + images, targets = self.transform(images, targets) features = self.backbone(images.tensors) if isinstance(features, torch.Tensor): - features = OrderedDict([(0, features)]) + features = OrderedDict([('0', features)]) proposals, proposal_losses = self.rpn(images, features, targets) detections, detector_losses = self.roi_heads(features, proposals, images.image_sizes, targets) detections = self.transform.postprocess(detections, images.image_sizes, original_image_sizes) @@ -56,7 +75,10 @@ def forward(self, images, targets=None): losses.update(detector_losses) losses.update(proposal_losses) - if self.training: - return losses - - return detections + if torch.jit.is_scripting(): + if not self._has_warned: + warnings.warn("RCNN always returns a (Losses, Detections) tuple in scripting") + self._has_warned = True + return (losses, detections) + else: + return self.eager_outputs(losses, detections) diff --git a/torchvision/models/detection/image_list.py b/torchvision/models/detection/image_list.py index 25162cc397f..ca0f5b20c31 100644 --- a/torchvision/models/detection/image_list.py +++ b/torchvision/models/detection/image_list.py @@ -2,6 +2,8 @@ from __future__ import division import torch +from torch.jit.annotations import List, Tuple +from torch import Tensor class ImageList(object): @@ -13,6 +15,7 @@ class ImageList(object): """ def __init__(self, tensors, image_sizes): + # type: (Tensor, List[Tuple[int, int]]) -> None """ Arguments: tensors (tensor) @@ -21,6 +24,7 @@ def __init__(self, tensors, image_sizes): self.tensors = tensors self.image_sizes = image_sizes - def to(self, *args, **kwargs): - cast_tensor = self.tensors.to(*args, **kwargs) + def to(self, device): + # type: (Device) -> ImageList # noqa + cast_tensor = self.tensors.to(device) return ImageList(cast_tensor, self.image_sizes) diff --git a/torchvision/models/detection/keypoint_rcnn.py b/torchvision/models/detection/keypoint_rcnn.py index 2efdb1de03d..17a83ea7806 100644 --- a/torchvision/models/detection/keypoint_rcnn.py +++ b/torchvision/models/detection/keypoint_rcnn.py @@ -2,6 +2,7 @@ from torch import nn from torchvision.ops import misc as misc_nn_ops + from torchvision.ops import MultiScaleRoIAlign from ..utils import load_state_dict_from_url @@ -180,7 +181,7 @@ def __init__(self, backbone, num_classes=None, if keypoint_roi_pool is None: keypoint_roi_pool = MultiScaleRoIAlign( - featmap_names=[0, 1, 2, 3], + featmap_names=['0', '1', '2', '3'], output_size=14, sampling_ratio=2) @@ -220,10 +221,10 @@ class KeypointRCNNHeads(nn.Sequential): def __init__(self, in_channels, layers): d = [] next_feature = in_channels - for l in layers: - d.append(misc_nn_ops.Conv2d(next_feature, l, 3, stride=1, padding=1)) + for out_channels in layers: + d.append(misc_nn_ops.Conv2d(next_feature, out_channels, 3, stride=1, padding=1)) d.append(nn.ReLU(inplace=True)) - next_feature = l + next_feature = out_channels super(KeypointRCNNHeads, self).__init__(*d) for m in self.children(): if isinstance(m, misc_nn_ops.Conv2d): @@ -253,7 +254,7 @@ def __init__(self, in_channels, num_keypoints): def forward(self, x): x = self.kps_score_lowres(x) x = misc_nn_ops.interpolate( - x, scale_factor=self.up_scale, mode="bilinear", align_corners=False + x, scale_factor=float(self.up_scale), mode="bilinear", align_corners=False ) return x diff --git a/torchvision/models/detection/mask_rcnn.py b/torchvision/models/detection/mask_rcnn.py index dba9d7eafd4..90e02405b47 100644 --- a/torchvision/models/detection/mask_rcnn.py +++ b/torchvision/models/detection/mask_rcnn.py @@ -179,7 +179,7 @@ def __init__(self, backbone, num_classes=None, if mask_roi_pool is None: mask_roi_pool = MultiScaleRoIAlign( - featmap_names=[0, 1, 2, 3], + featmap_names=['0', '1', '2', '3'], output_size=14, sampling_ratio=2) diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index 63d3977c847..d57bb6c138d 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -3,16 +3,20 @@ import torchvision import torch.nn.functional as F -from torch import nn +from torch import nn, Tensor from torchvision.ops import boxes as box_ops from torchvision.ops import misc as misc_nn_ops + from torchvision.ops import roi_align from . import _utils as det_utils +from torch.jit.annotations import Optional, List, Dict, Tuple + def fastrcnn_loss(class_logits, box_regression, labels, regression_targets): + # type: (Tensor, Tensor, List[Tensor], List[Tensor]) -> Tuple[Tensor, Tensor] """ Computes the loss for Faster R-CNN. @@ -51,6 +55,7 @@ def fastrcnn_loss(class_logits, box_regression, labels, regression_targets): def maskrcnn_inference(x, labels): + # type: (Tensor, List[Tensor]) -> List[Tensor] """ From the results of the CNN, post process the masks by taking the mask corresponding to the class with max @@ -70,21 +75,17 @@ def maskrcnn_inference(x, labels): # select masks coresponding to the predicted classes num_masks = x.shape[0] - boxes_per_image = [len(l) for l in labels] + boxes_per_image = [label.shape[0] for label in labels] labels = torch.cat(labels) index = torch.arange(num_masks, device=labels.device) mask_prob = mask_prob[index, labels][:, None] - - if len(boxes_per_image) == 1: - # TODO : remove when dynamic split supported in ONNX - mask_prob = (mask_prob,) - else: - mask_prob = mask_prob.split(boxes_per_image, dim=0) + mask_prob = mask_prob.split(boxes_per_image, dim=0) return mask_prob def project_masks_on_boxes(gt_masks, boxes, matched_idxs, M): + # type: (Tensor, Tensor, Tensor, int) -> Tensor """ Given segmentation masks and the bounding boxes corresponding to the location of the masks in the image, this function @@ -95,10 +96,11 @@ def project_masks_on_boxes(gt_masks, boxes, matched_idxs, M): matched_idxs = matched_idxs.to(boxes) rois = torch.cat([matched_idxs[:, None], boxes], dim=1) gt_masks = gt_masks[:, None].to(rois) - return roi_align(gt_masks, rois, (M, M), 1)[:, 0] + return roi_align(gt_masks, rois, (M, M), 1.)[:, 0] def maskrcnn_loss(mask_logits, proposals, gt_masks, gt_labels, mask_matched_idxs): + # type: (Tensor, List[Tensor], List[Tensor], List[Tensor], List[Tensor]) -> Tensor """ Arguments: proposals (list[BoxList]) @@ -110,7 +112,7 @@ def maskrcnn_loss(mask_logits, proposals, gt_masks, gt_labels, mask_matched_idxs """ discretization_size = mask_logits.shape[-1] - labels = [l[idxs] for l, idxs in zip(gt_labels, mask_matched_idxs)] + labels = [gt_label[idxs] for gt_label, idxs in zip(gt_labels, mask_matched_idxs)] mask_targets = [ project_masks_on_boxes(m, p, i, discretization_size) for m, p, i in zip(gt_masks, proposals, mask_matched_idxs) @@ -131,6 +133,7 @@ def maskrcnn_loss(mask_logits, proposals, gt_masks, gt_labels, mask_matched_idxs def keypoints_to_heatmap(keypoints, rois, heatmap_size): + # type: (Tensor, Tensor, int) -> Tuple[Tensor, Tensor] offset_x = rois[:, 0] offset_y = rois[:, 1] scale_x = heatmap_size / (rois[:, 2] - rois[:, 0]) @@ -258,6 +261,7 @@ def heatmaps_to_keypoints(maps, rois): # roi_map_probs = scores_to_probs(roi_map.copy()) w = roi_map.shape[2] pos = roi_map.reshape(num_keypoints, -1).argmax(dim=1) + x_int = pos % w y_int = (pos - x_int) // w # assert (roi_map_probs[k, y_int, x_int] == @@ -273,6 +277,7 @@ def heatmaps_to_keypoints(maps, rois): def keypointrcnn_loss(keypoint_logits, proposals, gt_keypoints, keypoint_matched_idxs): + # type: (Tensor, List[Tensor], List[Tensor], List[Tensor]) -> Tensor N, K, H, W = keypoint_logits.shape assert H == W discretization_size = H @@ -302,16 +307,11 @@ def keypointrcnn_loss(keypoint_logits, proposals, gt_keypoints, keypoint_matched def keypointrcnn_inference(x, boxes): + # type: (Tensor, List[Tensor]) -> Tuple[List[Tensor], List[Tensor]] kp_probs = [] kp_scores = [] boxes_per_image = [box.size(0) for box in boxes] - - if len(boxes_per_image) == 1: - # TODO : remove when dynamic split supported in ONNX - kp_prob, scores = heatmaps_to_keypoints(x, boxes[0]) - return [kp_prob], [scores] - x2 = x.split(boxes_per_image, dim=0) for xx, bb in zip(x2, boxes): @@ -323,6 +323,7 @@ def keypointrcnn_inference(x, boxes): def _onnx_expand_boxes(boxes, scale): + # type: (Tensor, float) -> Tensor w_half = (boxes[:, 2] - boxes[:, 0]) * .5 h_half = (boxes[:, 3] - boxes[:, 1]) * .5 x_c = (boxes[:, 2] + boxes[:, 0]) * .5 @@ -343,6 +344,7 @@ def _onnx_expand_boxes(boxes, scale): # but are kept here for the moment while we need them # temporarily for paste_mask_in_image def expand_boxes(boxes, scale): + # type: (Tensor, float) -> Tensor if torchvision._is_tracing(): return _onnx_expand_boxes(boxes, scale) w_half = (boxes[:, 2] - boxes[:, 0]) * .5 @@ -361,10 +363,17 @@ def expand_boxes(boxes, scale): return boxes_exp +@torch.jit.unused +def expand_masks_tracing_scale(M, padding): + # type: (int, int) -> float + return torch.tensor(M + 2 * padding).to(torch.float32) / torch.tensor(M).to(torch.float32) + + def expand_masks(mask, padding): + # type: (Tensor, int) -> Tuple[Tensor, float] M = mask.shape[-1] - if torchvision._is_tracing(): - scale = (M + 2 * padding).to(torch.float32) / M.to(torch.float32) + if torch._C._get_tracing_state(): # could not import is_tracing(), not sure why + scale = expand_masks_tracing_scale(M, padding) else: scale = float(M + 2 * padding) / M padded_mask = torch.nn.functional.pad(mask, (padding,) * 4) @@ -372,6 +381,7 @@ def expand_masks(mask, padding): def paste_mask_in_image(mask, box, im_h, im_w): + # type: (Tensor, Tensor, int, int) -> Tensor TO_REMOVE = 1 w = int(box[2] - box[0] + TO_REMOVE) h = int(box[3] - box[1] + TO_REMOVE) @@ -449,29 +459,33 @@ def _onnx_paste_masks_in_image_loop(masks, boxes, im_h, im_w): def paste_masks_in_image(masks, boxes, img_shape, padding=1): + # type: (Tensor, Tensor, Tuple[int, int], int) -> Tensor masks, scale = expand_masks(masks, padding=padding) boxes = expand_boxes(boxes, scale).to(dtype=torch.int64) - # im_h, im_w = img_shape.tolist() im_h, im_w = img_shape if torchvision._is_tracing(): return _onnx_paste_masks_in_image_loop(masks, boxes, torch.scalar_tensor(im_h, dtype=torch.int64), torch.scalar_tensor(im_w, dtype=torch.int64))[:, None] - - boxes = boxes.tolist() res = [ paste_mask_in_image(m[0], b, im_h, im_w) for m, b in zip(masks, boxes) ] if len(res) > 0: - res = torch.stack(res, dim=0)[:, None] + ret = torch.stack(res, dim=0)[:, None] else: - res = masks.new_empty((0, 1, im_h, im_w)) - return res + ret = masks.new_empty((0, 1, im_h, im_w)) + return ret class RoIHeads(torch.nn.Module): + __annotations__ = { + 'box_coder': det_utils.BoxCoder, + 'proposal_matcher': det_utils.Matcher, + 'fg_bg_sampler': det_utils.BalancedPositiveNegativeSampler, + } + def __init__(self, box_roi_pool, box_head, @@ -525,7 +539,6 @@ def __init__(self, self.keypoint_head = keypoint_head self.keypoint_predictor = keypoint_predictor - @property def has_mask(self): if self.mask_roi_pool is None: return False @@ -535,7 +548,6 @@ def has_mask(self): return False return True - @property def has_keypoint(self): if self.keypoint_roi_pool is None: return False @@ -546,30 +558,44 @@ def has_keypoint(self): return True def assign_targets_to_proposals(self, proposals, gt_boxes, gt_labels): + # type: (List[Tensor], List[Tensor], List[Tensor]) -> Tuple[List[Tensor], List[Tensor]] matched_idxs = [] labels = [] for proposals_in_image, gt_boxes_in_image, gt_labels_in_image in zip(proposals, gt_boxes, gt_labels): - match_quality_matrix = self.box_similarity(gt_boxes_in_image, proposals_in_image) - matched_idxs_in_image = self.proposal_matcher(match_quality_matrix) - clamped_matched_idxs_in_image = matched_idxs_in_image.clamp(min=0) + if gt_boxes_in_image.numel() == 0: + # Background image + device = proposals_in_image.device + clamped_matched_idxs_in_image = torch.zeros( + (proposals_in_image.shape[0],), dtype=torch.int64, device=device + ) + labels_in_image = torch.zeros( + (proposals_in_image.shape[0],), dtype=torch.int64, device=device + ) + else: + # set to self.box_similarity when https://github.com/pytorch/pytorch/issues/27495 lands + match_quality_matrix = box_ops.box_iou(gt_boxes_in_image, proposals_in_image) + matched_idxs_in_image = self.proposal_matcher(match_quality_matrix) + + clamped_matched_idxs_in_image = matched_idxs_in_image.clamp(min=0) - labels_in_image = gt_labels_in_image[clamped_matched_idxs_in_image] - labels_in_image = labels_in_image.to(dtype=torch.int64) + labels_in_image = gt_labels_in_image[clamped_matched_idxs_in_image] + labels_in_image = labels_in_image.to(dtype=torch.int64) - # Label background (below the low threshold) - bg_inds = matched_idxs_in_image == self.proposal_matcher.BELOW_LOW_THRESHOLD - labels_in_image[bg_inds] = 0 + # Label background (below the low threshold) + bg_inds = matched_idxs_in_image == self.proposal_matcher.BELOW_LOW_THRESHOLD + labels_in_image[bg_inds] = 0 - # Label ignore proposals (between low and high thresholds) - ignore_inds = matched_idxs_in_image == self.proposal_matcher.BETWEEN_THRESHOLDS - labels_in_image[ignore_inds] = -1 # -1 is ignored by sampler + # Label ignore proposals (between low and high thresholds) + ignore_inds = matched_idxs_in_image == self.proposal_matcher.BETWEEN_THRESHOLDS + labels_in_image[ignore_inds] = -1 # -1 is ignored by sampler matched_idxs.append(clamped_matched_idxs_in_image) labels.append(labels_in_image) return matched_idxs, labels def subsample(self, labels): + # type: (List[Tensor]) -> List[Tensor] sampled_pos_inds, sampled_neg_inds = self.fg_bg_sampler(labels) sampled_inds = [] for img_idx, (pos_inds_img, neg_inds_img) in enumerate( @@ -580,6 +606,7 @@ def subsample(self, labels): return sampled_inds def add_gt_proposals(self, proposals, gt_boxes): + # type: (List[Tensor], List[Tensor]) -> List[Tensor] proposals = [ torch.cat((proposal, gt_box)) for proposal, gt_box in zip(proposals, gt_boxes) @@ -588,15 +615,23 @@ def add_gt_proposals(self, proposals, gt_boxes): return proposals def check_targets(self, targets): + # type: (Optional[List[Dict[str, Tensor]]]) -> None assert targets is not None - assert all("boxes" in t for t in targets) - assert all("labels" in t for t in targets) - if self.has_mask: - assert all("masks" in t for t in targets) - - def select_training_samples(self, proposals, targets): + assert all(["boxes" in t for t in targets]) + assert all(["labels" in t for t in targets]) + if self.has_mask(): + assert all(["masks" in t for t in targets]) + + def select_training_samples(self, + proposals, # type: List[Tensor] + targets # type: Optional[List[Dict[str, Tensor]]] + ): + # type: (...) -> Tuple[List[Tensor], List[Tensor], List[Tensor], List[Tensor]] self.check_targets(targets) + assert targets is not None dtype = proposals[0].dtype + device = proposals[0].device + gt_boxes = [t["boxes"].to(dtype) for t in targets] gt_labels = [t["labels"] for t in targets] @@ -614,33 +649,37 @@ def select_training_samples(self, proposals, targets): proposals[img_id] = proposals[img_id][img_sampled_inds] labels[img_id] = labels[img_id][img_sampled_inds] matched_idxs[img_id] = matched_idxs[img_id][img_sampled_inds] - matched_gt_boxes.append(gt_boxes[img_id][matched_idxs[img_id]]) + + gt_boxes_in_image = gt_boxes[img_id] + if gt_boxes_in_image.numel() == 0: + gt_boxes_in_image = torch.zeros((1, 4), dtype=dtype, device=device) + matched_gt_boxes.append(gt_boxes_in_image[matched_idxs[img_id]]) regression_targets = self.box_coder.encode(matched_gt_boxes, proposals) return proposals, matched_idxs, labels, regression_targets - def postprocess_detections(self, class_logits, box_regression, proposals, image_shapes): + def postprocess_detections(self, + class_logits, # type: Tensor + box_regression, # type: Tensor + proposals, # type: List[Tensor] + image_shapes # type: List[Tuple[int, int]] + ): + # type: (...) -> Tuple[List[Tensor], List[Tensor], List[Tensor]] device = class_logits.device num_classes = class_logits.shape[-1] - boxes_per_image = [len(boxes_in_image) for boxes_in_image in proposals] + boxes_per_image = [boxes_in_image.shape[0] for boxes_in_image in proposals] pred_boxes = self.box_coder.decode(box_regression, proposals) pred_scores = F.softmax(class_logits, -1) - # split boxes and scores per image - if len(boxes_per_image) == 1: - # TODO : remove this when ONNX support dynamic split sizes - pred_boxes = (pred_boxes,) - pred_scores = (pred_scores,) - else: - pred_boxes = pred_boxes.split(boxes_per_image, 0) - pred_scores = pred_scores.split(boxes_per_image, 0) + pred_boxes_list = pred_boxes.split(boxes_per_image, 0) + pred_scores_list = pred_scores.split(boxes_per_image, 0) all_boxes = [] all_scores = [] all_labels = [] - for boxes, scores, image_shape in zip(pred_boxes, pred_scores, image_shapes): + for boxes, scores, image_shape in zip(pred_boxes_list, pred_scores_list, image_shapes): boxes = box_ops.clip_boxes_to_image(boxes, image_shape) # create labels for each prediction @@ -677,7 +716,13 @@ def postprocess_detections(self, class_logits, box_regression, proposals, image_ return all_boxes, all_scores, all_labels - def forward(self, features, proposals, image_shapes, targets=None): + def forward(self, + features, # type: Dict[str, Tensor] + proposals, # type: List[Tensor] + image_shapes, # type: List[Tuple[int, int]] + targets=None # type: Optional[List[Dict[str, Tensor]]] + ): + # type: (...) -> Tuple[List[Dict[str, Tensor]], Dict[str, Tensor]] """ Arguments: features (List[Tensor]) @@ -687,38 +732,50 @@ def forward(self, features, proposals, image_shapes, targets=None): """ if targets is not None: for t in targets: - assert t["boxes"].dtype.is_floating_point, 'target boxes must of float type' + # TODO: https://github.com/pytorch/pytorch/issues/26731 + floating_point_types = (torch.float, torch.double, torch.half) + assert t["boxes"].dtype in floating_point_types, 'target boxes must of float type' assert t["labels"].dtype == torch.int64, 'target labels must of int64 type' - if self.has_keypoint: + if self.has_keypoint(): assert t["keypoints"].dtype == torch.float32, 'target keypoints must of float type' if self.training: proposals, matched_idxs, labels, regression_targets = self.select_training_samples(proposals, targets) + else: + labels = None + regression_targets = None + matched_idxs = None box_features = self.box_roi_pool(features, proposals, image_shapes) box_features = self.box_head(box_features) class_logits, box_regression = self.box_predictor(box_features) - result, losses = [], {} + result = torch.jit.annotate(List[Dict[str, torch.Tensor]], []) + losses = {} if self.training: + assert labels is not None and regression_targets is not None loss_classifier, loss_box_reg = fastrcnn_loss( class_logits, box_regression, labels, regression_targets) - losses = dict(loss_classifier=loss_classifier, loss_box_reg=loss_box_reg) + losses = { + "loss_classifier": loss_classifier, + "loss_box_reg": loss_box_reg + } else: boxes, scores, labels = self.postprocess_detections(class_logits, box_regression, proposals, image_shapes) num_images = len(boxes) for i in range(num_images): result.append( - dict( - boxes=boxes[i], - labels=labels[i], - scores=scores[i], - ) + { + "boxes": boxes[i], + "labels": labels[i], + "scores": scores[i], + } ) - if self.has_mask: + if self.has_mask(): mask_proposals = [p["boxes"] for p in result] if self.training: + assert matched_idxs is not None # during training, only focus on positive boxes num_images = len(proposals) mask_proposals = [] @@ -727,19 +784,31 @@ def forward(self, features, proposals, image_shapes, targets=None): pos = torch.nonzero(labels[img_id] > 0).squeeze(1) mask_proposals.append(proposals[img_id][pos]) pos_matched_idxs.append(matched_idxs[img_id][pos]) + else: + pos_matched_idxs = None - mask_features = self.mask_roi_pool(features, mask_proposals, image_shapes) - mask_features = self.mask_head(mask_features) - mask_logits = self.mask_predictor(mask_features) + if self.mask_roi_pool is not None: + mask_features = self.mask_roi_pool(features, mask_proposals, image_shapes) + mask_features = self.mask_head(mask_features) + mask_logits = self.mask_predictor(mask_features) + else: + mask_logits = torch.tensor(0) + raise Exception("Expected mask_roi_pool to be not None") loss_mask = {} if self.training: + assert targets is not None + assert pos_matched_idxs is not None + assert mask_logits is not None + gt_masks = [t["masks"] for t in targets] gt_labels = [t["labels"] for t in targets] - loss_mask = maskrcnn_loss( + rcnn_loss_mask = maskrcnn_loss( mask_logits, mask_proposals, gt_masks, gt_labels, pos_matched_idxs) - loss_mask = dict(loss_mask=loss_mask) + loss_mask = { + "loss_mask": rcnn_loss_mask + } else: labels = [r["labels"] for r in result] masks_probs = maskrcnn_inference(mask_logits, labels) @@ -748,17 +817,23 @@ def forward(self, features, proposals, image_shapes, targets=None): losses.update(loss_mask) - if self.has_keypoint: + # keep none checks in if conditional so torchscript will conditionally + # compile each branch + if self.keypoint_roi_pool is not None and self.keypoint_head is not None \ + and self.keypoint_predictor is not None: keypoint_proposals = [p["boxes"] for p in result] if self.training: # during training, only focus on positive boxes num_images = len(proposals) keypoint_proposals = [] pos_matched_idxs = [] + assert matched_idxs is not None for img_id in range(num_images): pos = torch.nonzero(labels[img_id] > 0).squeeze(1) keypoint_proposals.append(proposals[img_id][pos]) pos_matched_idxs.append(matched_idxs[img_id][pos]) + else: + pos_matched_idxs = None keypoint_features = self.keypoint_roi_pool(features, keypoint_proposals, image_shapes) keypoint_features = self.keypoint_head(keypoint_features) @@ -766,12 +841,20 @@ def forward(self, features, proposals, image_shapes, targets=None): loss_keypoint = {} if self.training: + assert targets is not None + assert pos_matched_idxs is not None + gt_keypoints = [t["keypoints"] for t in targets] - loss_keypoint = keypointrcnn_loss( + rcnn_loss_keypoint = keypointrcnn_loss( keypoint_logits, keypoint_proposals, gt_keypoints, pos_matched_idxs) - loss_keypoint = dict(loss_keypoint=loss_keypoint) + loss_keypoint = { + "loss_keypoint": rcnn_loss_keypoint + } else: + assert keypoint_logits is not None + assert keypoint_proposals is not None + keypoints_probs, kp_scores = keypointrcnn_inference(keypoint_logits, keypoint_proposals) for keypoint_prob, kps, r in zip(keypoints_probs, kp_scores, result): r["keypoints"] = keypoint_prob diff --git a/torchvision/models/detection/rpn.py b/torchvision/models/detection/rpn.py index 2b2bed4af67..bfce098d789 100644 --- a/torchvision/models/detection/rpn.py +++ b/torchvision/models/detection/rpn.py @@ -1,34 +1,44 @@ +from __future__ import division + # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. import torch from torch.nn import functional as F -from torch import nn +from torch import nn, Tensor import torchvision from torchvision.ops import boxes as box_ops from . import _utils as det_utils +from .image_list import ImageList + +from torch.jit.annotations import List, Optional, Dict, Tuple @torch.jit.unused def _onnx_get_num_anchors_and_pre_nms_top_n(ob, orig_pre_nms_top_n): + # type: (Tensor, int) -> Tuple[int, int] from torch.onnx import operators num_anchors = operators.shape_as_tensor(ob)[1].unsqueeze(0) - # TODO : remove cast to IntTensor/num_anchors.dtype when - # ONNX Runtime version is updated with ReduceMin int64 support pre_nms_top_n = torch.min(torch.cat( (torch.tensor([orig_pre_nms_top_n], dtype=num_anchors.dtype), - num_anchors), 0).to(torch.int32)).to(num_anchors.dtype) + num_anchors), 0)) return num_anchors, pre_nms_top_n class AnchorGenerator(nn.Module): + __annotations__ = { + "cell_anchors": Optional[List[torch.Tensor]], + "_cache": Dict[str, List[torch.Tensor]] + } + """ Module that generates anchors for a set of feature maps and image sizes. The module support computing anchors at multiple sizes and aspect ratios - per feature map. + per feature map. This module assumes aspect ratio = height / width for + each anchor. sizes and aspect_ratios should have the same number of elements, and it should correspond to the number of feature maps. @@ -62,8 +72,12 @@ def __init__( self.cell_anchors = None self._cache = {} - @staticmethod - def generate_anchors(scales, aspect_ratios, dtype=torch.float32, device="cpu"): + # TODO: https://github.com/pytorch/pytorch/issues/26792 + # For every (aspect_ratios, scales) combination, output a zero-centered anchor with those values. + # (scales, aspect_ratios) are usually an element of zip(self.scales, self.aspect_ratios) + # This method assumes aspect ratio = height / width for an anchor. + def generate_anchors(self, scales, aspect_ratios, dtype=torch.float32, device="cpu"): + # type: (List[int], List[float], int, Device) -> Tensor # noqa: F821 scales = torch.as_tensor(scales, dtype=dtype, device=device) aspect_ratios = torch.as_tensor(aspect_ratios, dtype=dtype, device=device) h_ratios = torch.sqrt(aspect_ratios) @@ -76,8 +90,15 @@ def generate_anchors(scales, aspect_ratios, dtype=torch.float32, device="cpu"): return base_anchors.round() def set_cell_anchors(self, dtype, device): + # type: (int, Device) -> None # noqa: F821 if self.cell_anchors is not None: - return self.cell_anchors + cell_anchors = self.cell_anchors + assert cell_anchors is not None + # suppose that all anchors have the same device + # which is a valid assumption in the current state of the codebase + if cell_anchors[0].device == device: + return + cell_anchors = [ self.generate_anchors( sizes, @@ -92,18 +113,22 @@ def set_cell_anchors(self, dtype, device): def num_anchors_per_location(self): return [len(s) * len(a) for s, a in zip(self.sizes, self.aspect_ratios)] + # For every combination of (a, (g, s), i) in (self.cell_anchors, zip(grid_sizes, strides), 0:2), + # output g[i] anchors that are s[i] distance apart in direction i, with the same dimensions as a. def grid_anchors(self, grid_sizes, strides): + # type: (List[List[int]], List[List[Tensor]]) -> List[Tensor] anchors = [] + cell_anchors = self.cell_anchors + assert cell_anchors is not None + for size, stride, base_anchors in zip( - grid_sizes, strides, self.cell_anchors + grid_sizes, strides, cell_anchors ): grid_height, grid_width = size stride_height, stride_width = stride - if torchvision._is_tracing(): - # required in ONNX export for mult operation with float32 - stride_width = torch.tensor(stride_width, dtype=torch.float32) - stride_height = torch.tensor(stride_height, dtype=torch.float32) device = base_anchors.device + + # For output anchor, compute [x_center, y_center, x_center, y_center] shifts_x = torch.arange( 0, grid_width, dtype=torch.float32, device=device ) * stride_width @@ -115,6 +140,8 @@ def grid_anchors(self, grid_sizes, strides): shift_y = shift_y.reshape(-1) shifts = torch.stack((shift_x, shift_y, shift_x, shift_y), dim=1) + # For every (base anchor, output anchor) pair, + # offset each zero-centered base anchor by the center of the output anchor. anchors.append( (shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4) ) @@ -122,7 +149,8 @@ def grid_anchors(self, grid_sizes, strides): return anchors def cached_grid_anchors(self, grid_sizes, strides): - key = tuple(grid_sizes) + tuple(strides) + # type: (List[List[int]], List[List[Tensor]]) -> List[Tensor] + key = str(grid_sizes) + str(strides) if key in self._cache: return self._cache[key] anchors = self.grid_anchors(grid_sizes, strides) @@ -130,21 +158,23 @@ def cached_grid_anchors(self, grid_sizes, strides): return anchors def forward(self, image_list, feature_maps): - grid_sizes = tuple([feature_map.shape[-2:] for feature_map in feature_maps]) + # type: (ImageList, List[Tensor]) -> List[Tensor] + grid_sizes = list([feature_map.shape[-2:] for feature_map in feature_maps]) image_size = image_list.tensors.shape[-2:] - strides = tuple((float(image_size[0]) / float(g[0]), - float(image_size[1]) / float(g[1])) - for g in grid_sizes) dtype, device = feature_maps[0].dtype, feature_maps[0].device + strides = [[torch.tensor(image_size[0] // g[0], dtype=torch.int64, device=device), + torch.tensor(image_size[1] // g[1], dtype=torch.int64, device=device)] for g in grid_sizes] self.set_cell_anchors(dtype, device) anchors_over_all_feature_maps = self.cached_grid_anchors(grid_sizes, strides) - anchors = [] + anchors = torch.jit.annotate(List[List[torch.Tensor]], []) for i, (image_height, image_width) in enumerate(image_list.image_sizes): anchors_in_image = [] for anchors_per_feature_map in anchors_over_all_feature_maps: anchors_in_image.append(anchors_per_feature_map) anchors.append(anchors_in_image) anchors = [torch.cat(anchors_per_image) for anchors_per_image in anchors] + # Clear the cache in case that memory leaks. + self._cache.clear() return anchors @@ -167,11 +197,12 @@ def __init__(self, in_channels, num_anchors): in_channels, num_anchors * 4, kernel_size=1, stride=1 ) - for l in self.children(): - torch.nn.init.normal_(l.weight, std=0.01) - torch.nn.init.constant_(l.bias, 0) + for layer in self.children(): + torch.nn.init.normal_(layer.weight, std=0.01) + torch.nn.init.constant_(layer.bias, 0) def forward(self, x): + # type: (List[Tensor]) -> Tuple[List[Tensor], List[Tensor]] logits = [] bbox_reg = [] for feature in x: @@ -182,6 +213,7 @@ def forward(self, x): def permute_and_flatten(layer, N, A, C, H, W): + # type: (Tensor, int, int, int, int, int) -> Tensor layer = layer.view(N, -1, C, H, W) layer = layer.permute(0, 3, 4, 1, 2) layer = layer.reshape(N, -1, C) @@ -189,6 +221,7 @@ def permute_and_flatten(layer, N, A, C, H, W): def concat_box_prediction_layers(box_cls, box_regression): + # type: (List[Tensor], List[Tensor]) -> Tuple[Tensor, Tensor] box_cls_flattened = [] box_regression_flattened = [] # for each feature level, permute the outputs to make them be in the @@ -214,7 +247,7 @@ def concat_box_prediction_layers(box_cls, box_regression): # concatenate on the first dimension (representing the feature levels), to # take into account the way the labels were generated (with all feature maps # being concatenated as well) - box_cls = torch.cat(box_cls_flattened, dim=1).reshape(-1, C) + box_cls = torch.cat(box_cls_flattened, dim=1).flatten(0, -2) box_regression = torch.cat(box_regression_flattened, dim=1).reshape(-1, 4) return box_cls, box_regression @@ -244,6 +277,13 @@ class RegionProposalNetwork(torch.nn.Module): nms_thresh (float): NMS threshold used for postprocessing the RPN proposals """ + __annotations__ = { + 'box_coder': det_utils.BoxCoder, + 'proposal_matcher': det_utils.Matcher, + 'fg_bg_sampler': det_utils.BalancedPositiveNegativeSampler, + 'pre_nms_top_n': Dict[str, int], + 'post_nms_top_n': Dict[str, int], + } def __init__(self, anchor_generator, @@ -276,61 +316,69 @@ def __init__(self, self.nms_thresh = nms_thresh self.min_size = 1e-3 - @property def pre_nms_top_n(self): if self.training: return self._pre_nms_top_n['training'] return self._pre_nms_top_n['testing'] - @property def post_nms_top_n(self): if self.training: return self._post_nms_top_n['training'] return self._post_nms_top_n['testing'] def assign_targets_to_anchors(self, anchors, targets): + # type: (List[Tensor], List[Dict[str, Tensor]]) -> Tuple[List[Tensor], List[Tensor]] labels = [] matched_gt_boxes = [] for anchors_per_image, targets_per_image in zip(anchors, targets): gt_boxes = targets_per_image["boxes"] - match_quality_matrix = self.box_similarity(gt_boxes, anchors_per_image) - matched_idxs = self.proposal_matcher(match_quality_matrix) - # get the targets corresponding GT for each proposal - # NB: need to clamp the indices because we can have a single - # GT in the image, and matched_idxs can be -2, which goes - # out of bounds - matched_gt_boxes_per_image = gt_boxes[matched_idxs.clamp(min=0)] - labels_per_image = matched_idxs >= 0 - labels_per_image = labels_per_image.to(dtype=torch.float32) + if gt_boxes.numel() == 0: + # Background image (negative example) + device = anchors_per_image.device + matched_gt_boxes_per_image = torch.zeros(anchors_per_image.shape, dtype=torch.float32, device=device) + labels_per_image = torch.zeros((anchors_per_image.shape[0],), dtype=torch.float32, device=device) + else: + match_quality_matrix = box_ops.box_iou(gt_boxes, anchors_per_image) + matched_idxs = self.proposal_matcher(match_quality_matrix) + # get the targets corresponding GT for each proposal + # NB: need to clamp the indices because we can have a single + # GT in the image, and matched_idxs can be -2, which goes + # out of bounds + matched_gt_boxes_per_image = gt_boxes[matched_idxs.clamp(min=0)] + + labels_per_image = matched_idxs >= 0 + labels_per_image = labels_per_image.to(dtype=torch.float32) - # Background (negative examples) - bg_indices = matched_idxs == self.proposal_matcher.BELOW_LOW_THRESHOLD - labels_per_image[bg_indices] = 0 + # Background (negative examples) + bg_indices = matched_idxs == self.proposal_matcher.BELOW_LOW_THRESHOLD + labels_per_image[bg_indices] = 0.0 - # discard indices that are between thresholds - inds_to_discard = matched_idxs == self.proposal_matcher.BETWEEN_THRESHOLDS - labels_per_image[inds_to_discard] = -1 + # discard indices that are between thresholds + inds_to_discard = matched_idxs == self.proposal_matcher.BETWEEN_THRESHOLDS + labels_per_image[inds_to_discard] = -1.0 labels.append(labels_per_image) matched_gt_boxes.append(matched_gt_boxes_per_image) return labels, matched_gt_boxes def _get_top_n_idx(self, objectness, num_anchors_per_level): + # type: (Tensor, List[int]) -> Tensor r = [] offset = 0 for ob in objectness.split(num_anchors_per_level, 1): if torchvision._is_tracing(): - num_anchors, pre_nms_top_n = _onnx_get_num_anchors_and_pre_nms_top_n(ob, self.pre_nms_top_n) + num_anchors, pre_nms_top_n = _onnx_get_num_anchors_and_pre_nms_top_n(ob, self.pre_nms_top_n()) else: num_anchors = ob.shape[1] - pre_nms_top_n = min(self.pre_nms_top_n, num_anchors) + pre_nms_top_n = min(self.pre_nms_top_n(), num_anchors) _, top_n_idx = ob.topk(pre_nms_top_n, dim=1) r.append(top_n_idx + offset) offset += num_anchors return torch.cat(r, dim=1) def filter_proposals(self, proposals, objectness, image_shapes, num_anchors_per_level): + # type: (Tensor, Tensor, List[Tuple[int, int]], List[int]) -> Tuple[List[Tensor], List[Tensor]] num_images = proposals.shape[0] device = proposals.device # do not backprop throught objectness @@ -346,7 +394,10 @@ def filter_proposals(self, proposals, objectness, image_shapes, num_anchors_per_ # select top_n boxes independently per level before applying nms top_n_idx = self._get_top_n_idx(objectness, num_anchors_per_level) - batch_idx = torch.arange(num_images, device=device)[:, None] + + image_range = torch.arange(num_images, device=device) + batch_idx = image_range[:, None] + objectness = objectness[batch_idx, top_n_idx] levels = levels[batch_idx, top_n_idx] proposals = proposals[batch_idx, top_n_idx] @@ -360,13 +411,14 @@ def filter_proposals(self, proposals, objectness, image_shapes, num_anchors_per_ # non-maximum suppression, independently done per level keep = box_ops.batched_nms(boxes, scores, lvl, self.nms_thresh) # keep only topk scoring predictions - keep = keep[:self.post_nms_top_n] + keep = keep[:self.post_nms_top_n()] boxes, scores = boxes[keep], scores[keep] final_boxes.append(boxes) final_scores.append(scores) return final_boxes, final_scores def compute_loss(self, objectness, pred_bbox_deltas, labels, regression_targets): + # type: (Tensor, Tensor, List[Tensor], List[Tensor]) -> Tuple[Tensor, Tensor] """ Arguments: objectness (Tensor) @@ -402,7 +454,12 @@ def compute_loss(self, objectness, pred_bbox_deltas, labels, regression_targets) return objectness_loss, box_loss - def forward(self, images, features, targets=None): + def forward(self, + images, # type: ImageList + features, # type: Dict[str, Tensor] + targets=None # type: Optional[List[Dict[str, Tensor]]] + ): + # type: (...) -> Tuple[List[Tensor], Dict[str, Tensor]] """ Arguments: images (ImageList): images for which we want to compute the predictions @@ -425,7 +482,8 @@ def forward(self, images, features, targets=None): anchors = self.anchor_generator(images, features) num_images = len(anchors) - num_anchors_per_level = [o[0].numel() for o in objectness] + num_anchors_per_level_shape_tensors = [o[0].shape for o in objectness] + num_anchors_per_level = [s[0] * s[1] * s[2] for s in num_anchors_per_level_shape_tensors] objectness, pred_bbox_deltas = \ concat_box_prediction_layers(objectness, pred_bbox_deltas) # apply pred_bbox_deltas to anchors to obtain the decoded proposals @@ -437,6 +495,7 @@ def forward(self, images, features, targets=None): losses = {} if self.training: + assert targets is not None labels, matched_gt_boxes = self.assign_targets_to_anchors(anchors, targets) regression_targets = self.box_coder.encode(matched_gt_boxes, anchors) loss_objectness, loss_rpn_box_reg = self.compute_loss( diff --git a/torchvision/models/detection/transform.py b/torchvision/models/detection/transform.py index 8ce96eec723..544387cc6f0 100644 --- a/torchvision/models/detection/transform.py +++ b/torchvision/models/detection/transform.py @@ -1,14 +1,62 @@ +from __future__ import division + import random import math import torch -from torch import nn +from torch import nn, Tensor import torchvision +from torch.jit.annotations import List, Tuple, Dict, Optional from torchvision.ops import misc as misc_nn_ops from .image_list import ImageList from .roi_heads import paste_masks_in_image +@torch.jit.unused +def _resize_image_and_masks_onnx(image, self_min_size, self_max_size, target): + # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]] + from torch.onnx import operators + im_shape = operators.shape_as_tensor(image)[-2:] + min_size = torch.min(im_shape).to(dtype=torch.float32) + max_size = torch.max(im_shape).to(dtype=torch.float32) + scale_factor = torch.min(self_min_size / min_size, self_max_size / max_size) + + image = torch.nn.functional.interpolate( + image[None], scale_factor=scale_factor, mode='bilinear', + align_corners=False)[0] + + if target is None: + return image, target + + if "masks" in target: + mask = target["masks"] + mask = misc_nn_ops.interpolate(mask[None].float(), scale_factor=scale_factor)[0].byte() + target["masks"] = mask + return image, target + + +def _resize_image_and_masks(image, self_min_size, self_max_size, target): + # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]] + im_shape = torch.tensor(image.shape[-2:]) + min_size = float(torch.min(im_shape)) + max_size = float(torch.max(im_shape)) + scale_factor = self_min_size / min_size + if max_size * scale_factor > self_max_size: + scale_factor = self_max_size / max_size + image = torch.nn.functional.interpolate( + image[None], scale_factor=scale_factor, mode='bilinear', + align_corners=False)[0] + + if target is None: + return image, target + + if "masks" in target: + mask = target["masks"] + mask = misc_nn_ops.interpolate(mask[None].float(), scale_factor=scale_factor)[0].byte() + target["masks"] = mask + return image, target + + class GeneralizedRCNNTransform(nn.Module): """ Performs input / target transformation before feeding the data to a GeneralizedRCNN @@ -30,23 +78,33 @@ def __init__(self, min_size, max_size, image_mean, image_std): self.image_mean = image_mean self.image_std = image_std - def forward(self, images, targets=None): + def forward(self, + images, # type: List[Tensor] + targets=None # type: Optional[List[Dict[str, Tensor]]] + ): + # type: (...) -> Tuple[ImageList, Optional[List[Dict[str, Tensor]]]] images = [img for img in images] for i in range(len(images)): image = images[i] - target = targets[i] if targets is not None else targets + target_index = targets[i] if targets is not None else None + if image.dim() != 3: raise ValueError("images is expected to be a list of 3d tensors " "of shape [C, H, W], got {}".format(image.shape)) image = self.normalize(image) - image, target = self.resize(image, target) + image, target_index = self.resize(image, target_index) images[i] = image - if targets is not None: - targets[i] = target + if targets is not None and target_index is not None: + targets[i] = target_index image_sizes = [img.shape[-2:] for img in images] images = self.batch_images(images) - image_list = ImageList(images, image_sizes) + image_sizes_list = torch.jit.annotate(List[Tuple[int, int]], []) + for image_size in image_sizes: + assert len(image_size) == 2 + image_sizes_list.append((image_size[0], image_size[1])) + + image_list = ImageList(images, image_sizes_list) return image_list, targets def normalize(self, image): @@ -55,21 +113,28 @@ def normalize(self, image): std = torch.as_tensor(self.image_std, dtype=dtype, device=device) return (image - mean[:, None, None]) / std[:, None, None] + def torch_choice(self, k): + # type: (List[int]) -> int + """ + Implements `random.choice` via torch ops so it can be compiled with + TorchScript. Remove if https://github.com/pytorch/pytorch/issues/25803 + is fixed. + """ + index = int(torch.empty(1).uniform_(0., float(len(k))).item()) + return k[index] + def resize(self, image, target): + # type: (Tensor, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]] h, w = image.shape[-2:] - im_shape = torch.tensor(image.shape[-2:]) - min_size = float(torch.min(im_shape)) - max_size = float(torch.max(im_shape)) if self.training: - size = random.choice(self.min_size) + size = float(self.torch_choice(self.min_size)) else: # FIXME assume for now that testing uses the largest scale - size = self.min_size[-1] - scale_factor = size / min_size - if max_size * scale_factor > self.max_size: - scale_factor = self.max_size / max_size - image = torch.nn.functional.interpolate( - image[None], scale_factor=scale_factor, mode='bilinear', align_corners=False)[0] + size = float(self.min_size[-1]) + if torchvision._is_tracing(): + image, target = _resize_image_and_masks_onnx(image, size, float(self.max_size), target) + else: + image, target = _resize_image_and_masks(image, size, float(self.max_size), target) if target is None: return image, target @@ -78,11 +143,6 @@ def resize(self, image, target): bbox = resize_boxes(bbox, (h, w), image.shape[-2:]) target["boxes"] = bbox - if "masks" in target: - mask = target["masks"] - mask = misc_nn_ops.interpolate(mask[None].float(), scale_factor=scale_factor)[0].byte() - target["masks"] = mask - if "keypoints" in target: keypoints = target["keypoints"] keypoints = resize_keypoints(keypoints, (h, w), image.shape[-2:]) @@ -91,7 +151,9 @@ def resize(self, image, target): # _onnx_batch_images() is an implementation of # batch_images() that is supported by ONNX tracing. + @torch.jit.unused def _onnx_batch_images(self, images, size_divisible=32): + # type: (List[Tensor], int) -> Tensor max_size = [] for i in range(images[0].dim()): max_size_i = torch.max(torch.stack([img.shape[i] for img in images]).to(torch.float32)).to(torch.int64) @@ -112,27 +174,40 @@ def _onnx_batch_images(self, images, size_divisible=32): return torch.stack(padded_imgs) + def max_by_axis(self, the_list): + # type: (List[List[int]]) -> List[int] + maxes = the_list[0] + for sublist in the_list[1:]: + for index, item in enumerate(sublist): + maxes[index] = max(maxes[index], item) + return maxes + def batch_images(self, images, size_divisible=32): + # type: (List[Tensor], int) -> Tensor if torchvision._is_tracing(): # batch_images() does not export well to ONNX # call _onnx_batch_images() instead return self._onnx_batch_images(images, size_divisible) - max_size = tuple(max(s) for s in zip(*[img.shape for img in images])) - stride = size_divisible + max_size = self.max_by_axis([list(img.shape) for img in images]) + stride = float(size_divisible) max_size = list(max_size) max_size[1] = int(math.ceil(float(max_size[1]) / stride) * stride) max_size[2] = int(math.ceil(float(max_size[2]) / stride) * stride) - max_size = tuple(max_size) - batch_shape = (len(images),) + max_size - batched_imgs = images[0].new(*batch_shape).zero_() + batch_shape = [len(images)] + max_size + batched_imgs = images[0].new_full(batch_shape, 0) for img, pad_img in zip(images, batched_imgs): pad_img[: img.shape[0], : img.shape[1], : img.shape[2]].copy_(img) return batched_imgs - def postprocess(self, result, image_shapes, original_image_sizes): + def postprocess(self, + result, # type: List[Dict[str, Tensor]] + image_shapes, # type: List[Tuple[int, int]] + original_image_sizes # type: List[Tuple[int, int]] + ): + # type: (...) -> List[Dict[str, Tensor]] if self.training: return result for i, (pred, im_s, o_im_s) in enumerate(zip(result, image_shapes, original_image_sizes)): @@ -149,9 +224,23 @@ def postprocess(self, result, image_shapes, original_image_sizes): result[i]["keypoints"] = keypoints return result + def __repr__(self): + format_string = self.__class__.__name__ + '(' + _indent = '\n ' + format_string += "{0}Normalize(mean={1}, std={2})".format(_indent, self.image_mean, self.image_std) + format_string += "{0}Resize(min_size={1}, max_size={2}, mode='bilinear')".format(_indent, self.min_size, + self.max_size) + format_string += '\n)' + return format_string + def resize_keypoints(keypoints, original_size, new_size): - ratios = tuple(float(s) / float(s_orig) for s, s_orig in zip(new_size, original_size)) + # type: (Tensor, List[int], List[int]) -> Tensor + ratios = [ + torch.tensor(s, dtype=torch.float32, device=keypoints.device) / + torch.tensor(s_orig, dtype=torch.float32, device=keypoints.device) + for s, s_orig in zip(new_size, original_size) + ] ratio_h, ratio_w = ratios resized_data = keypoints.clone() if torch._C._get_tracing_state(): @@ -165,7 +254,12 @@ def resize_keypoints(keypoints, original_size, new_size): def resize_boxes(boxes, original_size, new_size): - ratios = tuple(float(s) / float(s_orig) for s, s_orig in zip(new_size, original_size)) + # type: (Tensor, List[int], List[int]) -> Tensor + ratios = [ + torch.tensor(s, dtype=torch.float32, device=boxes.device) / + torch.tensor(s_orig, dtype=torch.float32, device=boxes.device) + for s, s_orig in zip(new_size, original_size) + ] ratio_height, ratio_width = ratios xmin, ymin, xmax, ymax = boxes.unbind(1) diff --git a/torchvision/models/mobilenet.py b/torchvision/models/mobilenet.py index b3ba049a4c6..6d10610b633 100644 --- a/torchvision/models/mobilenet.py +++ b/torchvision/models/mobilenet.py @@ -147,14 +147,16 @@ def __init__(self, nn.init.normal_(m.weight, 0, 0.01) nn.init.zeros_(m.bias) - def _forward(self, x): + def _forward_impl(self, x): + # This exists since TorchScript doesn't support inheritance, so the superclass method + # (this one) needs to have a name other than `forward` that can be accessed in a subclass x = self.features(x) x = x.mean([2, 3]) x = self.classifier(x) return x - # Allow for accessing forward method in a inherited class - forward = _forward + def forward(self, x): + return self._forward_impl(x) def mobilenet_v2(pretrained=False, progress=True, **kwargs): diff --git a/torchvision/models/quantization/mobilenet.py b/torchvision/models/quantization/mobilenet.py index e665f121234..1d14410f376 100644 --- a/torchvision/models/quantization/mobilenet.py +++ b/torchvision/models/quantization/mobilenet.py @@ -44,7 +44,7 @@ def __init__(self, *args, **kwargs): def forward(self, x): x = self.quant(x) - x = self._forward(x) + x = self._forward_impl(x) x = self.dequant(x) return x diff --git a/torchvision/models/quantization/resnet.py b/torchvision/models/quantization/resnet.py index f00b7ed46d3..5fd3c039299 100644 --- a/torchvision/models/quantization/resnet.py +++ b/torchvision/models/quantization/resnet.py @@ -95,7 +95,7 @@ def forward(self, x): # Ensure scriptability # super(QuantizableResNet,self).forward(x) # is not scriptable - x = self._forward(x) + x = self._forward_impl(x) x = self.dequant(x) return x diff --git a/torchvision/models/quantization/shufflenetv2.py b/torchvision/models/quantization/shufflenetv2.py index ec888ec6a33..a2030ca5ece 100644 --- a/torchvision/models/quantization/shufflenetv2.py +++ b/torchvision/models/quantization/shufflenetv2.py @@ -46,7 +46,7 @@ def __init__(self, *args, **kwargs): def forward(self, x): x = self.quant(x) - x = self._forward(x) + x = self._forward_impl(x) x = self.dequant(x) return x diff --git a/torchvision/models/resnet.py b/torchvision/models/resnet.py index 223159ccae6..527eab8ff05 100644 --- a/torchvision/models/resnet.py +++ b/torchvision/models/resnet.py @@ -194,7 +194,8 @@ def _make_layer(self, block, planes, blocks, stride=1, dilate=False): return nn.Sequential(*layers) - def _forward(self, x): + def _forward_impl(self, x): + # See note [TorchScript super()] x = self.conv1(x) x = self.bn1(x) x = self.relu(x) @@ -211,8 +212,8 @@ def _forward(self, x): return x - # Allow for accessing forward method in a inherited class - forward = _forward + def forward(self, x): + return self._forward_impl(x) def _resnet(arch, block, layers, pretrained, progress, **kwargs): diff --git a/torchvision/models/shufflenetv2.py b/torchvision/models/shufflenetv2.py index 7817e8aa1c1..14f9521886c 100644 --- a/torchvision/models/shufflenetv2.py +++ b/torchvision/models/shufflenetv2.py @@ -122,7 +122,8 @@ def __init__(self, stages_repeats, stages_out_channels, num_classes=1000, invert self.fc = nn.Linear(output_channels, num_classes) - def _forward(self, x): + def _forward_impl(self, x): + # See note [TorchScript super()] x = self.conv1(x) x = self.maxpool(x) x = self.stage2(x) @@ -133,7 +134,8 @@ def _forward(self, x): x = self.fc(x) return x - forward = _forward + def forward(self, x): + return self._forward_impl(x) def _shufflenetv2(arch, pretrained, progress, *args, **kwargs): diff --git a/torchvision/ops/__init__.py b/torchvision/ops/__init__.py index 2d175d7f9db..4921d2d0335 100644 --- a/torchvision/ops/__init__.py +++ b/torchvision/ops/__init__.py @@ -1,4 +1,5 @@ from .boxes import nms, box_iou +from .new_empty_tensor import _new_empty_tensor from .roi_align import roi_align, RoIAlign from .roi_pool import roi_pool, RoIPool from .ps_roi_align import ps_roi_align, PSRoIAlign @@ -12,7 +13,7 @@ __all__ = [ - 'nms', 'roi_align', 'RoIAlign', 'roi_pool', 'RoIPool', + 'nms', 'roi_align', 'RoIAlign', 'roi_pool', 'RoIPool', '_new_empty_tensor', 'ps_roi_align', 'PSRoIAlign', 'ps_roi_pool', 'PSRoIPool', 'MultiScaleRoIAlign', 'FeaturePyramidNetwork' ] diff --git a/torchvision/ops/_register_onnx_ops.py b/torchvision/ops/_register_onnx_ops.py index 5aeb1dbec46..d9d9c5c0948 100644 --- a/torchvision/ops/_register_onnx_ops.py +++ b/torchvision/ops/_register_onnx_ops.py @@ -5,7 +5,8 @@ def _register_custom_op(): - from torch.onnx.symbolic_helper import parse_args, scalar_type_to_onnx + from torch.onnx.symbolic_helper import parse_args, scalar_type_to_onnx, scalar_type_to_pytorch_type, \ + cast_pytorch_to_onnx from torch.onnx.symbolic_opset9 import select, unsqueeze, squeeze, _cast_Long, reshape @parse_args('v', 'v', 'f') @@ -17,8 +18,10 @@ def symbolic_multi_label_nms(g, boxes, scores, iou_threshold): nms_out = g.op('NonMaxSuppression', boxes, scores, max_output_per_class, iou_threshold) return squeeze(g, select(g, nms_out, 1, g.op('Constant', value_t=torch.tensor([2], dtype=torch.long))), 1) - @parse_args('v', 'v', 'f', 'i', 'i', 'i') - def roi_align(g, input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio): + @parse_args('v', 'v', 'f', 'i', 'i', 'i', 'i') + def roi_align(g, input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio, aligned): + if(aligned): + raise RuntimeError('Unsupported: ONNX export of roi_align with aligned') batch_indices = _cast_Long(g, squeeze(g, select(g, rois, 1, g.op('Constant', value_t=torch.tensor([0], dtype=torch.long))), 1), False) rois = select(g, rois, 1, g.op('Constant', value_t=torch.tensor([1, 2, 3, 4], dtype=torch.long))) @@ -31,7 +34,18 @@ def roi_pool(g, input, rois, spatial_scale, pooled_height, pooled_width): pooled_shape_i=(pooled_height, pooled_width), spatial_scale_f=spatial_scale) return roi_pool, None + @parse_args('v', 'is') + def new_empty_tensor_op(g, input, shape): + dtype = input.type().scalarType() + if dtype is None: + dtype = 'Float' + dtype = scalar_type_to_onnx.index(cast_pytorch_to_onnx[dtype]) + shape = g.op("Constant", value_t=torch.tensor(shape)) + return g.op("ConstantOfShape", shape, + value_t=torch.tensor([0], dtype=scalar_type_to_pytorch_type[dtype])) + from torch.onnx import register_custom_op_symbolic register_custom_op_symbolic('torchvision::nms', symbolic_multi_label_nms, _onnx_opset_version) register_custom_op_symbolic('torchvision::roi_align', roi_align, _onnx_opset_version) register_custom_op_symbolic('torchvision::roi_pool', roi_pool, _onnx_opset_version) + register_custom_op_symbolic('torchvision::_new_empty_tensor_op', new_empty_tensor_op, _onnx_opset_version) diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index 219c13b36e7..5f4031e2df0 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -1,7 +1,14 @@ +from __future__ import division + import torch +from torch.jit.annotations import Tuple +from torch import Tensor +import torchvision +@torch.jit.script def nms(boxes, scores, iou_threshold): + # type: (Tensor, Tensor, float) -> Tensor """ Performs non-maximum suppression (NMS) on the boxes according to their intersection-over-union (IoU). @@ -31,7 +38,9 @@ def nms(boxes, scores, iou_threshold): return torch.ops.torchvision.nms(boxes, scores, iou_threshold) +@torch.jit.script def batched_nms(boxes, scores, idxs, iou_threshold): + # type: (Tensor, Tensor, Tensor, float) -> Tensor """ Performs non-maximum suppression in a batched fashion. @@ -64,20 +73,22 @@ def batched_nms(boxes, scores, idxs, iou_threshold): # we add an offset to all the boxes. The offset is dependent # only on the class idx, and is large enough so that boxes # from different classes do not overlap - max_coordinate = boxes.max() - offsets = idxs.to(boxes) * (max_coordinate + 1) - boxes_for_nms = boxes + offsets[:, None] - keep = nms(boxes_for_nms, scores, iou_threshold) - return keep + else: + max_coordinate = boxes.max() + offsets = idxs.to(boxes) * (max_coordinate + torch.tensor(1).to(boxes)) + boxes_for_nms = boxes + offsets[:, None] + keep = nms(boxes_for_nms, scores, iou_threshold) + return keep def remove_small_boxes(boxes, min_size): + # type: (Tensor, float) -> Tensor """ Remove boxes which contains at least one side smaller than min_size. Arguments: boxes (Tensor[N, 4]): boxes in (x1, y1, x2, y2) format - min_size (int): minimum size + min_size (float): minimum size Returns: keep (Tensor[K]): indices of the boxes that have both sides @@ -90,6 +101,7 @@ def remove_small_boxes(boxes, min_size): def clip_boxes_to_image(boxes, size): + # type: (Tensor, Tuple[int, int]) -> Tensor """ Clip boxes so that they lie inside an image of size `size`. @@ -104,8 +116,16 @@ def clip_boxes_to_image(boxes, size): boxes_x = boxes[..., 0::2] boxes_y = boxes[..., 1::2] height, width = size - boxes_x = boxes_x.clamp(min=0, max=width) - boxes_y = boxes_y.clamp(min=0, max=height) + + if torchvision._is_tracing(): + boxes_x = torch.max(boxes_x, torch.tensor(0, dtype=boxes.dtype, device=boxes.device)) + boxes_x = torch.min(boxes_x, torch.tensor(width, dtype=boxes.dtype, device=boxes.device)) + boxes_y = torch.max(boxes_y, torch.tensor(0, dtype=boxes.dtype, device=boxes.device)) + boxes_y = torch.min(boxes_y, torch.tensor(height, dtype=boxes.dtype, device=boxes.device)) + else: + boxes_x = boxes_x.clamp(min=0, max=width) + boxes_y = boxes_y.clamp(min=0, max=height) + clipped_boxes = torch.stack((boxes_x, boxes_y), dim=dim) return clipped_boxes.reshape(boxes.shape) diff --git a/torchvision/ops/feature_pyramid_network.py b/torchvision/ops/feature_pyramid_network.py index 23687e7f568..a2d8c409490 100644 --- a/torchvision/ops/feature_pyramid_network.py +++ b/torchvision/ops/feature_pyramid_network.py @@ -2,7 +2,9 @@ import torch import torch.nn.functional as F -from torch import nn +from torch import nn, Tensor + +from torch.jit.annotations import Tuple, List, Dict class FeaturePyramidNetwork(nn.Module): @@ -42,14 +44,13 @@ class FeaturePyramidNetwork(nn.Module): >>> ('feat3', torch.Size([1, 5, 8, 8]))] """ - def __init__(self, in_channels_list, out_channels, extra_blocks=None): super(FeaturePyramidNetwork, self).__init__() self.inner_blocks = nn.ModuleList() self.layer_blocks = nn.ModuleList() for in_channels in in_channels_list: if in_channels == 0: - continue + raise ValueError("in_channels=0 is currently not supported") inner_block_module = nn.Conv2d(in_channels, out_channels, 1) layer_block_module = nn.Conv2d(out_channels, out_channels, 3, padding=1) self.inner_blocks.append(inner_block_module) @@ -65,7 +66,46 @@ def __init__(self, in_channels_list, out_channels, extra_blocks=None): assert isinstance(extra_blocks, ExtraFPNBlock) self.extra_blocks = extra_blocks + def get_result_from_inner_blocks(self, x, idx): + # type: (Tensor, int) -> Tensor + """ + This is equivalent to self.inner_blocks[idx](x), + but torchscript doesn't support this yet + """ + num_blocks = 0 + for m in self.inner_blocks: + num_blocks += 1 + if idx < 0: + idx += num_blocks + i = 0 + out = x + for module in self.inner_blocks: + if i == idx: + out = module(x) + i += 1 + return out + + def get_result_from_layer_blocks(self, x, idx): + # type: (Tensor, int) -> Tensor + """ + This is equivalent to self.layer_blocks[idx](x), + but torchscript doesn't support this yet + """ + num_blocks = 0 + for m in self.layer_blocks: + num_blocks += 1 + if idx < 0: + idx += num_blocks + i = 0 + out = x + for module in self.layer_blocks: + if i == idx: + out = module(x) + i += 1 + return out + def forward(self, x): + # type: (Dict[str, Tensor]) -> Dict[str, Tensor] """ Computes the FPN for a set of feature maps. @@ -80,19 +120,16 @@ def forward(self, x): names = list(x.keys()) x = list(x.values()) - last_inner = self.inner_blocks[-1](x[-1]) + last_inner = self.get_result_from_inner_blocks(x[-1], -1) results = [] - results.append(self.layer_blocks[-1](last_inner)) - for feature, inner_block, layer_block in zip( - x[:-1][::-1], self.inner_blocks[:-1][::-1], self.layer_blocks[:-1][::-1] - ): - if not inner_block: - continue - inner_lateral = inner_block(feature) + results.append(self.get_result_from_layer_blocks(last_inner, -1)) + + for idx in range(len(x) - 2, -1, -1): + inner_lateral = self.get_result_from_inner_blocks(x[idx], idx) feat_shape = inner_lateral.shape[-2:] inner_top_down = F.interpolate(last_inner, size=feat_shape, mode="nearest") last_inner = inner_lateral + inner_top_down - results.insert(0, layer_block(last_inner)) + results.insert(0, self.get_result_from_layer_blocks(last_inner, idx)) if self.extra_blocks is not None: results, names = self.extra_blocks(results, x, names) @@ -127,6 +164,7 @@ class LastLevelMaxPool(ExtraFPNBlock): Applies a max_pool2d on top of the last feature map """ def forward(self, x, y, names): + # type: (List[Tensor], List[Tensor], List[str]) -> Tuple[List[Tensor], List[str]] names.append("pool") x.append(F.max_pool2d(x[-1], 1, 2, 0)) return x, names diff --git a/torchvision/ops/misc.py b/torchvision/ops/misc.py index d06d702732e..ccd44b85472 100644 --- a/torchvision/ops/misc.py +++ b/torchvision/ops/misc.py @@ -1,4 +1,8 @@ from __future__ import division +import warnings +from collections import OrderedDict +from torch.jit.annotations import Optional, List +from torch import Tensor """ helper class that supports empty tensors on some nn functions. @@ -12,40 +16,9 @@ import math import torch -from torch.nn.modules.utils import _ntuple - - -class _NewEmptyTensorOp(torch.autograd.Function): - @staticmethod - def forward(ctx, x, new_shape): - ctx.shape = x.shape - return x.new_empty(new_shape) - - @staticmethod - def backward(ctx, grad): - shape = ctx.shape - return _NewEmptyTensorOp.apply(grad, shape), None - - -class Conv2d(torch.nn.Conv2d): - """ - Equivalent to nn.Conv2d, but with support for empty batch sizes. - This will eventually be supported natively by PyTorch, and this - class can go away. - """ - def forward(self, x): - if x.numel() > 0: - return super(Conv2d, self).forward(x) - # get output shape - - output_shape = [ - (i + 2 * p - (di * (k - 1) + 1)) // d + 1 - for i, p, di, k, d in zip( - x.shape[-2:], self.padding, self.dilation, self.kernel_size, self.stride - ) - ] - output_shape = [x.shape[0], self.weight.shape[0]] + output_shape - return _NewEmptyTensorOp.apply(x, output_shape) +from torchvision.ops import _new_empty_tensor +from torch.nn import Module, Conv2d +import torch.nn.functional as F class ConvTranspose2d(torch.nn.ConvTranspose2d): @@ -56,22 +29,33 @@ class can go away. """ def forward(self, x): if x.numel() > 0: - return super(ConvTranspose2d, self).forward(x) + return self.super_forward(x) # get output shape output_shape = [ (i - 1) * d - 2 * p + (di * (k - 1) + 1) + op for i, p, di, k, d, op in zip( x.shape[-2:], - self.padding, - self.dilation, - self.kernel_size, - self.stride, - self.output_padding, + list(self.padding), + list(self.dilation), + list(self.kernel_size), + list(self.stride), + list(self.output_padding), ) ] output_shape = [x.shape[0], self.bias.shape[0]] + output_shape - return _NewEmptyTensorOp.apply(x, output_shape) + return _new_empty_tensor(x, output_shape) + + def super_forward(self, input, output_size=None): + # type: (Tensor, Optional[List[int]]) -> Tensor + if self.padding_mode != 'zeros': + raise ValueError('Only `zeros` padding mode is supported for ConvTranspose2d') + + output_padding = self._output_padding(input, output_size, self.stride, self.padding, self.kernel_size) + + return F.conv_transpose2d( + input, self.weight, self.bias, self.stride, self.padding, + output_padding, self.groups, self.dilation) class BatchNorm2d(torch.nn.BatchNorm2d): @@ -85,12 +69,65 @@ def forward(self, x): return super(BatchNorm2d, self).forward(x) # get output shape output_shape = x.shape - return _NewEmptyTensorOp.apply(x, output_shape) + return _new_empty_tensor(x, output_shape) -def interpolate( - input, size=None, scale_factor=None, mode="nearest", align_corners=None -): +class Conv2d(torch.nn.Conv2d): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + warnings.warn( + "torchvision.ops.misc.Conv2d is deprecated and will be " + "removed in future versions, use torch.nn.Conv2d instead.", FutureWarning) + + +class ConvTranspose2d(torch.nn.ConvTranspose2d): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + warnings.warn( + "torchvision.ops.misc.ConvTranspose2d is deprecated and will be " + "removed in future versions, use torch.nn.ConvTranspose2d instead.", FutureWarning) + + +class BatchNorm2d(torch.nn.BatchNorm2d): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + warnings.warn( + "torchvision.ops.misc.BatchNorm2d is deprecated and will be " + "removed in future versions, use torch.nn.BatchNorm2d instead.", FutureWarning) + + +def _check_size_scale_factor(dim, size, scale_factor): + # type: (int, Optional[List[int]], Optional[float]) -> None + if size is None and scale_factor is None: + raise ValueError("either size or scale_factor should be defined") + if size is not None and scale_factor is not None: + raise ValueError("only one of size or scale_factor should be defined") + if scale_factor is not None: + if isinstance(scale_factor, (list, tuple)): + if len(scale_factor) != dim: + raise ValueError( + "scale_factor shape must match input shape. " + "Input is {}D, scale_factor size is {}".format(dim, len(scale_factor)) + ) + + +def _output_size(dim, input, size, scale_factor): + # type: (int, Tensor, Optional[List[int]], Optional[float]) -> List[int] + assert dim == 2 + _check_size_scale_factor(dim, size, scale_factor) + if size is not None: + return size + # if dim is not 2 or scale_factor is iterable use _ntuple instead of concat + assert scale_factor is not None and isinstance(scale_factor, (int, float)) + scale_factors = [scale_factor, scale_factor] + # math.floor might return float in py2.7 + return [ + int(math.floor(input.size(i + 2) * scale_factors[i])) for i in range(dim) + ] + + +def interpolate(input, size=None, scale_factor=None, mode="nearest", align_corners=None): + # type: (Tensor, Optional[List[int]], Optional[float], str, Optional[bool]) -> Tensor """ Equivalent to nn.functional.interpolate, but with support for empty batch sizes. This will eventually be supported natively by PyTorch, and this @@ -101,34 +138,9 @@ class can go away. input, size, scale_factor, mode, align_corners ) - def _check_size_scale_factor(dim): - if size is None and scale_factor is None: - raise ValueError("either size or scale_factor should be defined") - if size is not None and scale_factor is not None: - raise ValueError("only one of size or scale_factor should be defined") - if ( - scale_factor is not None and - isinstance(scale_factor, tuple) and - len(scale_factor) != dim - ): - raise ValueError( - "scale_factor shape must match input shape. " - "Input is {}D, scale_factor size is {}".format(dim, len(scale_factor)) - ) - - def _output_size(dim): - _check_size_scale_factor(dim) - if size is not None: - return size - scale_factors = _ntuple(dim)(scale_factor) - # math.floor might return float in py2.7 - return [ - int(math.floor(input.size(i + 2) * scale_factors[i])) for i in range(dim) - ] - - output_shape = tuple(_output_size(2)) - output_shape = input.shape[:-2] + output_shape - return _NewEmptyTensorOp.apply(input, output_shape) + output_shape = _output_size(2, input, size, scale_factor) + output_shape = list(input.shape[:-2]) + list(output_shape) + return _new_empty_tensor(input, output_shape) # This is not in nn diff --git a/torchvision/ops/new_empty_tensor.py b/torchvision/ops/new_empty_tensor.py new file mode 100644 index 00000000000..74455a98c4f --- /dev/null +++ b/torchvision/ops/new_empty_tensor.py @@ -0,0 +1,16 @@ +import torch +from torch.jit.annotations import List +from torch import Tensor + + +def _new_empty_tensor(x, shape): + # type: (Tensor, List[int]) -> Tensor + """ + Arguments: + input (Tensor): input tensor + shape List[int]: the new empty tensor shape + + Returns: + output (Tensor) + """ + return torch.ops.torchvision._new_empty_tensor_op(x, shape) diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index 8fabbc9571d..42698245277 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -1,33 +1,45 @@ +from __future__ import division + # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. import torch import torch.nn.functional as F -from torch import nn +from torch import nn, Tensor -import torchvision from torchvision.ops import roi_align from torchvision.ops.boxes import box_area +from torch.jit.annotations import Optional, List, Dict, Tuple +import torchvision + # copying result_idx_in_level to a specific index in result[] # is not supported by ONNX tracing yet. # _onnx_merge_levels() is an implementation supported by ONNX # that merges the levels to the right indices +@torch.jit.unused def _onnx_merge_levels(levels, unmerged_results): + # type: (Tensor, List[Tensor]) -> Tensor first_result = unmerged_results[0] dtype, device = first_result.dtype, first_result.device res = torch.zeros((levels.size(0), first_result.size(1), first_result.size(2), first_result.size(3)), dtype=dtype, device=device) - for l in range(len(unmerged_results)): - index = (levels == l).nonzero().view(-1, 1, 1, 1) + for level in range(len(unmerged_results)): + index = (levels == level).nonzero().view(-1, 1, 1, 1) index = index.expand(index.size(0), - unmerged_results[l].size(1), - unmerged_results[l].size(2), - unmerged_results[l].size(3)) - res = res.scatter(0, index, unmerged_results[l]) + unmerged_results[level].size(1), + unmerged_results[level].size(2), + unmerged_results[level].size(3)) + res = res.scatter(0, index, unmerged_results[level]) return res +# TODO: (eellison) T54974082 https://github.com/pytorch/pytorch/issues/26744/pytorch/issues/26744 +def initLevelMapper(k_min, k_max, canonical_scale=224, canonical_level=4, eps=1e-6): + # type: (int, int, int, int, float) -> LevelMapper + return LevelMapper(k_min, k_max, canonical_scale, canonical_level, eps) + + class LevelMapper(object): """Determine which FPN level each RoI in a set of RoIs should map to based on the heuristic in the FPN paper. @@ -41,6 +53,7 @@ class LevelMapper(object): """ def __init__(self, k_min, k_max, canonical_scale=224, canonical_level=4, eps=1e-6): + # type: (int, int, int, int, float) -> None self.k_min = k_min self.k_max = k_max self.s0 = canonical_scale @@ -48,6 +61,7 @@ def __init__(self, k_min, k_max, canonical_scale=224, canonical_level=4, eps=1e- self.eps = eps def __call__(self, boxlists): + # type: (List[Tensor]) -> Tensor """ Arguments: boxlists (list[BoxList]) @@ -90,6 +104,11 @@ class MultiScaleRoIAlign(nn.Module): """ + __annotations__ = { + 'scales': Optional[List[float]], + 'map_levels': Optional[LevelMapper] + } + def __init__(self, featmap_names, output_size, sampling_ratio): super(MultiScaleRoIAlign, self).__init__() if isinstance(output_size, int): @@ -101,11 +120,12 @@ def __init__(self, featmap_names, output_size, sampling_ratio): self.map_levels = None def convert_to_roi_format(self, boxes): + # type: (List[Tensor]) -> Tensor concat_boxes = torch.cat(boxes, dim=0) device, dtype = concat_boxes.device, concat_boxes.dtype ids = torch.cat( [ - torch.full_like(b[:, :1], i, dtype=dtype, device=device) + torch.full_like(b[:, :1], i, dtype=dtype, layout=torch.strided, device=device) for i, b in enumerate(boxes) ], dim=0, @@ -114,27 +134,37 @@ def convert_to_roi_format(self, boxes): return rois def infer_scale(self, feature, original_size): + # type: (Tensor, List[int]) -> float # assumption: the scale is of the form 2 ** (-k), with k integer size = feature.shape[-2:] - possible_scales = [] + possible_scales = torch.jit.annotate(List[float], []) for s1, s2 in zip(size, original_size): - approx_scale = float(s1) / s2 - scale = 2 ** torch.tensor(approx_scale).log2().round().item() + approx_scale = float(s1) / float(s2) + scale = 2 ** float(torch.tensor(approx_scale).log2().round()) possible_scales.append(scale) assert possible_scales[0] == possible_scales[1] return possible_scales[0] def setup_scales(self, features, image_shapes): - original_input_shape = tuple(max(s) for s in zip(*image_shapes)) + # type: (List[Tensor], List[Tuple[int, int]]) -> None + assert len(image_shapes) != 0 + max_x = 0 + max_y = 0 + for shape in image_shapes: + max_x = max(shape[0], max_x) + max_y = max(shape[1], max_y) + original_input_shape = (max_x, max_y) + scales = [self.infer_scale(feat, original_input_shape) for feat in features] # get the levels in the feature map by leveraging the fact that the network always # downsamples by a factor of 2 at each level. lvl_min = -torch.log2(torch.tensor(scales[0], dtype=torch.float32)).item() lvl_max = -torch.log2(torch.tensor(scales[-1], dtype=torch.float32)).item() self.scales = scales - self.map_levels = LevelMapper(lvl_min, lvl_max) + self.map_levels = initLevelMapper(int(lvl_min), int(lvl_max)) def forward(self, x, boxes, image_shapes): + # type: (Dict[str, Tensor], List[Tensor], List[Tuple[int, int]]) -> Tensor """ Arguments: x (OrderedDict[Tensor]): feature maps for each level. They are assumed to have @@ -148,34 +178,43 @@ def forward(self, x, boxes, image_shapes): Returns: result (Tensor) """ - x = [v for k, v in x.items() if k in self.featmap_names] - num_levels = len(x) + x_filtered = [] + for k, v in x.items(): + if k in self.featmap_names: + x_filtered.append(v) + num_levels = len(x_filtered) rois = self.convert_to_roi_format(boxes) if self.scales is None: - self.setup_scales(x, image_shapes) + self.setup_scales(x_filtered, image_shapes) + + scales = self.scales + assert scales is not None if num_levels == 1: return roi_align( - x[0], rois, + x_filtered[0], rois, output_size=self.output_size, - spatial_scale=self.scales[0], + spatial_scale=scales[0], sampling_ratio=self.sampling_ratio ) - levels = self.map_levels(boxes) + mapper = self.map_levels + assert mapper is not None + + levels = mapper(boxes) num_rois = len(rois) - num_channels = x[0].shape[1] + num_channels = x_filtered[0].shape[1] - dtype, device = x[0].dtype, x[0].device + dtype, device = x_filtered[0].dtype, x_filtered[0].device result = torch.zeros( (num_rois, num_channels,) + self.output_size, dtype=dtype, device=device, ) - results = [] - for level, (per_level_feature, scale) in enumerate(zip(x, self.scales)): + tracing_results = [] + for level, (per_level_feature, scale) in enumerate(zip(x_filtered, scales)): idx_in_level = torch.nonzero(levels == level).squeeze(1) rois_per_level = rois[idx_in_level] @@ -185,10 +224,11 @@ def forward(self, x, boxes, image_shapes): spatial_scale=scale, sampling_ratio=self.sampling_ratio) if torchvision._is_tracing(): - results.append(result_idx_in_level.to(dtype)) + tracing_results.append(result_idx_in_level.to(dtype)) else: result[idx_in_level] = result_idx_in_level if torchvision._is_tracing(): - result = _onnx_merge_levels(levels, results) + result = _onnx_merge_levels(levels, tracing_results) + return result diff --git a/torchvision/ops/roi_align.py b/torchvision/ops/roi_align.py index abba99d420a..09ed6e547f4 100644 --- a/torchvision/ops/roi_align.py +++ b/torchvision/ops/roi_align.py @@ -2,13 +2,13 @@ from torch import nn, Tensor from torch.nn.modules.utils import _pair -from torch.jit.annotations import List +from torch.jit.annotations import List, BroadcastingList2 from ._utils import convert_boxes_to_roi_format def roi_align(input, boxes, output_size, spatial_scale=1.0, sampling_ratio=-1): - # type: (Tensor, Tensor, int, float, int) -> Tensor + # type: (Tensor, Tensor, BroadcastingList2[int], float, int) -> Tensor """ Performs Region of Interest (RoI) Align operator described in Mask R-CNN diff --git a/torchvision/ops/roi_pool.py b/torchvision/ops/roi_pool.py index 50381c4ff2f..f94373436db 100644 --- a/torchvision/ops/roi_pool.py +++ b/torchvision/ops/roi_pool.py @@ -2,13 +2,13 @@ from torch import nn, Tensor from torch.nn.modules.utils import _pair -from torch.jit.annotations import List +from torch.jit.annotations import List, BroadcastingList2 from ._utils import convert_boxes_to_roi_format def roi_pool(input, boxes, output_size, spatial_scale=1.0): - # type: (Tensor, Tensor, int, float) -> Tensor + # type: (Tensor, Tensor, BroadcastingList2[int], float) -> Tensor """ Performs Region of Interest (RoI) Pool operator described in Fast R-CNN diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index f6b4161869b..8f1d12f1509 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -642,7 +642,7 @@ def adjust_hue(img, hue_factor): PIL Image: Hue adjusted image. """ if not(-0.5 <= hue_factor <= 0.5): - raise ValueError('hue_factor is not in [-0.5, 0.5].'.format(hue_factor)) + raise ValueError('hue_factor ({}) is not in [-0.5, 0.5].'.format(hue_factor)) if not _is_pil_image(img): raise TypeError('img should be PIL Image. Got {}'.format(type(img))) diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 0e72d391508..6c74a7acb94 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -812,8 +812,8 @@ def __init__(self, transformation_matrix, mean_vector): if mean_vector.size(0) != transformation_matrix.size(0): raise ValueError("mean_vector should have the same length {}".format(mean_vector.size(0)) + - " as any one of the dimensions of the transformation_matrix [{} x {}]" - .format(transformation_matrix.size())) + " as any one of the dimensions of the transformation_matrix [{}]" + .format(tuple(transformation_matrix.size()))) self.transformation_matrix = transformation_matrix self.mean_vector = mean_vector From a645468615ebe0a8845bdce04c92397f9fab6772 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Jun 2020 03:02:18 -0700 Subject: [PATCH 065/357] Update circleci (#2306) Summary: Stack of PRs for code sync Pull Request resolved: https://github.com/pytorch/vision/pull/2306 Reviewed By: lw Differential Revision: D21971343 Pulled By: fmassa fbshipit-source-id: bda18d47672729bb7aff8891c17ebdf9ec076475 --- .circleci/config.yml | 875 ++++++++++++++---- .circleci/config.yml.in | 116 ++- .circleci/regenerate.py | 36 +- packaging/build_wheel.sh | 6 +- packaging/conda/build_vision.sh | 4 + packaging/pkg_helpers.bash | 14 +- packaging/vs2019/meta.yaml | 21 - packaging/windows/internal/build_conda.bat | 15 + packaging/windows/internal/build_wheels.bat | 12 + packaging/windows/internal/cuda_install.bat | 8 +- .../windows/internal/nightly_defaults.bat | 2 +- packaging/windows/internal/setup.bat | 2 +- packaging/windows/internal/test.bat | 2 +- packaging/windows/internal/vc_env_helper.bat | 43 + .../windows/internal/vc_install_helper.sh | 16 + packaging/windows/internal/vs2017_install.ps1 | 25 + packaging/windows/internal/vs2019_install.ps1 | 21 + packaging/windows/templates/upload_to_s3.yml | 2 +- 18 files changed, 957 insertions(+), 263 deletions(-) create mode 100644 packaging/windows/internal/build_conda.bat create mode 100644 packaging/windows/internal/build_wheels.bat create mode 100644 packaging/windows/internal/vc_env_helper.bat create mode 100644 packaging/windows/internal/vc_install_helper.sh create mode 100644 packaging/windows/internal/vs2017_install.ps1 create mode 100644 packaging/windows/internal/vs2019_install.ps1 diff --git a/.circleci/config.yml b/.circleci/config.yml index 02a24180bc4..0d62d00e410 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,14 +6,17 @@ version: 2.1 # - Replace binary_linux_wheel_py3.7 with the name of the job you want to test. # Job names are 'name:' key. -orbs: - win: circleci/windows@2.0.0 - executors: - windows-gpu-prototype: + windows-cpu: + machine: + resource_class: windows.xlarge + image: windows-server-2019-vs2019:stable + shell: bash.exe + + windows-gpu: machine: - resource_class: windows.gpu.small.prototype - image: windows-server-2019-nvidia:201908-28 + resource_class: windows.gpu.nvidia.medium + image: windows-server-2019-nvidia:stable shell: bash.exe commands: @@ -30,6 +33,18 @@ commands: # git fetch --force origin ${CIRCLE_BRANCH}/merge:merged/${CIRCLE_BRANCH} # git checkout "merged/$CIRCLE_BRANCH" # fi + designate_upload_channel: + description: "inserts the correct upload channel into ${BASH_ENV}" + steps: + - run: + name: adding UPLOAD_CHANNEL to BASH_ENV + command: | + our_upload_channel=nightly + # On tags upload to test instead + if [[ -n "${CIRCLE_TAG}" ]]; then + our_upload_channel=test + fi + echo "export UPLOAD_CHANNEL=${our_upload_channel}" >> ${BASH_ENV} binary_common: &binary_common parameters: @@ -59,7 +74,6 @@ binary_common: &binary_common default: "pytorch/manylinux-cuda101" environment: PYTHON_VERSION: << parameters.python_version >> - BUILD_VERSION: << parameters.build_version >> PYTORCH_VERSION: << parameters.pytorch_version >> UNICODE_ABI: << parameters.unicode_abi >> CU_VERSION: << parameters.cu_version >> @@ -118,7 +132,7 @@ jobs: - run: name: Setup environment command: | - set -e + set -ex curl -L https://packagecloud.io/circleci/trusty/gpgkey | sudo apt-key add - curl -L https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add - @@ -152,7 +166,7 @@ jobs: sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit=${NVIDIA_CONTAINER_VERSION} sudo systemctl restart docker - DRIVER_FN="NVIDIA-Linux-x86_64-410.104.run" + DRIVER_FN="NVIDIA-Linux-x86_64-440.59.run" wget "https://s3.amazonaws.com/ossci-linux/nvidia_driver/$DRIVER_FN" sudo /bin/bash "$DRIVER_FN" -s --no-drm || (sudo cat /var/log/nvidia-installer.log && false) nvidia-smi @@ -160,7 +174,7 @@ jobs: - run: name: Pull docker image command: | - set -e + set -ex export DOCKER_IMAGE=pytorch/conda-cuda echo Pulling docker image $DOCKER_IMAGE docker pull $DOCKER_IMAGE >/dev/null @@ -168,7 +182,7 @@ jobs: - run: name: Build and run tests command: | - set -e + set -ex cd ${HOME}/project/ @@ -179,35 +193,79 @@ jobs: binary_win_conda: <<: *binary_common - executor: - name: win/default - shell: bash.exe + executor: windows-cpu steps: - checkout_merge - run: command: | - choco install miniconda3 - (& "C:\tools\miniconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | Invoke-Expression + set -ex + source packaging/windows/internal/vc_install_helper.sh + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" conda activate base conda install -yq conda-build "conda-package-handling!=1.5.0" - bash packaging/build_conda.sh - shell: powershell.exe + packaging/build_conda.sh - store_test_results: path: build_results/ binary_win_conda_cuda: <<: *binary_common - executor: windows-gpu-prototype + executor: windows-gpu + steps: + - checkout_merge + - run: + command: | + set -ex + source packaging/windows/internal/vc_install_helper.sh + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate base + conda install -yq conda-build "conda-package-handling!=1.5.0" + packaging/build_conda.sh + + binary_win_conda_release: + <<: *binary_common + executor: windows-cpu steps: - checkout_merge - run: + name: Build conda packages command: | - choco install miniconda3 - (& "C:\tools\miniconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | Invoke-Expression + set -ex + source packaging/windows/internal/vc_install_helper.sh + packaging/windows/internal/cuda_install.bat + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" conda activate base conda install -yq conda-build "conda-package-handling!=1.5.0" - bash packaging/build_conda.sh - shell: powershell.exe + packaging/build_conda.sh + rm /C/tools/miniconda3/conda-bld/win-64/vs${VC_YEAR}*.tar.bz2 + - store_artifacts: + path: C:/tools/miniconda3/conda-bld/win-64 + - persist_to_workspace: + root: C:/tools/miniconda3/conda-bld/win-64 + paths: + - "*" + - store_test_results: + path: build_results/ + + binary_win_wheel_release: + <<: *binary_common + executor: windows-cpu + steps: + - checkout_merge + - run: + name: Build wheel packages + command: | + set -ex + source packaging/windows/internal/vc_install_helper.sh + packaging/windows/internal/cuda_install.bat + packaging/build_wheel.sh + - store_artifacts: + path: dist + - persist_to_workspace: + root: dist + paths: + - "*" + - store_test_results: + path: build_results/ binary_macos_wheel: <<: *binary_common @@ -260,12 +318,13 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: command: | # Prevent credential from leaking conda install -yq anaconda-client set -x - anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u pytorch-nightly --label main --no-progress --force + anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u "pytorch-${UPLOAD_CHANNEL}" --label main --no-progress --force # Requires org-member context binary_wheel_upload: @@ -278,6 +337,7 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - checkout - run: command: | @@ -289,7 +349,7 @@ jobs: export AWS_SECRET_ACCESS_KEY="${PYTORCH_BINARY_AWS_SECRET_ACCESS_KEY}" set -x for pkg in ~/workspace/*.whl; do - aws s3 cp "$pkg" "s3://pytorch/whl/nightly/<< parameters.subfolder >>" --acl public-read + aws s3 cp "$pkg" "s3://pytorch/whl/${UPLOAD_CHANNEL}/<< parameters.subfolder >>" --acl public-read done @@ -297,26 +357,6 @@ workflows: build: jobs: - circleci_consistency - - binary_linux_wheel: - cu_version: cpu - name: binary_linux_wheel_py3.5_cpu - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - - binary_linux_wheel: - cu_version: cu92 - name: binary_linux_wheel_py3.5_cu92 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_wheel: - cu_version: cu101 - name: binary_linux_wheel_py3.5_cu101 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda101 - - binary_linux_wheel: - cu_version: cu102 - name: binary_linux_wheel_py3.5_cu102 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: cu_version: cpu name: binary_linux_wheel_py3.6_cpu @@ -377,11 +417,6 @@ workflows: name: binary_linux_wheel_py3.8_cu102 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 - - binary_macos_wheel: - cu_version: cpu - name: binary_macos_wheel_py3.5_cpu - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - binary_macos_wheel: cu_version: cpu name: binary_macos_wheel_py3.6_cpu @@ -397,26 +432,84 @@ workflows: name: binary_macos_wheel_py3.8_cpu python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 - - binary_linux_conda: + - binary_win_wheel_release: cu_version: cpu - name: binary_linux_conda_py3.5_cpu - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - - binary_linux_conda: + filters: + branches: + only: master + name: binary_win_wheel_py3.6_cpu + python_version: '3.6' + - binary_win_wheel_release: cu_version: cu92 - name: binary_linux_conda_py3.5_cu92 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_linux_conda: + filters: + branches: + only: master + name: binary_win_wheel_py3.6_cu92 + python_version: '3.6' + - binary_win_wheel_release: cu_version: cu101 - name: binary_linux_conda_py3.5_cu101 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda101 - - binary_linux_conda: + filters: + branches: + only: master + name: binary_win_wheel_py3.6_cu101 + python_version: '3.6' + - binary_win_wheel_release: cu_version: cu102 - name: binary_linux_conda_py3.5_cu102 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 + filters: + branches: + only: master + name: binary_win_wheel_py3.6_cu102 + python_version: '3.6' + - binary_win_wheel_release: + cu_version: cpu + filters: + branches: + only: master + name: binary_win_wheel_py3.7_cpu + python_version: '3.7' + - binary_win_wheel_release: + cu_version: cu92 + filters: + branches: + only: master + name: binary_win_wheel_py3.7_cu92 + python_version: '3.7' + - binary_win_wheel_release: + cu_version: cu101 + filters: + branches: + only: master + name: binary_win_wheel_py3.7_cu101 + python_version: '3.7' + - binary_win_wheel_release: + cu_version: cu102 + filters: + branches: + only: master + name: binary_win_wheel_py3.7_cu102 + python_version: '3.7' + - binary_win_wheel_release: + cu_version: cpu + name: binary_win_wheel_py3.8_cpu + python_version: '3.8' + - binary_win_wheel_release: + cu_version: cu92 + filters: + branches: + only: master + name: binary_win_wheel_py3.8_cu92 + python_version: '3.8' + - binary_win_wheel_release: + cu_version: cu101 + filters: + branches: + only: master + name: binary_win_wheel_py3.8_cu101 + python_version: '3.8' + - binary_win_wheel_release: + cu_version: cu102 + name: binary_win_wheel_py3.8_cu102 + python_version: '3.8' - binary_linux_conda: cu_version: cpu name: binary_linux_conda_py3.6_cpu @@ -477,11 +570,6 @@ workflows: name: binary_linux_conda_py3.8_cu102 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 - - binary_macos_conda: - cu_version: cpu - name: binary_macos_conda_py3.5_cpu - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - binary_macos_conda: cu_version: cpu name: binary_macos_conda_py3.6_cpu @@ -497,86 +585,100 @@ workflows: name: binary_macos_conda_py3.8_cpu python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 - - binary_win_conda: - name: torchvision_win_py3.6_cpu - python_version: "3.6" - cu_version: "cpu" - - binary_win_conda_cuda: - name: torchvision_win_py3.6_cu101 - python_version: "3.6" - cu_version: "cu101" - - nightly: - jobs: - - circleci_consistency - - binary_linux_wheel: + - binary_win_conda_release: cu_version: cpu filters: branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_cpu - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - - binary_wheel_upload: - context: org-member + only: master + name: binary_win_conda_py3.6_cpu + python_version: '3.6' + - binary_win_conda_release: + cu_version: cu92 filters: branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_cpu_upload - requires: - - nightly_binary_linux_wheel_py3.5_cpu - subfolder: cpu/ - - binary_linux_wheel: - cu_version: cu92 + only: master + name: binary_win_conda_py3.6_cu92 + python_version: '3.6' + - binary_win_conda_release: + cu_version: cu101 filters: branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_cu92 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_wheel_upload: - context: org-member + only: master + name: binary_win_conda_py3.6_cu101 + python_version: '3.6' + - binary_win_conda_release: + cu_version: cu102 filters: branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_cu92_upload - requires: - - nightly_binary_linux_wheel_py3.5_cu92 - subfolder: cu92/ - - binary_linux_wheel: - cu_version: cu101 + only: master + name: binary_win_conda_py3.6_cu102 + python_version: '3.6' + - binary_win_conda_release: + cu_version: cpu filters: branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_cu101 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda101 - - binary_wheel_upload: - context: org-member + only: master + name: binary_win_conda_py3.7_cpu + python_version: '3.7' + - binary_win_conda_release: + cu_version: cu92 filters: branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_cu101_upload - requires: - - nightly_binary_linux_wheel_py3.5_cu101 - subfolder: cu101/ - - binary_linux_wheel: + only: master + name: binary_win_conda_py3.7_cu92 + python_version: '3.7' + - binary_win_conda_release: + cu_version: cu101 + filters: + branches: + only: master + name: binary_win_conda_py3.7_cu101 + python_version: '3.7' + - binary_win_conda_release: cu_version: cu102 filters: branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_cu102 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - - binary_wheel_upload: - context: org-member + only: master + name: binary_win_conda_py3.7_cu102 + python_version: '3.7' + - binary_win_conda_release: + cu_version: cpu + name: binary_win_conda_py3.8_cpu + python_version: '3.8' + - binary_win_conda_release: + cu_version: cu92 filters: branches: - only: nightly - name: nightly_binary_linux_wheel_py3.5_cu102_upload - requires: - - nightly_binary_linux_wheel_py3.5_cu102 - subfolder: cu102/ + only: master + name: binary_win_conda_py3.8_cu92 + python_version: '3.8' + - binary_win_conda_release: + cu_version: cu101 + filters: + branches: + only: master + name: binary_win_conda_py3.8_cu101 + python_version: '3.8' + - binary_win_conda_release: + cu_version: cu102 + name: binary_win_conda_py3.8_cu102 + python_version: '3.8' + - binary_linux_conda_cuda: + name: torchvision_linux_py3.8_cu102_cuda + python_version: "3.8" + cu_version: "cu102" + - binary_win_conda: + name: torchvision_win_py3.6_cpu + python_version: "3.6" + cu_version: "cpu" + - binary_win_conda_cuda: + name: torchvision_win_py3.6_cu101 + python_version: "3.6" + cu_version: "cu101" + + nightly: + jobs: + - circleci_consistency - binary_linux_wheel: cu_version: cpu filters: @@ -590,6 +692,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.6_cpu_upload requires: - nightly_binary_linux_wheel_py3.6_cpu @@ -607,6 +711,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.6_cu92_upload requires: - nightly_binary_linux_wheel_py3.6_cu92 @@ -624,6 +730,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.6_cu101_upload requires: - nightly_binary_linux_wheel_py3.6_cu101 @@ -641,6 +749,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.6_cu102_upload requires: - nightly_binary_linux_wheel_py3.6_cu102 @@ -658,6 +768,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.7_cpu_upload requires: - nightly_binary_linux_wheel_py3.7_cpu @@ -675,6 +787,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.7_cu92_upload requires: - nightly_binary_linux_wheel_py3.7_cu92 @@ -692,6 +806,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.7_cu101_upload requires: - nightly_binary_linux_wheel_py3.7_cu101 @@ -709,6 +825,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.7_cu102_upload requires: - nightly_binary_linux_wheel_py3.7_cu102 @@ -726,6 +844,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.8_cpu_upload requires: - nightly_binary_linux_wheel_py3.8_cpu @@ -743,6 +863,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.8_cu92_upload requires: - nightly_binary_linux_wheel_py3.8_cu92 @@ -760,6 +882,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.8_cu101_upload requires: - nightly_binary_linux_wheel_py3.8_cu101 @@ -777,27 +901,12 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.8_cu102_upload requires: - nightly_binary_linux_wheel_py3.8_cu102 subfolder: cu102/ - - binary_macos_wheel: - cu_version: cpu - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.5_cpu - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_wheel_py3.5_cpu_upload - requires: - - nightly_binary_macos_wheel_py3.5_cpu - subfolder: '' - binary_macos_wheel: cu_version: cpu filters: @@ -811,6 +920,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_wheel_py3.6_cpu_upload requires: - nightly_binary_macos_wheel_py3.6_cpu @@ -828,6 +939,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_wheel_py3.7_cpu_upload requires: - nightly_binary_macos_wheel_py3.7_cpu @@ -845,74 +958,228 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_wheel_py3.8_cpu_upload requires: - nightly_binary_macos_wheel_py3.8_cpu subfolder: '' - - binary_linux_conda: + - binary_win_wheel_release: cu_version: cpu filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cpu - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - - binary_conda_upload: + name: nightly_binary_win_wheel_py3.6_cpu + python_version: '3.6' + - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cpu_upload + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.6_cpu_upload requires: - - nightly_binary_linux_conda_py3.5_cpu - - binary_linux_conda: + - nightly_binary_win_wheel_py3.6_cpu + subfolder: cpu/ + - binary_win_wheel_release: cu_version: cu92 filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu92 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda92 - - binary_conda_upload: + name: nightly_binary_win_wheel_py3.6_cu92 + python_version: '3.6' + - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu92_upload + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.6_cu92_upload requires: - - nightly_binary_linux_conda_py3.5_cu92 - - binary_linux_conda: + - nightly_binary_win_wheel_py3.6_cu92 + subfolder: cu92/ + - binary_win_wheel_release: cu_version: cu101 filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu101 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda101 - - binary_conda_upload: + name: nightly_binary_win_wheel_py3.6_cu101 + python_version: '3.6' + - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu101_upload + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.6_cu101_upload requires: - - nightly_binary_linux_conda_py3.5_cu101 - - binary_linux_conda: + - nightly_binary_win_wheel_py3.6_cu101 + subfolder: cu101/ + - binary_win_wheel_release: cu_version: cu102 filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu102 - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - - binary_conda_upload: + name: nightly_binary_win_wheel_py3.6_cu102 + python_version: '3.6' + - binary_wheel_upload: context: org-member filters: branches: only: nightly - name: nightly_binary_linux_conda_py3.5_cu102_upload + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.6_cu102_upload requires: - - nightly_binary_linux_conda_py3.5_cu102 + - nightly_binary_win_wheel_py3.6_cu102 + subfolder: cu102/ + - binary_win_wheel_release: + cu_version: cpu + filters: + branches: + only: nightly + name: nightly_binary_win_wheel_py3.7_cpu + python_version: '3.7' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.7_cpu_upload + requires: + - nightly_binary_win_wheel_py3.7_cpu + subfolder: cpu/ + - binary_win_wheel_release: + cu_version: cu92 + filters: + branches: + only: nightly + name: nightly_binary_win_wheel_py3.7_cu92 + python_version: '3.7' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.7_cu92_upload + requires: + - nightly_binary_win_wheel_py3.7_cu92 + subfolder: cu92/ + - binary_win_wheel_release: + cu_version: cu101 + filters: + branches: + only: nightly + name: nightly_binary_win_wheel_py3.7_cu101 + python_version: '3.7' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.7_cu101_upload + requires: + - nightly_binary_win_wheel_py3.7_cu101 + subfolder: cu101/ + - binary_win_wheel_release: + cu_version: cu102 + filters: + branches: + only: nightly + name: nightly_binary_win_wheel_py3.7_cu102 + python_version: '3.7' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.7_cu102_upload + requires: + - nightly_binary_win_wheel_py3.7_cu102 + subfolder: cu102/ + - binary_win_wheel_release: + cu_version: cpu + filters: + branches: + only: nightly + name: nightly_binary_win_wheel_py3.8_cpu + python_version: '3.8' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.8_cpu_upload + requires: + - nightly_binary_win_wheel_py3.8_cpu + subfolder: cpu/ + - binary_win_wheel_release: + cu_version: cu92 + filters: + branches: + only: nightly + name: nightly_binary_win_wheel_py3.8_cu92 + python_version: '3.8' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.8_cu92_upload + requires: + - nightly_binary_win_wheel_py3.8_cu92 + subfolder: cu92/ + - binary_win_wheel_release: + cu_version: cu101 + filters: + branches: + only: nightly + name: nightly_binary_win_wheel_py3.8_cu101 + python_version: '3.8' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.8_cu101_upload + requires: + - nightly_binary_win_wheel_py3.8_cu101 + subfolder: cu101/ + - binary_win_wheel_release: + cu_version: cu102 + filters: + branches: + only: nightly + name: nightly_binary_win_wheel_py3.8_cu102 + python_version: '3.8' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.8_cu102_upload + requires: + - nightly_binary_win_wheel_py3.8_cu102 + subfolder: cu102/ - binary_linux_conda: cu_version: cpu filters: @@ -926,6 +1193,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.6_cpu_upload requires: - nightly_binary_linux_conda_py3.6_cpu @@ -942,6 +1211,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.6_cu92_upload requires: - nightly_binary_linux_conda_py3.6_cu92 @@ -958,6 +1229,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.6_cu101_upload requires: - nightly_binary_linux_conda_py3.6_cu101 @@ -974,6 +1247,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.6_cu102_upload requires: - nightly_binary_linux_conda_py3.6_cu102 @@ -990,6 +1265,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.7_cpu_upload requires: - nightly_binary_linux_conda_py3.7_cpu @@ -1006,6 +1283,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.7_cu92_upload requires: - nightly_binary_linux_conda_py3.7_cu92 @@ -1022,6 +1301,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.7_cu101_upload requires: - nightly_binary_linux_conda_py3.7_cu101 @@ -1038,6 +1319,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.7_cu102_upload requires: - nightly_binary_linux_conda_py3.7_cu102 @@ -1054,6 +1337,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.8_cpu_upload requires: - nightly_binary_linux_conda_py3.8_cpu @@ -1070,6 +1355,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.8_cu92_upload requires: - nightly_binary_linux_conda_py3.8_cu92 @@ -1086,6 +1373,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.8_cu101_upload requires: - nightly_binary_linux_conda_py3.8_cu101 @@ -1102,25 +1391,11 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.8_cu102_upload requires: - nightly_binary_linux_conda_py3.8_cu102 - - binary_macos_conda: - cu_version: cpu - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.5_cpu - python_version: '3.5' - wheel_docker_image: pytorch/manylinux-cuda102 - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - name: nightly_binary_macos_conda_py3.5_cpu_upload - requires: - - nightly_binary_macos_conda_py3.5_cpu - binary_macos_conda: cu_version: cpu filters: @@ -1134,6 +1409,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_conda_py3.6_cpu_upload requires: - nightly_binary_macos_conda_py3.6_cpu @@ -1150,6 +1427,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_conda_py3.7_cpu_upload requires: - nightly_binary_macos_conda_py3.7_cpu @@ -1166,6 +1445,212 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_conda_py3.8_cpu_upload requires: - - nightly_binary_macos_conda_py3.8_cpu \ No newline at end of file + - nightly_binary_macos_conda_py3.8_cpu + - binary_win_conda_release: + cu_version: cpu + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.6_cpu + python_version: '3.6' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.6_cpu_upload + requires: + - nightly_binary_win_conda_py3.6_cpu + - binary_win_conda_release: + cu_version: cu92 + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.6_cu92 + python_version: '3.6' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.6_cu92_upload + requires: + - nightly_binary_win_conda_py3.6_cu92 + - binary_win_conda_release: + cu_version: cu101 + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.6_cu101 + python_version: '3.6' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.6_cu101_upload + requires: + - nightly_binary_win_conda_py3.6_cu101 + - binary_win_conda_release: + cu_version: cu102 + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.6_cu102 + python_version: '3.6' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.6_cu102_upload + requires: + - nightly_binary_win_conda_py3.6_cu102 + - binary_win_conda_release: + cu_version: cpu + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.7_cpu + python_version: '3.7' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.7_cpu_upload + requires: + - nightly_binary_win_conda_py3.7_cpu + - binary_win_conda_release: + cu_version: cu92 + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.7_cu92 + python_version: '3.7' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.7_cu92_upload + requires: + - nightly_binary_win_conda_py3.7_cu92 + - binary_win_conda_release: + cu_version: cu101 + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.7_cu101 + python_version: '3.7' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.7_cu101_upload + requires: + - nightly_binary_win_conda_py3.7_cu101 + - binary_win_conda_release: + cu_version: cu102 + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.7_cu102 + python_version: '3.7' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.7_cu102_upload + requires: + - nightly_binary_win_conda_py3.7_cu102 + - binary_win_conda_release: + cu_version: cpu + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.8_cpu + python_version: '3.8' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.8_cpu_upload + requires: + - nightly_binary_win_conda_py3.8_cpu + - binary_win_conda_release: + cu_version: cu92 + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.8_cu92 + python_version: '3.8' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.8_cu92_upload + requires: + - nightly_binary_win_conda_py3.8_cu92 + - binary_win_conda_release: + cu_version: cu101 + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.8_cu101 + python_version: '3.8' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.8_cu101_upload + requires: + - nightly_binary_win_conda_py3.8_cu101 + - binary_win_conda_release: + cu_version: cu102 + filters: + branches: + only: nightly + name: nightly_binary_win_conda_py3.8_cu102 + python_version: '3.8' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.8_cu102_upload + requires: + - nightly_binary_win_conda_py3.8_cu102 \ No newline at end of file diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 62d411ce4b8..e8f03474ce9 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -6,14 +6,17 @@ version: 2.1 # - Replace binary_linux_wheel_py3.7 with the name of the job you want to test. # Job names are 'name:' key. -orbs: - win: circleci/windows@2.0.0 - executors: - windows-gpu-prototype: + windows-cpu: machine: - resource_class: windows.gpu.small.prototype - image: windows-server-2019-nvidia:201908-28 + resource_class: windows.xlarge + image: windows-server-2019-vs2019:stable + shell: bash.exe + + windows-gpu: + machine: + resource_class: windows.gpu.nvidia.medium + image: windows-server-2019-nvidia:stable shell: bash.exe commands: @@ -30,6 +33,18 @@ commands: # git fetch --force origin ${CIRCLE_BRANCH}/merge:merged/${CIRCLE_BRANCH} # git checkout "merged/$CIRCLE_BRANCH" # fi + designate_upload_channel: + description: "inserts the correct upload channel into ${BASH_ENV}" + steps: + - run: + name: adding UPLOAD_CHANNEL to BASH_ENV + command: | + our_upload_channel=nightly + # On tags upload to test instead + if [[ -n "${CIRCLE_TAG}" ]]; then + our_upload_channel=test + fi + echo "export UPLOAD_CHANNEL=${our_upload_channel}" >> ${BASH_ENV} binary_common: &binary_common parameters: @@ -59,7 +74,6 @@ binary_common: &binary_common default: "pytorch/manylinux-cuda101" environment: PYTHON_VERSION: << parameters.python_version >> - BUILD_VERSION: << parameters.build_version >> PYTORCH_VERSION: << parameters.pytorch_version >> UNICODE_ABI: << parameters.unicode_abi >> CU_VERSION: << parameters.cu_version >> @@ -118,7 +132,7 @@ jobs: - run: name: Setup environment command: | - set -e + set -ex curl -L https://packagecloud.io/circleci/trusty/gpgkey | sudo apt-key add - curl -L https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add - @@ -152,7 +166,7 @@ jobs: sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit=${NVIDIA_CONTAINER_VERSION} sudo systemctl restart docker - DRIVER_FN="NVIDIA-Linux-x86_64-410.104.run" + DRIVER_FN="NVIDIA-Linux-x86_64-440.59.run" wget "https://s3.amazonaws.com/ossci-linux/nvidia_driver/$DRIVER_FN" sudo /bin/bash "$DRIVER_FN" -s --no-drm || (sudo cat /var/log/nvidia-installer.log && false) nvidia-smi @@ -160,7 +174,7 @@ jobs: - run: name: Pull docker image command: | - set -e + set -ex export DOCKER_IMAGE=pytorch/conda-cuda echo Pulling docker image $DOCKER_IMAGE docker pull $DOCKER_IMAGE >/dev/null @@ -168,7 +182,7 @@ jobs: - run: name: Build and run tests command: | - set -e + set -ex cd ${HOME}/project/ @@ -179,35 +193,79 @@ jobs: binary_win_conda: <<: *binary_common - executor: - name: win/default - shell: bash.exe + executor: windows-cpu steps: - checkout_merge - run: command: | - choco install miniconda3 - (& "C:\tools\miniconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | Invoke-Expression + set -ex + source packaging/windows/internal/vc_install_helper.sh + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" conda activate base conda install -yq conda-build "conda-package-handling!=1.5.0" - bash packaging/build_conda.sh - shell: powershell.exe + packaging/build_conda.sh - store_test_results: path: build_results/ binary_win_conda_cuda: <<: *binary_common - executor: windows-gpu-prototype + executor: windows-gpu + steps: + - checkout_merge + - run: + command: | + set -ex + source packaging/windows/internal/vc_install_helper.sh + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate base + conda install -yq conda-build "conda-package-handling!=1.5.0" + packaging/build_conda.sh + + binary_win_conda_release: + <<: *binary_common + executor: windows-cpu steps: - checkout_merge - run: + name: Build conda packages command: | - choco install miniconda3 - (& "C:\tools\miniconda3\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | Invoke-Expression + set -ex + source packaging/windows/internal/vc_install_helper.sh + packaging/windows/internal/cuda_install.bat + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" conda activate base conda install -yq conda-build "conda-package-handling!=1.5.0" - bash packaging/build_conda.sh - shell: powershell.exe + packaging/build_conda.sh + rm /C/tools/miniconda3/conda-bld/win-64/vs${VC_YEAR}*.tar.bz2 + - store_artifacts: + path: C:/tools/miniconda3/conda-bld/win-64 + - persist_to_workspace: + root: C:/tools/miniconda3/conda-bld/win-64 + paths: + - "*" + - store_test_results: + path: build_results/ + + binary_win_wheel_release: + <<: *binary_common + executor: windows-cpu + steps: + - checkout_merge + - run: + name: Build wheel packages + command: | + set -ex + source packaging/windows/internal/vc_install_helper.sh + packaging/windows/internal/cuda_install.bat + packaging/build_wheel.sh + - store_artifacts: + path: dist + - persist_to_workspace: + root: dist + paths: + - "*" + - store_test_results: + path: build_results/ binary_macos_wheel: <<: *binary_common @@ -260,12 +318,13 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - run: command: | # Prevent credential from leaking conda install -yq anaconda-client set -x - anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u pytorch-nightly --label main --no-progress --force + anaconda -t "${CONDA_PYTORCHBOT_TOKEN}" upload ~/workspace/*.tar.bz2 -u "pytorch-${UPLOAD_CHANNEL}" --label main --no-progress --force # Requires org-member context binary_wheel_upload: @@ -278,6 +337,7 @@ jobs: steps: - attach_workspace: at: ~/workspace + - designate_upload_channel - checkout - run: command: | @@ -289,7 +349,7 @@ jobs: export AWS_SECRET_ACCESS_KEY="${PYTORCH_BINARY_AWS_SECRET_ACCESS_KEY}" set -x for pkg in ~/workspace/*.whl; do - aws s3 cp "$pkg" "s3://pytorch/whl/nightly/<< parameters.subfolder >>" --acl public-read + aws s3 cp "$pkg" "s3://pytorch/whl/${UPLOAD_CHANNEL}/<< parameters.subfolder >>" --acl public-read done @@ -298,7 +358,11 @@ workflows: {%- if True %} jobs: - circleci_consistency - {{ workflows() }} + {{ workflows(windows_latest_only=True) }} + - binary_linux_conda_cuda: + name: torchvision_linux_py3.8_cu102_cuda + python_version: "3.8" + cu_version: "cu102" - binary_win_conda: name: torchvision_win_py3.6_cpu python_version: "3.6" diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 24c40506417..1e929242974 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -19,16 +19,23 @@ import os.path -def workflows(prefix='', filter_branch=None, upload=False, indentation=6): +def workflows(prefix='', filter_branch=None, upload=False, indentation=6, windows_latest_only=False): w = [] for btype in ["wheel", "conda"]: - for os_type in ["linux", "macos"]: - for python_version in ["3.5", "3.6", "3.7", "3.8"]: - for cu_version in (["cpu", "cu92", "cu101", "cu102"] if os_type == "linux" else ["cpu"]): + for os_type in ["linux", "macos", "win"]: + python_versions = ["3.6", "3.7", "3.8"] + cu_versions = (["cpu", "cu92", "cu101", "cu102"] if os_type == "linux" or os_type == "win" else ["cpu"]) + for python_version in python_versions: + for cu_version in cu_versions: for unicode in ([False, True] if btype == "wheel" and python_version == "2.7" else [False]): + fb = filter_branch + if windows_latest_only and os_type == "win" and filter_branch is None and \ + (python_version != python_versions[-1] or + (cu_version not in [cu_versions[0], cu_versions[-1]])): + fb = "master" w += workflow_pair( btype, os_type, python_version, cu_version, - unicode, prefix, upload, filter_branch=filter_branch) + unicode, prefix, upload, filter_branch=fb) return indent(indentation, w) @@ -72,15 +79,17 @@ def generate_base_workflow(base_workflow_name, python_version, cu_version, "cu_version": cu_version, } - if unicode: + if os_type != "win" and unicode: d["unicode_abi"] = '1' - d["wheel_docker_image"] = get_manylinux_image(cu_version) + if os_type != "win": + d["wheel_docker_image"] = get_manylinux_image(cu_version) if filter_branch is not None: d["filters"] = {"branches": {"only": filter_branch}} - return {f"binary_{os_type}_{btype}": d} + w = f"binary_{os_type}_{btype}_release" if os_type == "win" else f"binary_{os_type}_{btype}" + return {w: d} def generate_upload_workflow(base_workflow_name, os_type, btype, cu_version, *, filter_branch=None): @@ -94,7 +103,16 @@ def generate_upload_workflow(base_workflow_name, os_type, btype, cu_version, *, d["subfolder"] = "" if os_type == 'macos' else cu_version + "/" if filter_branch is not None: - d["filters"] = {"branches": {"only": filter_branch}} + d["filters"] = { + "branches": { + "only": filter_branch + }, + "tags": { + # Using a raw string here to avoid having to escape + # anything + "only": r"/v[0-9]+(\.[0-9]+)*-rc[0-9]+/" + } + } return {f"binary_{btype}_upload": d} diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index f83bd2101c5..93c6998211a 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -12,4 +12,8 @@ pip_install numpy pyyaml future ninja pip_install six setup_pip_pytorch_version python setup.py clean -IS_WHEEL=1 python setup.py bdist_wheel +if [[ "$OSTYPE" == "msys" ]]; then + IS_WHEEL=1 "$script_dir/windows/internal/vc_env_helper.bat" python setup.py bdist_wheel +else + IS_WHEEL=1 python setup.py bdist_wheel +fi diff --git a/packaging/conda/build_vision.sh b/packaging/conda/build_vision.sh index 8c99fd57fc5..29784739c79 100755 --- a/packaging/conda/build_vision.sh +++ b/packaging/conda/build_vision.sh @@ -5,6 +5,10 @@ fi set -ex +if [[ "$CIRCLECI" == 'true' ]]; then + export PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:.:$PATH" +fi + # Function to retry functions that sometimes timeout or have flaky failures retry () { $* || (sleep 1 && $*) || (sleep 2 && $*) || (sleep 4 && $*) || (sleep 8 && $*) diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 9e87fcfe8a1..ad5a9038fdd 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -117,6 +117,12 @@ setup_build_version() { else export BUILD_VERSION="$BUILD_VERSION$VERSION_SUFFIX" fi + + # Set build version based on tag if on tag + if [[ -n "${CIRCLE_TAG}" ]]; then + # Strip tag + export BUILD_VERSION="$(echo "${CIRCLE_TAG}" | sed -e 's/^v//' -e 's/-.*$//')" + fi } # Set some useful variables for OS X, if applicable @@ -159,7 +165,7 @@ retry () { # # Precondition: If Linux, you are in a soumith/manylinux-cuda* Docker image setup_wheel_python() { - if [[ "$(uname)" == Darwin ]]; then + if [[ "$(uname)" == Darwin || "$OSTYPE" == "msys" ]]; then eval "$(conda shell.bash hook)" conda env remove -n "env$PYTHON_VERSION" || true conda create -yn "env$PYTHON_VERSION" python="$PYTHON_VERSION" @@ -242,6 +248,9 @@ setup_conda_pytorch_constraint() { export CONDA_PYTORCH_BUILD_CONSTRAINT="- pytorch==${PYTORCH_VERSION}${PYTORCH_VERSION_SUFFIX}" export CONDA_PYTORCH_CONSTRAINT="- pytorch==${PYTORCH_VERSION}${PYTORCH_VERSION_SUFFIX}" fi + if [[ "$OSTYPE" == msys && "$CU_VERSION" == cu92 ]]; then + export CONDA_CHANNEL_FLAGS="${CONDA_CHANNEL_FLAGS} -c defaults -c numba/label/dev" + fi } # Translate CUDA_VERSION into CUDA_CUDATOOLKIT_CONSTRAINT @@ -278,8 +287,7 @@ setup_conda_cudatoolkit_constraint() { # Build the proper compiler package before building the final package setup_visual_studio_constraint() { if [[ "$OSTYPE" == "msys" ]]; then - export VSTOOLCHAIN_PACKAGE=vs2019 - export VSDEVCMD_ARGS='' + export VSTOOLCHAIN_PACKAGE=vs$VC_YEAR conda build $CONDA_CHANNEL_FLAGS --no-anaconda-upload packaging/$VSTOOLCHAIN_PACKAGE cp packaging/$VSTOOLCHAIN_PACKAGE/conda_build_config.yaml packaging/torchvision/conda_build_config.yaml fi diff --git a/packaging/vs2019/meta.yaml b/packaging/vs2019/meta.yaml index e3f8b471481..94a0ed4db3e 100644 --- a/packaging/vs2019/meta.yaml +++ b/packaging/vs2019/meta.yaml @@ -19,27 +19,6 @@ outputs: # VS 2019 is binary-compatible with VS 2017/vc 14.1 and 2015/vc14. Tools are "v142". strong: - vc{{ vcfeature }} - run_exports: - - vc {{ vcver }} about: summary: Activation and version verification of MSVC {{ vcver }} (VS {{ vsyear }}) compiler license: BSD 3-clause - - name: vs{{ vsyear }}_runtime - script: install_runtime.bat - - name: vc - version: {{ vcver }} - track_features: - - vc{{ vcfeature }} - requirements: - run: - - {{ pin_subpackage('vs' ~ vsyear ~ '_runtime') }} - about: - home: https://github.com/conda/conda/wiki/VC-features - license: Modified BSD License (3-clause) - license_family: BSD - summary: A meta-package to track VC features. - description: | - This metapackage is used to activate vc features without - depending on Python. - doc_url: https://github.com/conda/conda/wiki/VC-features - dev_url: https://github.com/conda/conda/wiki/VC-features diff --git a/packaging/windows/internal/build_conda.bat b/packaging/windows/internal/build_conda.bat new file mode 100644 index 00000000000..e66d5596298 --- /dev/null +++ b/packaging/windows/internal/build_conda.bat @@ -0,0 +1,15 @@ +if "%VC_YEAR%" == "2017" set VSDEVCMD_ARGS=-vcvars_ver=14.11 +if "%VC_YEAR%" == "2017" powershell packaging/windows/internal/vs2017_install.ps1 +if errorlevel 1 exit /b 1 + +call packaging/windows/internal/cuda_install.bat +if errorlevel 1 exit /b 1 + +call packaging/windows/internal/nightly_defaults.bat Conda +if errorlevel 1 exit /b 1 + +set PYTORCH_FINAL_PACKAGE_DIR=%CD%\packaging\windows\output +if not exist "%PYTORCH_FINAL_PACKAGE_DIR%" mkdir %PYTORCH_FINAL_PACKAGE_DIR% + +bash ./packaging/conda/build_vision.sh %CUDA_VERSION% %TORCHVISION_BUILD_VERSION% %TORCHVISION_BUILD_NUMBER% +if errorlevel 1 exit /b 1 diff --git a/packaging/windows/internal/build_wheels.bat b/packaging/windows/internal/build_wheels.bat new file mode 100644 index 00000000000..eea6db2b6ea --- /dev/null +++ b/packaging/windows/internal/build_wheels.bat @@ -0,0 +1,12 @@ +if "%VC_YEAR%" == "2017" set VSDEVCMD_ARGS=-vcvars_ver=14.11 +if "%VC_YEAR%" == "2017" powershell packaging/windows/internal/vs2017_install.ps1 +if errorlevel 1 exit /b 1 + +call packaging/windows/internal/cuda_install.bat +if errorlevel 1 exit /b 1 + +call packaging/windows/internal/nightly_defaults.bat Conda +if errorlevel 1 exit /b 1 + +call packaging/windows/build_vision.bat %CUDA_VERSION% %TORCHVISION_BUILD_VERSION% %TORCHVISION_BUILD_NUMBER% +if errorlevel 1 exit /b 1 diff --git a/packaging/windows/internal/cuda_install.bat b/packaging/windows/internal/cuda_install.bat index cdd5a9ac206..35b4da115cc 100644 --- a/packaging/windows/internal/cuda_install.bat +++ b/packaging/windows/internal/cuda_install.bat @@ -1,6 +1,6 @@ @echo on -if "%CUDA_VERSION%" == "cpu" ( +if "%CU_VERSION%" == "cpu" ( echo Skipping for CPU builds exit /b 0 ) @@ -9,9 +9,9 @@ set SRC_DIR=%~dp0\.. if not exist "%SRC_DIR%\temp_build" mkdir "%SRC_DIR%\temp_build" -set /a CUDA_VER=%CUDA_VERSION% -set CUDA_VER_MAJOR=%CUDA_VERSION:~0,-1% -set CUDA_VER_MINOR=%CUDA_VERSION:~-1,1% +set /a CUDA_VER=%CU_VERSION:cu=% +set CUDA_VER_MAJOR=%CUDA_VER:~0,-1% +set CUDA_VER_MINOR=%CUDA_VER:~-1,1% set CUDA_VERSION_STR=%CUDA_VER_MAJOR%.%CUDA_VER_MINOR% if %CUDA_VER% EQU 92 goto cuda92 diff --git a/packaging/windows/internal/nightly_defaults.bat b/packaging/windows/internal/nightly_defaults.bat index e87acf78cd2..5a65781e600 100644 --- a/packaging/windows/internal/nightly_defaults.bat +++ b/packaging/windows/internal/nightly_defaults.bat @@ -102,7 +102,7 @@ if "%PYTORCH_REPO%" == "" set PYTORCH_REPO=pytorch :: my_branch_name) or can be a git commit (git checkout 4b2674n...). Default :: is 'latest', which is a special term that signals to pull the last commit :: before 0:00 midnight on the NIGHTLIES_DATE -if "%PYTORCH_BRANCH%" == "" set PYTORCH_BRANCH=latest +if "%PYTORCH_BRANCH%" == "" set PYTORCH_BRANCH=nightly :: Clone the requested pytorch checkout if exist "%NIGHTLIES_PYTORCH_ROOT%" ( goto clone_end ) else ( goto clone_start ) diff --git a/packaging/windows/internal/setup.bat b/packaging/windows/internal/setup.bat index d18dfb35023..96cb7fb23a7 100644 --- a/packaging/windows/internal/setup.bat +++ b/packaging/windows/internal/setup.bat @@ -30,7 +30,7 @@ if "%CXX%"=="sccache cl" ( :pytorch :: This stores in e.g. D:/_work/1/s/windows/output/cpu -pip wheel -e . --no-deps --wheel-dir ../output/%CUDA_PREFIX% +pip wheel -e . --no-deps --wheel-dir ../output :build_end IF ERRORLEVEL 1 exit /b 1 diff --git a/packaging/windows/internal/test.bat b/packaging/windows/internal/test.bat index a87fc1a2858..2f51f79aac9 100644 --- a/packaging/windows/internal/test.bat +++ b/packaging/windows/internal/test.bat @@ -11,7 +11,7 @@ if "%BUILD_VISION%" == "" ( pip install future pytest "pillow>=4.1.1" mock ) -for /F "delims=" %%i in ('where /R %SRC_DIR%\output\%CUDA_PREFIX% *%MODULE_NAME%*%PYTHON_VERSION%*.whl') do pip install "%%i" +for /F "delims=" %%i in ('where /R %SRC_DIR%\output *%MODULE_NAME%*%PYTHON_VERSION%*.whl') do pip install "%%i" if ERRORLEVEL 1 exit /b 1 diff --git a/packaging/windows/internal/vc_env_helper.bat b/packaging/windows/internal/vc_env_helper.bat new file mode 100644 index 00000000000..e85a372f93d --- /dev/null +++ b/packaging/windows/internal/vc_env_helper.bat @@ -0,0 +1,43 @@ +@echo on + +set VC_VERSION_LOWER=16 +set VC_VERSION_UPPER=17 +if "%VC_YEAR%" == "2017" ( + set VC_VERSION_LOWER=15 + set VC_VERSION_UPPER=16 +) + +for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -legacy -products * -version [%VC_VERSION_LOWER%^,%VC_VERSION_UPPER%^) -property installationPath`) do ( + if exist "%%i" if exist "%%i\VC\Auxiliary\Build\vcvarsall.bat" ( + set "VS15INSTALLDIR=%%i" + set "VS15VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat" + goto vswhere + ) +) + +:vswhere +if "%VSDEVCMD_ARGS%" == "" ( + call "%VS15VCVARSALL%" x64 || exit /b 1 +) else ( + call "%VS15VCVARSALL%" x64 %VSDEVCMD_ARGS% || exit /b 1 +) + +@echo on + +set DISTUTILS_USE_SDK=1 + +set args=%1 +shift +:start +if [%1] == [] goto done +set args=%args% %1 +shift +goto start + +:done +if "%args%" == "" ( + echo Usage: vc_env_helper.bat [command] [args] + echo e.g. vc_env_helper.bat cl /c test.cpp +) + +%args% || exit /b 1 diff --git a/packaging/windows/internal/vc_install_helper.sh b/packaging/windows/internal/vc_install_helper.sh new file mode 100644 index 00000000000..9910677acac --- /dev/null +++ b/packaging/windows/internal/vc_install_helper.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -ex + +if [[ "$CU_VERSION" == "cu92" ]]; then + export VC_YEAR=2017 + export VSDEVCMD_ARGS="-vcvars_ver=14.11" + powershell packaging/windows/internal/vs2017_install.ps1 +elif [[ "$CU_VERSION" == "cu100" ]]; then + export VC_YEAR=2017 + export VSDEVCMD_ARGS="" + powershell packaging/windows/internal/vs2017_install.ps1 +else + export VC_YEAR=2019 + export VSDEVCMD_ARGS="" +fi diff --git a/packaging/windows/internal/vs2017_install.ps1 b/packaging/windows/internal/vs2017_install.ps1 new file mode 100644 index 00000000000..6bbb1deb310 --- /dev/null +++ b/packaging/windows/internal/vs2017_install.ps1 @@ -0,0 +1,25 @@ +$VS_DOWNLOAD_LINK = "https://aka.ms/vs/15/release/vs_buildtools.exe" +$VS_INSTALL_ARGS = @("--nocache","--quiet","--wait", "--add Microsoft.VisualStudio.Workload.VCTools", + "--add Microsoft.VisualStudio.Component.VC.Tools.14.11", + "--add Microsoft.Component.MSBuild", + "--add Microsoft.VisualStudio.Component.Roslyn.Compiler", + "--add Microsoft.VisualStudio.Component.TextTemplating", + "--add Microsoft.VisualStudio.Component.VC.CoreIde", + "--add Microsoft.VisualStudio.Component.VC.Redist.14.Latest", + "--add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core", + "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "--add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Win81") + +curl.exe --retry 3 -kL $VS_DOWNLOAD_LINK --output vs_installer.exe +if ($LASTEXITCODE -ne 0) { + echo "Download of the VS 2017 installer failed" + exit 1 +} + +$process = Start-Process "${PWD}\vs_installer.exe" -ArgumentList $VS_INSTALL_ARGS -NoNewWindow -Wait -PassThru +Remove-Item -Path vs_installer.exe -Force +$exitCode = $process.ExitCode +if (($exitCode -ne 0) -and ($exitCode -ne 3010)) { + echo "VS 2017 installer exited with code $exitCode, which should be one of [0, 3010]." + exit 1 +} diff --git a/packaging/windows/internal/vs2019_install.ps1 b/packaging/windows/internal/vs2019_install.ps1 new file mode 100644 index 00000000000..e436051f0db --- /dev/null +++ b/packaging/windows/internal/vs2019_install.ps1 @@ -0,0 +1,21 @@ +$VS_DOWNLOAD_LINK = "https://aka.ms/vs/16/release/vs_buildtools.exe" +$VS_INSTALL_ARGS = @("--nocache","--quiet","--wait", "--add Microsoft.VisualStudio.Workload.VCTools", + "--add Microsoft.Component.MSBuild", + "--add Microsoft.VisualStudio.Component.Roslyn.Compiler", + "--add Microsoft.VisualStudio.Component.VC.CoreBuildTools", + "--add Microsoft.VisualStudio.Component.VC.Redist.14.Latest", + "--add Microsoft.VisualStudio.Component.VC.Tools.x86.x64") + +curl.exe --retry 3 -kL $VS_DOWNLOAD_LINK --output vs_installer.exe +if ($LASTEXITCODE -ne 0) { + echo "Download of the VS 2019 installer failed" + exit 1 +} + +$process = Start-Process "${PWD}\vs_installer.exe" -ArgumentList $VS_INSTALL_ARGS -NoNewWindow -Wait -PassThru +Remove-Item -Path vs_installer.exe -Force +$exitCode = $process.ExitCode +if (($exitCode -ne 0) -and ($exitCode -ne 3010)) { + echo "VS 2019 installer exited with code $exitCode, which should be one of [0, 3010]." + exit 1 +} diff --git a/packaging/windows/templates/upload_to_s3.yml b/packaging/windows/templates/upload_to_s3.yml index a31bcb15ae1..1de91b5786d 100644 --- a/packaging/windows/templates/upload_to_s3.yml +++ b/packaging/windows/templates/upload_to_s3.yml @@ -8,7 +8,7 @@ steps: inputs: awsCredentials: 'Pytorch S3 bucket' bucketName: 'pytorch' - sourceFolder: 'packaging/windows/output/${{ parameters.cudaVer }}' + sourceFolder: 'packaging/windows/output' globExpressions: '*.whl' targetFolder: 'whl/nightly/${{ parameters.cuVer }}/' filesAcl: 'public-read' From 673e6df322bd120d3843cef02a6ebb00d4dd9139 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 8 Jul 2020 08:36:13 -0700 Subject: [PATCH 066/357] Import DeformConv2d to fbsync (#2404) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2404 Reviewed By: zhangguanheng66 Differential Revision: D22432324 Pulled By: fmassa fbshipit-source-id: d3d93e98758f55c7acd6e7e10078be82351090ff --- test/test_ops.py | 196 ++++- torchvision/csrc/DeformConv.h | 215 +++++ torchvision/csrc/cpu/DeformConv_cpu.cpp | 954 ++++++++++++++++++++++ torchvision/csrc/cpu/vision_cpu.h | 24 + torchvision/csrc/cuda/DeformConv_cuda.cu | 988 +++++++++++++++++++++++ torchvision/csrc/cuda/vision_cuda.h | 24 + torchvision/csrc/vision.cpp | 2 + torchvision/ops/__init__.py | 7 +- torchvision/ops/deform_conv.py | 139 ++++ 9 files changed, 2510 insertions(+), 39 deletions(-) create mode 100644 torchvision/csrc/DeformConv.h create mode 100644 torchvision/csrc/cpu/DeformConv_cpu.cpp create mode 100644 torchvision/csrc/cuda/DeformConv_cuda.cu create mode 100644 torchvision/ops/deform_conv.py diff --git a/test/test_ops.py b/test/test_ops.py index 9d4916771ab..42056d421ea 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1,15 +1,18 @@ from __future__ import division +import math +import unittest + import numpy as np + import torch +from torch import Tensor from torch.autograd import gradcheck - +from torch.jit.annotations import Tuple +from torch.nn.modules.utils import _pair from torchvision import ops -from itertools import product -import unittest - -class RoIOpTester(object): +class OpTester(object): @classmethod def setUpClass(cls): cls.dtype = torch.float64 @@ -42,6 +45,14 @@ def test_backward_cuda_contiguous(self): def test_backward_cuda_non_contiguous(self): self._test_backward(device=torch.device('cuda'), contiguous=False) + def _test_forward(self, device, contiguous): + pass + + def _test_backward(self, device, contiguous): + pass + + +class RoIOpTester(OpTester): def _test_forward(self, device, contiguous): pool_size = 5 # n_channels % (pool_size ** 2) == 0 required for PS opeartions. @@ -79,7 +90,6 @@ def func(z): self.assertTrue(gradcheck(func, (x,))) self.assertTrue(gradcheck(script_func, (x,))) - return def fn(*args, **kwargs): pass @@ -98,7 +108,7 @@ def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwar def get_script_fn(self, rois, pool_size): @torch.jit.script def script_fn(input, rois, pool_size): - # type: (torch.Tensor, torch.Tensor, int) -> torch.Tensor + # type: (Tensor, Tensor, int) -> Tensor return ops.roi_pool(input, rois, pool_size, 1.0)[0] return lambda x: script_fn(x, rois, pool_size) @@ -137,7 +147,7 @@ def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwar def get_script_fn(self, rois, pool_size): @torch.jit.script def script_fn(input, rois, pool_size): - # type: (torch.Tensor, torch.Tensor, int) -> torch.Tensor + # type: (Tensor, Tensor, int) -> Tensor return ops.ps_roi_pool(input, rois, pool_size, 1.0)[0] return lambda x: script_fn(x, rois, pool_size) @@ -174,29 +184,35 @@ def get_slice(k, block): return y -def bilinear_interpolate(data, height, width, y, x): - if y < -1.0 or y > height or x < -1.0 or x > width: - return 0. +def bilinear_interpolate(data, y, x, snap_border=False): + height, width = data.shape - y = min(max(0, y), height - 1) - x = min(max(0, x), width - 1) + if snap_border: + if -1 < y <= 0: + y = 0 + elif height - 1 <= y < height: + y = height - 1 - y_low = int(y) - y_high = min(y_low + 1, height - 1) + if -1 < x <= 0: + x = 0 + elif width - 1 <= x < width: + x = width - 1 - x_low = int(x) - x_high = min(x_low + 1, width - 1) + y_low = int(math.floor(y)) + x_low = int(math.floor(x)) + y_high = y_low + 1 + x_high = x_low + 1 wy_h = y - y_low - wy_l = 1 - wy_h - wx_h = x - x_low + wy_l = 1 - wy_h wx_l = 1 - wx_h val = 0 - for wx, x in zip((wx_l, wx_h), (x_low, x_high)): - for wy, y in zip((wy_l, wy_h), (y_low, y_high)): - val += wx * wy * data[y * width + x] + for wx, xp in zip((wx_l, wx_h), (x_low, x_high)): + for wy, yp in zip((wy_l, wy_h), (y_low, y_high)): + if 0 <= yp < height and 0 <= xp < width: + val += wx * wy * data[yp, xp] return val @@ -208,7 +224,7 @@ def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwar def get_script_fn(self, rois, pool_size): @torch.jit.script def script_fn(input, rois, pool_size): - # type: (torch.Tensor, torch.Tensor, int) -> torch.Tensor + # type: (Tensor, Tensor, int) -> Tensor return ops.roi_align(input, rois, pool_size, 1.0)[0] return lambda x: script_fn(x, rois, pool_size) @@ -242,12 +258,7 @@ def expected_fn(self, in_data, rois, pool_h, pool_w, spatial_scale=1, sampling_r y = start_h + (iy + 0.5) * bin_h / grid_h for ix in range(0, grid_w): x = start_w + (ix + 0.5) * bin_w / grid_w - val += bilinear_interpolate( - in_data[batch_idx, channel, :, :].flatten(), - in_data.size(-2), - in_data.size(-1), - y, x - ) + val += bilinear_interpolate(in_data[batch_idx, channel, :, :], y, x, snap_border=True) val /= grid_h * grid_w out_data[r, channel, i, j] = val @@ -262,7 +273,7 @@ def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwar def get_script_fn(self, rois, pool_size): @torch.jit.script def script_fn(input, rois, pool_size): - # type: (torch.Tensor, torch.Tensor, int) -> torch.Tensor + # type: (Tensor, Tensor, int) -> Tensor return ops.ps_roi_align(input, rois, pool_size, 1.0)[0] return lambda x: script_fn(x, rois, pool_size) @@ -298,12 +309,7 @@ def expected_fn(self, in_data, rois, pool_h, pool_w, device, spatial_scale=1, y = start_h + (iy + 0.5) * bin_h / grid_h for ix in range(0, grid_w): x = start_w + (ix + 0.5) * bin_w / grid_w - val += bilinear_interpolate( - in_data[batch_idx, c_in, :, :].flatten(), - in_data.size(-2), - in_data.size(-1), - y, x - ) + val += bilinear_interpolate(in_data[batch_idx, c_in, :, :], y, x, snap_border=True) val /= grid_h * grid_w out_data[r, c_out, i, j] = val @@ -376,5 +382,123 @@ def test_new_empty_tensor(self): assert out.dtype == input.dtype +class DeformConvTester(OpTester, unittest.TestCase): + def expected_fn(self, x, weight, offset, bias, stride=1, padding=0, dilation=1): + stride_h, stride_w = _pair(stride) + pad_h, pad_w = _pair(padding) + dil_h, dil_w = _pair(dilation) + weight_h, weight_w = weight.shape[-2:] + + n_batches, n_in_channels, in_h, in_w = x.shape + n_out_channels = weight.shape[0] + + out_h = (in_h + 2 * pad_h - (dil_h * (weight_h - 1) + 1)) // stride_h + 1 + out_w = (in_w + 2 * pad_w - (dil_w * (weight_w - 1) + 1)) // stride_w + 1 + + n_offset_grps = offset.shape[1] // (2 * weight_h * weight_w) + in_c_per_offset_grp = n_in_channels // n_offset_grps + + n_weight_grps = n_in_channels // weight.shape[1] + in_c_per_weight_grp = weight.shape[1] + out_c_per_weight_grp = n_out_channels // n_weight_grps + + out = torch.zeros(n_batches, n_out_channels, out_h, out_w, device=x.device, dtype=x.dtype) + for b in range(n_batches): + for c_out in range(n_out_channels): + for i in range(out_h): + for j in range(out_w): + for di in range(weight_h): + for dj in range(weight_w): + for c in range(in_c_per_weight_grp): + weight_grp = c_out // out_c_per_weight_grp + c_in = weight_grp * in_c_per_weight_grp + c + + offset_grp = c_in // in_c_per_offset_grp + offset_idx = 2 * (offset_grp * (weight_h * weight_w) + di * weight_w + dj) + + pi = stride_h * i - pad_h + dil_h * di + offset[b, offset_idx, i, j] + pj = stride_w * j - pad_w + dil_w * dj + offset[b, offset_idx + 1, i, j] + + out[b, c_out, i, j] += (weight[c_out, c, di, dj] * + bilinear_interpolate(x[b, c_in, :, :], pi, pj)) + out += bias.view(1, n_out_channels, 1, 1) + return out + + def get_fn_args(self, device, contiguous): + batch_sz = 33 + n_in_channels = 6 + n_out_channels = 2 + n_weight_grps = 2 + n_offset_grps = 3 + + stride = (2, 1) + pad = (1, 0) + dilation = (2, 1) + + stride_h, stride_w = stride + pad_h, pad_w = pad + dil_h, dil_w = dilation + weight_h, weight_w = (3, 2) + in_h, in_w = (5, 4) + + out_h = (in_h + 2 * pad_h - (dil_h * (weight_h - 1) + 1)) // stride_h + 1 + out_w = (in_w + 2 * pad_w - (dil_w * (weight_w - 1) + 1)) // stride_w + 1 + + x = torch.rand(batch_sz, n_in_channels, in_h, in_w, device=device, dtype=self.dtype, requires_grad=True) + + offset = torch.randn(batch_sz, n_offset_grps * 2 * weight_h * weight_w, out_h, out_w, + device=device, dtype=self.dtype, requires_grad=True) + + weight = torch.randn(n_out_channels, n_in_channels // n_weight_grps, weight_h, weight_w, + device=device, dtype=self.dtype, requires_grad=True) + + bias = torch.randn(n_out_channels, device=device, dtype=self.dtype, requires_grad=True) + + if not contiguous: + x = x.permute(0, 1, 3, 2).contiguous().permute(0, 1, 3, 2) + offset = offset.permute(1, 3, 0, 2).contiguous().permute(2, 0, 3, 1) + weight = weight.permute(3, 2, 0, 1).contiguous().permute(2, 3, 1, 0) + + return x, weight, offset, bias, stride, pad, dilation + + def _test_forward(self, device, contiguous): + x, _, offset, _, stride, padding, dilation = self.get_fn_args(device, contiguous) + in_channels = 6 + out_channels = 2 + kernel_size = (3, 2) + groups = 2 + + layer = ops.DeformConv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, + dilation=dilation, groups=groups).to(device=x.device, dtype=x.dtype) + res = layer(x, offset) + + weight = layer.weight.data + bias = layer.bias.data + expected = self.expected_fn(x, weight, offset, bias, stride=stride, padding=padding, dilation=dilation) + + self.assertTrue(torch.allclose(res, expected), '\nres:\n{}\nexpected:\n{}'.format(res, expected)) + + # test for wrong sizes + with self.assertRaises(RuntimeError): + wrong_offset = torch.rand_like(offset[:, :2]) + res = layer(x, wrong_offset) + + def _test_backward(self, device, contiguous): + x, weight, offset, bias, stride, padding, dilation = self.get_fn_args(device, contiguous) + + def func(x_, offset_, weight_, bias_): + return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride, padding=padding, dilation=dilation) + + gradcheck(func, (x, offset, weight, bias), nondet_tol=1e-5) + + @torch.jit.script + def script_func(x_, offset_, weight_, bias_, stride_, pad_, dilation_): + # type: (Tensor, Tensor, Tensor, Tensor, Tuple[int, int], Tuple[int, int], Tuple[int, int]) -> Tensor + return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride_, padding=pad_, dilation=dilation_) + + gradcheck(lambda z, off, wei, bi: script_func(z, off, wei, bi, stride, padding, dilation), + (x, offset, weight, bias), nondet_tol=1e-5) + + if __name__ == '__main__': unittest.main() diff --git a/torchvision/csrc/DeformConv.h b/torchvision/csrc/DeformConv.h new file mode 100644 index 00000000000..7ce41824cab --- /dev/null +++ b/torchvision/csrc/DeformConv.h @@ -0,0 +1,215 @@ +#pragma once + +#include "cpu/vision_cpu.h" + +#ifdef WITH_CUDA +#include "cuda/vision_cuda.h" +#endif + +at::Tensor DeformConv2d_forward( + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& bias, + const std::pair& stride, + const std::pair& padding, + const std::pair& dilation, + const int groups, + const int offset_groups) { + if (input.type().is_cuda()) { +#ifdef WITH_CUDA + return DeformConv2d_forward_cuda( + input.contiguous(), + weight.contiguous(), + offset.contiguous(), + bias.contiguous(), + stride, + padding, + dilation, + groups, + offset_groups); +#else + AT_ERROR("Not compiled with GPU support"); +#endif + } + return DeformConv2d_forward_cpu( + input.contiguous(), + weight.contiguous(), + offset.contiguous(), + bias.contiguous(), + stride, + padding, + dilation, + groups, + offset_groups); +} + +std::tuple DeformConv2d_backward( + const at::Tensor& grad, + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& bias, + const std::pair& stride, + const std::pair& padding, + const std::pair& dilation, + const int groups, + const int offset_groups) { + if (grad.type().is_cuda()) { +#ifdef WITH_CUDA + return DeformConv2d_backward_cuda( + grad.contiguous(), + input.contiguous(), + weight.contiguous(), + offset.contiguous(), + bias.contiguous(), + stride, + padding, + dilation, + groups, + offset_groups); +#else + AT_ERROR("Not compiled with GPU support"); +#endif + } + return DeformConv2d_backward_cpu( + grad.contiguous(), + input.contiguous(), + weight.contiguous(), + offset.contiguous(), + bias.contiguous(), + stride, + padding, + dilation, + groups, + offset_groups); +} + +using namespace at; +using torch::Tensor; +using torch::autograd::AutogradContext; +using torch::autograd::Variable; +using torch::autograd::variable_list; + +class DeformConv2dFunction + : public torch::autograd::Function { + public: + static variable_list forward( + AutogradContext* ctx, + Variable input, + Variable weight, + Variable offset, + Variable bias, + int64_t stride_h, + int64_t stride_w, + int64_t pad_h, + int64_t pad_w, + int64_t dilation_h, + int64_t dilation_w, + int64_t groups, + int64_t offset_groups) { + auto output = DeformConv2d_forward( + input, + weight, + offset, + bias, + {stride_h, stride_w}, + {pad_h, pad_w}, + {dilation_h, dilation_w}, + groups, + offset_groups); + + ctx->save_for_backward({input, weight, offset, bias}); + ctx->saved_data["stride_h"] = stride_h; + ctx->saved_data["stride_w"] = stride_w; + ctx->saved_data["pad_h"] = pad_h; + ctx->saved_data["pad_w"] = pad_w; + ctx->saved_data["dilation_h"] = dilation_h; + ctx->saved_data["dilation_w"] = dilation_w; + ctx->saved_data["groups"] = groups; + ctx->saved_data["offset_groups"] = offset_groups; + + return { + output, + }; + } + + static variable_list backward( + AutogradContext* ctx, + variable_list grad_output) { + auto saved = ctx->get_saved_variables(); + auto input = saved[0]; + auto weight = saved[1]; + auto offset = saved[2]; + auto bias = saved[3]; + + auto stride_h = ctx->saved_data["stride_h"].toInt(); + auto stride_w = ctx->saved_data["stride_w"].toInt(); + auto pad_h = ctx->saved_data["pad_h"].toInt(); + auto pad_w = ctx->saved_data["pad_w"].toInt(); + auto dilation_h = ctx->saved_data["dilation_h"].toInt(); + auto dilation_w = ctx->saved_data["dilation_w"].toInt(); + auto groups = ctx->saved_data["groups"].toInt(); + auto offset_groups = ctx->saved_data["offset_groups"].toInt(); + + auto grads = DeformConv2d_backward( + grad_output[0], + input, + weight, + offset, + bias, + {stride_h, stride_w}, + {pad_h, pad_w}, + {dilation_h, dilation_w}, + groups, + offset_groups); + auto grad_input = std::get<0>(grads); + auto grad_weight = std::get<1>(grads); + auto grad_offset = std::get<2>(grads); + auto grad_bias = std::get<3>(grads); + + return { + grad_input, + grad_weight, + grad_offset, + grad_bias, + Variable(), + Variable(), + Variable(), + Variable(), + Variable(), + Variable(), + Variable(), + Variable(), + }; + } +}; + +at::Tensor deform_conv2d( + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& bias, + int64_t stride_h, + int64_t stride_w, + int64_t pad_h, + int64_t pad_w, + int64_t dilation_h, + int64_t dilation_w, + int64_t groups, + int64_t offset_groups) { + auto result = DeformConv2dFunction::apply( + input, + weight, + offset, + bias, + stride_h, + stride_w, + pad_h, + pad_w, + dilation_h, + dilation_w, + groups, + offset_groups); + return result[0]; +} diff --git a/torchvision/csrc/cpu/DeformConv_cpu.cpp b/torchvision/csrc/cpu/DeformConv_cpu.cpp new file mode 100644 index 00000000000..65e9c0fe450 --- /dev/null +++ b/torchvision/csrc/cpu/DeformConv_cpu.cpp @@ -0,0 +1,954 @@ +/*! + ******************* BEGIN Caffe Copyright Notice and Disclaimer + ***************** + * + * COPYRIGHT + * + * All contributions by the University of California: + * Copyright (c) 2014-2017 The Regents of the University of California (Regents) + * All rights reserved. + * + * All other contributions: + * Copyright (c) 2014-2017, the respective contributors + * All rights reserved. + * + * Caffe uses a shared copyright model: each contributor holds copyright over + * their contributions to Caffe. The project versioning records all such + * contribution and copyright details. If a contributor wants to further mark + * their specific copyright on a particular contribution, they should indicate + * their copyright solely in the commit message of the change when it is + * committed. + * + * LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + *AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + *CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + *OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + *OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CONTRIBUTION AGREEMENT + * + * By contributing to the BVLC/caffe repository through pull-request, comment, + * or otherwise, the contributor releases their content to the + * license and copyright terms herein. + * + ***************** END Caffe Copyright Notice and Disclaimer + ********************* + * + * Copyright (c) 2018 Microsoft + * Licensed under The MIT License [see LICENSE for details] + * \file modulated_deformable_im2col.cuh + * \brief Function definitions of converting an image to + * column matrix based on kernel, padding, dilation, and offset. + * These functions are mainly used in deformable convolution operators. + * \ref: https://arxiv.org/abs/1703.06211 + * \author Yuwen Xiong, Haozhi Qi, Jifeng Dai, Xizhou Zhu, Han Hu, Dazhi Cheng + */ + +// modified from +// https://github.com/chengdazhi/Deformable-Convolution-V2-PyTorch/blob/mmdetection/mmdet/ops/dcn/src/deform_conv_cuda_kernel.cu + +// modified from +// https://github.com/open-mmlab/mmdetection/blob/master/mmdet/ops/dcn/src/deform_conv_cuda.cpp + +#include +#include +#include + +#include +#include +#include + +using namespace at; + +const int kMaxParallelImgs = 32; + +template +static scalar_t bilinear_interpolate( + const scalar_t* in, + const int height, + const int width, + scalar_t h, + scalar_t w) { + if (h <= -1 || height <= h || w <= -1 || width <= w) { + return 0; + } + + int h_low = floor(h); + int w_low = floor(w); + int h_high = h_low + 1; + int w_high = w_low + 1; + + scalar_t lh = h - h_low; + scalar_t lw = w - w_low; + scalar_t hh = 1 - lh, hw = 1 - lw; + + scalar_t v1 = 0; + if (h_low >= 0 && w_low >= 0) + v1 = in[h_low * width + w_low]; + scalar_t v2 = 0; + if (h_low >= 0 && w_high <= width - 1) + v2 = in[h_low * width + w_high]; + scalar_t v3 = 0; + if (h_high <= height - 1 && w_low >= 0) + v3 = in[h_high * width + w_low]; + scalar_t v4 = 0; + if (h_high <= height - 1 && w_high <= width - 1) + v4 = in[h_high * width + w_high]; + + scalar_t w1 = hh * hw, w2 = hh * lw, w3 = lh * hw, w4 = lh * lw; + + scalar_t val = (w1 * v1 + w2 * v2 + w3 * v3 + w4 * v4); + return val; +} + +template +static void deformable_im2col_kernel( + const int n, + const scalar_t* input, + const scalar_t* offset, + const int height, + const int width, + const int weight_h, + const int weight_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dil_h, + const int dil_w, + const int batch_sz, + const int n_in_channels, + const int n_offset_grps, + const int out_h, + const int out_w, + scalar_t* columns) { + for (int index = 0; index != n; ++index) { + const int out_x = index % out_w; + const int out_y = (index / out_w) % out_h; + const int out_b = (index / (out_w * out_h)) % batch_sz; + const int in_c = index / (out_w * out_h * batch_sz); + const int out_c = in_c * weight_h * weight_w; + + int c_per_offset_grp = n_in_channels / n_offset_grps; + const int grp_idx = in_c / c_per_offset_grp; + + auto columns_ptr = columns + + (out_c * (batch_sz * out_h * out_w) + out_b * (out_h * out_w) + + out_y * out_w + out_x); + + auto input_ptr = input + + (out_b * (n_in_channels * height * width) + in_c * (height * width)); + + auto offset_ptr = offset + + (out_b * n_offset_grps + grp_idx) * 2 * weight_h * weight_w * out_h * + out_w; + + for (int i = 0; i < weight_h; ++i) { + for (int j = 0; j < weight_w; ++j) { + const int offset_idx = 2 * (i * weight_w + j); + const scalar_t offset_h = + offset_ptr[offset_idx * (out_h * out_w) + out_y * out_w + out_x]; + const scalar_t offset_w = offset_ptr + [(offset_idx + 1) * (out_h * out_w) + out_y * out_w + out_x]; + const scalar_t y = (out_y * stride_h - pad_h) + i * dil_h + offset_h; + const scalar_t x = (out_x * stride_w - pad_w) + j * dil_w + offset_w; + *columns_ptr = bilinear_interpolate(input_ptr, height, width, y, x); + columns_ptr += batch_sz * out_h * out_w; + } + } + } +} + +static void deformable_im2col( + const at::Tensor input, + const at::Tensor data_offset, + int n_in_channels, + int height, + int width, + int weight_h, + int weight_w, + int pad_h, + int pad_w, + int stride_h, + int stride_w, + int dil_h, + int dil_w, + int out_h, + int out_w, + int parallel_imgs, + int deformable_group, + at::Tensor data_col) { + int num_kernels = n_in_channels * out_h * out_w * parallel_imgs; + + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + input.scalar_type(), "deformable_im2col", ([&] { + deformable_im2col_kernel( + num_kernels, + input.data_ptr(), + data_offset.data_ptr(), + height, + width, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + parallel_imgs, + n_in_channels, + deformable_group, + out_h, + out_w, + data_col.data_ptr()); + })); +} + +static int get_greatest_divisor_below_bound(int n, int bound) { + for (int k = bound; k > 1; --k) { + if (n % k == 0) { + return k; + } + } + return 1; +} + +at::Tensor DeformConv2d_forward_cpu( + const at::Tensor& input_param, + const at::Tensor& weight_param, + const at::Tensor& offset_param, + const at::Tensor& bias, + std::pair stride, + std::pair pad, + std::pair dilation, + int n_weight_grps, + int n_offset_grps) { + at::Tensor input = input_param; + at::Tensor offset = offset_param; + at::Tensor weight = weight_param; + + TORCH_CHECK(input.ndimension() == 4); + TORCH_CHECK(offset.ndimension() == 4); + TORCH_CHECK(weight.ndimension() == 4); + TORCH_CHECK(input.is_contiguous()); + TORCH_CHECK(offset.is_contiguous()); + TORCH_CHECK(weight.is_contiguous()); + TORCH_CHECK(input.device().is_cpu(), "input must be a CPU tensor"); + + int batch_sz = input.size(0); + int n_in_channels = input.size(1); + int in_h = input.size(2); + int in_w = input.size(3); + + int n_parallel_imgs = + get_greatest_divisor_below_bound(batch_sz, kMaxParallelImgs); + + // Unpack shapes and args + int out_channels = weight.size(0); + int weight_h = weight.size(2); + int weight_w = weight.size(3); + + int stride_h = stride.first; + int stride_w = stride.second; + + int pad_h = pad.first; + int pad_w = pad.second; + + int dil_h = dilation.first; + int dil_w = dilation.second; + + int ker_h = dil_h * (weight_h - 1) + 1; + int ker_w = dil_w * (weight_w - 1) + 1; + int out_h = ((in_h + 2 * pad_h - ker_h) / stride_h) + 1; + int out_w = ((in_w + 2 * pad_w - ker_w) / stride_w) + 1; + + TORCH_CHECK( + weight_h > 0 && weight_w > 0, + "weight_h: ", + weight_h, + " weight_w: ", + weight_w); + TORCH_CHECK( + stride_h > 0 && stride_w > 0, + "stride_h: ", + stride_h, + " stride_w: ", + stride_w); + TORCH_CHECK(pad_h >= 0 && pad_w >= 0, "pad_h: ", pad_h, " pad_w: ", pad_w); + TORCH_CHECK(dil_h > 0 && dil_w > 0, "dil_h: ", dil_h, " dil_w: ", dil_w); + + TORCH_CHECK(weight.size(1) * n_weight_grps == input.size(1)); + TORCH_CHECK(weight.size(0) % n_weight_grps == 0); + TORCH_CHECK( + (offset.size(1) == n_offset_grps * 2 * weight_h * weight_w), + "offset.shape[1] is not valid: got: ", + offset.size(1), + " expected: ", + n_offset_grps * 2 * weight_h * weight_w); + TORCH_CHECK(input.size(1) % n_offset_grps == 0); + + TORCH_CHECK( + (offset.size(0) == input.size(0)), "invalid batch size of offset"); + TORCH_CHECK( + (offset.size(2) == out_h && offset.size(3) == out_w), + "offset output dims: (", + offset.size(2), + ", ", + offset.size(3), + ") - ", + "computed output dims: (", + out_h, + ", ", + out_w, + ")"); + TORCH_CHECK( + out_h > 0 && out_w > 0, + "Calculated output size too small - out_h: ", + out_h, + " out_w: ", + out_w); + + auto out = at::zeros({batch_sz, out_channels, out_h, out_w}, input.options()); + + // Separate batches into blocks + out = out.view({batch_sz / n_parallel_imgs, + n_parallel_imgs, + out_channels, + out_h, + out_w}); + input = input.view( + {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + offset = offset.view({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * 2 * weight_h * weight_w, + out_h, + out_w}); + at::Tensor out_buf = at::zeros( + {batch_sz / n_parallel_imgs, + out_channels, + n_parallel_imgs * out_h, + out_w}, + out.options()); + + // Separate channels into convolution groups + out_buf = out_buf.view({out_buf.size(0), + n_weight_grps, + out_buf.size(1) / n_weight_grps, + out_buf.size(2), + out_buf.size(3)}); + weight = weight.view({n_weight_grps, + weight.size(0) / n_weight_grps, + weight.size(1), + weight.size(2), + weight.size(3)}); + + // Sample points and perform convolution + auto columns = at::zeros( + {n_in_channels * weight_h * weight_w, n_parallel_imgs * out_h * out_w}, + input.options()); + for (int b = 0; b < batch_sz / n_parallel_imgs; b++) { + deformable_im2col( + input[b], + offset[b], + n_in_channels, + in_h, + in_w, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + out_h, + out_w, + n_parallel_imgs, + n_offset_grps, + columns); + + columns = columns.view( + {n_weight_grps, columns.size(0) / n_weight_grps, columns.size(1)}); + for (int g = 0; g < n_weight_grps; g++) { + out_buf[b][g] = out_buf[b][g] + .flatten(1) + .addmm_(weight[g].flatten(1), columns[g]) + .view_as(out_buf[b][g]); + } + columns = + columns.view({columns.size(0) * columns.size(1), columns.size(2)}); + } + + out_buf = out_buf.view({batch_sz / n_parallel_imgs, + out_channels, + n_parallel_imgs, + out_h, + out_w}); + out_buf.transpose_(1, 2); + out.copy_(out_buf); + out = out.view({batch_sz, out_channels, out_h, out_w}); + + return out + bias.view({1, out_channels, 1, 1}); +} + +template +static void deformable_col2im_kernel( + const int n, + const scalar_t* col, + const scalar_t* offset, + const int channels, + const int height, + const int width, + const int kernel_h, + const int kernel_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dilation_h, + const int dilation_w, + const int batch_sz, + const int n_offset_grps, + const int out_h, + const int out_w, + scalar_t* grad_im) { + for (int index = 0; index != n; ++index) { + const int out_x = index % out_w; + const int out_y = (index / out_w) % out_h; + const int b = (index / (out_w * out_h)) % batch_sz; + const int j = (index / (out_w * out_h * batch_sz)) % kernel_w; + const int i = (index / (out_w * out_h * batch_sz * kernel_w)) % kernel_h; + const int c = index / (out_w * out_h * batch_sz * kernel_w * kernel_h); + + int c_per_offset_grp = channels / n_offset_grps; + const int offset_grp = c / c_per_offset_grp; + + auto offset_ptr = offset + + (b * n_offset_grps + offset_grp) * 2 * kernel_h * kernel_w * out_h * + out_w; + const int offset_h_ptr = + ((2 * (i * kernel_w + j)) * out_h + out_y) * out_w + out_x; + const int offset_w_ptr = + ((2 * (i * kernel_w + j) + 1) * out_h + out_y) * out_w + out_x; + const scalar_t offset_h = offset_ptr[offset_h_ptr]; + const scalar_t offset_w = offset_ptr[offset_w_ptr]; + const scalar_t y = (out_y * stride_h - pad_h) + i * dilation_h + offset_h; + const scalar_t x = (out_x * stride_w - pad_w) + j * dilation_w + offset_w; + + for (int dy = -1; dy <= 1; dy++) { + for (int dx = -1; dx <= 1; dx++) { + int yp = int(y) + dy; + int xp = int(x) + dx; + if (0 <= yp && yp < height && 0 <= xp && xp < width && + std::abs(y - yp) < 1 && std::abs(x - xp) < 1) { + int grad_pos = ((b * channels + c) * height + yp) * width + xp; + scalar_t weight = (1 - std::abs(y - yp)) * (1 - std::abs(x - xp)); + grad_im[grad_pos] += weight * col[index]; + } + } + } + } +} + +static void compute_grad_input( + const at::Tensor columns, + const at::Tensor offset, + const int channels, + const int height, + const int width, + const int weight_h, + const int weight_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dilation_h, + const int dilation_w, + const int parallel_imgs, + const int n_offset_grps, + at::Tensor grad_im) { + int out_h = + (height + 2 * pad_h - (dilation_h * (weight_h - 1) + 1)) / stride_h + 1; + int out_w = + (width + 2 * pad_w - (dilation_w * (weight_w - 1) + 1)) / stride_w + 1; + int num_kernels = + channels * weight_h * weight_w * out_h * out_w * parallel_imgs; + + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + columns.scalar_type(), "deformable_col2im", ([&] { + deformable_col2im_kernel( + num_kernels, + columns.data_ptr(), + offset.data_ptr(), + channels, + height, + width, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dilation_h, + dilation_w, + parallel_imgs, + n_offset_grps, + out_h, + out_w, + grad_im.data_ptr()); + })); +} + +template +static scalar_t get_coordinate_weight( + const scalar_t* im_data, + const int height, + const int width, + scalar_t y, + scalar_t x, + bool is_y_direction) { + int y_l = floor(y); + int x_l = floor(x); + int y_h = y_l + 1; + int x_h = x_l + 1; + + bool valid_y_l = 0 <= y_l && y_l < height; + bool valid_y_h = 0 <= y_h && y_h < height; + bool valid_x_l = 0 <= x_l && x_l < width; + bool valid_x_h = 0 <= x_h && x_h < width; + + scalar_t zero = 0; + scalar_t v_yx = (valid_y_l && valid_x_l) ? im_data[y_l * width + x_l] : zero; + scalar_t v_yX = (valid_y_l && valid_x_h) ? im_data[y_l * width + x_h] : zero; + scalar_t v_Yx = (valid_y_h && valid_x_l) ? im_data[y_h * width + x_l] : zero; + scalar_t v_YX = (valid_y_h && valid_x_h) ? im_data[y_h * width + x_h] : zero; + + if (is_y_direction) { + scalar_t dx = x - x_l; + return dx * (v_YX - v_yX) + (1 - dx) * (v_Yx - v_yx); + } else { + scalar_t dy = y - y_l; + return dy * (v_YX - v_Yx) + (1 - dy) * (v_yX - v_yx); + } +} + +template +static void deformable_col2im_coord_kernel( + const int n, + const scalar_t* col, + const scalar_t* im, + const scalar_t* offset, + const int channels, + const int height, + const int width, + const int weight_h, + const int weight_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dilation_h, + const int dilation_w, + const int batch_sz, + const int offset_channels, + const int n_offset_grps, + const int out_h, + const int out_w, + scalar_t* grad_offset) { + for (int index = 0; index != n; ++index) { + scalar_t val = 0; + int w = index % out_w; + int h = (index / out_w) % out_h; + int c = (index / (out_w * out_h)) % offset_channels; + int b = index / (out_w * out_h * offset_channels); + + const int offset_grp = c / (2 * weight_h * weight_w); + const int col_step = weight_h * weight_w; + + int c_per_offset_grp = channels / n_offset_grps; + + auto col_ptr = col + + offset_grp * c_per_offset_grp * weight_h * weight_w * batch_sz * out_w * + out_h; + auto im_ptr = im + + (b * n_offset_grps + offset_grp) * c_per_offset_grp * height * width; + auto offset_ptr = offset + + (b * n_offset_grps + offset_grp) * 2 * weight_h * weight_w * out_h * + out_w; + + const int offset_c = c - offset_grp * 2 * weight_h * weight_w; + const int is_y_direction = offset_c % 2 == 0; + + const int c_bound = c_per_offset_grp * weight_h * weight_w; + for (int col_c = (offset_c / 2); col_c < c_bound; col_c += col_step) { + const int col_pos = (((col_c * batch_sz + b) * out_h) + h) * out_w + w; + + int out_x = col_pos % out_w; + int out_y = (col_pos / out_w) % out_h; + int j = (col_pos / (out_w * out_h * batch_sz)) % weight_w; + int i = (col_pos / (out_w * out_h * batch_sz * weight_w)) % weight_h; + + const int offset_h_idx = + (((2 * (i * weight_w + j)) * out_h + out_y) * out_w + out_x); + const int offset_w_idx = + (((2 * (i * weight_w + j) + 1) * out_h + out_y) * out_w + out_x); + const scalar_t offset_h = offset_ptr[offset_h_idx]; + const scalar_t offset_w = offset_ptr[offset_w_idx]; + + scalar_t y = (out_y * stride_h - pad_h) + i * dilation_h + offset_h; + scalar_t x = (out_x * stride_w - pad_w) + j * dilation_w + offset_w; + + const scalar_t weight = + get_coordinate_weight(im_ptr, height, width, y, x, is_y_direction); + val += weight * col_ptr[col_pos]; + im_ptr += height * width; + } + + grad_offset[index] = val; + } +} + +static void compute_grad_offset( + const at::Tensor columns, + const at::Tensor input, + const at::Tensor offset, + const int channels, + const int height, + const int width, + const int weight_h, + const int weight_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dilation_h, + const int dilation_w, + const int parallel_imgs, + const int n_offset_grps, + at::Tensor grad_offset) { + int out_h = + (height + 2 * pad_h - (dilation_h * (weight_h - 1) + 1)) / stride_h + 1; + int out_w = + (width + 2 * pad_w - (dilation_w * (weight_w - 1) + 1)) / stride_w + 1; + int num_kernels = + out_h * out_w * 2 * weight_h * weight_w * n_offset_grps * parallel_imgs; + + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + columns.scalar_type(), "deformable_col2im_coord", ([&] { + deformable_col2im_coord_kernel( + num_kernels, + columns.data_ptr(), + input.data_ptr(), + offset.data_ptr(), + channels, + height, + width, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dilation_h, + dilation_w, + parallel_imgs, + 2 * weight_h * weight_w * n_offset_grps, + n_offset_grps, + out_h, + out_w, + grad_offset.data_ptr()); + })); +} + +static std::tuple deform_conv2d_backward_input_cpu( + at::Tensor input, + at::Tensor weight, + at::Tensor offset, + at::Tensor grad_out, + std::pair stride, + std::pair pad, + std::pair dilation, + int n_weight_grps, + int n_offset_grps, + int n_parallel_imgs) { + int batch_sz = input.size(0); + int n_in_channels = input.size(1); + int in_h = input.size(2); + int in_w = input.size(3); + + n_parallel_imgs = std::min(batch_sz, n_parallel_imgs); + + long n_out_channels = weight.size(0); + int weight_h = weight.size(2); + int weight_w = weight.size(3); + + int stride_h = stride.first; + int stride_w = stride.second; + + int pad_h = pad.first; + int pad_w = pad.second; + + int dil_h = dilation.first; + int dil_w = dilation.second; + + long out_h = (in_h + 2 * pad_h - (dil_h * (weight_h - 1) + 1)) / stride_h + 1; + long out_w = (in_w + 2 * pad_w - (dil_w * (weight_w - 1) + 1)) / stride_w + 1; + + auto grad_input = at::zeros_like(input); + auto grad_offset = at::zeros_like(offset); + auto columns = at::empty( + {n_in_channels * weight_w * weight_h, n_parallel_imgs * out_h * out_w}, + input.options()); + + // Separate into blocks + grad_input = grad_input.reshape( + {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + input = input.reshape( + {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + grad_offset = grad_offset.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * 2 * weight_h * weight_w, + out_h, + out_w}); + offset = offset.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * 2 * weight_h * weight_w, + out_h, + out_w}); + + grad_out = grad_out.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_weight_grps, + n_out_channels / n_weight_grps, + out_h, + out_w}).permute({0, 2, 3, 1, 4, 5}); + + weight = weight.reshape({n_weight_grps, + weight.size(0) / n_weight_grps, + weight.size(1), + weight.size(2), + weight.size(3)}); + + columns = columns.view( + {n_weight_grps, columns.size(0) / n_weight_grps, columns.size(1)}); + + for (int elt = 0; elt < batch_sz / n_parallel_imgs; elt++) { + columns.zero_(); + // Separate into weight groups + for (int g = 0; g < n_weight_grps; g++) { + columns[g] = columns[g].addmm_( + weight[g].flatten(1).transpose(0, 1), grad_out[elt][g].flatten(1)); + } + + compute_grad_offset( + columns, + input[elt], + offset[elt], + n_in_channels, + in_h, + in_w, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + n_parallel_imgs, + n_offset_grps, + grad_offset[elt]); + + compute_grad_input( + columns, + offset[elt], + n_in_channels, + in_h, + in_w, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + n_parallel_imgs, + n_offset_grps, + grad_input[elt]); + } + + grad_input = grad_input.view({batch_sz, n_in_channels, in_h, in_w}); + grad_offset = grad_offset.view( + {batch_sz, n_offset_grps * 2 * weight_h * weight_w, out_h, out_w}); + + return std::make_tuple(grad_input, grad_offset); +} + +static at::Tensor deform_conv2d_backward_parameters_cpu( + at::Tensor input, + at::Tensor weight, + at::Tensor offset, + at::Tensor grad_out, + std::pair stride, + std::pair pad, + std::pair dilation, + int n_weight_grps, + int n_offset_grps, + int n_parallel_imgs) { + int batch_sz = input.size(0); + int n_in_channels = input.size(1); + int in_h = input.size(2); + int in_w = input.size(3); + + n_parallel_imgs = std::min(batch_sz, n_parallel_imgs); + + long n_out_channels = weight.size(0); + int weight_h = weight.size(2); + int weight_w = weight.size(3); + + int stride_h = stride.first; + int stride_w = stride.second; + + int pad_h = pad.first; + int pad_w = pad.second; + + int dil_h = dilation.first; + int dil_w = dilation.second; + + long out_h = grad_out.size(2); + long out_w = grad_out.size(3); + + auto grad_weight = at::zeros_like(weight); + + at::Tensor grad_out_buf = grad_out.reshape( + {batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_weight_grps, + n_out_channels / n_weight_grps, + out_h, + out_w} + ).permute({0, 2, 3, 1, 4, 5}).contiguous(); + + input = input.reshape( + {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + offset = offset.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * 2 * weight_h * weight_w, + out_h, + out_w}); + + grad_weight = grad_weight.view({n_weight_grps, + grad_weight.size(0) / n_weight_grps, + grad_weight.size(1), + grad_weight.size(2), + grad_weight.size(3)}); + + auto columns = at::empty( + {n_weight_grps, + n_in_channels * weight_w * weight_h / n_weight_grps, + n_parallel_imgs * out_h * out_w}, + input.options()); + + for (int elt = 0; elt < batch_sz / n_parallel_imgs; elt++) { + deformable_im2col( + input[elt], + offset[elt], + n_in_channels, + in_h, + in_w, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + out_h, + out_w, + n_parallel_imgs, + n_offset_grps, + columns); + + for (int g = 0; g < n_weight_grps; g++) { + grad_weight[g] = + grad_weight[g] + .flatten(1) + .addmm_( + grad_out_buf[elt][g].flatten(1), columns[g].transpose(1, 0)) + .view_as(grad_weight[g]); + } + } + + grad_weight = grad_weight.view({grad_weight.size(0) * grad_weight.size(1), + grad_weight.size(2), + grad_weight.size(3), + grad_weight.size(4)}); + return grad_weight; +} + +std::tuple +DeformConv2d_backward_cpu( + const at::Tensor& grad_out, + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& bias, + std::pair stride, + std::pair pad, + std::pair dilation, + int n_weight_grps, + int n_offset_grps) { + const int batch_sz = input.size(0); + const int n_parallel_imgs = + get_greatest_divisor_below_bound(batch_sz, kMaxParallelImgs); + + auto grad_input_and_offset = deform_conv2d_backward_input_cpu( + input, + weight, + offset, + grad_out, + stride, + pad, + dilation, + n_weight_grps, + n_offset_grps, + n_parallel_imgs); + + auto grad_input = std::get<0>(grad_input_and_offset); + auto grad_offset = std::get<1>(grad_input_and_offset); + + auto grad_weight = deform_conv2d_backward_parameters_cpu( + input, + weight, + offset, + grad_out, + stride, + pad, + dilation, + n_weight_grps, + n_offset_grps, + n_parallel_imgs); + + auto grad_bias = at::ones_like(bias) * grad_out.sum({0, 2, 3}); + + return std::make_tuple(grad_input, grad_weight, grad_offset, grad_bias); +} diff --git a/torchvision/csrc/cpu/vision_cpu.h b/torchvision/csrc/cpu/vision_cpu.h index d84b172ba49..b133c9ff1a3 100644 --- a/torchvision/csrc/cpu/vision_cpu.h +++ b/torchvision/csrc/cpu/vision_cpu.h @@ -84,3 +84,27 @@ at::Tensor nms_cpu( const at::Tensor& dets, const at::Tensor& scores, const float iou_threshold); + +at::Tensor DeformConv2d_forward_cpu( + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& bias, + std::pair stride, + std::pair pad, + std::pair dilation, + int groups, + int deformable_groups); + +std::tuple +DeformConv2d_backward_cpu( + const at::Tensor& grad_out, + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& bias, + std::pair stride, + std::pair pad, + std::pair dilation, + int groups, + int deformable_groups); diff --git a/torchvision/csrc/cuda/DeformConv_cuda.cu b/torchvision/csrc/cuda/DeformConv_cuda.cu new file mode 100644 index 00000000000..1b923965e54 --- /dev/null +++ b/torchvision/csrc/cuda/DeformConv_cuda.cu @@ -0,0 +1,988 @@ +/*! + ******************* BEGIN Caffe Copyright Notice and Disclaimer + ***************** + * + * COPYRIGHT + * + * All contributions by the University of California: + * Copyright (c) 2014-2017 The Regents of the University of California (Regents) + * All rights reserved. + * + * All other contributions: + * Copyright (c) 2014-2017, the respective contributors + * All rights reserved. + * + * Caffe uses a shared copyright model: each contributor holds copyright over + * their contributions to Caffe. The project versioning records all such + * contribution and copyright details. If a contributor wants to further mark + * their specific copyright on a particular contribution, they should indicate + * their copyright solely in the commit message of the change when it is + * committed. + * + * LICENSE + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + *this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + *AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + *IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + *DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + *SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + *CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + *OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + *OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * CONTRIBUTION AGREEMENT + * + * By contributing to the BVLC/caffe repository through pull-request, comment, + * or otherwise, the contributor releases their content to the + * license and copyright terms herein. + * + ***************** END Caffe Copyright Notice and Disclaimer + ********************* + * + * Copyright (c) 2018 Microsoft + * Licensed under The MIT License [see LICENSE for details] + * \file modulated_deformable_im2col.cuh + * \brief Function definitions of converting an image to + * column matrix based on kernel, padding, dilation, and offset. + * These functions are mainly used in deformable convolution operators. + * \ref: https://arxiv.org/abs/1703.06211 + * \author Yuwen Xiong, Haozhi Qi, Jifeng Dai, Xizhou Zhu, Han Hu, Dazhi Cheng + */ + +// modified from +// https://github.com/chengdazhi/Deformable-Convolution-V2-PyTorch/blob/mmdetection/mmdet/ops/dcn/src/deform_conv_cuda_kernel.cu + +// modified from +// https://github.com/open-mmlab/mmdetection/blob/master/mmdet/ops/dcn/src/deform_conv_cuda.cpp + +#include +#include +#include +#include +#include + +#include "cuda_helpers.h" + +#include +#include +#include + +using namespace at; + +const int CUDA_NUM_THREADS = 1024; +const int kMaxGridNum = 65535; + +const int kMaxParallelImgs = 32; + +inline int GET_BLOCKS(const int N) { + return std::min(kMaxGridNum, (N + CUDA_NUM_THREADS - 1) / CUDA_NUM_THREADS); +} + +template +__device__ scalar_t bilinear_interpolate( + const scalar_t* in, + const int height, + const int width, + scalar_t h, + scalar_t w) { + if (h <= -1 || height <= h || w <= -1 || width <= w) { + return 0; + } + + int h_low = floor(h); + int w_low = floor(w); + int h_high = h_low + 1; + int w_high = w_low + 1; + + scalar_t lh = h - h_low; + scalar_t lw = w - w_low; + scalar_t hh = 1 - lh, hw = 1 - lw; + + scalar_t v1 = 0; + if (h_low >= 0 && w_low >= 0) + v1 = in[h_low * width + w_low]; + scalar_t v2 = 0; + if (h_low >= 0 && w_high <= width - 1) + v2 = in[h_low * width + w_high]; + scalar_t v3 = 0; + if (h_high <= height - 1 && w_low >= 0) + v3 = in[h_high * width + w_low]; + scalar_t v4 = 0; + if (h_high <= height - 1 && w_high <= width - 1) + v4 = in[h_high * width + w_high]; + + scalar_t w1 = hh * hw, w2 = hh * lw, w3 = lh * hw, w4 = lh * lw; + + scalar_t val = (w1 * v1 + w2 * v2 + w3 * v3 + w4 * v4); + return val; +} + +template +__global__ void deformable_im2col_gpu_kernel( + const int n, + const scalar_t* input_ptr, + const scalar_t* offset_ptr, + const int height, + const int width, + const int weight_h, + const int weight_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dil_h, + const int dil_w, + const int batch_sz, + const int n_in_channels, + const int n_offset_grps, + const int out_h, + const int out_w, + scalar_t* columns_ptr) { + CUDA_1D_KERNEL_LOOP(index, n) { + const int out_x = index % out_w; + const int out_y = (index / out_w) % out_h; + const int out_b = (index / (out_w * out_h)) % batch_sz; + const int in_c = index / (out_w * out_h * batch_sz); + const int out_c = in_c * weight_h * weight_w; + + int c_per_offset_grp = n_in_channels / n_offset_grps; + const int grp_idx = in_c / c_per_offset_grp; + + columns_ptr += + (out_c * (batch_sz * out_h * out_w) + out_b * (out_h * out_w) + + out_y * out_w + out_x); + + input_ptr += + (out_b * (n_in_channels * height * width) + in_c * (height * width)); + + offset_ptr += (out_b * n_offset_grps + grp_idx) * 2 * weight_h * weight_w * + out_h * out_w; + + for (int i = 0; i < weight_h; ++i) { + for (int j = 0; j < weight_w; ++j) { + const int offset_idx = 2 * (i * weight_w + j); + const scalar_t offset_h = + offset_ptr[offset_idx * (out_h * out_w) + out_y * out_w + out_x]; + const scalar_t offset_w = offset_ptr + [(offset_idx + 1) * (out_h * out_w) + out_y * out_w + out_x]; + const scalar_t y = (out_y * stride_h - pad_h) + i * dil_h + offset_h; + const scalar_t x = (out_x * stride_w - pad_w) + j * dil_w + offset_w; + *columns_ptr = bilinear_interpolate(input_ptr, height, width, y, x); + columns_ptr += batch_sz * out_h * out_w; + } + } + } +} + +static void deformable_im2col( + const at::Tensor input, + const at::Tensor data_offset, + int n_in_channels, + int height, + int width, + int weight_h, + int weight_w, + int pad_h, + int pad_w, + int stride_h, + int stride_w, + int dil_h, + int dil_w, + int out_h, + int out_w, + int parallel_imgs, + int deformable_group, + at::Tensor data_col) { + int num_kernels = n_in_channels * out_h * out_w * parallel_imgs; + + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + input.scalar_type(), "deformable_im2col_gpu", ([&] { + deformable_im2col_gpu_kernel<<< + GET_BLOCKS(num_kernels), + CUDA_NUM_THREADS>>>( + num_kernels, + input.data_ptr(), + data_offset.data_ptr(), + height, + width, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + parallel_imgs, + n_in_channels, + deformable_group, + out_h, + out_w, + data_col.data_ptr()); + })); + + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("error in deformable_im2col: %s\n", cudaGetErrorString(err)); + } +} + +static int get_greatest_divisor_below_bound(int n, int bound) { + for (int k = bound; k > 1; --k) { + if (n % k == 0) { + return k; + } + } + return 1; +} + +at::Tensor DeformConv2d_forward_cuda( + const at::Tensor& input_param, + const at::Tensor& weight_param, + const at::Tensor& offset_param, + const at::Tensor& bias, + std::pair stride, + std::pair pad, + std::pair dilation, + int n_weight_grps, + int n_offset_grps) { + at::Tensor input = input_param; + at::Tensor weight = weight_param; + at::Tensor offset = offset_param; + + TORCH_CHECK(input.ndimension() == 4); + TORCH_CHECK(offset.ndimension() == 4); + TORCH_CHECK(weight.ndimension() == 4); + TORCH_CHECK(input.is_contiguous()); + TORCH_CHECK(offset.is_contiguous()); + TORCH_CHECK(weight.is_contiguous()); + TORCH_CHECK(input.device().is_cuda(), "input must be a CUDA tensor"); + + at::DeviceGuard guard(input.device()); + + int batch_sz = input.size(0); + int in_channels = input.size(1); + int in_h = input.size(2); + int in_w = input.size(3); + + int n_parallel_imgs = + get_greatest_divisor_below_bound(batch_sz, kMaxParallelImgs); + + int out_channels = weight.size(0); + int weight_h = weight.size(2); + int weight_w = weight.size(3); + + int stride_h = stride.first; + int stride_w = stride.second; + + int pad_h = pad.first; + int pad_w = pad.second; + + int dil_h = dilation.first; + int dil_w = dilation.second; + + int ker_h = dil_h * (weight_h - 1) + 1; + int ker_w = dil_w * (weight_w - 1) + 1; + int out_h = ((in_h + 2 * pad_h - ker_h) / stride_h) + 1; + int out_w = ((in_w + 2 * pad_w - ker_w) / stride_w) + 1; + + TORCH_CHECK( + weight_h > 0 && weight_w > 0, + "weight_h: ", + weight_h, + " weight_w: ", + weight_w); + TORCH_CHECK( + stride_h > 0 && stride_w > 0, + "stride_h: ", + stride_h, + " stride_w: ", + stride_w); + TORCH_CHECK(pad_h >= 0 && pad_w >= 0, "pad_h: ", pad_h, " pad_w: ", pad_w); + TORCH_CHECK(dil_h > 0 && dil_w > 0, "dil_h: ", dil_h, " dil_w: ", dil_w); + + TORCH_CHECK(weight.size(1) * n_weight_grps == input.size(1)); + TORCH_CHECK(weight.size(0) % n_weight_grps == 0); + TORCH_CHECK( + (offset.size(1) == n_offset_grps * 2 * weight_h * weight_w), + "offset.shape[1] is not valid: got: ", + offset.size(1), + " expected: ", + n_offset_grps * 2 * weight_h * weight_w); + TORCH_CHECK(input.size(1) % n_offset_grps == 0); + + TORCH_CHECK( + (offset.size(0) == input.size(0)), "invalid batch size of offset"); + TORCH_CHECK( + (offset.size(2) == out_h && offset.size(3) == out_w), + "offset output dims: (", + offset.size(2), + ", ", + offset.size(3), + ") - ", + "computed output dims: (", + out_h, + ", ", + out_w, + ")"); + TORCH_CHECK( + out_h > 0 && out_w > 0, + "Calculated output size too small - out_h: ", + out_h, + " out_w: ", + out_w); + + auto out = at::zeros({batch_sz, out_channels, out_h, out_w}, input.options()); + + // Separate batches into blocks + out = out.view({batch_sz / n_parallel_imgs, + n_parallel_imgs, + out_channels, + out_h, + out_w}); + input = input.view( + {batch_sz / n_parallel_imgs, n_parallel_imgs, in_channels, in_h, in_w}); + offset = offset.view({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * 2 * weight_h * weight_w, + out_h, + out_w}); + at::Tensor out_buf = at::zeros( + {batch_sz / n_parallel_imgs, + out_channels, + n_parallel_imgs * out_h, + out_w}, + out.options()); + + // Separate channels into convolution groups + out_buf = out_buf.view({out_buf.size(0), + n_weight_grps, + out_buf.size(1) / n_weight_grps, + out_buf.size(2), + out_buf.size(3)}); + weight = weight.view({n_weight_grps, + weight.size(0) / n_weight_grps, + weight.size(1), + weight.size(2), + weight.size(3)}); + + // Sample points and perform convolution + auto columns = at::zeros( + {in_channels * weight_h * weight_w, n_parallel_imgs * out_h * out_w}, + input.options()); + for (int b = 0; b < batch_sz / n_parallel_imgs; b++) { + deformable_im2col( + input[b], + offset[b], + in_channels, + in_h, + in_w, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + out_h, + out_w, + n_parallel_imgs, + n_offset_grps, + columns); + + columns = columns.view( + {n_weight_grps, columns.size(0) / n_weight_grps, columns.size(1)}); + for (int g = 0; g < n_weight_grps; g++) { + out_buf[b][g] = out_buf[b][g] + .flatten(1) + .addmm_(weight[g].flatten(1), columns[g]) + .view_as(out_buf[b][g]); + } + columns = columns.view( + {columns.size(0) * columns.size(1), columns.size(2)}); + } + + out_buf = out_buf.view({batch_sz / n_parallel_imgs, + out_channels, + n_parallel_imgs, + out_h, + out_w}); + out_buf.transpose_(1, 2); + out.copy_(out_buf); + out = out.view({batch_sz, out_channels, out_h, out_w}); + + return out + bias.view({1, out_channels, 1, 1}); +} + +template +__global__ void deformable_col2im_gpu_kernel( + const int n, + const scalar_t* col, + const scalar_t* offset_ptr, + const int channels, + const int height, + const int width, + const int kernel_h, + const int kernel_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dilation_h, + const int dilation_w, + const int batch_sz, + const int n_offset_grps, + const int out_h, + const int out_w, + scalar_t* grad_im) { + CUDA_1D_KERNEL_LOOP(index, n) { + const int out_x = index % out_w; + const int out_y = (index / out_w) % out_h; + const int b = (index / (out_w * out_h)) % batch_sz; + const int j = (index / (out_w * out_h * batch_sz)) % kernel_w; + const int i = (index / (out_w * out_h * batch_sz * kernel_w)) % kernel_h; + const int c = index / (out_w * out_h * batch_sz * kernel_w * kernel_h); + + int c_per_offset_grp = channels / n_offset_grps; + const int offset_grp = c / c_per_offset_grp; + + offset_ptr += (b * n_offset_grps + offset_grp) * 2 * kernel_h * kernel_w * + out_h * out_w; + const int offset_h_ptr = + ((2 * (i * kernel_w + j)) * out_h + out_y) * out_w + out_x; + const int offset_w_ptr = + ((2 * (i * kernel_w + j) + 1) * out_h + out_y) * out_w + out_x; + const scalar_t offset_h = offset_ptr[offset_h_ptr]; + const scalar_t offset_w = offset_ptr[offset_w_ptr]; + const scalar_t y = (out_y * stride_h - pad_h) + i * dilation_h + offset_h; + const scalar_t x = (out_x * stride_w - pad_w) + j * dilation_w + offset_w; + + for (int dy = -1; dy <= 1; dy++) { + for (int dx = -1; dx <= 1; dx++) { + int yp = int(y) + dy; + int xp = int(x) + dx; + if (0 <= yp && yp < height && 0 <= xp && xp < width && + std::abs(y - yp) < 1 && std::abs(x - xp) < 1) { + int grad_pos = ((b * channels + c) * height + yp) * width + xp; + scalar_t weight = (1 - std::abs(y - yp)) * (1 - std::abs(x - xp)); + atomicAdd(grad_im + grad_pos, weight * col[index]); + } + } + } + } +} + +static void compute_grad_input( + const at::Tensor columns, + const at::Tensor offset, + const int channels, + const int height, + const int width, + const int weight_h, + const int weight_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dilation_h, + const int dilation_w, + const int parallel_imgs, + const int n_offset_grps, + at::Tensor grad_im) { + int out_h = + (height + 2 * pad_h - (dilation_h * (weight_h - 1) + 1)) / stride_h + 1; + int out_w = + (width + 2 * pad_w - (dilation_w * (weight_w - 1) + 1)) / stride_w + 1; + int num_kernels = + channels * weight_h * weight_w * out_h * out_w * parallel_imgs; + + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + columns.scalar_type(), "deformable_col2im_gpu", ([&] { + deformable_col2im_gpu_kernel<<< + GET_BLOCKS(num_kernels), + CUDA_NUM_THREADS>>>( + num_kernels, + columns.data_ptr(), + offset.data_ptr(), + channels, + height, + width, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dilation_h, + dilation_w, + parallel_imgs, + n_offset_grps, + out_h, + out_w, + grad_im.data_ptr()); + })); + + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("error in compute_grad_input: %s\n", cudaGetErrorString(err)); + } +} + +template +__device__ scalar_t get_coordinate_weight( + const scalar_t* im_data, + const int height, + const int width, + scalar_t y, + scalar_t x, + bool is_y_direction) { + int y_l = floor(y); + int x_l = floor(x); + int y_h = y_l + 1; + int x_h = x_l + 1; + + bool valid_y_l = 0 <= y_l && y_l < height; + bool valid_y_h = 0 <= y_h && y_h < height; + bool valid_x_l = 0 <= x_l && x_l < width; + bool valid_x_h = 0 <= x_h && x_h < width; + + scalar_t zero = 0; + scalar_t v_yx = (valid_y_l && valid_x_l) ? im_data[y_l * width + x_l] : zero; + scalar_t v_yX = (valid_y_l && valid_x_h) ? im_data[y_l * width + x_h] : zero; + scalar_t v_Yx = (valid_y_h && valid_x_l) ? im_data[y_h * width + x_l] : zero; + scalar_t v_YX = (valid_y_h && valid_x_h) ? im_data[y_h * width + x_h] : zero; + + if (is_y_direction) { + scalar_t dx = x - x_l; + return dx * (v_YX - v_yX) + (1 - dx) * (v_Yx - v_yx); + } else { + scalar_t dy = y - y_l; + return dy * (v_YX - v_Yx) + (1 - dy) * (v_yX - v_yx); + } +} + +template +__global__ void deformable_col2im_coord_gpu_kernel( + const int n, + const scalar_t* col_ptr, + const scalar_t* im_ptr, + const scalar_t* offset_ptr, + const int channels, + const int height, + const int width, + const int weight_h, + const int weight_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dilation_h, + const int dilation_w, + const int batch_sz, + const int offset_channels, + const int n_offset_grps, + const int out_h, + const int out_w, + scalar_t* grad_offset) { + CUDA_1D_KERNEL_LOOP(index, n) { + scalar_t val = 0; + int w = index % out_w; + int h = (index / out_w) % out_h; + int c = (index / (out_w * out_h)) % offset_channels; + int b = index / (out_w * out_h * offset_channels); + + const int offset_grp = c / (2 * weight_h * weight_w); + const int col_step = weight_h * weight_w; + + int c_per_offset_grp = channels / n_offset_grps; + + col_ptr += offset_grp * c_per_offset_grp * weight_h * weight_w * batch_sz * + out_w * out_h; + im_ptr += + (b * n_offset_grps + offset_grp) * c_per_offset_grp * height * width; + offset_ptr += (b * n_offset_grps + offset_grp) * 2 * weight_h * weight_w * + out_h * out_w; + + const int offset_c = c - offset_grp * 2 * weight_h * weight_w; + const int is_y_direction = offset_c % 2 == 0; + + const int c_bound = c_per_offset_grp * weight_h * weight_w; + for (int col_c = (offset_c / 2); col_c < c_bound; col_c += col_step) { + const int col_pos = (((col_c * batch_sz + b) * out_h) + h) * out_w + w; + + int out_x = col_pos % out_w; + int out_y = (col_pos / out_w) % out_h; + int j = (col_pos / (out_w * out_h * batch_sz)) % weight_w; + int i = (col_pos / (out_w * out_h * batch_sz * weight_w)) % weight_h; + + const int offset_h_ptr = + (((2 * (i * weight_w + j)) * out_h + out_y) * out_w + out_x); + const int offset_w_ptr = + (((2 * (i * weight_w + j) + 1) * out_h + out_y) * out_w + out_x); + const scalar_t offset_h = offset_ptr[offset_h_ptr]; + const scalar_t offset_w = offset_ptr[offset_w_ptr]; + + scalar_t y = (out_y * stride_h - pad_h) + i * dilation_h + offset_h; + scalar_t x = (out_x * stride_w - pad_w) + j * dilation_w + offset_w; + + const scalar_t weight = + get_coordinate_weight(im_ptr, height, width, y, x, is_y_direction); + val += weight * col_ptr[col_pos]; + im_ptr += height * width; + } + + grad_offset[index] = val; + } +} + +static void compute_grad_offset( + const at::Tensor columns, + const at::Tensor input, + const at::Tensor offset, + const int channels, + const int height, + const int width, + const int weight_h, + const int weight_w, + const int pad_h, + const int pad_w, + const int stride_h, + const int stride_w, + const int dilation_h, + const int dilation_w, + const int parallel_imgs, + const int n_offset_grps, + at::Tensor grad_offset) { + int out_h = + (height + 2 * pad_h - (dilation_h * (weight_h - 1) + 1)) / stride_h + 1; + int out_w = + (width + 2 * pad_w - (dilation_w * (weight_w - 1) + 1)) / stride_w + 1; + int num_kernels = + out_h * out_w * 2 * weight_h * weight_w * n_offset_grps * parallel_imgs; + + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + columns.scalar_type(), "deformable_col2im_coord_gpu", ([&] { + deformable_col2im_coord_gpu_kernel<<< + GET_BLOCKS(num_kernels), + CUDA_NUM_THREADS>>>( + num_kernels, + columns.data_ptr(), + input.data_ptr(), + offset.data_ptr(), + channels, + height, + width, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dilation_h, + dilation_w, + parallel_imgs, + 2 * weight_h * weight_w * n_offset_grps, + n_offset_grps, + out_h, + out_w, + grad_offset.data_ptr()); + })); + + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("error in compute_grad_offset: %s\n", cudaGetErrorString(err)); + } +} + +static std::tuple deform_conv_backward_input_cuda( + at::Tensor input, + at::Tensor weight, + at::Tensor offset, + at::Tensor grad_out, + std::pair stride, + std::pair pad, + std::pair dilation, + int n_weight_grps, + int n_offset_grps, + int n_parallel_imgs) { + at::DeviceGuard guard(input.device()); + + int batch_sz = input.size(0); + long n_in_channels = input.size(1); + long in_h = input.size(2); + long in_w = input.size(3); + + n_parallel_imgs = std::min(batch_sz, n_parallel_imgs); + + long n_out_channels = weight.size(0); + int weight_h = weight.size(2); + int weight_w = weight.size(3); + + int stride_h = stride.first; + int stride_w = stride.second; + + int pad_h = pad.first; + int pad_w = pad.second; + + int dil_h = dilation.first; + int dil_w = dilation.second; + + long out_w = (in_w + 2 * pad_w - (dil_w * (weight_w - 1) + 1)) / stride_w + 1; + long out_h = (in_h + 2 * pad_h - (dil_h * (weight_h - 1) + 1)) / stride_h + 1; + + auto grad_input = at::zeros_like(input); + auto grad_offset = at::zeros_like(offset); + auto columns = at::empty( + {n_in_channels * weight_w * weight_h, n_parallel_imgs * out_h * out_w}, + input.options()); + + // Separate into blocks + grad_input = grad_input.reshape( + {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + input = input.reshape( + {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + grad_offset = grad_offset.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * 2 * weight_h * weight_w, + out_h, + out_w}); + offset = offset.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * 2 * weight_h * weight_w, + out_h, + out_w}); + + grad_out = grad_out.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_weight_grps, + n_out_channels / n_weight_grps, + out_h, + out_w}).permute({0, 2, 3, 1, 4, 5}); + + weight = weight.reshape({n_weight_grps, + weight.size(0) / n_weight_grps, + weight.size(1), + weight.size(2), + weight.size(3)}); + + columns = columns.view( + {n_weight_grps, columns.size(0) / n_weight_grps, columns.size(1)}); + for (int elt = 0; elt < batch_sz / n_parallel_imgs; elt++) { + columns.zero_(); + // Separate into weight groups + for (int g = 0; g < n_weight_grps; g++) { + columns[g] = columns[g].addmm_( + weight[g].flatten(1).transpose(0, 1), grad_out[elt][g].flatten(1)); + } + + compute_grad_offset( + columns, + input[elt], + offset[elt], + n_in_channels, + in_h, + in_w, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + n_parallel_imgs, + n_offset_grps, + grad_offset[elt]); + + compute_grad_input( + columns, + offset[elt], + n_in_channels, + in_h, + in_w, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + n_parallel_imgs, + n_offset_grps, + grad_input[elt]); + } + + + grad_input = grad_input.view({batch_sz, n_in_channels, in_h, in_w}); + grad_offset = grad_offset.view( + {batch_sz, n_offset_grps * 2 * weight_h * weight_w, out_h, out_w}); + + return std::make_tuple(grad_input, grad_offset); +} + +static at::Tensor deform_conv_backward_parameters_cuda( + at::Tensor input, + at::Tensor weight, + at::Tensor offset, + at::Tensor grad_out, + std::pair stride, + std::pair pad, + std::pair dilation, + int n_weight_grps, + int n_offset_grps, + int n_parallel_imgs) { + at::DeviceGuard guard(input.device()); + + int batch_sz = input.size(0); + long n_in_channels = input.size(1); + long in_h = input.size(2); + long in_w = input.size(3); + + n_parallel_imgs = std::min(batch_sz, n_parallel_imgs); + + long n_out_channels = weight.size(0); + int weight_h = weight.size(2); + int weight_w = weight.size(3); + + int stride_h = stride.first; + int stride_w = stride.second; + + int pad_h = pad.first; + int pad_w = pad.second; + + int dil_h = dilation.first; + int dil_w = dilation.second; + + long out_h = grad_out.size(2); + long out_w = grad_out.size(3); + + auto grad_weight = at::zeros_like(weight); + + at::Tensor grad_out_buf = grad_out.reshape( + {batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_weight_grps, + n_out_channels / n_weight_grps, + out_h, + out_w} + ).permute({0, 2, 3, 1, 4, 5}).contiguous(); + + input = input.reshape( + {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + offset = offset.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * 2 * weight_h * weight_w, + out_h, + out_w}); + + grad_weight = grad_weight.reshape({n_weight_grps, + grad_weight.size(0) / n_weight_grps, + grad_weight.size(1), + grad_weight.size(2), + grad_weight.size(3)}); + + auto columns = at::empty( + {n_weight_grps, + n_in_channels * weight_w * weight_h / n_weight_grps, + n_parallel_imgs * out_h * out_w}, + input.options()); + + for (int elt = 0; elt < batch_sz / n_parallel_imgs; elt++) { + deformable_im2col( + input[elt], + offset[elt], + n_in_channels, + in_h, + in_w, + weight_h, + weight_w, + pad_h, + pad_w, + stride_h, + stride_w, + dil_h, + dil_w, + out_h, + out_w, + n_parallel_imgs, + n_offset_grps, + columns); + + for (int g = 0; g < n_weight_grps; g++) { + grad_weight[g] = + grad_weight[g] + .flatten(1) + .addmm_( + grad_out_buf[elt][g].flatten(1), columns[g].transpose(1, 0)) + .view_as(grad_weight[g]); + } + } + + grad_weight = grad_weight.view({grad_weight.size(0) * grad_weight.size(1), + grad_weight.size(2), + grad_weight.size(3), + grad_weight.size(4)}); + return grad_weight; +} + +std::tuple +DeformConv2d_backward_cuda( + const at::Tensor& grad_out, + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& bias, + std::pair stride, + std::pair pad, + std::pair dilation, + int n_weight_grps, + int n_offset_grps) { + const int batch_sz = input.size(0); + const int n_parallel_imgs = + get_greatest_divisor_below_bound(batch_sz, kMaxParallelImgs); + + auto grad_input_and_offset = deform_conv_backward_input_cuda( + input, + weight, + offset, + grad_out, + stride, + pad, + dilation, + n_weight_grps, + n_offset_grps, + n_parallel_imgs); + + auto grad_input = std::get<0>(grad_input_and_offset); + auto grad_offset = std::get<1>(grad_input_and_offset); + + auto grad_weight = deform_conv_backward_parameters_cuda( + input, + weight, + offset, + grad_out, + stride, + pad, + dilation, + n_weight_grps, + n_offset_grps, + n_parallel_imgs); + + auto value = grad_out.sum({0, 2, 3}); + auto grad_bias = at::ones_like(bias) * value; + + return std::make_tuple(grad_input, grad_weight, grad_offset, grad_bias); +} diff --git a/torchvision/csrc/cuda/vision_cuda.h b/torchvision/csrc/cuda/vision_cuda.h index b35c4c909c1..36e6b3d090b 100644 --- a/torchvision/csrc/cuda/vision_cuda.h +++ b/torchvision/csrc/cuda/vision_cuda.h @@ -85,3 +85,27 @@ at::Tensor nms_cuda( const at::Tensor& dets, const at::Tensor& scores, const float iou_threshold); + +at::Tensor DeformConv2d_forward_cuda( + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& bias, + std::pair stride, + std::pair pad, + std::pair dilation, + int groups, + int deformable_groups); + +std::tuple +DeformConv2d_backward_cuda( + const at::Tensor& grad_out, + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& bias, + std::pair stride, + std::pair pad, + std::pair dilation, + int groups, + int deformable_groups); diff --git a/torchvision/csrc/vision.cpp b/torchvision/csrc/vision.cpp index 38dcdfc1cc0..8d8699ecc26 100644 --- a/torchvision/csrc/vision.cpp +++ b/torchvision/csrc/vision.cpp @@ -5,6 +5,7 @@ #include #endif +#include "DeformConv.h" #include "PSROIAlign.h" #include "PSROIPool.h" #include "ROIAlign.h" @@ -47,4 +48,5 @@ static auto registry = .op("torchvision::_new_empty_tensor_op", &new_empty_tensor) .op("torchvision::ps_roi_align", &ps_roi_align) .op("torchvision::ps_roi_pool", &ps_roi_pool) + .op("torchvision::deform_conv2d", &deform_conv2d) .op("torchvision::_cuda_version", &_cuda_version); diff --git a/torchvision/ops/__init__.py b/torchvision/ops/__init__.py index 4921d2d0335..0ff2b0be2ce 100644 --- a/torchvision/ops/__init__.py +++ b/torchvision/ops/__init__.py @@ -1,5 +1,6 @@ from .boxes import nms, box_iou from .new_empty_tensor import _new_empty_tensor +from .deform_conv import deform_conv2d, DeformConv2d from .roi_align import roi_align, RoIAlign from .roi_pool import roi_pool, RoIPool from .ps_roi_align import ps_roi_align, PSRoIAlign @@ -13,7 +14,7 @@ __all__ = [ - 'nms', 'roi_align', 'RoIAlign', 'roi_pool', 'RoIPool', '_new_empty_tensor', - 'ps_roi_align', 'PSRoIAlign', 'ps_roi_pool', 'PSRoIPool', - 'MultiScaleRoIAlign', 'FeaturePyramidNetwork' + 'deform_conv2d', 'DeformConv2d', 'nms', 'roi_align', 'RoIAlign', 'roi_pool', + 'RoIPool', '_new_empty_tensor', 'ps_roi_align', 'PSRoIAlign', 'ps_roi_pool', + 'PSRoIPool', 'MultiScaleRoIAlign', 'FeaturePyramidNetwork' ] diff --git a/torchvision/ops/deform_conv.py b/torchvision/ops/deform_conv.py new file mode 100644 index 00000000000..c948b164196 --- /dev/null +++ b/torchvision/ops/deform_conv.py @@ -0,0 +1,139 @@ +import math + +import torch +from torch import nn, Tensor +from torch.nn import init +from torch.nn.parameter import Parameter +from torch.nn.modules.utils import _pair +from torch.jit.annotations import Optional, Tuple + + +def deform_conv2d(input, offset, weight, bias=None, stride=(1, 1), padding=(0, 0), dilation=(1, 1)): + # type: (Tensor, Tensor, Tensor, Optional[Tensor], Tuple[int, int], Tuple[int, int], Tuple[int, int]) -> Tensor + """ + Performs Deformable Convolution, described in Deformable Convolutional Networks + + Arguments: + input (Tensor[batch_size, in_channels, in_height, in_width]): input tensor + offset (Tensor[batch_size, 2 * offset_groups * kernel_height * kernel_width, + out_height, out_width]): offsets to be applied for each position in the + convolution kernel. + weight (Tensor[out_channels, in_channels // groups, kernel_height, kernel_width]): + convolution weights, split into groups of size (in_channels // groups) + bias (Tensor[out_channels]): optional bias of shape (out_channels,). Default: None + stride (int or Tuple[int, int]): distance between convolution centers. Default: 1 + padding (int or Tuple[int, int]): height/width of padding of zeroes around + each image. Default: 0 + dilation (int or Tuple[int, int]): the spacing between kernel elements. Default: 1 + + Returns: + output (Tensor[batch_sz, out_channels, out_h, out_w]): result of convolution + + + Examples:: + >>> input = torch.rand(1, 3, 10, 10) + >>> kh, kw = 3, 3 + >>> weight = torch.rand(5, 3, kh, kw) + >>> # offset should have the same spatial size as the output + >>> # of the convolution. In this case, for an input of 10, stride of 1 + >>> # and kernel size of 3, without padding, the output size is 8 + >>> offset = torch.rand(5, 2 * kh * kw, 8, 8) + >>> out = deform_conv2d(input, offset, weight) + >>> print(out.shape) + >>> # returns + >>> torch.Size([1, 5, 8, 8]) + """ + + out_channels = weight.shape[0] + if bias is None: + bias = torch.zeros(out_channels, device=input.device, dtype=input.dtype) + + stride_h, stride_w = _pair(stride) + pad_h, pad_w = _pair(padding) + dil_h, dil_w = _pair(dilation) + weights_h, weights_w = weight.shape[-2:] + _, n_in_channels, in_h, in_w = input.shape + + n_offset_grps = offset.shape[1] // (2 * weights_h * weights_w) + n_weight_grps = n_in_channels // weight.shape[1] + + if n_offset_grps == 0: + raise RuntimeError( + "the shape of the offset tensor at dimension 1 is not valid. It should " + "be a multiple of 2 * weight.size[2] * weight.size[3].\n" + "Got offset.shape[1]={}, while 2 * weight.size[2] * weight.size[3]={}".format( + offset.shape[1], 2 * weights_h * weights_w)) + + return torch.ops.torchvision.deform_conv2d( + input, + weight, + offset, + bias, + stride_h, stride_w, + pad_h, pad_w, + dil_h, dil_w, + n_weight_grps, + n_offset_grps) + + +class DeformConv2d(nn.Module): + """ + See deform_conv2d + """ + def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, + dilation=1, groups=1, bias=True): + super(DeformConv2d, self).__init__() + + if in_channels % groups != 0: + raise ValueError('in_channels must be divisible by groups') + if out_channels % groups != 0: + raise ValueError('out_channels must be divisible by groups') + + self.in_channels = in_channels + self.out_channels = out_channels + self.kernel_size = _pair(kernel_size) + self.stride = _pair(stride) + self.padding = _pair(padding) + self.dilation = _pair(dilation) + self.groups = groups + + self.weight = Parameter(torch.empty(out_channels, in_channels // groups, + self.kernel_size[0], self.kernel_size[1])) + + if bias: + self.bias = Parameter(torch.empty(out_channels)) + else: + self.register_parameter('bias', None) + + self.reset_parameters() + + def reset_parameters(self): + init.kaiming_uniform_(self.weight, a=math.sqrt(5)) + if self.bias is not None: + fan_in, _ = init._calculate_fan_in_and_fan_out(self.weight) + bound = 1 / math.sqrt(fan_in) + init.uniform_(self.bias, -bound, bound) + + def forward(self, input, offset): + """ + Arguments: + input (Tensor[batch_size, in_channels, in_height, in_width]): input tensor + offset (Tensor[batch_size, 2 * offset_groups * kernel_height * kernel_width, + out_height, out_width]): offsets to be applied for each position in the + convolution kernel. + """ + return deform_conv2d(input, offset, self.weight, self.bias, stride=self.stride, + padding=self.padding, dilation=self.dilation) + + def __repr__(self): + s = self.__class__.__name__ + '(' + s += '{in_channels}' + s += ', {out_channels}' + s += ', kernel_size={kernel_size}' + s += ', stride={stride}' + s += ', padding={padding}' if self.padding != (0, 0) else '' + s += ', dilation={dilation}' if self.dilation != (1, 1) else '' + s += ', groups={groups}' if self.groups != 1 else '' + s += ', bias=False' if self.bias is None else '' + s += ')' + return s.format(**self.__dict__) From 75d8a1c9738ca3d4f75cb5127a86aa0e42c1e863 Mon Sep 17 00:00:00 2001 From: Tongzhou Wang Date: Wed, 8 Jul 2020 09:39:04 -0700 Subject: [PATCH 067/357] fix lsun docstring example (#1935) (#2408) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2408 Reviewed By: zhangguanheng66 Differential Revision: D22432488 Pulled By: fmassa fbshipit-source-id: beb5adb8176228dd0d0c4367b411e5b5c0b054ab --- torchvision/datasets/lsun.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/datasets/lsun.py b/torchvision/datasets/lsun.py index 8127fc9cbf4..3b5b5136088 100644 --- a/torchvision/datasets/lsun.py +++ b/torchvision/datasets/lsun.py @@ -67,7 +67,7 @@ class LSUN(VisionDataset): Args: root (string): Root directory for the database files. classes (string or list): One of {'train', 'val', 'test'} or a list of - categories to load. e,g. ['bedroom_train', 'church_train']. + categories to load. e,g. ['bedroom_train', 'church_outdoor_train']. transform (callable, optional): A function/transform that takes in an PIL image and returns a transformed version. E.g, ``transforms.RandomCrop`` target_transform (callable, optional): A function/transform that takes in the From dd041522d329076c95a0073e6255471e86ae5568 Mon Sep 17 00:00:00 2001 From: AhnDW Date: Wed, 8 Jul 2020 09:39:29 -0700 Subject: [PATCH 068/357] `aligned` flag in ROIAlign (#1908) (#2405) Summary: * Aligned flag in the interfaces * Aligned flag in the impl, and remove unused comments * Handling empty bin in forward * Remove raise error in roi_width * Aligned flag in the Testcodes Pull Request resolved: https://github.com/pytorch/vision/pull/2405 Reviewed By: zhangguanheng66 Differential Revision: D22432395 Pulled By: fmassa fbshipit-source-id: a412083e044a370a4a02e4f54b409ed1192f4a7e --- test/test_ops.py | 10 ++++--- torchvision/csrc/ROIAlign.h | 35 +++++++++++++++--------- torchvision/csrc/cpu/ROIAlign_cpu.cpp | 37 +++++++++++++++----------- torchvision/csrc/cpu/vision_cpu.h | 6 +++-- torchvision/csrc/cuda/ROIAlign_cuda.cu | 33 +++++++++++++++-------- torchvision/csrc/cuda/vision_cuda.h | 6 +++-- torchvision/csrc/vision.cpp | 2 +- torchvision/ops/roi_align.py | 15 +++++++---- 8 files changed, 92 insertions(+), 52 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index 42056d421ea..e6d681898c0 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -217,9 +217,9 @@ def bilinear_interpolate(data, y, x, snap_border=False): class RoIAlignTester(RoIOpTester, unittest.TestCase): - def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwargs): + def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, aligned=False, **kwargs): return ops.RoIAlign((pool_h, pool_w), spatial_scale=spatial_scale, - sampling_ratio=sampling_ratio)(x, rois) + sampling_ratio=sampling_ratio, aligned=aligned)(x, rois) def get_script_fn(self, rois, pool_size): @torch.jit.script @@ -228,16 +228,18 @@ def script_fn(input, rois, pool_size): return ops.roi_align(input, rois, pool_size, 1.0)[0] return lambda x: script_fn(x, rois, pool_size) - def expected_fn(self, in_data, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, + def expected_fn(self, in_data, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, aligned=False, device=None, dtype=torch.float64): if device is None: device = torch.device("cpu") n_channels = in_data.size(1) out_data = torch.zeros(rois.size(0), n_channels, pool_h, pool_w, dtype=dtype, device=device) + offset = 0.5 if aligned else 0. + for r, roi in enumerate(rois): batch_idx = int(roi[0]) - j_begin, i_begin, j_end, i_end = (x.item() * spatial_scale for x in roi[1:]) + j_begin, i_begin, j_end, i_end = (x.item() * spatial_scale - offset for x in roi[1:]) roi_h = i_end - i_begin roi_w = j_end - j_begin diff --git a/torchvision/csrc/ROIAlign.h b/torchvision/csrc/ROIAlign.h index 765d4879d99..e292da9a033 100644 --- a/torchvision/csrc/ROIAlign.h +++ b/torchvision/csrc/ROIAlign.h @@ -14,7 +14,8 @@ at::Tensor ROIAlign_forward( // scaled to this. const int64_t pooled_height, // The height of the pooled feature map. const int64_t pooled_width, // The width of the pooled feature - const int64_t sampling_ratio) // The number of points to sample in each bin + const int64_t sampling_ratio, // The number of points to sample in each bin + const bool aligned) // The flag for pixel shift // along each axis. { if (input.type().is_cuda()) { @@ -25,13 +26,14 @@ at::Tensor ROIAlign_forward( spatial_scale, pooled_height, pooled_width, - sampling_ratio); + sampling_ratio, + aligned); #else AT_ERROR("Not compiled with GPU support"); #endif } return ROIAlign_forward_cpu( - input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio); + input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio, aligned); } at::Tensor ROIAlign_backward( @@ -44,7 +46,8 @@ at::Tensor ROIAlign_backward( const int channels, const int height, const int width, - const int sampling_ratio) { + const int sampling_ratio, + const bool aligned) { if (grad.type().is_cuda()) { #ifdef WITH_CUDA return ROIAlign_backward_cuda( @@ -57,7 +60,8 @@ at::Tensor ROIAlign_backward( channels, height, width, - sampling_ratio); + sampling_ratio, + aligned); #else AT_ERROR("Not compiled with GPU support"); #endif @@ -72,7 +76,8 @@ at::Tensor ROIAlign_backward( channels, height, width, - sampling_ratio); + sampling_ratio, + aligned); } using namespace at; @@ -90,11 +95,13 @@ class ROIAlignFunction : public torch::autograd::Function { const double spatial_scale, const int64_t pooled_height, const int64_t pooled_width, - const int64_t sampling_ratio) { + const int64_t sampling_ratio, + const bool aligned) { ctx->saved_data["spatial_scale"] = spatial_scale; ctx->saved_data["pooled_height"] = pooled_height; ctx->saved_data["pooled_width"] = pooled_width; ctx->saved_data["sampling_ratio"] = sampling_ratio; + ctx->saved_data["aligned"] = aligned; ctx->saved_data["input_shape"] = input.sizes(); ctx->save_for_backward({rois}); auto result = ROIAlign_forward( @@ -103,7 +110,8 @@ class ROIAlignFunction : public torch::autograd::Function { spatial_scale, pooled_height, pooled_width, - sampling_ratio); + sampling_ratio, + aligned); return {result}; } @@ -124,9 +132,10 @@ class ROIAlignFunction : public torch::autograd::Function { input_shape[1], input_shape[2], input_shape[3], - ctx->saved_data["sampling_ratio"].toInt()); + ctx->saved_data["sampling_ratio"].toInt(), + ctx->saved_data["aligned"].toBool()); return { - grad_in, Variable(), Variable(), Variable(), Variable(), Variable()}; + grad_in, Variable(), Variable(), Variable(), Variable(), Variable(), Variable()}; } }; @@ -136,12 +145,14 @@ Tensor roi_align( const double spatial_scale, const int64_t pooled_height, const int64_t pooled_width, - const int64_t sampling_ratio) { + const int64_t sampling_ratio, + const bool aligned) { return ROIAlignFunction::apply( input, rois, spatial_scale, pooled_height, pooled_width, - sampling_ratio)[0]; + sampling_ratio, + aligned)[0]; } diff --git a/torchvision/csrc/cpu/ROIAlign_cpu.cpp b/torchvision/csrc/cpu/ROIAlign_cpu.cpp index 0b8f8a490fc..87453b84dd4 100644 --- a/torchvision/csrc/cpu/ROIAlign_cpu.cpp +++ b/torchvision/csrc/cpu/ROIAlign_cpu.cpp @@ -121,6 +121,7 @@ void ROIAlignForward( const int pooled_height, const int pooled_width, const int sampling_ratio, + const bool aligned, const T* rois, T* output) { int n_rois = nthreads / channels / pooled_width / pooled_height; @@ -134,18 +135,16 @@ void ROIAlignForward( int roi_batch_ind = offset_rois[0]; // Do not using rounding; this implementation detail is critical - T roi_start_w = offset_rois[1] * spatial_scale; - T roi_start_h = offset_rois[2] * spatial_scale; - T roi_end_w = offset_rois[3] * spatial_scale; - T roi_end_h = offset_rois[4] * spatial_scale; - // T roi_start_w = round(offset_rois[0] * spatial_scale); - // T roi_start_h = round(offset_rois[1] * spatial_scale); - // T roi_end_w = round(offset_rois[2] * spatial_scale); - // T roi_end_h = round(offset_rois[3] * spatial_scale); + T offset = aligned ? (T)0.5 : (T)0.0; + T roi_start_w = offset_rois[1] * spatial_scale - offset; + T roi_start_h = offset_rois[2] * spatial_scale - offset; + T roi_end_w = offset_rois[3] * spatial_scale - offset; + T roi_end_h = offset_rois[4] * spatial_scale - offset; // Force malformed ROIs to be 1x1 T roi_width = std::max(roi_end_w - roi_start_w, (T)1.); T roi_height = std::max(roi_end_h - roi_start_h, (T)1.); + T bin_size_h = static_cast(roi_height) / static_cast(pooled_height); T bin_size_w = static_cast(roi_width) / static_cast(pooled_width); @@ -157,7 +156,8 @@ void ROIAlignForward( (sampling_ratio > 0) ? sampling_ratio : ceil(roi_width / pooled_width); // We do average (integral) pooling inside a bin - const T count = roi_bin_grid_h * roi_bin_grid_w; // e.g. = 4 + // When the grid is empty, output zeros. + const T count = std::max(roi_bin_grid_h * roi_bin_grid_w, 1); // e.g. = 4 // we want to precalculate indeces and weights shared by all chanels, // this is the key point of optimiation @@ -285,6 +285,7 @@ void ROIAlignBackward( const int pooled_height, const int pooled_width, const int sampling_ratio, + const bool aligned, T* grad_input, const T* rois, const int n_stride, @@ -302,14 +303,16 @@ void ROIAlignBackward( int roi_batch_ind = offset_rois[0]; // Do not using rounding; this implementation detail is critical - T roi_start_w = offset_rois[1] * spatial_scale; - T roi_start_h = offset_rois[2] * spatial_scale; - T roi_end_w = offset_rois[3] * spatial_scale; - T roi_end_h = offset_rois[4] * spatial_scale; + T offset = aligned ? (T)0.5 : (T)0.0; + T roi_start_w = offset_rois[1] * spatial_scale - offset; + T roi_start_h = offset_rois[2] * spatial_scale - offset; + T roi_end_w = offset_rois[3] * spatial_scale - offset; + T roi_end_h = offset_rois[4] * spatial_scale - offset; // Force malformed ROIs to be 1x1 T roi_width = std::max(roi_end_w - roi_start_w, (T)1.); T roi_height = std::max(roi_end_h - roi_start_h, (T)1.); + T bin_size_h = static_cast(roi_height) / static_cast(pooled_height); T bin_size_w = static_cast(roi_width) / static_cast(pooled_width); @@ -381,7 +384,8 @@ at::Tensor ROIAlign_forward_cpu( const float spatial_scale, const int pooled_height, const int pooled_width, - const int sampling_ratio) { + const int sampling_ratio, + const bool aligned) { AT_ASSERTM(input.device().is_cpu(), "input must be a CPU tensor"); AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); @@ -414,6 +418,7 @@ at::Tensor ROIAlign_forward_cpu( pooled_height, pooled_width, sampling_ratio, + aligned, rois.contiguous().data_ptr(), output.data_ptr()); }); @@ -430,7 +435,8 @@ at::Tensor ROIAlign_backward_cpu( const int channels, const int height, const int width, - const int sampling_ratio) { + const int sampling_ratio, + const bool aligned) { AT_ASSERTM(grad.device().is_cpu(), "grad must be a CPU tensor"); AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); @@ -464,6 +470,7 @@ at::Tensor ROIAlign_backward_cpu( pooled_height, pooled_width, sampling_ratio, + aligned, grad_input.data_ptr(), rois.contiguous().data_ptr(), n_stride, diff --git a/torchvision/csrc/cpu/vision_cpu.h b/torchvision/csrc/cpu/vision_cpu.h index b133c9ff1a3..d81a51a59c4 100644 --- a/torchvision/csrc/cpu/vision_cpu.h +++ b/torchvision/csrc/cpu/vision_cpu.h @@ -26,7 +26,8 @@ at::Tensor ROIAlign_forward_cpu( const float spatial_scale, const int pooled_height, const int pooled_width, - const int sampling_ratio); + const int sampling_ratio, + const bool aligned); at::Tensor ROIAlign_backward_cpu( const at::Tensor& grad, @@ -38,7 +39,8 @@ at::Tensor ROIAlign_backward_cpu( const int channels, const int height, const int width, - const int sampling_ratio); + const int sampling_ratio, + const bool aligned); std::tuple PSROIPool_forward_cpu( const at::Tensor& input, diff --git a/torchvision/csrc/cuda/ROIAlign_cuda.cu b/torchvision/csrc/cuda/ROIAlign_cuda.cu index bafe0b2e6c0..3098414dd7e 100644 --- a/torchvision/csrc/cuda/ROIAlign_cuda.cu +++ b/torchvision/csrc/cuda/ROIAlign_cuda.cu @@ -71,6 +71,7 @@ __global__ void RoIAlignForward( const int pooled_height, const int pooled_width, const int sampling_ratio, + const bool aligned, const T* rois, T* output) { CUDA_1D_KERNEL_LOOP(index, nthreads) { @@ -84,14 +85,16 @@ __global__ void RoIAlignForward( int roi_batch_ind = offset_rois[0]; // Do not using rounding; this implementation detail is critical - T roi_start_w = offset_rois[1] * spatial_scale; - T roi_start_h = offset_rois[2] * spatial_scale; - T roi_end_w = offset_rois[3] * spatial_scale; - T roi_end_h = offset_rois[4] * spatial_scale; + T offset = aligned ? (T)0.5 : (T)0.0; + T roi_start_w = offset_rois[1] * spatial_scale - offset; + T roi_start_h = offset_rois[2] * spatial_scale - offset; + T roi_end_w = offset_rois[3] * spatial_scale - offset; + T roi_end_h = offset_rois[4] * spatial_scale - offset; // Force malformed ROIs to be 1x1 T roi_width = max(roi_end_w - roi_start_w, (T)1.); T roi_height = max(roi_end_h - roi_start_h, (T)1.); + T bin_size_h = static_cast(roi_height) / static_cast(pooled_height); T bin_size_w = static_cast(roi_width) / static_cast(pooled_width); @@ -106,7 +109,8 @@ __global__ void RoIAlignForward( (sampling_ratio > 0) ? sampling_ratio : ceil(roi_width / pooled_width); // We do average (integral) pooling inside a bin - const T count = roi_bin_grid_h * roi_bin_grid_w; // e.g. = 4 + // When the grid is empty, output zeros. + const T count = max(roi_bin_grid_h * roi_bin_grid_w, 1); // e.g. = 4 T output_val = 0.; for (int iy = 0; iy < roi_bin_grid_h; iy++) // e.g., iy = 0, 1 @@ -201,6 +205,7 @@ __global__ void RoIAlignBackward( const int pooled_height, const int pooled_width, const int sampling_ratio, + const bool aligned, T* grad_input, const T* rois, const int n_stride, @@ -218,14 +223,16 @@ __global__ void RoIAlignBackward( int roi_batch_ind = offset_rois[0]; // Do not using rounding; this implementation detail is critical - T roi_start_w = offset_rois[1] * spatial_scale; - T roi_start_h = offset_rois[2] * spatial_scale; - T roi_end_w = offset_rois[3] * spatial_scale; - T roi_end_h = offset_rois[4] * spatial_scale; + T offset = aligned ? (T)0.5 : (T)0.0; + T roi_start_w = offset_rois[1] * spatial_scale - offset; + T roi_start_h = offset_rois[2] * spatial_scale - offset; + T roi_end_w = offset_rois[3] * spatial_scale - offset; + T roi_end_h = offset_rois[4] * spatial_scale - offset; // Force malformed ROIs to be 1x1 T roi_width = max(roi_end_w - roi_start_w, (T)1.); T roi_height = max(roi_end_h - roi_start_h, (T)1.); + T bin_size_h = static_cast(roi_height) / static_cast(pooled_height); T bin_size_w = static_cast(roi_width) / static_cast(pooled_width); @@ -303,7 +310,8 @@ at::Tensor ROIAlign_forward_cuda( const float spatial_scale, const int pooled_height, const int pooled_width, - const int sampling_ratio) { + const int sampling_ratio, + const bool aligned) { AT_ASSERTM(input.device().is_cuda(), "input must be a CUDA tensor"); AT_ASSERTM(rois.device().is_cuda(), "rois must be a CUDA tensor"); @@ -348,6 +356,7 @@ at::Tensor ROIAlign_forward_cuda( pooled_height, pooled_width, sampling_ratio, + aligned, rois.contiguous().data_ptr(), output.data_ptr()); }); @@ -365,7 +374,8 @@ at::Tensor ROIAlign_backward_cuda( const int channels, const int height, const int width, - const int sampling_ratio) { + const int sampling_ratio, + const bool aligned) { AT_ASSERTM(grad.device().is_cuda(), "grad must be a CUDA tensor"); AT_ASSERTM(rois.device().is_cuda(), "rois must be a CUDA tensor"); @@ -410,6 +420,7 @@ at::Tensor ROIAlign_backward_cuda( pooled_height, pooled_width, sampling_ratio, + aligned, grad_input.data_ptr(), rois.contiguous().data_ptr(), n_stride, diff --git a/torchvision/csrc/cuda/vision_cuda.h b/torchvision/csrc/cuda/vision_cuda.h index 36e6b3d090b..1a0cb356471 100644 --- a/torchvision/csrc/cuda/vision_cuda.h +++ b/torchvision/csrc/cuda/vision_cuda.h @@ -8,7 +8,8 @@ at::Tensor ROIAlign_forward_cuda( const float spatial_scale, const int pooled_height, const int pooled_width, - const int sampling_ratio); + const int sampling_ratio, + const bool aligned); at::Tensor ROIAlign_backward_cuda( const at::Tensor& grad, @@ -20,7 +21,8 @@ at::Tensor ROIAlign_backward_cuda( const int channels, const int height, const int width, - const int sampling_ratio); + const int sampling_ratio, + const bool aligned); std::tuple ROIPool_forward_cuda( const at::Tensor& input, diff --git a/torchvision/csrc/vision.cpp b/torchvision/csrc/vision.cpp index 8d8699ecc26..ed8d4134831 100644 --- a/torchvision/csrc/vision.cpp +++ b/torchvision/csrc/vision.cpp @@ -42,7 +42,7 @@ int64_t _cuda_version() { static auto registry = torch::RegisterOperators() .op("torchvision::nms", &nms) - .op("torchvision::roi_align(Tensor input, Tensor rois, float spatial_scale, int pooled_height, int pooled_width, int sampling_ratio) -> Tensor", + .op("torchvision::roi_align(Tensor input, Tensor rois, float spatial_scale, int pooled_height, int pooled_width, int sampling_ratio, bool aligned) -> Tensor", &roi_align) .op("torchvision::roi_pool", &roi_pool) .op("torchvision::_new_empty_tensor_op", &new_empty_tensor) diff --git a/torchvision/ops/roi_align.py b/torchvision/ops/roi_align.py index 09ed6e547f4..0e8a978aff0 100644 --- a/torchvision/ops/roi_align.py +++ b/torchvision/ops/roi_align.py @@ -7,8 +7,8 @@ from ._utils import convert_boxes_to_roi_format -def roi_align(input, boxes, output_size, spatial_scale=1.0, sampling_ratio=-1): - # type: (Tensor, Tensor, BroadcastingList2[int], float, int) -> Tensor +def roi_align(input, boxes, output_size, spatial_scale=1.0, sampling_ratio=-1, aligned=False): + # type: (Tensor, Tensor, BroadcastingList2[int], float, int, bool) -> Tensor """ Performs Region of Interest (RoI) Align operator described in Mask R-CNN @@ -28,6 +28,9 @@ def roi_align(input, boxes, output_size, spatial_scale=1.0, sampling_ratio=-1): then exactly sampling_ratio x sampling_ratio grid points are used. If <= 0, then an adaptive number of grid points are used (computed as ceil(roi_width / pooled_w), and likewise for height). Default: -1 + aligned (bool): If False, use the legacy implementation. + If True, pixel shift it by -0.5 for align more perfectly about two neighboring pixel indices. + This version in Detectron2 Returns: output (Tensor[K, C, output_size[0], output_size[1]]) @@ -38,26 +41,28 @@ def roi_align(input, boxes, output_size, spatial_scale=1.0, sampling_ratio=-1): rois = convert_boxes_to_roi_format(rois) return torch.ops.torchvision.roi_align(input, rois, spatial_scale, output_size[0], output_size[1], - sampling_ratio) + sampling_ratio, aligned) class RoIAlign(nn.Module): """ See roi_align """ - def __init__(self, output_size, spatial_scale, sampling_ratio): + def __init__(self, output_size, spatial_scale, sampling_ratio, aligned=False): super(RoIAlign, self).__init__() self.output_size = output_size self.spatial_scale = spatial_scale self.sampling_ratio = sampling_ratio + self.aligned = aligned def forward(self, input, rois): - return roi_align(input, rois, self.output_size, self.spatial_scale, self.sampling_ratio) + return roi_align(input, rois, self.output_size, self.spatial_scale, self.sampling_ratio, self.aligned) def __repr__(self): tmpstr = self.__class__.__name__ + '(' tmpstr += 'output_size=' + str(self.output_size) tmpstr += ', spatial_scale=' + str(self.spatial_scale) tmpstr += ', sampling_ratio=' + str(self.sampling_ratio) + tmpstr += ', aligned=' + str(self.aligned) tmpstr += ')' return tmpstr From 6b56a2d309b9772ac178335034ff3265b4d1882a Mon Sep 17 00:00:00 2001 From: Peter Steinbach Date: Wed, 8 Jul 2020 09:43:49 -0700 Subject: [PATCH 069/357] fix link URL to flickr8k (#2178) (#2414) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2414 Reviewed By: zhangguanheng66 Differential Revision: D22432549 Pulled By: fmassa fbshipit-source-id: f5b1e62bedfd4fef41f93e324fd1470bf69e4f50 --- torchvision/datasets/flickr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/datasets/flickr.py b/torchvision/datasets/flickr.py index af8b1fee36b..2bceb1308a3 100644 --- a/torchvision/datasets/flickr.py +++ b/torchvision/datasets/flickr.py @@ -51,7 +51,7 @@ def handle_data(self, data): class Flickr8k(VisionDataset): - """`Flickr8k Entities `_ Dataset. + """`Flickr8k Entities `_ Dataset. Args: root (string): Root directory where images are downloaded to. From c0e7157d5a2624a0324b9b47af89bcbab6d03f27 Mon Sep 17 00:00:00 2001 From: Shunta Saito Date: Wed, 8 Jul 2020 09:45:21 -0700 Subject: [PATCH 070/357] =?UTF-8?q?Use=20Module=20objects=20instead=20of?= =?UTF-8?q?=20functions=20for=20some=20layers=20of=20Inception3=E2=80=A6?= =?UTF-8?q?=20(#2423)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: … (https://github.com/pytorch/vision/issues/2287) Pull Request resolved: https://github.com/pytorch/vision/pull/2423 Reviewed By: zhangguanheng66 Differential Revision: D22432629 Pulled By: fmassa fbshipit-source-id: 609ad51d4913cb683a22afcaa61c0fe956af0a2d --- torchvision/models/inception.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/torchvision/models/inception.py b/torchvision/models/inception.py index 9da411516d0..1a0ccc01fa1 100644 --- a/torchvision/models/inception.py +++ b/torchvision/models/inception.py @@ -86,8 +86,10 @@ def __init__(self, num_classes=1000, aux_logits=True, transform_input=False, self.Conv2d_1a_3x3 = conv_block(3, 32, kernel_size=3, stride=2) self.Conv2d_2a_3x3 = conv_block(32, 32, kernel_size=3) self.Conv2d_2b_3x3 = conv_block(32, 64, kernel_size=3, padding=1) + self.maxpool1 = nn.MaxPool2d(kernel_size=3, stride=2) self.Conv2d_3b_1x1 = conv_block(64, 80, kernel_size=1) self.Conv2d_4a_3x3 = conv_block(80, 192, kernel_size=3) + self.maxpool2 = nn.MaxPool2d(kernel_size=3, stride=2) self.Mixed_5b = inception_a(192, pool_features=32) self.Mixed_5c = inception_a(256, pool_features=64) self.Mixed_5d = inception_a(288, pool_features=64) @@ -101,6 +103,8 @@ def __init__(self, num_classes=1000, aux_logits=True, transform_input=False, self.Mixed_7a = inception_d(768) self.Mixed_7b = inception_e(1280) self.Mixed_7c = inception_e(2048) + self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) + self.dropout = nn.Dropout() self.fc = nn.Linear(2048, num_classes) for m in self.modules(): @@ -132,13 +136,13 @@ def _forward(self, x): # N x 32 x 147 x 147 x = self.Conv2d_2b_3x3(x) # N x 64 x 147 x 147 - x = F.max_pool2d(x, kernel_size=3, stride=2) + x = self.maxpool1(x) # N x 64 x 73 x 73 x = self.Conv2d_3b_1x1(x) # N x 80 x 73 x 73 x = self.Conv2d_4a_3x3(x) # N x 192 x 71 x 71 - x = F.max_pool2d(x, kernel_size=3, stride=2) + x = self.maxpool2(x) # N x 192 x 35 x 35 x = self.Mixed_5b(x) # N x 256 x 35 x 35 @@ -169,9 +173,9 @@ def _forward(self, x): x = self.Mixed_7c(x) # N x 2048 x 8 x 8 # Adaptive average pooling - x = F.adaptive_avg_pool2d(x, (1, 1)) + x = self.avgpool(x) # N x 2048 x 1 x 1 - x = F.dropout(x, training=self.training) + x = self.dropout(x) # N x 2048 x 1 x 1 x = torch.flatten(x, 1) # N x 2048 From 3f477d15a20c6a7f62f119aa6aae17f567d2a8c8 Mon Sep 17 00:00:00 2001 From: os-gabe <47365564+os-gabe@users.noreply.github.com> Date: Wed, 8 Jul 2020 09:49:38 -0700 Subject: [PATCH 071/357] =?UTF-8?q?Fixes=20#1797=20by=20adding=20an=20init?= =?UTF-8?q?=5Fweights=20keyword=20argument=20to=20Inception3=20=E2=80=A6?= =?UTF-8?q?=20(#2420)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: …(https://github.com/pytorch/vision/issues/1832) Pull Request resolved: https://github.com/pytorch/vision/pull/2420 Reviewed By: zhangguanheng66 Differential Revision: D22432607 Pulled By: fmassa fbshipit-source-id: e87cad1cc6015d05e413bc77cb0feda00d610919 --- torchvision/models/inception.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/torchvision/models/inception.py b/torchvision/models/inception.py index 1a0ccc01fa1..d8b7fec2202 100644 --- a/torchvision/models/inception.py +++ b/torchvision/models/inception.py @@ -65,7 +65,7 @@ def inception_v3(pretrained=False, progress=True, **kwargs): class Inception3(nn.Module): def __init__(self, num_classes=1000, aux_logits=True, transform_input=False, - inception_blocks=None): + inception_blocks=None, init_weights=True): super(Inception3, self).__init__() if inception_blocks is None: inception_blocks = [ @@ -106,19 +106,19 @@ def __init__(self, num_classes=1000, aux_logits=True, transform_input=False, self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) self.dropout = nn.Dropout() self.fc = nn.Linear(2048, num_classes) - - for m in self.modules(): - if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): - import scipy.stats as stats - stddev = m.stddev if hasattr(m, 'stddev') else 0.1 - X = stats.truncnorm(-2, 2, scale=stddev) - values = torch.as_tensor(X.rvs(m.weight.numel()), dtype=m.weight.dtype) - values = values.view(m.weight.size()) - with torch.no_grad(): - m.weight.copy_(values) - elif isinstance(m, nn.BatchNorm2d): - nn.init.constant_(m.weight, 1) - nn.init.constant_(m.bias, 0) + if init_weights: + for m in self.modules(): + if isinstance(m, nn.Conv2d) or isinstance(m, nn.Linear): + import scipy.stats as stats + stddev = m.stddev if hasattr(m, 'stddev') else 0.1 + X = stats.truncnorm(-2, 2, scale=stddev) + values = torch.as_tensor(X.rvs(m.weight.numel()), dtype=m.weight.dtype) + values = values.view(m.weight.size()) + with torch.no_grad(): + m.weight.copy_(values) + elif isinstance(m, nn.BatchNorm2d): + nn.init.constant_(m.weight, 1) + nn.init.constant_(m.bias, 0) def _transform_input(self, x): if self.transform_input: From f0c61cbc79bf7977b25038ba59dbc6d66885c3bf Mon Sep 17 00:00:00 2001 From: Arash Javanmard Date: Wed, 8 Jul 2020 09:57:42 -0700 Subject: [PATCH 072/357] Making ASPP-Layer in DeepLab more generic (#2174) (#2427) Summary: At the moment in the ASPP-Layer the number of output channels are predefined as a constant, which is good for DeepLab but not necessairly in other projects, where another out-channel Nr. is required. Also the number of "atrous rates" is fixed to three, which also could be sometimes more or less depending on the notwork-arch. Again these fixed values may make sense in DeepLab-Model but not necessarily in other type of models. This pull-req. contains the needed changes to make ASPP-Layer generic. Pull Request resolved: https://github.com/pytorch/vision/pull/2427 Reviewed By: zhangguanheng66 Differential Revision: D22432655 Pulled By: fmassa fbshipit-source-id: d8c135807ae35f2d7611898a130642afed101e8d --- torchvision/models/segmentation/deeplabv3.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/torchvision/models/segmentation/deeplabv3.py b/torchvision/models/segmentation/deeplabv3.py index ae652cd7d2a..ee5c0c7fe64 100644 --- a/torchvision/models/segmentation/deeplabv3.py +++ b/torchvision/models/segmentation/deeplabv3.py @@ -63,19 +63,18 @@ def forward(self, x): class ASPP(nn.Module): - def __init__(self, in_channels, atrous_rates): + def __init__(self, in_channels, atrous_rates, out_channels=256): super(ASPP, self).__init__() - out_channels = 256 modules = [] modules.append(nn.Sequential( nn.Conv2d(in_channels, out_channels, 1, bias=False), nn.BatchNorm2d(out_channels), nn.ReLU())) - rate1, rate2, rate3 = tuple(atrous_rates) - modules.append(ASPPConv(in_channels, out_channels, rate1)) - modules.append(ASPPConv(in_channels, out_channels, rate2)) - modules.append(ASPPConv(in_channels, out_channels, rate3)) + rates = tuple(atrous_rates) + for rate in rates: + modules.append(ASPPConv(in_channels, out_channels, rate)) + modules.append(ASPPPooling(in_channels, out_channels)) self.convs = nn.ModuleList(modules) From 70503fa005621fd52b547106613b5b8a78c15442 Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 8 Jul 2020 10:25:52 -0700 Subject: [PATCH 073/357] add comment (#1932) (#2417) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2417 Reviewed By: zhangguanheng66 Differential Revision: D22432594 Pulled By: fmassa fbshipit-source-id: d931e1561b61ace31c1d7bcd3c7b5adc853fd5b2 --- torchvision/models/googlenet.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/torchvision/models/googlenet.py b/torchvision/models/googlenet.py index e0a45cf7e89..a96f903a882 100644 --- a/torchvision/models/googlenet.py +++ b/torchvision/models/googlenet.py @@ -224,6 +224,8 @@ def __init__(self, in_channels, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_pr self.branch3 = nn.Sequential( conv_block(in_channels, ch5x5red, kernel_size=1), + # Here, kernel_size=3 instead of kernel_size=5 is a known bug. + # Please see https://github.com/pytorch/vision/issues/906 for details. conv_block(ch5x5red, ch5x5, kernel_size=3, padding=1) ) From 2eddf2ad74b6f64294859652c131d58781a23f03 Mon Sep 17 00:00:00 2001 From: Lutz Roeder Date: Wed, 8 Jul 2020 10:34:25 -0700 Subject: [PATCH 074/357] Remove 'downsample' constants (#1721) (#1923) (#2419) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2419 Reviewed By: zhangguanheng66 Differential Revision: D22432605 Pulled By: fmassa fbshipit-source-id: f677348d87fb7ee852d158222387313fd26d5dc3 --- torchvision/models/resnet.py | 2 -- torchvision/models/video/resnet.py | 1 - 2 files changed, 3 deletions(-) diff --git a/torchvision/models/resnet.py b/torchvision/models/resnet.py index 527eab8ff05..5291b4003f3 100644 --- a/torchvision/models/resnet.py +++ b/torchvision/models/resnet.py @@ -34,7 +34,6 @@ def conv1x1(in_planes, out_planes, stride=1): class BasicBlock(nn.Module): expansion = 1 - __constants__ = ['downsample'] def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, base_width=64, dilation=1, norm_layer=None): @@ -75,7 +74,6 @@ def forward(self, x): class Bottleneck(nn.Module): expansion = 4 - __constants__ = ['downsample'] def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, base_width=64, dilation=1, norm_layer=None): diff --git a/torchvision/models/video/resnet.py b/torchvision/models/video/resnet.py index 1d01df88425..a9e59a149c0 100644 --- a/torchvision/models/video/resnet.py +++ b/torchvision/models/video/resnet.py @@ -81,7 +81,6 @@ def get_downsample_stride(stride): class BasicBlock(nn.Module): - __constants__ = ['downsample'] expansion = 1 def __init__(self, inplanes, planes, conv_builder, stride=1, downsample=None): From f036ff3bef7334ba363de66ac9195b16135fee40 Mon Sep 17 00:00:00 2001 From: Tee Jung Date: Wed, 8 Jul 2020 10:35:07 -0700 Subject: [PATCH 075/357] bug fix on downloading voc2007 test dataset (#1991) (#2411) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2411 Reviewed By: zhangguanheng66 Differential Revision: D22432523 Pulled By: fmassa fbshipit-source-id: ab3ca9180f9ba1edcc647a9c165580cf1c692a5e --- torchvision/datasets/voc.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/torchvision/datasets/voc.py b/torchvision/datasets/voc.py index 57e885610d7..0a4f7055193 100644 --- a/torchvision/datasets/voc.py +++ b/torchvision/datasets/voc.py @@ -48,6 +48,12 @@ 'filename': 'VOCtrainval_06-Nov-2007.tar', 'md5': 'c52e279531787c972589f7e41ab4ae64', 'base_dir': os.path.join('VOCdevkit', 'VOC2007') + }, + '2007-test': { + 'url': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar', + 'filename': 'VOCtest_06-Nov-2007.tar', + 'md5': 'b6e924de25625d8de591ea690078ad9f', + 'base_dir': os.path.join('VOCdevkit', 'VOC2007') } } @@ -80,11 +86,13 @@ def __init__(self, transforms=None): super(VOCSegmentation, self).__init__(root, transforms, transform, target_transform) self.year = year + if year == "2007" and image_set == "test": + year = "2007-test" self.url = DATASET_YEAR_DICT[year]['url'] self.filename = DATASET_YEAR_DICT[year]['filename'] self.md5 = DATASET_YEAR_DICT[year]['md5'] valid_sets = ["train", "trainval", "val"] - if year == "2007": + if year == "2007-test": valid_sets.append("test") self.image_set = verify_str_arg(image_set, "image_set", valid_sets) base_dir = DATASET_YEAR_DICT[year]['base_dir'] @@ -159,11 +167,13 @@ def __init__(self, transforms=None): super(VOCDetection, self).__init__(root, transforms, transform, target_transform) self.year = year + if year == "2007" and image_set == "test": + year = "2007-test" self.url = DATASET_YEAR_DICT[year]['url'] self.filename = DATASET_YEAR_DICT[year]['filename'] self.md5 = DATASET_YEAR_DICT[year]['md5'] valid_sets = ["train", "trainval", "val"] - if year == "2007": + if year == "2007-test": valid_sets.append("test") self.image_set = verify_str_arg(image_set, "image_set", valid_sets) From de9a2c19bcf17a7987f3a1bce244bbc0bed5ac40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20K=C3=B6sel?= Date: Wed, 8 Jul 2020 10:35:15 -0700 Subject: [PATCH 076/357] Add support for other normalizations in MobileNetV2 (#2267) (#2422) Summary: * Add norm_layer to MobileNetV2 * Add simple test case * Small fix Pull Request resolved: https://github.com/pytorch/vision/pull/2422 Reviewed By: zhangguanheng66 Differential Revision: D22432628 Pulled By: fmassa fbshipit-source-id: f48915ddcabc23df0955caf258ef69f8064bf123 --- test/test_models.py | 12 ++++++++++++ torchvision/models/mobilenet.py | 33 ++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/test/test_models.py b/test/test_models.py index 24b5a8b6b66..b139b84c645 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -2,6 +2,7 @@ from collections import OrderedDict from itertools import product import torch +import torch.nn as nn import numpy as np from torchvision import models import unittest @@ -212,6 +213,17 @@ def test_mobilenetv2_residual_setting(self): out = model(x) self.assertEqual(out.shape[-1], 1000) + def test_mobilenetv2_norm_layer(self): + model = models.__dict__["mobilenet_v2"]() + self.assertTrue(any(isinstance(x, nn.BatchNorm2d) for x in model.modules())) + + def get_gn(num_channels): + return nn.GroupNorm(32, num_channels) + + model = models.__dict__["mobilenet_v2"](norm_layer=get_gn) + self.assertFalse(any(isinstance(x, nn.BatchNorm2d) for x in model.modules())) + self.assertTrue(any(isinstance(x, nn.GroupNorm) for x in model.modules())) + def test_fasterrcnn_double(self): model = models.detection.fasterrcnn_resnet50_fpn(num_classes=50, pretrained_backbone=False) model.double() diff --git a/torchvision/models/mobilenet.py b/torchvision/models/mobilenet.py index 6d10610b633..7c1d5700bf2 100644 --- a/torchvision/models/mobilenet.py +++ b/torchvision/models/mobilenet.py @@ -31,34 +31,39 @@ def _make_divisible(v, divisor, min_value=None): class ConvBNReLU(nn.Sequential): - def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, groups=1): + def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, groups=1, norm_layer=None): padding = (kernel_size - 1) // 2 + if norm_layer is None: + norm_layer = nn.BatchNorm2d super(ConvBNReLU, self).__init__( nn.Conv2d(in_planes, out_planes, kernel_size, stride, padding, groups=groups, bias=False), - nn.BatchNorm2d(out_planes), + norm_layer(out_planes), nn.ReLU6(inplace=True) ) class InvertedResidual(nn.Module): - def __init__(self, inp, oup, stride, expand_ratio): + def __init__(self, inp, oup, stride, expand_ratio, norm_layer=None): super(InvertedResidual, self).__init__() self.stride = stride assert stride in [1, 2] + if norm_layer is None: + norm_layer = nn.BatchNorm2d + hidden_dim = int(round(inp * expand_ratio)) self.use_res_connect = self.stride == 1 and inp == oup layers = [] if expand_ratio != 1: # pw - layers.append(ConvBNReLU(inp, hidden_dim, kernel_size=1)) + layers.append(ConvBNReLU(inp, hidden_dim, kernel_size=1, norm_layer=norm_layer)) layers.extend([ # dw - ConvBNReLU(hidden_dim, hidden_dim, stride=stride, groups=hidden_dim), + ConvBNReLU(hidden_dim, hidden_dim, stride=stride, groups=hidden_dim, norm_layer=norm_layer), # pw-linear nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False), - nn.BatchNorm2d(oup), + norm_layer(oup), ]) self.conv = nn.Sequential(*layers) @@ -75,7 +80,8 @@ def __init__(self, width_mult=1.0, inverted_residual_setting=None, round_nearest=8, - block=None): + block=None, + norm_layer=None): """ MobileNet V2 main class @@ -86,12 +92,17 @@ def __init__(self, round_nearest (int): Round the number of channels in each layer to be a multiple of this number Set to 1 to turn off rounding block: Module specifying inverted residual building block for mobilenet + norm_layer: Module specifying the normalization layer to use """ super(MobileNetV2, self).__init__() if block is None: block = InvertedResidual + + if norm_layer is None: + norm_layer = nn.BatchNorm2d + input_channel = 32 last_channel = 1280 @@ -115,16 +126,16 @@ def __init__(self, # building first layer input_channel = _make_divisible(input_channel * width_mult, round_nearest) self.last_channel = _make_divisible(last_channel * max(1.0, width_mult), round_nearest) - features = [ConvBNReLU(3, input_channel, stride=2)] + features = [ConvBNReLU(3, input_channel, stride=2, norm_layer=norm_layer)] # building inverted residual blocks for t, c, n, s in inverted_residual_setting: output_channel = _make_divisible(c * width_mult, round_nearest) for i in range(n): stride = s if i == 0 else 1 - features.append(block(input_channel, output_channel, stride, expand_ratio=t)) + features.append(block(input_channel, output_channel, stride, expand_ratio=t, norm_layer=norm_layer)) input_channel = output_channel # building last several layers - features.append(ConvBNReLU(input_channel, self.last_channel, kernel_size=1)) + features.append(ConvBNReLU(input_channel, self.last_channel, kernel_size=1, norm_layer=norm_layer)) # make it nn.Sequential self.features = nn.Sequential(*features) @@ -140,7 +151,7 @@ def __init__(self, nn.init.kaiming_normal_(m.weight, mode='fan_out') if m.bias is not None: nn.init.zeros_(m.bias) - elif isinstance(m, nn.BatchNorm2d): + elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)): nn.init.ones_(m.weight) nn.init.zeros_(m.bias) elif isinstance(m, nn.Linear): From c9e838a80415550c7d407e05b94fbe53e46d0414 Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 8 Jul 2020 10:36:29 -0700 Subject: [PATCH 077/357] Remove six dependency (#2017) (#2410) Summary: * remove six from python code * remove six from setup.py * remove six from tests * remove six from references * remove six from packaging * revert str to torch._six._string_classes * revert str to torch._six._string_classes Pull Request resolved: https://github.com/pytorch/vision/pull/2410 Reviewed By: zhangguanheng66 Differential Revision: D22432521 Pulled By: fmassa fbshipit-source-id: 9fa1dcfb9c5da0bbd6d62a07fbcb268e264cd562 --- packaging/torchvision/meta.yaml | 1 - setup.py | 1 - test/common_utils.py | 3 ++- test/test_datasets_utils.py | 3 --- torchvision/datasets/flickr.py | 4 ++-- torchvision/datasets/lsun.py | 4 ++-- torchvision/datasets/sbu.py | 1 - torchvision/datasets/utils.py | 6 ++---- 8 files changed, 8 insertions(+), 15 deletions(-) diff --git a/packaging/torchvision/meta.yaml b/packaging/torchvision/meta.yaml index a97bc429e32..104ce2af846 100644 --- a/packaging/torchvision/meta.yaml +++ b/packaging/torchvision/meta.yaml @@ -20,7 +20,6 @@ requirements: - python - pillow >=4.1.1 - numpy >=1.11 - - six {{ environ.get('CONDA_PYTORCH_CONSTRAINT') }} {{ environ.get('CONDA_CUDATOOLKIT_CONSTRAINT') }} diff --git a/setup.py b/setup.py index 0e5dfc3a18e..e476459d53b 100644 --- a/setup.py +++ b/setup.py @@ -68,7 +68,6 @@ def write_version_file(): requirements = [ 'numpy', - 'six', pytorch_dep, ] diff --git a/test/common_utils.py b/test/common_utils.py index b0a8fbe1c97..9dbd04f4217 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -11,7 +11,7 @@ import __main__ from numbers import Number -from torch._six import string_classes, inf +from torch._six import string_classes from collections import OrderedDict @@ -255,6 +255,7 @@ def assertTensorsEqual(a, b): elif isinstance(x, bool) and isinstance(y, bool): super(TestCase, self).assertEqual(x, y, message) elif isinstance(x, Number) and isinstance(y, Number): + inf = float("inf") if abs(x) == inf or abs(y) == inf: if allow_inf: super(TestCase, self).assertEqual(x, y, message) diff --git a/test/test_datasets_utils.py b/test/test_datasets_utils.py index dadbb99ab92..ec9f7af2961 100644 --- a/test/test_datasets_utils.py +++ b/test/test_datasets_utils.py @@ -7,7 +7,6 @@ import tarfile import gzip import warnings -from torch._six import PY2 from torch._utils_internal import get_file_path_2 from common_utils import get_tmp_dir @@ -41,7 +40,6 @@ def test_check_integrity(self): self.assertTrue(utils.check_integrity(existing_fpath)) self.assertFalse(utils.check_integrity(nonexisting_fpath)) - @unittest.skipIf(PY2, "https://github.com/pytorch/vision/issues/1268") def test_download_url(self): with get_tmp_dir() as temp_dir: url = "http://github.com/pytorch/vision/archive/master.zip" @@ -53,7 +51,6 @@ def test_download_url(self): warnings.warn(msg, RuntimeWarning) raise unittest.SkipTest(msg) - @unittest.skipIf(PY2, "https://github.com/pytorch/vision/issues/1268") def test_download_url_retry_http(self): with get_tmp_dir() as temp_dir: url = "https://github.com/pytorch/vision/archive/master.zip" diff --git a/torchvision/datasets/flickr.py b/torchvision/datasets/flickr.py index 2bceb1308a3..ad4a3295da8 100644 --- a/torchvision/datasets/flickr.py +++ b/torchvision/datasets/flickr.py @@ -1,13 +1,13 @@ from collections import defaultdict from PIL import Image -from six.moves import html_parser +from html.parser import HTMLParser import glob import os from .vision import VisionDataset -class Flickr8kParser(html_parser.HTMLParser): +class Flickr8kParser(HTMLParser): """Parser for extracting captions from the Flickr8k dataset web page.""" def __init__(self, root): diff --git a/torchvision/datasets/lsun.py b/torchvision/datasets/lsun.py index 3b5b5136088..3dae747ef1c 100644 --- a/torchvision/datasets/lsun.py +++ b/torchvision/datasets/lsun.py @@ -2,7 +2,7 @@ from PIL import Image import os import os.path -import six +import io import string import sys @@ -43,7 +43,7 @@ def __getitem__(self, index): with env.begin(write=False) as txn: imgbuf = txn.get(self.keys[index]) - buf = six.BytesIO() + buf = io.BytesIO() buf.write(imgbuf) buf.seek(0) img = Image.open(buf).convert('RGB') diff --git a/torchvision/datasets/sbu.py b/torchvision/datasets/sbu.py index 8be27dbf409..70cb68344bc 100644 --- a/torchvision/datasets/sbu.py +++ b/torchvision/datasets/sbu.py @@ -1,5 +1,4 @@ from PIL import Image -from six.moves import zip from .utils import download_url, check_integrity import os diff --git a/torchvision/datasets/utils.py b/torchvision/datasets/utils.py index aa61237a6d2..527eaaf34a3 100644 --- a/torchvision/datasets/utils.py +++ b/torchvision/datasets/utils.py @@ -8,7 +8,6 @@ import torch from torch.utils.model_zoo import tqdm -from torch._six import PY3 def gen_bar_updater(): @@ -65,7 +64,7 @@ def download_url(url, root, filename=None, md5=None): filename (str, optional): Name to save the file under. If None, use the basename of the URL md5 (str, optional): MD5 checksum of the download. If None, do not check """ - from six.moves import urllib + import urllib root = os.path.expanduser(root) if not filename: @@ -235,8 +234,7 @@ def extract_archive(from_path, to_path=None, remove_finished=False): elif _is_targz(from_path) or _is_tgz(from_path): with tarfile.open(from_path, 'r:gz') as tar: tar.extractall(path=to_path) - elif _is_tarxz(from_path) and PY3: - # .tar.xz archive only supported in Python 3.x + elif _is_tarxz(from_path): with tarfile.open(from_path, 'r:xz') as tar: tar.extractall(path=to_path) elif _is_gzip(from_path): From ef2d3255455e4fa63a58b483bf51688786d60d45 Mon Sep 17 00:00:00 2001 From: moto <855818+mthrok@users.noreply.github.com> Date: Wed, 8 Jul 2020 10:36:54 -0700 Subject: [PATCH 078/357] Add `fcn_resnet50` and `deeplabv3_resnet50` pretrained models. (#2086) (#2426) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2426 Reviewed By: zhangguanheng66 Differential Revision: D22432651 Pulled By: fmassa fbshipit-source-id: 29244e5fb7b40121c72c897c0467dd1e6a1ba295 --- docs/source/models.rst | 6 ++++-- test/test_models.py | 2 ++ torchvision/models/segmentation/segmentation.py | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/source/models.rst b/docs/source/models.rst index e1a141092dc..0ca9b35483d 100644 --- a/docs/source/models.rst +++ b/docs/source/models.rst @@ -228,8 +228,8 @@ Semantic Segmentation The models subpackage contains definitions for the following model architectures for semantic segmentation: -- `FCN ResNet101 `_ -- `DeepLabV3 ResNet101 `_ +- `FCN ResNet50, ResNet101 `_ +- `DeepLabV3 ResNet50, ResNet101 `_ As with image classification models, all pre-trained models expect input images normalized in the same way. The images have to be loaded in to a range of ``[0, 1]`` and then normalized using @@ -252,7 +252,9 @@ The accuracies of the pre-trained models evaluated on COCO val2017 are as follow ================================ ============= ==================== Network mean IoU global pixelwise acc ================================ ============= ==================== +FCN ResNet50 60.5 91.4 FCN ResNet101 63.7 91.9 +DeepLabV3 ResNet50 66.4 92.4 DeepLabV3 ResNet101 67.4 92.4 ================================ ============= ==================== diff --git a/test/test_models.py b/test/test_models.py index b139b84c645..97377d6870d 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -43,9 +43,11 @@ def get_available_video_models(): # before they are compared to the eager model outputs. This is useful if the # model outputs are different between TorchScript / Eager mode script_test_models = { + 'deeplabv3_resnet50': {}, 'deeplabv3_resnet101': {}, 'mobilenet_v2': {}, 'resnext50_32x4d': {}, + 'fcn_resnet50': {}, 'fcn_resnet101': {}, 'googlenet': { 'unwrapper': lambda x: x.logits diff --git a/torchvision/models/segmentation/segmentation.py b/torchvision/models/segmentation/segmentation.py index 15df4d8ae39..158ba5e3d0e 100644 --- a/torchvision/models/segmentation/segmentation.py +++ b/torchvision/models/segmentation/segmentation.py @@ -9,9 +9,9 @@ model_urls = { - 'fcn_resnet50_coco': None, + 'fcn_resnet50_coco': 'https://download.pytorch.org/models/fcn_resnet50_coco-1167a1af.pth', 'fcn_resnet101_coco': 'https://download.pytorch.org/models/fcn_resnet101_coco-7ecb50ca.pth', - 'deeplabv3_resnet50_coco': None, + 'deeplabv3_resnet50_coco': 'https://download.pytorch.org/models/deeplabv3_resnet50_coco-cd0a2569.pth', 'deeplabv3_resnet101_coco': 'https://download.pytorch.org/models/deeplabv3_resnet101_coco-586e9e4e.pth', } From e81b922aa4a418239400093726f08b7bf7988254 Mon Sep 17 00:00:00 2001 From: talcs Date: Wed, 8 Jul 2020 10:39:15 -0700 Subject: [PATCH 079/357] replaced mean on dimensions 2,3 by adaptive_avg_pooling2d (#1838) (#2416) Summary: * replaced mean on dimensions 2,3 by adaptive_avg_pooling2d with destination of 1, to remove hardcoded dimension ordering * replaced reshape command by torch.squeeze after global_avg_pool2d, which is cleaner * reshape rather than squeeze for BS=1 * remove import torch Pull Request resolved: https://github.com/pytorch/vision/pull/2416 Reviewed By: zhangguanheng66 Differential Revision: D22432590 Pulled By: fmassa fbshipit-source-id: a335e8b9342833cfe02702ebea75041f09c4924e --- torchvision/models/mobilenet.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/torchvision/models/mobilenet.py b/torchvision/models/mobilenet.py index 7c1d5700bf2..0359ae34c2d 100644 --- a/torchvision/models/mobilenet.py +++ b/torchvision/models/mobilenet.py @@ -162,7 +162,8 @@ def _forward_impl(self, x): # This exists since TorchScript doesn't support inheritance, so the superclass method # (this one) needs to have a name other than `forward` that can be accessed in a subclass x = self.features(x) - x = x.mean([2, 3]) + # Cannot use "squeeze" as batch-size can be 1 => must use reshape with x.shape[0] + x = nn.functional.adaptive_avg_pool2d(x, 1).reshape(x.shape[0], -1) x = self.classifier(x) return x From 6e6d5b16cd5ccf5c02bd0d0d9ca1434a68d086d6 Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 8 Jul 2020 10:40:44 -0700 Subject: [PATCH 080/357] Fix DatasetFolder error message (#2143) (#2415) Summary: * only display extensions if available * add tests * fix lint Pull Request resolved: https://github.com/pytorch/vision/pull/2415 Reviewed By: zhangguanheng66 Differential Revision: D22432554 Pulled By: fmassa fbshipit-source-id: afe39b08ee24cc6fea4e40999586b2514af5b623 --- test/test_datasets.py | 10 ++++++++++ torchvision/datasets/folder.py | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/test/test_datasets.py b/test/test_datasets.py index 2410f18de09..143838d5c27 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -81,6 +81,16 @@ def test_imagefolder(self): outputs = sorted([dataset[i] for i in range(len(dataset))]) self.assertEqual(imgs, outputs) + def test_imagefolder_empty(self): + with get_tmp_dir() as root: + with self.assertRaises(RuntimeError): + torchvision.datasets.ImageFolder(root, loader=lambda x: x) + + with self.assertRaises(RuntimeError): + torchvision.datasets.ImageFolder( + root, loader=lambda x: x, is_valid_file=lambda x: False + ) + @mock.patch('torchvision.datasets.mnist.download_and_extract_archive') def test_mnist(self, mock_download_extract): num_examples = 30 diff --git a/torchvision/datasets/folder.py b/torchvision/datasets/folder.py index dffa0a9bfc8..e40b40fa5cd 100644 --- a/torchvision/datasets/folder.py +++ b/torchvision/datasets/folder.py @@ -93,8 +93,10 @@ def __init__(self, root, loader, extensions=None, transform=None, classes, class_to_idx = self._find_classes(self.root) samples = make_dataset(self.root, class_to_idx, extensions, is_valid_file) if len(samples) == 0: - raise (RuntimeError("Found 0 files in subfolders of: " + self.root + "\n" - "Supported extensions are: " + ",".join(extensions))) + msg = "Found 0 files in subfolders of: {}\n".format(self.root) + if extensions is not None: + msg += "Supported extensions are: {}".format(",".join(extensions)) + raise RuntimeError(msg) self.loader = loader self.extensions = extensions From 9627194a70b670422ebfb460696c18a3f79f255d Mon Sep 17 00:00:00 2001 From: Ross Wightman Date: Wed, 8 Jul 2020 10:43:40 -0700 Subject: [PATCH 081/357] Fix #2221, DenseNet issue with gradient checkpoints (#2236) (#2421) Summary: * Fix https://github.com/pytorch/vision/issues/2221, DenseNet issue with gradient checkpoints (memory_efficient=True) * Add grad/param count test for mem_efficient densenet Pull Request resolved: https://github.com/pytorch/vision/pull/2421 Reviewed By: zhangguanheng66 Differential Revision: D22432623 Pulled By: fmassa fbshipit-source-id: ff13ea4354199d54178c1e0a0014949f89825e78 --- test/test_models.py | 3 +++ torchvision/models/densenet.py | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/test_models.py b/test/test_models.py index 97377d6870d..056e8eea588 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -184,9 +184,11 @@ def test_memory_efficient_densenet(self): for name in ['densenet121', 'densenet169', 'densenet201', 'densenet161']: model1 = models.__dict__[name](num_classes=50, memory_efficient=True) params = model1.state_dict() + num_params = sum([x.numel() for x in model1.parameters()]) model1.eval() out1 = model1(x) out1.sum().backward() + num_grad = sum([x.grad.numel() for x in model1.parameters() if x.grad is not None]) model2 = models.__dict__[name](num_classes=50, memory_efficient=False) model2.load_state_dict(params) @@ -195,6 +197,7 @@ def test_memory_efficient_densenet(self): max_diff = (out1 - out2).abs().max() + self.assertTrue(num_params == num_grad) self.assertTrue(max_diff < 1e-5) def test_resnet_dilation(self): diff --git a/torchvision/models/densenet.py b/torchvision/models/densenet.py index b58e8b413e1..443fafea0a2 100644 --- a/torchvision/models/densenet.py +++ b/torchvision/models/densenet.py @@ -53,9 +53,9 @@ def any_requires_grad(self, input): def call_checkpoint_bottleneck(self, input): # type: (List[Tensor]) -> Tensor def closure(*inputs): - return self.bn_function(*inputs) + return self.bn_function(inputs) - return cp.checkpoint(closure, input) + return cp.checkpoint(closure, *input) @torch.jit._overload_method # noqa: F811 def forward(self, input): From 5d5efe236b5e80bd9dda6489c1d9b2e7230b77e1 Mon Sep 17 00:00:00 2001 From: dwSun <5899962+dwSun@users.noreply.github.com> Date: Wed, 8 Jul 2020 10:53:58 -0700 Subject: [PATCH 082/357] improve documentation of DatasetFolder and ImageFolder (#2112) (#2409) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2409 Reviewed By: zhangguanheng66 Differential Revision: D22432518 Pulled By: fmassa fbshipit-source-id: 7970c276b52315f7e5fa65a29d02407437af6d1a --- torchvision/datasets/folder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchvision/datasets/folder.py b/torchvision/datasets/folder.py index e40b40fa5cd..3176131d051 100644 --- a/torchvision/datasets/folder.py +++ b/torchvision/datasets/folder.py @@ -80,7 +80,7 @@ class DatasetFolder(VisionDataset): both extensions and is_valid_file should not be passed. Attributes: - classes (list): List of the class names. + classes (list): List of the class names sorted alphabetically. class_to_idx (dict): Dict with items (class_name, class_index). samples (list): List of (sample path, class_index) tuples targets (list): The class_index value for each image in the dataset @@ -198,7 +198,7 @@ class ImageFolder(DatasetFolder): and check if the file is a valid file (used to check of corrupt files) Attributes: - classes (list): List of the class names. + classes (list): List of the class names sorted alphabetically. class_to_idx (dict): Dict with items (class_name, class_index). imgs (list): List of (image path, class_index) tuples """ From 446f900dd439702e3663f0412ae0b5d66e5c70ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Fernandes?= Date: Wed, 8 Jul 2020 11:02:39 -0700 Subject: [PATCH 083/357] Force object annotiation to be a list (#1790) (#2406) Summary: * Force object annotiation to be an array * Remove unecessary parentheses * Change object check * Remove check for list * Add test coverage to xml parsing * Tidy up whitespace Pull Request resolved: https://github.com/pytorch/vision/pull/2406 Reviewed By: zhangguanheng66 Differential Revision: D22432460 Pulled By: fmassa fbshipit-source-id: 475e5b62b9dccae085217d56e740b37e32ca9843 --- test/fakedata_generation.py | 12 ++++++++++++ test/test_datasets.py | 29 ++++++++++++++++++++++++++++- torchvision/datasets/voc.py | 2 ++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/test/fakedata_generation.py b/test/fakedata_generation.py index d14bc0c8304..c7d17738a28 100644 --- a/test/fakedata_generation.py +++ b/test/fakedata_generation.py @@ -258,3 +258,15 @@ def _make_mat(file): _make_mat(os.path.join(root, "extra_32x32.mat")) yield root + +@contextlib.contextmanager +def voc_root(): + with get_tmp_dir() as tmp_dir: + voc_dir = os.path.join(tmp_dir, 'VOCdevkit', + 'VOC2012','ImageSets','Main') + os.makedirs(voc_dir) + train_file = os.path.join(voc_dir,'train.txt') + with open(train_file, 'w') as f: + f.write('test') + + yield tmp_dir diff --git a/test/test_datasets.py b/test/test_datasets.py index 143838d5c27..d2fa2d9885f 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -9,7 +9,8 @@ import torchvision from common_utils import get_tmp_dir from fakedata_generation import mnist_root, cifar_root, imagenet_root, \ - cityscapes_root, svhn_root + cityscapes_root, svhn_root, voc_root +import xml.etree.ElementTree as ET try: @@ -220,6 +221,32 @@ def test_svhn(self, mock_check): dataset = torchvision.datasets.SVHN(root, split="extra") self.generic_classification_dataset_test(dataset, num_images=2) + @mock.patch('torchvision.datasets.voc.download_extract') + def test_voc_parse_xml(self, mock_download_extract): + with voc_root() as root: + dataset = torchvision.datasets.VOCDetection(root) + + single_object_xml = """ + + cat + + """ + multiple_object_xml = """ + + cat + + + dog + + """ + single_object_parsed = dataset.parse_voc_xml(ET.fromstring(single_object_xml + )) + multiple_object_parsed = dataset.parse_voc_xml(ET.fromstring(multiple_object_xml)) + + self.assertEqual(single_object_parsed, {'annotation': {'object':[{'name': 'cat'}]}}) + self.assertEqual(multiple_object_parsed, {'annotation': + {'object':[{'name': 'cat'}, {'name': 'dog'}]}}) + if __name__ == '__main__': unittest.main() diff --git a/torchvision/datasets/voc.py b/torchvision/datasets/voc.py index 0a4f7055193..c26a38a3ca5 100644 --- a/torchvision/datasets/voc.py +++ b/torchvision/datasets/voc.py @@ -228,6 +228,8 @@ def parse_voc_xml(self, node): for dc in map(self.parse_voc_xml, children): for ind, v in dc.items(): def_dic[ind].append(v) + if node.tag == 'annotation': + def_dic['object'] = [def_dic['object']] voc_dict = { node.tag: {ind: v[0] if len(v) == 1 else v From 4ace8f8e5610eaf6830dc857c7479b48b71555c9 Mon Sep 17 00:00:00 2001 From: Charles Pao <32415549+Dirtybluer@users.noreply.github.com> Date: Wed, 8 Jul 2020 11:12:18 -0700 Subject: [PATCH 084/357] add comments for the modified implementation of ResNet (#1983) (#2424) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2424 Reviewed By: zhangguanheng66 Differential Revision: D22432635 Pulled By: fmassa fbshipit-source-id: 16fa637f14c4bac61f3705ec2c742a0d9e713596 Co-authored-by: Charles Pao --- torchvision/models/resnet.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/torchvision/models/resnet.py b/torchvision/models/resnet.py index 5291b4003f3..797f459f5cb 100644 --- a/torchvision/models/resnet.py +++ b/torchvision/models/resnet.py @@ -73,6 +73,12 @@ def forward(self, x): class Bottleneck(nn.Module): + # Bottleneck in torchvision places the stride for downsampling at 3x3 convolution(self.conv2) + # while original implementation places the stride at the first 1x1 convolution(self.conv1) + # according to "Deep residual learning for image recognition"https://arxiv.org/abs/1512.03385. + # This variant is also known as ResNet V1.5 and improves accuracy according to + # https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch. + expansion = 4 def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, From e2825e86d6f017d5fe79722093055954645b2b0f Mon Sep 17 00:00:00 2001 From: Yonghye Kwon Date: Wed, 8 Jul 2020 13:34:42 -0700 Subject: [PATCH 085/357] cleanup unused import (#2067) (#2425) Summary: cleanup Pull Request resolved: https://github.com/pytorch/vision/pull/2425 Reviewed By: zhangguanheng66 Differential Revision: D22432639 Pulled By: fmassa fbshipit-source-id: cb457765d50de5f02454a60fc9e048782b081d7c --- torchvision/models/mnasnet.py | 1 - 1 file changed, 1 deletion(-) diff --git a/torchvision/models/mnasnet.py b/torchvision/models/mnasnet.py index 59677427f1e..c2479a828c8 100644 --- a/torchvision/models/mnasnet.py +++ b/torchvision/models/mnasnet.py @@ -1,4 +1,3 @@ -import math import warnings import torch From 23880d473e0bf3a198d0c706198169e61fa2e4bd Mon Sep 17 00:00:00 2001 From: Francis Charette Migneault Date: Thu, 9 Jul 2020 05:48:57 -0700 Subject: [PATCH 086/357] =?UTF-8?q?replace=20torch=201.5.0=20items=20flagg?= =?UTF-8?q?ed=20with=20deprecation=20warnings=20(fix=20#190=E2=80=A6=20(#2?= =?UTF-8?q?435)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: …6) (https://github.com/pytorch/vision/issues/1918) Pull Request resolved: https://github.com/pytorch/vision/pull/2435 Reviewed By: lw Differential Revision: D22438546 Pulled By: fmassa fbshipit-source-id: 8200da87e3459ddaddf089d7d99f4535b5049743 --- torchvision/csrc/models/densenet.cpp | 12 ++++++------ torchvision/csrc/models/googlenet.cpp | 4 ++-- torchvision/csrc/models/googlenet.h | 2 +- torchvision/csrc/models/inception.cpp | 2 +- torchvision/csrc/models/inception.h | 2 +- torchvision/csrc/models/mnasnet.cpp | 20 ++++++++++---------- torchvision/csrc/models/mobilenet.cpp | 8 ++++---- torchvision/csrc/models/resnet.cpp | 10 +++++----- torchvision/csrc/models/resnet.h | 14 +++++++------- torchvision/csrc/models/shufflenetv2.cpp | 14 +++++++------- torchvision/csrc/models/vgg.cpp | 8 ++++---- 11 files changed, 48 insertions(+), 48 deletions(-) diff --git a/torchvision/csrc/models/densenet.cpp b/torchvision/csrc/models/densenet.cpp index 3c83f3ad137..0e3a46e04ff 100644 --- a/torchvision/csrc/models/densenet.cpp +++ b/torchvision/csrc/models/densenet.cpp @@ -15,14 +15,14 @@ struct _DenseLayerImpl : torch::nn::SequentialImpl { int64_t bn_size, double drop_rate) : drop_rate(drop_rate) { - push_back("norm1", torch::nn::BatchNorm(num_input_features)); + push_back("norm1", torch::nn::BatchNorm2d(num_input_features)); push_back("relu1", torch::nn::Functional(modelsimpl::relu_)); push_back( "conv1", torch::nn::Conv2d(Options(num_input_features, bn_size * growth_rate, 1) .stride(1) .bias(false))); - push_back("norm2", torch::nn::BatchNorm(bn_size * growth_rate)); + push_back("norm2", torch::nn::BatchNorm2d(bn_size * growth_rate)); push_back("relu2", torch::nn::Functional(modelsimpl::relu_)); push_back( "conv2", @@ -69,7 +69,7 @@ TORCH_MODULE(_DenseBlock); struct _TransitionImpl : torch::nn::SequentialImpl { _TransitionImpl(int64_t num_input_features, int64_t num_output_features) { - push_back("norm", torch::nn::BatchNorm(num_input_features)); + push_back("norm", torch::nn::BatchNorm2d(num_input_features)); push_back("relu ", torch::nn::Functional(modelsimpl::relu_)); push_back( "conv", @@ -102,7 +102,7 @@ DenseNetImpl::DenseNetImpl( torch::nn::Conv2d( Options(3, num_init_features, 7).stride(2).padding(3).bias(false))); - features->push_back("norm0", torch::nn::BatchNorm(num_init_features)); + features->push_back("norm0", torch::nn::BatchNorm2d(num_init_features)); features->push_back("relu0", torch::nn::Functional(modelsimpl::relu_)); features->push_back( "pool0", torch::nn::Functional(torch::max_pool2d, 3, 2, 1, 1, false)); @@ -125,7 +125,7 @@ DenseNetImpl::DenseNetImpl( } // Final batch norm - features->push_back("norm5", torch::nn::BatchNorm(num_features)); + features->push_back("norm5", torch::nn::BatchNorm2d(num_features)); // Linear layer classifier = torch::nn::Linear(num_features, num_classes); @@ -136,7 +136,7 @@ DenseNetImpl::DenseNetImpl( for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) torch::nn::init::kaiming_normal_(M->weight); - else if (auto M = dynamic_cast(module.get())) { + else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); torch::nn::init::constant_(M->bias, 0); } else if (auto M = dynamic_cast(module.get())) diff --git a/torchvision/csrc/models/googlenet.cpp b/torchvision/csrc/models/googlenet.cpp index 15a4fd6ee2f..14c12ebca5e 100644 --- a/torchvision/csrc/models/googlenet.cpp +++ b/torchvision/csrc/models/googlenet.cpp @@ -11,7 +11,7 @@ namespace _googlenetimpl { BasicConv2dImpl::BasicConv2dImpl(torch::nn::Conv2dOptions options) { options.bias(false); conv = torch::nn::Conv2d(options); - bn = torch::nn::BatchNorm( + bn = torch::nn::BatchNorm2d( torch::nn::BatchNormOptions(options.out_channels()).eps(0.001)); register_module("conv", conv); @@ -155,7 +155,7 @@ void GoogLeNetImpl::_initialize_weights() { else if (auto M = dynamic_cast(module.get())) torch::nn::init::normal_(M->weight); // Note: used instead of truncated // normal initialization - else if (auto M = dynamic_cast(module.get())) { + else if (auto M = dynamic_cast(module.get())) { torch::nn::init::ones_(M->weight); torch::nn::init::zeros_(M->bias); } diff --git a/torchvision/csrc/models/googlenet.h b/torchvision/csrc/models/googlenet.h index 94390fd5070..d466d0c2249 100644 --- a/torchvision/csrc/models/googlenet.h +++ b/torchvision/csrc/models/googlenet.h @@ -10,7 +10,7 @@ namespace models { namespace _googlenetimpl { struct VISION_API BasicConv2dImpl : torch::nn::Module { torch::nn::Conv2d conv{nullptr}; - torch::nn::BatchNorm bn{nullptr}; + torch::nn::BatchNorm2d bn{nullptr}; BasicConv2dImpl(torch::nn::Conv2dOptions options); diff --git a/torchvision/csrc/models/inception.cpp b/torchvision/csrc/models/inception.cpp index 1c5b7bbe1f7..625de5c4ab2 100644 --- a/torchvision/csrc/models/inception.cpp +++ b/torchvision/csrc/models/inception.cpp @@ -11,7 +11,7 @@ BasicConv2dImpl::BasicConv2dImpl( double std_dev) { options.bias(false); conv = torch::nn::Conv2d(options); - bn = torch::nn::BatchNorm( + bn = torch::nn::BatchNorm2d( torch::nn::BatchNormOptions(options.out_channels()).eps(0.001)); register_module("conv", conv); diff --git a/torchvision/csrc/models/inception.h b/torchvision/csrc/models/inception.h index d4edcbadd47..46c224752cd 100644 --- a/torchvision/csrc/models/inception.h +++ b/torchvision/csrc/models/inception.h @@ -9,7 +9,7 @@ namespace models { namespace _inceptionimpl { struct VISION_API BasicConv2dImpl : torch::nn::Module { torch::nn::Conv2d conv{nullptr}; - torch::nn::BatchNorm bn{nullptr}; + torch::nn::BatchNorm2d bn{nullptr}; BasicConv2dImpl(torch::nn::Conv2dOptions options, double std_dev = 0.1); diff --git a/torchvision/csrc/models/mnasnet.cpp b/torchvision/csrc/models/mnasnet.cpp index c6373f78999..3b08643f1f5 100644 --- a/torchvision/csrc/models/mnasnet.cpp +++ b/torchvision/csrc/models/mnasnet.cpp @@ -24,7 +24,7 @@ struct MNASNetInvertedResidualImpl : torch::nn::Module { apply_residual = input == output && stride == 1; layers->push_back(torch::nn::Conv2d(Options(input, mid, 1).bias(false))); - layers->push_back(torch::nn::BatchNorm( + layers->push_back(torch::nn::BatchNorm2d( torch::nn::BatchNormOptions(mid).momentum(bn_momentum))); layers->push_back( torch::nn::Functional(torch::nn::Functional(modelsimpl::relu_))); @@ -34,12 +34,12 @@ struct MNASNetInvertedResidualImpl : torch::nn::Module { .stride(stride) .groups(mid) .bias(false)))); - layers->push_back(torch::nn::BatchNorm( + layers->push_back(torch::nn::BatchNorm2d( torch::nn::BatchNormOptions(mid).momentum(bn_momentum))); layers->push_back( torch::nn::Functional(torch::nn::Functional(modelsimpl::relu_))); layers->push_back(torch::nn::Conv2d(Options(mid, output, 1).bias(false))); - layers->push_back(torch::nn::BatchNorm( + layers->push_back(torch::nn::BatchNorm2d( torch::nn::BatchNormOptions(output).momentum(bn_momentum))); register_module("layers", layers); @@ -109,9 +109,9 @@ void MNASNetImpl::_initialize_weights() { torch::nn::init::kaiming_normal_( M->weight, 0, - torch::nn::init::FanMode::FanOut, - torch::nn::init::Nonlinearity::ReLU); - else if (auto M = dynamic_cast(module.get())) { + torch::kFanOut, + torch::kReLU); + else if (auto M = dynamic_cast(module.get())) { torch::nn::init::ones_(M->weight); torch::nn::init::zeros_(M->bias); } else if (auto M = dynamic_cast(module.get())) { @@ -128,17 +128,17 @@ MNASNetImpl::MNASNetImpl(double alpha, int64_t num_classes, double dropout) { layers->push_back( torch::nn::Conv2d(Options(3, 32, 3).padding(1).stride(2).bias(false))); - layers->push_back(torch::nn::BatchNorm( + layers->push_back(torch::nn::BatchNorm2d( torch::nn::BatchNormOptions(32).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); layers->push_back(torch::nn::Conv2d( Options(32, 32, 3).padding(1).stride(1).groups(32).bias(false))); - layers->push_back(torch::nn::BatchNorm( + layers->push_back(torch::nn::BatchNorm2d( torch::nn::BatchNormOptions(32).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); layers->push_back( torch::nn::Conv2d(Options(32, 16, 1).padding(0).stride(1).bias(false))); - layers->push_back(torch::nn::BatchNorm( + layers->push_back(torch::nn::BatchNorm2d( torch::nn::BatchNormOptions(16).momentum(BN_MOMENTUM))); layers->push_back(stack(16, depths[0], 3, 2, 3, 3, BN_MOMENTUM)); @@ -150,7 +150,7 @@ MNASNetImpl::MNASNetImpl(double alpha, int64_t num_classes, double dropout) { layers->push_back(torch::nn::Conv2d( Options(depths[5], 1280, 1).padding(0).stride(1).bias(false))); - layers->push_back(torch::nn::BatchNorm( + layers->push_back(torch::nn::BatchNorm2d( torch::nn::BatchNormOptions(1280).momentum(BN_MOMENTUM))); layers->push_back(torch::nn::Functional(modelsimpl::relu_)); diff --git a/torchvision/csrc/models/mobilenet.cpp b/torchvision/csrc/models/mobilenet.cpp index ad5aaf3c997..4a989e77855 100644 --- a/torchvision/csrc/models/mobilenet.cpp +++ b/torchvision/csrc/models/mobilenet.cpp @@ -33,7 +33,7 @@ struct ConvBNReLUImpl : torch::nn::SequentialImpl { .padding(padding) .groups(groups) .bias(false))); - push_back(torch::nn::BatchNorm(out_planes)); + push_back(torch::nn::BatchNorm2d(out_planes)); push_back(torch::nn::Functional(modelsimpl::relu6_)); } @@ -68,7 +68,7 @@ struct MobileNetInvertedResidualImpl : torch::nn::Module { conv->push_back(ConvBNReLU(hidden_dim, hidden_dim, 3, stride, hidden_dim)); conv->push_back(torch::nn::Conv2d( Options(hidden_dim, output, 1).stride(1).padding(0).bias(false))); - conv->push_back(torch::nn::BatchNorm(output)); + conv->push_back(torch::nn::BatchNorm2d(output)); register_module("conv", conv); } @@ -135,10 +135,10 @@ MobileNetV2Impl::MobileNetV2Impl( for (auto& module : modules(/*include_self=*/false)) { if (auto M = dynamic_cast(module.get())) { torch::nn::init::kaiming_normal_( - M->weight, 0, torch::nn::init::FanMode::FanOut); + M->weight, 0, torch::kFanOut); if (M->options.bias()) torch::nn::init::zeros_(M->bias); - } else if (auto M = dynamic_cast(module.get())) { + } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::ones_(M->weight); torch::nn::init::zeros_(M->bias); } else if (auto M = dynamic_cast(module.get())) { diff --git a/torchvision/csrc/models/resnet.cpp b/torchvision/csrc/models/resnet.cpp index 2be172ca03e..ce9e95ecf6f 100644 --- a/torchvision/csrc/models/resnet.cpp +++ b/torchvision/csrc/models/resnet.cpp @@ -40,8 +40,8 @@ BasicBlock::BasicBlock( conv1 = conv3x3(inplanes, planes, stride); conv2 = conv3x3(planes, planes); - bn1 = torch::nn::BatchNorm(planes); - bn2 = torch::nn::BatchNorm(planes); + bn1 = torch::nn::BatchNorm2d(planes); + bn2 = torch::nn::BatchNorm2d(planes); register_module("conv1", conv1); register_module("conv2", conv2); @@ -68,9 +68,9 @@ Bottleneck::Bottleneck( conv2 = conv3x3(width, width, stride, groups); conv3 = conv1x1(width, planes * expansion); - bn1 = torch::nn::BatchNorm(width); - bn2 = torch::nn::BatchNorm(width); - bn3 = torch::nn::BatchNorm(planes * expansion); + bn1 = torch::nn::BatchNorm2d(width); + bn2 = torch::nn::BatchNorm2d(width); + bn3 = torch::nn::BatchNorm2d(planes * expansion); register_module("conv1", conv1); register_module("conv2", conv2); diff --git a/torchvision/csrc/models/resnet.h b/torchvision/csrc/models/resnet.h index 5aada26af2f..16a5f183f25 100644 --- a/torchvision/csrc/models/resnet.h +++ b/torchvision/csrc/models/resnet.h @@ -28,7 +28,7 @@ struct VISION_API BasicBlock : torch::nn::Module { torch::nn::Sequential downsample; torch::nn::Conv2d conv1{nullptr}, conv2{nullptr}; - torch::nn::BatchNorm bn1{nullptr}, bn2{nullptr}; + torch::nn::BatchNorm2d bn1{nullptr}, bn2{nullptr}; static int expansion; @@ -51,7 +51,7 @@ struct VISION_API Bottleneck : torch::nn::Module { torch::nn::Sequential downsample; torch::nn::Conv2d conv1{nullptr}, conv2{nullptr}, conv3{nullptr}; - torch::nn::BatchNorm bn1{nullptr}, bn2{nullptr}, bn3{nullptr}; + torch::nn::BatchNorm2d bn1{nullptr}, bn2{nullptr}, bn3{nullptr}; static int expansion; @@ -71,7 +71,7 @@ template struct ResNetImpl : torch::nn::Module { int64_t groups, base_width, inplanes; torch::nn::Conv2d conv1; - torch::nn::BatchNorm bn1; + torch::nn::BatchNorm2d bn1; torch::nn::Sequential layer1, layer2, layer3, layer4; torch::nn::Linear fc; @@ -99,7 +99,7 @@ torch::nn::Sequential ResNetImpl::_make_layer( if (stride != 1 || inplanes != planes * Block::expansion) { downsample = torch::nn::Sequential( _resnetimpl::conv1x1(inplanes, planes * Block::expansion, stride), - torch::nn::BatchNorm(planes * Block::expansion)); + torch::nn::BatchNorm2d(planes * Block::expansion)); } torch::nn::Sequential layers; @@ -146,9 +146,9 @@ ResNetImpl::ResNetImpl( torch::nn::init::kaiming_normal_( M->weight, /*a=*/0, - torch::nn::init::FanMode::FanOut, - torch::nn::init::Nonlinearity::ReLU); - else if (auto M = dynamic_cast(module.get())) { + torch::kFanOut, + torch::kReLU); + else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); torch::nn::init::constant_(M->bias, 0); } diff --git a/torchvision/csrc/models/shufflenetv2.cpp b/torchvision/csrc/models/shufflenetv2.cpp index 658842dd566..2bafec9efc1 100644 --- a/torchvision/csrc/models/shufflenetv2.cpp +++ b/torchvision/csrc/models/shufflenetv2.cpp @@ -49,20 +49,20 @@ struct ShuffleNetV2InvertedResidualImpl : torch::nn::Module { if (stride > 1) { branch1 = torch::nn::Sequential( conv33(inp, inp, stride), - torch::nn::BatchNorm(inp), + torch::nn::BatchNorm2d(inp), conv11(inp, branch_features), - torch::nn::BatchNorm(branch_features), + torch::nn::BatchNorm2d(branch_features), torch::nn::Functional(modelsimpl::relu_)); } branch2 = torch::nn::Sequential( conv11(stride > 1 ? inp : branch_features, branch_features), - torch::nn::BatchNorm(branch_features), + torch::nn::BatchNorm2d(branch_features), torch::nn::Functional(modelsimpl::relu_), conv33(branch_features, branch_features, stride), - torch::nn::BatchNorm(branch_features), + torch::nn::BatchNorm2d(branch_features), conv11(branch_features, branch_features), - torch::nn::BatchNorm(branch_features), + torch::nn::BatchNorm2d(branch_features), torch::nn::Functional(modelsimpl::relu_)); if (!branch1.is_empty()) @@ -108,7 +108,7 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( .stride(2) .padding(1) .bias(false)), - torch::nn::BatchNorm(output_channels), + torch::nn::BatchNorm2d(output_channels), torch::nn::Functional(modelsimpl::relu_)); input_channels = output_channels; @@ -135,7 +135,7 @@ ShuffleNetV2Impl::ShuffleNetV2Impl( .stride(1) .padding(0) .bias(false)), - torch::nn::BatchNorm(output_channels), + torch::nn::BatchNorm2d(output_channels), torch::nn::Functional(modelsimpl::relu_)); fc = torch::nn::Linear(output_channels, num_classes); diff --git a/torchvision/csrc/models/vgg.cpp b/torchvision/csrc/models/vgg.cpp index c3677d6dd60..d33b98e275c 100644 --- a/torchvision/csrc/models/vgg.cpp +++ b/torchvision/csrc/models/vgg.cpp @@ -19,7 +19,7 @@ torch::nn::Sequential makeLayers( torch::nn::Conv2dOptions(channels, V, 3).padding(1))); if (batch_norm) - seq->push_back(torch::nn::BatchNorm(V)); + seq->push_back(torch::nn::BatchNorm2d(V)); seq->push_back(torch::nn::Functional(modelsimpl::relu_)); channels = V; @@ -35,10 +35,10 @@ void VGGImpl::_initialize_weights() { torch::nn::init::kaiming_normal_( M->weight, /*a=*/0, - torch::nn::init::FanMode::FanOut, - torch::nn::init::Nonlinearity::ReLU); + torch::kFanOut, + torch::kReLU); torch::nn::init::constant_(M->bias, 0); - } else if (auto M = dynamic_cast(module.get())) { + } else if (auto M = dynamic_cast(module.get())) { torch::nn::init::constant_(M->weight, 1); torch::nn::init::constant_(M->bias, 0); } else if (auto M = dynamic_cast(module.get())) { From bb779bb7a7ba8236e30ba90e7411adbe7ef59a40 Mon Sep 17 00:00:00 2001 From: Guanheng George Zhang <6156351+zhangguanheng66@users.noreply.github.com> Date: Thu, 9 Jul 2020 11:30:20 -0700 Subject: [PATCH 087/357] Check boxes shape in RoIPool / Align (#1968) (#2429) Summary: * add checkout/assert in roi_pool * add checkout/assert in roi_align * move check_roi_boxes_shape func to ops/_utils.py * add tests * fix CI * fix CI Pull Request resolved: https://github.com/pytorch/vision/pull/2429 Reviewed By: zhangguanheng66 Differential Revision: D22437763 Pulled By: fmassa fbshipit-source-id: 78727f3bfe2514e2c193e2b27d9146693fa800b0 Co-authored-by: Guanheng Zhang --- test/test_ops.py | 28 ++++++++++++++++++++++++++++ torchvision/ops/_utils.py | 12 ++++++++++++ torchvision/ops/ps_roi_align.py | 3 ++- torchvision/ops/ps_roi_pool.py | 3 ++- torchvision/ops/roi_align.py | 3 ++- torchvision/ops/roi_pool.py | 3 ++- 6 files changed, 48 insertions(+), 4 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index e6d681898c0..a683c5c60d6 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -91,6 +91,22 @@ def func(z): self.assertTrue(gradcheck(func, (x,))) self.assertTrue(gradcheck(script_func, (x,))) + def test_boxes_shape(self): + self._test_boxes_shape() + + def _helper_boxes_shape(self, func): + # test boxes as Tensor[N, 5] + with self.assertRaises(AssertionError): + a = torch.linspace(1, 8 * 8, 8 * 8).reshape(1, 1, 8, 8) + boxes = torch.tensor([[0, 0, 3, 3]], dtype=a.dtype) + func(a, boxes, output_size=(2, 2)) + + # test boxes as List[Tensor[N, 4]] + with self.assertRaises(AssertionError): + a = torch.linspace(1, 8 * 8, 8 * 8).reshape(1, 1, 8, 8) + boxes = torch.tensor([[0, 0, 3]], dtype=a.dtype) + ops.roi_pool(a, [boxes], output_size=(2, 2)) + def fn(*args, **kwargs): pass @@ -139,6 +155,9 @@ def get_slice(k, block): y[roi_idx, :, i, j] = bin_x.reshape(n_channels, -1).max(dim=1)[0] return y + def _test_boxes_shape(self): + self._helper_boxes_shape(ops.roi_pool) + class PSRoIPoolTester(RoIOpTester, unittest.TestCase): def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwargs): @@ -183,6 +202,9 @@ def get_slice(k, block): y[roi_idx, c_out, i, j] = t / area return y + def _test_boxes_shape(self): + self._helper_boxes_shape(ops.ps_roi_pool) + def bilinear_interpolate(data, y, x, snap_border=False): height, width = data.shape @@ -266,6 +288,9 @@ def expected_fn(self, in_data, rois, pool_h, pool_w, spatial_scale=1, sampling_r out_data[r, channel, i, j] = val return out_data + def _test_boxes_shape(self): + self._helper_boxes_shape(ops.roi_align) + class PSRoIAlignTester(RoIOpTester, unittest.TestCase): def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwargs): @@ -317,6 +342,9 @@ def expected_fn(self, in_data, rois, pool_h, pool_w, device, spatial_scale=1, out_data[r, c_out, i, j] = val return out_data + def _test_boxes_shape(self): + self._helper_boxes_shape(ops.ps_roi_align) + class NMSTester(unittest.TestCase): def reference_nms(self, boxes, scores, iou_threshold): diff --git a/torchvision/ops/_utils.py b/torchvision/ops/_utils.py index 269abaf7db3..714022f0421 100644 --- a/torchvision/ops/_utils.py +++ b/torchvision/ops/_utils.py @@ -24,3 +24,15 @@ def convert_boxes_to_roi_format(boxes): ids = _cat(temp, dim=0) rois = torch.cat([ids, concat_boxes], dim=1) return rois + + +def check_roi_boxes_shape(boxes): + if isinstance(boxes, list): + for _tensor in boxes: + assert _tensor.size(1) == 4, \ + 'The shape of the tensor in the boxes list is not correct as List[Tensor[L, 4]]' + elif isinstance(boxes, torch.Tensor): + assert boxes.size(1) == 5, 'The boxes tensor shape is not correct as Tensor[K, 5]' + else: + assert False, 'boxes is expected to be a Tensor[L, 5] or a List[Tensor[K, 4]]' + return diff --git a/torchvision/ops/ps_roi_align.py b/torchvision/ops/ps_roi_align.py index 4d265096a67..c0c761b72cc 100644 --- a/torchvision/ops/ps_roi_align.py +++ b/torchvision/ops/ps_roi_align.py @@ -4,7 +4,7 @@ from torch.nn.modules.utils import _pair from torch.jit.annotations import List -from ._utils import convert_boxes_to_roi_format +from ._utils import convert_boxes_to_roi_format, check_roi_boxes_shape def ps_roi_align(input, boxes, output_size, spatial_scale=1.0, sampling_ratio=-1): @@ -33,6 +33,7 @@ def ps_roi_align(input, boxes, output_size, spatial_scale=1.0, sampling_ratio=-1 Returns: output (Tensor[K, C, output_size[0], output_size[1]]) """ + check_roi_boxes_shape(boxes) rois = boxes output_size = _pair(output_size) if not isinstance(rois, torch.Tensor): diff --git a/torchvision/ops/ps_roi_pool.py b/torchvision/ops/ps_roi_pool.py index a033d15fff6..710f2cb0195 100644 --- a/torchvision/ops/ps_roi_pool.py +++ b/torchvision/ops/ps_roi_pool.py @@ -4,7 +4,7 @@ from torch.nn.modules.utils import _pair from torch.jit.annotations import List -from ._utils import convert_boxes_to_roi_format +from ._utils import convert_boxes_to_roi_format, check_roi_boxes_shape def ps_roi_pool(input, boxes, output_size, spatial_scale=1.0): @@ -28,6 +28,7 @@ def ps_roi_pool(input, boxes, output_size, spatial_scale=1.0): Returns: output (Tensor[K, C, output_size[0], output_size[1]]) """ + check_roi_boxes_shape(boxes) rois = boxes output_size = _pair(output_size) if not isinstance(rois, torch.Tensor): diff --git a/torchvision/ops/roi_align.py b/torchvision/ops/roi_align.py index 0e8a978aff0..14224d8a83e 100644 --- a/torchvision/ops/roi_align.py +++ b/torchvision/ops/roi_align.py @@ -4,7 +4,7 @@ from torch.nn.modules.utils import _pair from torch.jit.annotations import List, BroadcastingList2 -from ._utils import convert_boxes_to_roi_format +from ._utils import convert_boxes_to_roi_format, check_roi_boxes_shape def roi_align(input, boxes, output_size, spatial_scale=1.0, sampling_ratio=-1, aligned=False): @@ -35,6 +35,7 @@ def roi_align(input, boxes, output_size, spatial_scale=1.0, sampling_ratio=-1, a Returns: output (Tensor[K, C, output_size[0], output_size[1]]) """ + check_roi_boxes_shape(boxes) rois = boxes output_size = _pair(output_size) if not isinstance(rois, torch.Tensor): diff --git a/torchvision/ops/roi_pool.py b/torchvision/ops/roi_pool.py index f94373436db..10232f16b4a 100644 --- a/torchvision/ops/roi_pool.py +++ b/torchvision/ops/roi_pool.py @@ -4,7 +4,7 @@ from torch.nn.modules.utils import _pair from torch.jit.annotations import List, BroadcastingList2 -from ._utils import convert_boxes_to_roi_format +from ._utils import convert_boxes_to_roi_format, check_roi_boxes_shape def roi_pool(input, boxes, output_size, spatial_scale=1.0): @@ -27,6 +27,7 @@ def roi_pool(input, boxes, output_size, spatial_scale=1.0): Returns: output (Tensor[K, C, output_size[0], output_size[1]]) """ + check_roi_boxes_shape(boxes) rois = boxes output_size = _pair(output_size) if not isinstance(rois, torch.Tensor): From 496ed836bdd8d104bd8f1a98a012792482231bfd Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Thu, 9 Jul 2020 11:49:26 -0700 Subject: [PATCH 088/357] Type annotations for torchvision/utils.py (#2034) (#2428) Summary: * type annotations for torchvision/utils.py * add missing annotation for make_grid * fix annotation for save_image * mirror PIL annotation for fp Pull Request resolved: https://github.com/pytorch/vision/pull/2428 Reviewed By: zhangguanheng66 Differential Revision: D22437423 Pulled By: fmassa fbshipit-source-id: 77a46deb22e4fbf4de02f9f7d0e418c656d40a65 --- torchvision/utils.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/torchvision/utils.py b/torchvision/utils.py index 1a773b3fd2e..0572e46c7fb 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -1,10 +1,15 @@ +from typing import Union, Optional, Sequence, Tuple, Text, BinaryIO +import io +import pathlib import torch import math irange = range -def make_grid(tensor, nrow=8, padding=2, - normalize=False, range=None, scale_each=False, pad_value=0): +def make_grid(tensor: Union[torch.Tensor, Sequence[torch.Tensor]], nrow: int = 8, + padding: int = 2, normalize: bool = False, + range: Optional[Tuple[int, int]] = None, scale_each: bool = False, + pad_value: int = 0) -> torch.Tensor: """Make a grid of images. Args: @@ -88,8 +93,9 @@ def norm_range(t, range): return grid -def save_image(tensor, fp, nrow=8, padding=2, - normalize=False, range=None, scale_each=False, pad_value=0, format=None): +def save_image(tensor: Union[torch.Tensor, Sequence[torch.Tensor]], fp: Union[Text, pathlib.Path, BinaryIO], + nrow: int = 8, padding: int = 2, normalize: bool = False, range: Optional[Tuple[int, int]] = None, + scale_each: bool = False, pad_value: int = 0, format: Optional[str] = None) -> None: """Save a given Tensor into an image file. Args: From 3ea19695be67ea33055c0f6f3746ee2ed5e83a63 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Thu, 9 Jul 2020 12:50:01 -0700 Subject: [PATCH 089/357] Fix wrong clamping in RoIAlign with aligned=True (#2438) (#2445) Summary: * Fix wrong clamping in RoIAlign with aligned=True * Fix silly mistake * Bugfix pointed out during code-review Pull Request resolved: https://github.com/pytorch/vision/pull/2445 Reviewed By: zhangguanheng66 Differential Revision: D22458789 Pulled By: fmassa fbshipit-source-id: cbe4d7df64b56b2c0b44c21c3fb155d40c74e057 --- torchvision/csrc/cpu/ROIAlign_cpu.cpp | 20 ++++++++++++++------ torchvision/csrc/cuda/ROIAlign_cuda.cu | 20 ++++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/torchvision/csrc/cpu/ROIAlign_cpu.cpp b/torchvision/csrc/cpu/ROIAlign_cpu.cpp index 87453b84dd4..87766bd68cc 100644 --- a/torchvision/csrc/cpu/ROIAlign_cpu.cpp +++ b/torchvision/csrc/cpu/ROIAlign_cpu.cpp @@ -141,9 +141,13 @@ void ROIAlignForward( T roi_end_w = offset_rois[3] * spatial_scale - offset; T roi_end_h = offset_rois[4] * spatial_scale - offset; - // Force malformed ROIs to be 1x1 - T roi_width = std::max(roi_end_w - roi_start_w, (T)1.); - T roi_height = std::max(roi_end_h - roi_start_h, (T)1.); + T roi_width = roi_end_w - roi_start_w; + T roi_height = roi_end_h - roi_start_h; + if (!aligned) { + // Force malformed ROIs to be 1x1 + roi_width = std::max(roi_width, (T)1.); + roi_height = std::max(roi_height, (T)1.); + } T bin_size_h = static_cast(roi_height) / static_cast(pooled_height); T bin_size_w = static_cast(roi_width) / static_cast(pooled_width); @@ -309,9 +313,13 @@ void ROIAlignBackward( T roi_end_w = offset_rois[3] * spatial_scale - offset; T roi_end_h = offset_rois[4] * spatial_scale - offset; - // Force malformed ROIs to be 1x1 - T roi_width = std::max(roi_end_w - roi_start_w, (T)1.); - T roi_height = std::max(roi_end_h - roi_start_h, (T)1.); + T roi_width = roi_end_w - roi_start_w; + T roi_height = roi_end_h - roi_start_h; + if (!aligned) { + // Force malformed ROIs to be 1x1 + roi_width = std::max(roi_width, (T)1.); + roi_height = std::max(roi_height, (T)1.); + } T bin_size_h = static_cast(roi_height) / static_cast(pooled_height); T bin_size_w = static_cast(roi_width) / static_cast(pooled_width); diff --git a/torchvision/csrc/cuda/ROIAlign_cuda.cu b/torchvision/csrc/cuda/ROIAlign_cuda.cu index 3098414dd7e..4c88ee95c4d 100644 --- a/torchvision/csrc/cuda/ROIAlign_cuda.cu +++ b/torchvision/csrc/cuda/ROIAlign_cuda.cu @@ -91,9 +91,13 @@ __global__ void RoIAlignForward( T roi_end_w = offset_rois[3] * spatial_scale - offset; T roi_end_h = offset_rois[4] * spatial_scale - offset; - // Force malformed ROIs to be 1x1 - T roi_width = max(roi_end_w - roi_start_w, (T)1.); - T roi_height = max(roi_end_h - roi_start_h, (T)1.); + T roi_width = roi_end_w - roi_start_w; + T roi_height = roi_end_h - roi_start_h; + if (!aligned) { + // Force malformed ROIs to be 1x1 + roi_width = max(roi_width, (T)1.); + roi_height = max(roi_height, (T)1.); + } T bin_size_h = static_cast(roi_height) / static_cast(pooled_height); T bin_size_w = static_cast(roi_width) / static_cast(pooled_width); @@ -229,9 +233,13 @@ __global__ void RoIAlignBackward( T roi_end_w = offset_rois[3] * spatial_scale - offset; T roi_end_h = offset_rois[4] * spatial_scale - offset; - // Force malformed ROIs to be 1x1 - T roi_width = max(roi_end_w - roi_start_w, (T)1.); - T roi_height = max(roi_end_h - roi_start_h, (T)1.); + T roi_width = roi_end_w - roi_start_w; + T roi_height = roi_end_h - roi_start_h; + if (!aligned) { + // Force malformed ROIs to be 1x1 + roi_width = max(roi_width, (T)1.); + roi_height = max(roi_height, (T)1.); + } T bin_size_h = static_cast(roi_height) / static_cast(pooled_height); T bin_size_w = static_cast(roi_width) / static_cast(pooled_width); From 72697fd0eb8bf57cd889283fcdad292e8e65b0ee Mon Sep 17 00:00:00 2001 From: Fahri Ali Rahman Date: Thu, 9 Jul 2020 12:58:11 -0700 Subject: [PATCH 090/357] Improve documentation for NMS (#2159) (#2430) Summary: * Improve documentation for NMS * update nms doc for special case Pull Request resolved: https://github.com/pytorch/vision/pull/2430 Reviewed By: zhangguanheng66 Differential Revision: D22437783 Pulled By: fmassa fbshipit-source-id: 7380df421b4574962a4fc433edadf3919cd55a06 --- torchvision/ops/boxes.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index 5f4031e2df0..9cd590d29ac 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -17,6 +17,11 @@ def nms(boxes, scores, iou_threshold): IoU greater than iou_threshold with another (higher scoring) box. + If multiple boxes have the exact same score and satisfy the IoU + criterion with respect to a reference box, the selected box is + not guaranteed to be the same between CPU and GPU. This is similar + to the behavior of argsort in PyTorch when repeated values are present. + Parameters ---------- boxes : Tensor[N, 4]) From ac7604b0fa8261e25ed0df3a5591859b38a191e0 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Thu, 9 Jul 2020 13:11:35 -0700 Subject: [PATCH 091/357] Fix torchscript issue in ConvTranspose2d (#1917) (#2432) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2432 Reviewed By: zhangguanheng66 Differential Revision: D22437817 Pulled By: fmassa fbshipit-source-id: 4358dd941b90eb222d4ad7e211793bf21653be87 --- torchvision/ops/misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/ops/misc.py b/torchvision/ops/misc.py index ccd44b85472..a28e4755239 100644 --- a/torchvision/ops/misc.py +++ b/torchvision/ops/misc.py @@ -43,7 +43,7 @@ def forward(self, x): list(self.output_padding), ) ] - output_shape = [x.shape[0], self.bias.shape[0]] + output_shape + output_shape = [x.shape[0], self.out_channels] + output_shape return _new_empty_tensor(x, output_shape) def super_forward(self, input, output_size=None): From 3e14f2a5f8c5b6ca660d23826dc484d61bf1bce7 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Thu, 9 Jul 2020 13:18:56 -0700 Subject: [PATCH 092/357] Added number of features in FrozenBatchNorm2d __repr__ (#2168) (#2431) Summary: * feat: Added number of features in FrozenBatchNorm2d repr While BatchNorm layers have extensive information in their repr, FrozenBatchNorm2d has one * refactor: Refactored FrozenBatchNorm2d __repr__ * test: Added unittest for FrozenBatchNorm2d __repr__ * style: Removed blank lines in test_ops * refactor: Avoids creating an extra attribute for __repr__ * style: Switched __repr__ to f-string Since support of Python version ealier than 3.6 have been dropped, f-string can be used. * fix: Fixed typo in __repr__ * style: Switched unittest .format to f-string Pull Request resolved: https://github.com/pytorch/vision/pull/2431 Reviewed By: zhangguanheng66 Differential Revision: D22437793 Pulled By: fmassa fbshipit-source-id: 76fd6a42f0b6cabe47c96fcb5a343fe580a0005e --- test/test_ops.py | 10 ++++++++++ torchvision/ops/misc.py | 3 +++ 2 files changed, 13 insertions(+) diff --git a/test/test_ops.py b/test/test_ops.py index a683c5c60d6..cdc8cb0790f 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -530,5 +530,15 @@ def script_func(x_, offset_, weight_, bias_, stride_, pad_, dilation_): (x, offset, weight, bias), nondet_tol=1e-5) +class FrozenBNTester(unittest.TestCase): + def test_frozenbatchnorm2d_repr(self): + num_features = 32 + t = ops.misc.FrozenBatchNorm2d(num_features) + + # Check integrity of object __repr__ attribute + expected_string = f"FrozenBatchNorm2d({num_features})" + self.assertEqual(t.__repr__(), expected_string) + + if __name__ == '__main__': unittest.main() diff --git a/torchvision/ops/misc.py b/torchvision/ops/misc.py index a28e4755239..2dee82b6a29 100644 --- a/torchvision/ops/misc.py +++ b/torchvision/ops/misc.py @@ -177,3 +177,6 @@ def forward(self, x): scale = w * rv.rsqrt() bias = b - rm * scale return x * scale + bias + + def __repr__(self): + return f"{self.__class__.__name__}({self.weight.shape[0]})" From f487ab46cfbb3af21b27e3fd1f5fd452de63ae54 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Thu, 9 Jul 2020 14:03:27 -0700 Subject: [PATCH 093/357] Remove python2 compability code (#2033) (#2434) Summary: * remove sys.version_info == 2 * remove sys.version_info < 3 * remove from __future__ imports Pull Request resolved: https://github.com/pytorch/vision/pull/2434 Reviewed By: zhangguanheng66 Differential Revision: D22438377 Pulled By: fmassa fbshipit-source-id: 89ce27cd2f1bfbff7448a92831ead320784f0b88 --- references/classification/train.py | 11 +++------- .../classification/train_quantization.py | 1 - references/classification/utils.py | 1 - references/detection/utils.py | 2 -- references/segmentation/utils.py | 1 - references/video_classification/train.py | 12 +++-------- references/video_classification/utils.py | 1 - setup.py | 1 - test/fakedata_generation.py | 8 +------ test/test_functional_tensor.py | 1 - test/test_ops.py | 1 - test/test_transforms.py | 1 - test/test_transforms_video.py | 1 - test/test_video_reader.py | 6 +----- torchvision/datasets/caltech.py | 1 - torchvision/datasets/cifar.py | 18 +++------------- torchvision/datasets/lsun.py | 6 +----- torchvision/datasets/mnist.py | 1 - torchvision/datasets/omniglot.py | 1 - torchvision/datasets/semeion.py | 1 - torchvision/datasets/stl10.py | 1 - torchvision/datasets/svhn.py | 1 - torchvision/datasets/usps.py | 1 - torchvision/datasets/voc.py | 8 +------ torchvision/models/detection/_utils.py | 2 -- torchvision/models/detection/image_list.py | 2 -- torchvision/models/detection/roi_heads.py | 1 - torchvision/models/detection/rpn.py | 2 -- torchvision/models/detection/transform.py | 2 -- torchvision/models/googlenet.py | 2 -- torchvision/models/inception.py | 2 -- torchvision/ops/boxes.py | 2 -- torchvision/ops/misc.py | 1 - torchvision/ops/poolers.py | 2 -- torchvision/transforms/functional.py | 1 - torchvision/transforms/transforms.py | 1 - .../run-clang-format/run-clang-format.py | 21 +++---------------- 37 files changed, 16 insertions(+), 112 deletions(-) diff --git a/references/classification/train.py b/references/classification/train.py index 480092a0331..789bb8134ff 100644 --- a/references/classification/train.py +++ b/references/classification/train.py @@ -1,8 +1,6 @@ -from __future__ import print_function import datetime import os import time -import sys import torch import torch.utils.data @@ -141,12 +139,9 @@ def load_data(traindir, valdir, cache_dataset, distributed): def main(args): - if args.apex: - if sys.version_info < (3, 0): - raise RuntimeError("Apex currently only supports Python 3. Aborting.") - if amp is None: - raise RuntimeError("Failed to import apex. Please install apex from https://www.github.com/nvidia/apex " - "to enable mixed-precision training.") + if args.apex and amp is None: + raise RuntimeError("Failed to import apex. Please install apex from https://www.github.com/nvidia/apex " + "to enable mixed-precision training.") if args.output_dir: utils.mkdir(args.output_dir) diff --git a/references/classification/train_quantization.py b/references/classification/train_quantization.py index 22621fe2404..e59b8d4a64e 100644 --- a/references/classification/train_quantization.py +++ b/references/classification/train_quantization.py @@ -1,4 +1,3 @@ -from __future__ import print_function import datetime import os import time diff --git a/references/classification/utils.py b/references/classification/utils.py index 5ea6dfef341..3573b84d780 100644 --- a/references/classification/utils.py +++ b/references/classification/utils.py @@ -1,4 +1,3 @@ -from __future__ import print_function from collections import defaultdict, deque import datetime import time diff --git a/references/detection/utils.py b/references/detection/utils.py index 0e8e8560118..82ae79bc3fb 100644 --- a/references/detection/utils.py +++ b/references/detection/utils.py @@ -1,5 +1,3 @@ -from __future__ import print_function - from collections import defaultdict, deque import datetime import pickle diff --git a/references/segmentation/utils.py b/references/segmentation/utils.py index 2719996c808..d9251b72b9f 100644 --- a/references/segmentation/utils.py +++ b/references/segmentation/utils.py @@ -1,4 +1,3 @@ -from __future__ import print_function from collections import defaultdict, deque import datetime import math diff --git a/references/video_classification/train.py b/references/video_classification/train.py index 67905f83338..e71c03f174f 100644 --- a/references/video_classification/train.py +++ b/references/video_classification/train.py @@ -1,9 +1,6 @@ -from __future__ import print_function import datetime import os import time -import sys - import torch import torch.utils.data from torch.utils.data.dataloader import default_collate @@ -95,12 +92,9 @@ def collate_fn(batch): def main(args): - if args.apex: - if sys.version_info < (3, 0): - raise RuntimeError("Apex currently only supports Python 3. Aborting.") - if amp is None: - raise RuntimeError("Failed to import apex. Please install apex from https://www.github.com/nvidia/apex " - "to enable mixed-precision training.") + if args.apex and amp is None: + raise RuntimeError("Failed to import apex. Please install apex from https://www.github.com/nvidia/apex " + "to enable mixed-precision training.") if args.output_dir: utils.mkdir(args.output_dir) diff --git a/references/video_classification/utils.py b/references/video_classification/utils.py index 5ea6dfef341..3573b84d780 100644 --- a/references/video_classification/utils.py +++ b/references/video_classification/utils.py @@ -1,4 +1,3 @@ -from __future__ import print_function from collections import defaultdict, deque import datetime import time diff --git a/setup.py b/setup.py index e476459d53b..0f7c5676e75 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,3 @@ -from __future__ import print_function import os import io import re diff --git a/test/fakedata_generation.py b/test/fakedata_generation.py index c7d17738a28..dbbe01c06eb 100644 --- a/test/fakedata_generation.py +++ b/test/fakedata_generation.py @@ -1,5 +1,4 @@ import os -import sys import contextlib import tarfile import json @@ -7,12 +6,7 @@ import PIL import torch from common_utils import get_tmp_dir - -PYTHON2 = sys.version_info[0] == 2 -if PYTHON2: - import cPickle as pickle -else: - import pickle +import pickle @contextlib.contextmanager diff --git a/test/test_functional_tensor.py b/test/test_functional_tensor.py index e464bf733a8..ea2f5e55d0b 100644 --- a/test/test_functional_tensor.py +++ b/test/test_functional_tensor.py @@ -1,4 +1,3 @@ -from __future__ import division import torch import torchvision.transforms as transforms import torchvision.transforms.functional_tensor as F_t diff --git a/test/test_ops.py b/test/test_ops.py index cdc8cb0790f..120ecc4de2d 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1,4 +1,3 @@ -from __future__ import division import math import unittest diff --git a/test/test_transforms.py b/test/test_transforms.py index 6eb295d63bf..99317dcc41b 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -1,4 +1,3 @@ -from __future__ import division import os import mock import torch diff --git a/test/test_transforms_video.py b/test/test_transforms_video.py index 296d519f5c4..269a54789ba 100644 --- a/test/test_transforms_video.py +++ b/test/test_transforms_video.py @@ -1,4 +1,3 @@ -from __future__ import division import torch import torchvision.transforms._transforms_video as transforms from torchvision.transforms import Compose diff --git a/test/test_video_reader.py b/test/test_video_reader.py index 70cd9c64843..afdd2362536 100644 --- a/test/test_video_reader.py +++ b/test/test_video_reader.py @@ -1,7 +1,6 @@ import collections import math import os -import sys import time import unittest from fractions import Fraction @@ -22,10 +21,7 @@ av = None -if sys.version_info < (3,): - from urllib2 import URLError -else: - from urllib.error import URLError +from urllib.error import URLError VIDEO_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "videos") diff --git a/torchvision/datasets/caltech.py b/torchvision/datasets/caltech.py index e18349d76a0..ffe2f7faa20 100644 --- a/torchvision/datasets/caltech.py +++ b/torchvision/datasets/caltech.py @@ -1,4 +1,3 @@ -from __future__ import print_function from PIL import Image import os import os.path diff --git a/torchvision/datasets/cifar.py b/torchvision/datasets/cifar.py index 6230a64fa15..127c085cfb2 100644 --- a/torchvision/datasets/cifar.py +++ b/torchvision/datasets/cifar.py @@ -1,14 +1,8 @@ -from __future__ import print_function from PIL import Image import os import os.path import numpy as np -import sys - -if sys.version_info[0] == 2: - import cPickle as pickle -else: - import pickle +import pickle from .vision import VisionDataset from .utils import check_integrity, download_and_extract_archive @@ -79,10 +73,7 @@ def __init__(self, root, train=True, transform=None, target_transform=None, for file_name, checksum in downloaded_list: file_path = os.path.join(self.root, self.base_folder, file_name) with open(file_path, 'rb') as f: - if sys.version_info[0] == 2: - entry = pickle.load(f) - else: - entry = pickle.load(f, encoding='latin1') + entry = pickle.load(f, encoding='latin1') self.data.append(entry['data']) if 'labels' in entry: self.targets.extend(entry['labels']) @@ -100,10 +91,7 @@ def _load_meta(self): raise RuntimeError('Dataset metadata file not found or corrupted.' + ' You can use download=True to download it') with open(path, 'rb') as infile: - if sys.version_info[0] == 2: - data = pickle.load(infile) - else: - data = pickle.load(infile, encoding='latin1') + data = pickle.load(infile, encoding='latin1') self.classes = data[self.meta['key']] self.class_to_idx = {_class: i for i, _class in enumerate(self.classes)} diff --git a/torchvision/datasets/lsun.py b/torchvision/datasets/lsun.py index 3dae747ef1c..ab1997d20e4 100644 --- a/torchvision/datasets/lsun.py +++ b/torchvision/datasets/lsun.py @@ -11,11 +11,7 @@ else: from collections.abc import Iterable -if sys.version_info[0] == 2: - import cPickle as pickle -else: - import pickle - +import pickle from .utils import verify_str_arg, iterable_to_str diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index 66299cd9418..3b9db53a9ff 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -1,4 +1,3 @@ -from __future__ import print_function from .vision import VisionDataset import warnings from PIL import Image diff --git a/torchvision/datasets/omniglot.py b/torchvision/datasets/omniglot.py index 72d5a57e310..dd861284884 100644 --- a/torchvision/datasets/omniglot.py +++ b/torchvision/datasets/omniglot.py @@ -1,4 +1,3 @@ -from __future__ import print_function from PIL import Image from os.path import join import os diff --git a/torchvision/datasets/semeion.py b/torchvision/datasets/semeion.py index b543e21e1b5..12c92c4a35a 100644 --- a/torchvision/datasets/semeion.py +++ b/torchvision/datasets/semeion.py @@ -1,4 +1,3 @@ -from __future__ import print_function from PIL import Image import os import os.path diff --git a/torchvision/datasets/stl10.py b/torchvision/datasets/stl10.py index e01d0b86c45..6bec45afe2b 100644 --- a/torchvision/datasets/stl10.py +++ b/torchvision/datasets/stl10.py @@ -1,4 +1,3 @@ -from __future__ import print_function from PIL import Image import os import os.path diff --git a/torchvision/datasets/svhn.py b/torchvision/datasets/svhn.py index 923db46381a..184c8604748 100644 --- a/torchvision/datasets/svhn.py +++ b/torchvision/datasets/svhn.py @@ -1,4 +1,3 @@ -from __future__ import print_function from .vision import VisionDataset from PIL import Image import os diff --git a/torchvision/datasets/usps.py b/torchvision/datasets/usps.py index 371b2a85e83..ac4ae17b948 100644 --- a/torchvision/datasets/usps.py +++ b/torchvision/datasets/usps.py @@ -1,4 +1,3 @@ -from __future__ import print_function from PIL import Image import os import numpy as np diff --git a/torchvision/datasets/voc.py b/torchvision/datasets/voc.py index c26a38a3ca5..2be53c4fcc6 100644 --- a/torchvision/datasets/voc.py +++ b/torchvision/datasets/voc.py @@ -1,14 +1,8 @@ import os -import sys import tarfile import collections from .vision import VisionDataset - -if sys.version_info[0] == 2: - import xml.etree.cElementTree as ET -else: - import xml.etree.ElementTree as ET - +import xml.etree.ElementTree as ET from PIL import Image from .utils import download_url, check_integrity, verify_str_arg diff --git a/torchvision/models/detection/_utils.py b/torchvision/models/detection/_utils.py index 2d4e6284811..1701dda82bf 100644 --- a/torchvision/models/detection/_utils.py +++ b/torchvision/models/detection/_utils.py @@ -1,5 +1,3 @@ -from __future__ import division - import math import torch diff --git a/torchvision/models/detection/image_list.py b/torchvision/models/detection/image_list.py index ca0f5b20c31..dc8987a9f83 100644 --- a/torchvision/models/detection/image_list.py +++ b/torchvision/models/detection/image_list.py @@ -1,6 +1,4 @@ # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. -from __future__ import division - import torch from torch.jit.annotations import List, Tuple from torch import Tensor diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index d57bb6c138d..48a07a29aae 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -1,4 +1,3 @@ -from __future__ import division import torch import torchvision diff --git a/torchvision/models/detection/rpn.py b/torchvision/models/detection/rpn.py index bfce098d789..aadbf7ef904 100644 --- a/torchvision/models/detection/rpn.py +++ b/torchvision/models/detection/rpn.py @@ -1,5 +1,3 @@ -from __future__ import division - # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. import torch from torch.nn import functional as F diff --git a/torchvision/models/detection/transform.py b/torchvision/models/detection/transform.py index 544387cc6f0..1a3767f6475 100644 --- a/torchvision/models/detection/transform.py +++ b/torchvision/models/detection/transform.py @@ -1,5 +1,3 @@ -from __future__ import division - import random import math import torch diff --git a/torchvision/models/googlenet.py b/torchvision/models/googlenet.py index a96f903a882..7619f49775a 100644 --- a/torchvision/models/googlenet.py +++ b/torchvision/models/googlenet.py @@ -1,5 +1,3 @@ -from __future__ import division - import warnings from collections import namedtuple import torch diff --git a/torchvision/models/inception.py b/torchvision/models/inception.py index d8b7fec2202..4fb6a2fb932 100644 --- a/torchvision/models/inception.py +++ b/torchvision/models/inception.py @@ -1,5 +1,3 @@ -from __future__ import division - from collections import namedtuple import warnings import torch diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index 9cd590d29ac..784a303b60f 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -1,5 +1,3 @@ -from __future__ import division - import torch from torch.jit.annotations import Tuple from torch import Tensor diff --git a/torchvision/ops/misc.py b/torchvision/ops/misc.py index 2dee82b6a29..75b5db554ad 100644 --- a/torchvision/ops/misc.py +++ b/torchvision/ops/misc.py @@ -1,4 +1,3 @@ -from __future__ import division import warnings from collections import OrderedDict from torch.jit.annotations import Optional, List diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index 42698245277..06bbc86a93c 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -1,5 +1,3 @@ -from __future__ import division - # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. import torch import torch.nn.functional as F diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 8f1d12f1509..22e3db794f7 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -1,4 +1,3 @@ -from __future__ import division import torch import sys import math diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 6c74a7acb94..4f9c69a55f1 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -1,4 +1,3 @@ -from __future__ import division import torch import math import sys diff --git a/travis-scripts/run-clang-format/run-clang-format.py b/travis-scripts/run-clang-format/run-clang-format.py index 3f16c833b63..54e193db45b 100755 --- a/travis-scripts/run-clang-format/run-clang-format.py +++ b/travis-scripts/run-clang-format/run-clang-format.py @@ -8,8 +8,6 @@ """ -from __future__ import print_function, unicode_literals - import argparse import codecs import difflib @@ -129,11 +127,6 @@ def run_clang_format_diff(args, file): # > Each translation completely replaces the format string # > for the diagnostic. # > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation - # - # It's not pretty, due to Python 2 & 3 compatibility. - encoding_py3 = {} - if sys.version_info[0] >= 3: - encoding_py3['encoding'] = 'utf-8' try: proc = subprocess.Popen( @@ -141,7 +134,7 @@ def run_clang_format_diff(args, file): stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, - **encoding_py3) + encoding='utf-8') except OSError as exc: raise DiffError( "Command '{}' failed to start: {}".format( @@ -150,12 +143,7 @@ def run_clang_format_diff(args, file): ) proc_stdout = proc.stdout proc_stderr = proc.stderr - if sys.version_info[0] < 3: - # make the pipes compatible with Python 3, - # reading lines should output unicode - encoding = 'utf-8' - proc_stdout = codecs.getreader(encoding)(proc_stdout) - proc_stderr = codecs.getreader(encoding)(proc_stderr) + # hopefully the stderr pipe won't get full and block the process outs = list(proc_stdout.readlines()) errs = list(proc_stderr.readlines()) @@ -203,10 +191,7 @@ def red(s): def print_diff(diff_lines, use_color): if use_color: diff_lines = colorize(diff_lines) - if sys.version_info[0] < 3: - sys.stdout.writelines((l.encode('utf-8') for l in diff_lines)) - else: - sys.stdout.writelines(diff_lines) + sys.stdout.writelines(diff_lines) def print_trouble(prog, message, use_colors): From e83073b33444c87179d34bb22646b4b5bb67a832 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Thu, 9 Jul 2020 14:07:24 -0700 Subject: [PATCH 094/357] =?UTF-8?q?Add=20namespace=20to=20avoid=20conflict?= =?UTF-8?q?=20with=20ATen=20version=20of=20channel=5Fshuffle(=E2=80=A6=20(?= =?UTF-8?q?#2436)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: …). (https://github.com/pytorch/vision/issues/2206) Fix https://github.com/pytorch/vision/issues/2193. Pull Request resolved: https://github.com/pytorch/vision/pull/2436 Reviewed By: zhangguanheng66 Differential Revision: D22438556 Pulled By: fmassa fbshipit-source-id: e5eb446d730551529b86bab6190261b07d94771a --- torchvision/csrc/models/shufflenetv2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/csrc/models/shufflenetv2.cpp b/torchvision/csrc/models/shufflenetv2.cpp index 2bafec9efc1..d84c11de42c 100644 --- a/torchvision/csrc/models/shufflenetv2.cpp +++ b/torchvision/csrc/models/shufflenetv2.cpp @@ -80,7 +80,7 @@ struct ShuffleNetV2InvertedResidualImpl : torch::nn::Module { } else out = torch::cat({branch1->forward(x), branch2->forward(x)}, 1); - out = channel_shuffle(out, 2); + out = ::vision::models::channel_shuffle(out, 2); return out; } }; From 8c92a159af8333f43ae05ba2d28616b78012d95e Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Sat, 25 Jul 2020 13:49:48 -0700 Subject: [PATCH 095/357] add UUID in LOG() in decoder and provider lib Differential Revision: D22743393 fbshipit-source-id: 833fbadc86f3384568b8f1a281294e836d0e187d --- torchvision/csrc/cpu/decoder/decoder.cpp | 61 ++++++++++++++++-------- torchvision/csrc/cpu/decoder/stream.cpp | 25 +++++----- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/torchvision/csrc/cpu/decoder/decoder.cpp b/torchvision/csrc/cpu/decoder/decoder.cpp index e9d1acaa3e0..b62bc40af3c 100644 --- a/torchvision/csrc/cpu/decoder/decoder.cpp +++ b/torchvision/csrc/cpu/decoder/decoder.cpp @@ -1,5 +1,6 @@ #include "decoder.h" #include +#include #include #include #include @@ -149,7 +150,8 @@ bool Decoder::enableLogLevel(int level) const { } void Decoder::logCallback(int level, const std::string& message) { - LOG(INFO) << "Msg, level: " << level << ", msg: " << message; + LOG(INFO) << folly::sformat( + "Msg, uuid={} level={} msg={}", params_.loggingUuid, level, message); } /* static */ @@ -221,8 +223,9 @@ bool Decoder::init( cleanUp(); if ((params.uri.empty() || in) && (!params.uri.empty() || !in)) { - LOG(ERROR) << "Either external URI gets provided" - << " or explicit input callback"; + LOG(ERROR) << folly::sformat( + "uuid={} either external URI gets provided or explicit input callback", + params_.loggingUuid); return false; } @@ -230,7 +233,8 @@ bool Decoder::init( params_ = params; if (!(inputCtx_ = avformat_alloc_context())) { - LOG(ERROR) << "Cannot allocate format context"; + LOG(ERROR) << folly::sformat( + "uuid={} cannot allocate format context", params_.loggingUuid); return false; } @@ -243,7 +247,8 @@ bool Decoder::init( params_.timeoutMs, params_.maxSeekableBytes, params_.isImage ? &type : nullptr)) < 0) { - LOG(ERROR) << "can't initiate seekable buffer"; + LOG(ERROR) << folly::sformat( + "uuid={} can't initiate seekable buffer", params_.loggingUuid); cleanUp(); return false; } @@ -271,8 +276,10 @@ bool Decoder::init( uint8_t* avioCtxBuffer = (uint8_t*)av_malloc(avioCtxBufferSize + kIoPaddingSize); if (!avioCtxBuffer) { - LOG(ERROR) << "av_malloc cannot allocate " << avioCtxBufferSize - << " bytes"; + LOG(ERROR) << folly::sformat( + "uuid={} av_malloc cannot allocate {} bytes", + params_.loggingUuid, + avioCtxBufferSize); cleanUp(); return false; } @@ -285,7 +292,8 @@ bool Decoder::init( &Decoder::readFunction, nullptr, result == 1 ? &Decoder::seekFunction : nullptr))) { - LOG(ERROR) << "avio_alloc_context failed"; + LOG(ERROR) << folly::sformat( + "uuid={} avio_alloc_context failed", params_.loggingUuid); av_free(avioCtxBuffer); cleanUp(); return false; @@ -320,8 +328,10 @@ bool Decoder::init( guard = std::make_unique([&f, this]() { auto timeout = std::chrono::milliseconds(params_.timeoutMs); if (std::future_status::timeout == f.wait_for(timeout)) { - LOG(ERROR) << "Cannot open stream within " << params_.timeoutMs - << " ms"; + LOG(ERROR) << folly::sformat( + "uuid={} cannot open stream within {} ms", + params_.loggingUuid, + params_.timeoutMs); interrupted_ = true; } }); @@ -343,8 +353,10 @@ bool Decoder::init( } if (result < 0 || interrupted_) { - LOG(ERROR) << "avformat_open_input failed, error: " - << Util::generateErrorDesc(result); + LOG(ERROR) << folly::sformat( + "uuid={} avformat_open_input failed, error={}", + params_.loggingUuid, + Util::generateErrorDesc(result)); cleanUp(); return false; } @@ -352,14 +364,17 @@ bool Decoder::init( result = avformat_find_stream_info(inputCtx_, nullptr); if (result < 0) { - LOG(ERROR) << "avformat_find_stream_info failed, error: " - << Util::generateErrorDesc(result); + LOG(ERROR) << folly::sformat( + "uuid={} avformat_find_stream_info failed, error={}", + params_.loggingUuid, + Util::generateErrorDesc(result)); cleanUp(); return false; } if (!openStreams(metadata)) { - LOG(ERROR) << "Cannot activate streams"; + LOG(ERROR) << folly::sformat( + "uuid={} cannot activate streams", params_.loggingUuid); cleanUp(); return false; } @@ -415,7 +430,8 @@ bool Decoder::openStreams(std::vector* metadata) { params_.loggingUuid); CHECK(stream); if (stream->openCodec(metadata) < 0) { - LOG(ERROR) << "Cannot open codec " << i; + LOG(ERROR) << folly::sformat( + "uuid={} open codec failed, stream_idx={}", params_.loggingUuid, i); return false; } streams_.emplace(i, std::move(stream)); @@ -515,13 +531,18 @@ int Decoder::getFrame(size_t workingTimeInMs) { bool hasMsg = false; // packet either got consumed completely or not at all if ((result = processPacket(stream, &avPacket, &gotFrame, &hasMsg)) < 0) { - LOG(ERROR) << "processPacket failed with code: " << result; + LOG(ERROR) << folly::sformat( + "uuid={} processPacket failed with code={}", + params_.loggingUuid, + result); break; } if (!gotFrame && params_.maxProcessNoBytes != 0 && ++numConsecutiveNoBytes > params_.maxProcessNoBytes) { - LOG(ERROR) << "Exceeding max amount of consecutive no bytes"; + LOG(ERROR) << folly::sformat( + "uuid={} exceeding max amount of consecutive no bytes", + params_.loggingUuid); break; } if (result > 0) { @@ -535,7 +556,9 @@ int Decoder::getFrame(size_t workingTimeInMs) { if (result < 0) { if (params_.maxPackageErrors != 0 && // check errors ++decodingErrors >= params_.maxPackageErrors) { // reached the limit - LOG(ERROR) << "Exceeding max amount of consecutive package errors"; + LOG(ERROR) << folly::sformat( + "uuid={} exceeding max amount of consecutive package errors", + params_.loggingUuid); break; } } else { diff --git a/torchvision/csrc/cpu/decoder/stream.cpp b/torchvision/csrc/cpu/decoder/stream.cpp index ec508639e7a..67d2f57a6ee 100644 --- a/torchvision/csrc/cpu/decoder/stream.cpp +++ b/torchvision/csrc/cpu/decoder/stream.cpp @@ -32,30 +32,30 @@ int Stream::openCodec(std::vector* metadata) { AVCodec* codec = findCodec(steam->codecpar); if (!codec) { - LOG(ERROR) << "LoggingUuid #" << loggingUuid_ - << ", avcodec_find_decoder failed for codec_id: " + LOG(ERROR) << "uuid=" << loggingUuid_ + << " avcodec_find_decoder failed for codec_id=" << int(steam->codecpar->codec_id); return AVERROR(EINVAL); } if (!(codecCtx_ = avcodec_alloc_context3(codec))) { - LOG(ERROR) << "LoggingUuid #" << loggingUuid_ - << ", avcodec_alloc_context3 failed"; + LOG(ERROR) << "uuid=" << loggingUuid_ + << " avcodec_alloc_context3 failed"; return AVERROR(ENOMEM); } int ret; // Copy codec parameters from input stream to output codec context if ((ret = avcodec_parameters_to_context(codecCtx_, steam->codecpar)) < 0) { - LOG(ERROR) << "LoggingUuid #" << loggingUuid_ - << ", avcodec_parameters_to_context failed"; + LOG(ERROR) << "uuid=" << loggingUuid_ + << " avcodec_parameters_to_context failed"; return ret; } // after avcodec_open2, value of codecCtx_->time_base is NOT meaningful if ((ret = avcodec_open2(codecCtx_, codec, nullptr)) < 0) { - LOG(ERROR) << "LoggingUuid #" << loggingUuid_ - << ", avcodec_open2 failed: " << Util::generateErrorDesc(ret); + LOG(ERROR) << "uuid=" << loggingUuid_ + << " avcodec_open2 failed: " << Util::generateErrorDesc(ret); avcodec_free_context(&codecCtx_); codecCtx_ = nullptr; return ret; @@ -75,7 +75,8 @@ int Stream::openCodec(std::vector* metadata) { } if ((ret = initFormat())) { - LOG(ERROR) << "initFormat failed, type: " << format_.type; + LOG(ERROR) << "uuid=" << loggingUuid_ + << " initFormat failed, type=" << format_.type; } if (metadata) { @@ -104,7 +105,8 @@ int Stream::analyzePacket(const AVPacket* packet, bool* gotFrame) { return result; } } else if (result < 0) { - LOG(ERROR) << "avcodec_send_packet failed, err: " + LOG(ERROR) << "uuid=" << loggingUuid_ + << " avcodec_send_packet failed, err=" << Util::generateErrorDesc(result); return result; // error } else { @@ -126,7 +128,8 @@ int Stream::analyzePacket(const AVPacket* packet, bool* gotFrame) { // precaution, if no more frames are available assume we consume all bytes consumed = 0; } else { // error - LOG(ERROR) << "avcodec_receive_frame failed, err: " + LOG(ERROR) << "uuid=" << loggingUuid_ + << " avcodec_receive_frame failed, err=" << Util::generateErrorDesc(result); return result; } From df931146e3ff20e7d28ca9c32642f6eec8299cfa Mon Sep 17 00:00:00 2001 From: Yanan Cao Date: Sat, 1 Aug 2020 13:02:20 -0700 Subject: [PATCH 096/357] Support custom exception message (#41907) Summary: Raise and assert used to have a hard-coded error message "Exception". User provided error message was ignored. This PR adds support to represent user's error message in TorchScript. This breaks backward compatibility because now we actually need to script the user's error message, which can potentially contain unscriptable expressions. Such programs can break when scripting, but saved models can still continue to work. Increased an op count in test_mobile_optimizer.py because now we need aten::format to form the actual exception message. This is built upon an WIP PR: https://github.com/pytorch/pytorch/pull/34112 by driazati Pull Request resolved: https://github.com/pytorch/pytorch/pull/41907 Reviewed By: ngimel Differential Revision: D22778301 Pulled By: gmagogsfm fbshipit-source-id: 2b94f0db4ae9fe70c4cd03f4048e519ea96323ad --- torchvision/io/_video_opt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/io/_video_opt.py b/torchvision/io/_video_opt.py index e28c565bce7..8e4f5d502a1 100644 --- a/torchvision/io/_video_opt.py +++ b/torchvision/io/_video_opt.py @@ -79,7 +79,7 @@ def _validate_pts(pts_range): assert ( pts_range[0] <= pts_range[1] ), """Start pts should not be smaller than end pts, got - start pts: %d and end pts: %d""" % ( + start pts: {} and end pts: {}""".format( pts_range[0], pts_range[1], ) From c4c9042988ba0de626eb74cb137c33888276dc65 Mon Sep 17 00:00:00 2001 From: Aaron Jaech Date: Wed, 5 Aug 2020 22:30:35 -0700 Subject: [PATCH 097/357] simplify read_image_file and read_label_file functions (#2476) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/2476 I simplified the read_image_file and read_label_file functions to make it easier to adapt this code to use it with other file systems that aren't compatible with the simple open command. Reviewed By: fmassa Differential Revision: D22530585 fbshipit-source-id: 0dd20f917c947d1ec1eae23474c251ceea85f427 --- torchvision/datasets/mnist.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index 3b9db53a9ff..357b1c6312d 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -470,16 +470,14 @@ def read_sn3_pascalvincent_tensor(path, strict=True): def read_label_file(path): - with open(path, 'rb') as f: - x = read_sn3_pascalvincent_tensor(f, strict=False) + x = read_sn3_pascalvincent_tensor(path, strict=False) assert(x.dtype == torch.uint8) assert(x.ndimension() == 1) return x.long() def read_image_file(path): - with open(path, 'rb') as f: - x = read_sn3_pascalvincent_tensor(f, strict=False) + x = read_sn3_pascalvincent_tensor(path, strict=False) assert(x.dtype == torch.uint8) assert(x.ndimension() == 3) return x From 8f82f5b34d4d440686da575771e6bd37ef6eafa4 Mon Sep 17 00:00:00 2001 From: Keyun Tong Date: Wed, 26 Aug 2020 18:37:04 -0700 Subject: [PATCH 098/357] Add timeout for rtmp stream connection Summary: We are see thread got blocked in MUI prod. Currently rtmp stream connection has no tcp timeout, when there is failure in upstream, the connection would block the thread forever. This change pass the timeout value into libav. Since the timeout is set at 30s, in normal cases, it should be no different. Reviewed By: hansman Differential Revision: D23351684 fbshipit-source-id: 0301d0476808bfdc8a03271f228265fcc9ee731d --- torchvision/csrc/cpu/decoder/decoder.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/torchvision/csrc/cpu/decoder/decoder.cpp b/torchvision/csrc/cpu/decoder/decoder.cpp index b62bc40af3c..ceeffeb57b0 100644 --- a/torchvision/csrc/cpu/decoder/decoder.cpp +++ b/torchvision/csrc/cpu/decoder/decoder.cpp @@ -311,11 +311,14 @@ bool Decoder::init( inputCtx_->flags |= AVFMT_FLAG_NONBLOCK; AVDictionary* options = nullptr; - av_dict_set_int(&options, "analyzeduration", params_.timeoutMs * 1000, 0); - av_dict_set_int(&options, "stimeout", params_.timeoutMs * 1000, 0); if (params_.listen) { av_dict_set_int(&options, "listen", 1, 0); } + if (params_.timeoutMs > 0) { + av_dict_set_int(&options, "analyzeduration", params_.timeoutMs * 1000, 0); + av_dict_set_int(&options, "stimeout", params_.timeoutMs * 1000, 0); + av_dict_set_int(&options, "timeout", params_.timeoutMs * 1000, 0); + } interrupted_ = false; From 4cd51d1e1fad3879bfa1a8b3c469da4ab401ae1b Mon Sep 17 00:00:00 2001 From: Keyun Tong Date: Thu, 27 Aug 2020 22:52:30 -0700 Subject: [PATCH 099/357] Revert D23351684: Add timeout for rtmp stream connection Differential Revision: D23351684 Original commit changeset: 0301d0476808 fbshipit-source-id: 5ecec032276cee3ffe10e2ce760375275b34f0de --- torchvision/csrc/cpu/decoder/decoder.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/torchvision/csrc/cpu/decoder/decoder.cpp b/torchvision/csrc/cpu/decoder/decoder.cpp index ceeffeb57b0..b62bc40af3c 100644 --- a/torchvision/csrc/cpu/decoder/decoder.cpp +++ b/torchvision/csrc/cpu/decoder/decoder.cpp @@ -311,14 +311,11 @@ bool Decoder::init( inputCtx_->flags |= AVFMT_FLAG_NONBLOCK; AVDictionary* options = nullptr; + av_dict_set_int(&options, "analyzeduration", params_.timeoutMs * 1000, 0); + av_dict_set_int(&options, "stimeout", params_.timeoutMs * 1000, 0); if (params_.listen) { av_dict_set_int(&options, "listen", 1, 0); } - if (params_.timeoutMs > 0) { - av_dict_set_int(&options, "analyzeduration", params_.timeoutMs * 1000, 0); - av_dict_set_int(&options, "stimeout", params_.timeoutMs * 1000, 0); - av_dict_set_int(&options, "timeout", params_.timeoutMs * 1000, 0); - } interrupted_ = false; From 64053887e95eaf3853bbbee7b0c6ef1e69e9201e Mon Sep 17 00:00:00 2001 From: Keyun Tong Date: Sat, 29 Aug 2020 08:17:09 -0700 Subject: [PATCH 100/357] Enable rtmp timeout in decoder Summary: * Link libav change into fbcode * Set rw_timeout value Differential Revision: D23412524 fbshipit-source-id: 5755950be1b1b4c37cb0c3a69a8c875f8862a92c --- torchvision/csrc/cpu/decoder/decoder.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/torchvision/csrc/cpu/decoder/decoder.cpp b/torchvision/csrc/cpu/decoder/decoder.cpp index b62bc40af3c..6aafe7d0a1c 100644 --- a/torchvision/csrc/cpu/decoder/decoder.cpp +++ b/torchvision/csrc/cpu/decoder/decoder.cpp @@ -311,11 +311,14 @@ bool Decoder::init( inputCtx_->flags |= AVFMT_FLAG_NONBLOCK; AVDictionary* options = nullptr; - av_dict_set_int(&options, "analyzeduration", params_.timeoutMs * 1000, 0); - av_dict_set_int(&options, "stimeout", params_.timeoutMs * 1000, 0); if (params_.listen) { av_dict_set_int(&options, "listen", 1, 0); } + if (params_.timeoutMs > 0) { + av_dict_set_int(&options, "analyzeduration", params_.timeoutMs * 1000, 0); + av_dict_set_int(&options, "stimeout", params_.timeoutMs * 1000, 0); + av_dict_set_int(&options, "rw_timeout", params_.timeoutMs * 1000, 0); + } interrupted_ = false; From b2aeeec631f2b1c8070756f7730e0123b76ef263 Mon Sep 17 00:00:00 2001 From: Brian Hirsh Date: Mon, 16 Nov 2020 14:32:48 -0800 Subject: [PATCH 101/357] make duplicate def() calls an error in the dispatcher. Updating all fb operators to use the new dispatcher registration API (#47322) Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/47322 Updating all call-sites of the legacy dispatcher registration API in fbcode to the new API. I migrated all call sites that used the legacy dispatcher registration API (RegisterOperators()) to use the new API (TORCH_LIBRARY...). I found all call-sites by running `fbgs RegisterOperators()`. This includes several places, including other OSS code (nestedtensor, torchtext, torchvision). A few things to call out: For simple ops that only had one registered kernel without a dispatch key, I replaced them with: ``` TORCH_LIBRARY_FRAGMENT(ns, m) { m.def("opName", fn_name); } ``` For ops that registered to a specific dispatch key / had multiple kernels registered, I registered the common kernel (math/cpu) directly inside a `TORCH_LIBRARY_FRAGMENT` block, and registered any additional kernels from other files (e.g. cuda) in a separate `TORCH_LIBRARY_IMPL` block. ``` // cpu file TORCH_LIBRARY_FRAGMENT(ns, m) { m.def("opName(schema_inputs) -> schema_outputs"); m.impl("opName", torch::dispatch(c10::DispatchKey::CPU, TORCH_FN(cpu_kernel))); } // cuda file TORCH_LIBRARY_IMPL(ns, CUDA, m) { m.impl("opName", torch::dispatch(c10::DispatchKey::CUDA, TORCH_FN(cuda_kernel))); } ``` Special cases: I found a few ops that used a (legacy) `CPUTensorId`/`CUDATensorId` dispatch key. Updated those to use CPU/CUDA- this seems safe because the keys are aliased to one another in `DispatchKey.h` There were a handful of ops that registered a functor (function class) to the legacy API. As far as I could tell we don't allow this case in the new API, mainly because you can accomplish the same thing more cleanly with lambdas. Rather than delete the class I wrote a wrapper function on top of the class, which I passed to the new API. There were a handful of ops that were registered only to a CUDA dispatch key. I put them inside a TORCH_LIBRARY_FRAGMENT block, and used a `def()` and `impl()` call like in case two above. Test Plan: Imported from OSS Reviewed By: ezyang Differential Revision: D24714803 Pulled By: bdhirsh fbshipit-source-id: c809aad8a698db3fd0d832f117f833e997b159e1 --- .../csrc/cpu/video_reader/VideoReader.cpp | 15 +++++-------- torchvision/csrc/vision.cpp | 22 +++++++++---------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/torchvision/csrc/cpu/video_reader/VideoReader.cpp b/torchvision/csrc/cpu/video_reader/VideoReader.cpp index 3a184716b4d..7bbf8aa916e 100644 --- a/torchvision/csrc/cpu/video_reader/VideoReader.cpp +++ b/torchvision/csrc/cpu/video_reader/VideoReader.cpp @@ -669,12 +669,9 @@ torch::List probeVideoFromFile(std::string videoPath) { } // namespace video_reader -static auto registry = torch::RegisterOperators() - .op("video_reader::read_video_from_memory", - &video_reader::readVideoFromMemory) - .op("video_reader::read_video_from_file", - &video_reader::readVideoFromFile) - .op("video_reader::probe_video_from_memory", - &video_reader::probeVideoFromMemory) - .op("video_reader::probe_video_from_file", - &video_reader::probeVideoFromFile); +TORCH_LIBRARY_FRAGMENT(video_reader, m) { + m.def("read_video_from_memory", video_reader::readVideoFromMemory); + m.def("read_video_from_file", video_reader::readVideoFromFile); + m.def("probe_video_from_memory", video_reader::probeVideoFromMemory); + m.def("probe_video_from_file", video_reader::probeVideoFromFile); +} diff --git a/torchvision/csrc/vision.cpp b/torchvision/csrc/vision.cpp index ed8d4134831..5940191fdfc 100644 --- a/torchvision/csrc/vision.cpp +++ b/torchvision/csrc/vision.cpp @@ -39,14 +39,14 @@ int64_t _cuda_version() { #endif } -static auto registry = - torch::RegisterOperators() - .op("torchvision::nms", &nms) - .op("torchvision::roi_align(Tensor input, Tensor rois, float spatial_scale, int pooled_height, int pooled_width, int sampling_ratio, bool aligned) -> Tensor", - &roi_align) - .op("torchvision::roi_pool", &roi_pool) - .op("torchvision::_new_empty_tensor_op", &new_empty_tensor) - .op("torchvision::ps_roi_align", &ps_roi_align) - .op("torchvision::ps_roi_pool", &ps_roi_pool) - .op("torchvision::deform_conv2d", &deform_conv2d) - .op("torchvision::_cuda_version", &_cuda_version); +TORCH_LIBRARY_FRAGMENT(torchvision, m) { + m.def("nms", nms); + m.def("roi_align(Tensor input, Tensor rois, float spatial_scale, int pooled_height, int pooled_width, int sampling_ratio, bool aligned) -> Tensor", + &roi_align); + m.def("roi_pool", roi_pool); + m.def("_new_empty_tensor_op", new_empty_tensor); + m.def("ps_roi_align", ps_roi_align); + m.def("ps_roi_pool", ps_roi_pool); + m.def("deform_conv2d", deform_conv2d); + m.def("_cuda_version", _cuda_version); +} From 2bf961f5d9adcd54c18829a151cbf4e92067469a Mon Sep 17 00:00:00 2001 From: Brian Hirsh Date: Mon, 16 Nov 2020 17:06:26 -0800 Subject: [PATCH 102/357] Revert D24714803: make duplicate def() calls an error in the dispatcher. Updating all fb operators to use the new dispatcher registration API Differential Revision: D24714803 Original commit changeset: c809aad8a698 fbshipit-source-id: fb2ada65f9fc00d965708d202bd9d050f13ef467 --- .../csrc/cpu/video_reader/VideoReader.cpp | 15 ++++++++----- torchvision/csrc/vision.cpp | 22 +++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/torchvision/csrc/cpu/video_reader/VideoReader.cpp b/torchvision/csrc/cpu/video_reader/VideoReader.cpp index 7bbf8aa916e..3a184716b4d 100644 --- a/torchvision/csrc/cpu/video_reader/VideoReader.cpp +++ b/torchvision/csrc/cpu/video_reader/VideoReader.cpp @@ -669,9 +669,12 @@ torch::List probeVideoFromFile(std::string videoPath) { } // namespace video_reader -TORCH_LIBRARY_FRAGMENT(video_reader, m) { - m.def("read_video_from_memory", video_reader::readVideoFromMemory); - m.def("read_video_from_file", video_reader::readVideoFromFile); - m.def("probe_video_from_memory", video_reader::probeVideoFromMemory); - m.def("probe_video_from_file", video_reader::probeVideoFromFile); -} +static auto registry = torch::RegisterOperators() + .op("video_reader::read_video_from_memory", + &video_reader::readVideoFromMemory) + .op("video_reader::read_video_from_file", + &video_reader::readVideoFromFile) + .op("video_reader::probe_video_from_memory", + &video_reader::probeVideoFromMemory) + .op("video_reader::probe_video_from_file", + &video_reader::probeVideoFromFile); diff --git a/torchvision/csrc/vision.cpp b/torchvision/csrc/vision.cpp index 5940191fdfc..ed8d4134831 100644 --- a/torchvision/csrc/vision.cpp +++ b/torchvision/csrc/vision.cpp @@ -39,14 +39,14 @@ int64_t _cuda_version() { #endif } -TORCH_LIBRARY_FRAGMENT(torchvision, m) { - m.def("nms", nms); - m.def("roi_align(Tensor input, Tensor rois, float spatial_scale, int pooled_height, int pooled_width, int sampling_ratio, bool aligned) -> Tensor", - &roi_align); - m.def("roi_pool", roi_pool); - m.def("_new_empty_tensor_op", new_empty_tensor); - m.def("ps_roi_align", ps_roi_align); - m.def("ps_roi_pool", ps_roi_pool); - m.def("deform_conv2d", deform_conv2d); - m.def("_cuda_version", _cuda_version); -} +static auto registry = + torch::RegisterOperators() + .op("torchvision::nms", &nms) + .op("torchvision::roi_align(Tensor input, Tensor rois, float spatial_scale, int pooled_height, int pooled_width, int sampling_ratio, bool aligned) -> Tensor", + &roi_align) + .op("torchvision::roi_pool", &roi_pool) + .op("torchvision::_new_empty_tensor_op", &new_empty_tensor) + .op("torchvision::ps_roi_align", &ps_roi_align) + .op("torchvision::ps_roi_pool", &ps_roi_pool) + .op("torchvision::deform_conv2d", &deform_conv2d) + .op("torchvision::_cuda_version", &_cuda_version); From ff96c178707a7fa8c2eeeb88b6fa38142a976025 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 1 Dec 2020 07:42:43 -0800 Subject: [PATCH 103/357] Remove dependency on folly (#3073) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/3073 Removes folly as a dependency to torchvision, which was added in D22743393. TorchVision OSS shouldn't depend on folly, similarly to PyTorch. Reviewed By: datumbox Differential Revision: D25244509 fbshipit-source-id: 9b50435f311e749af779116c1c9d104ac288d692 --- torchvision/csrc/cpu/decoder/decoder.cpp | 70 ++++++++++-------------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/torchvision/csrc/cpu/decoder/decoder.cpp b/torchvision/csrc/cpu/decoder/decoder.cpp index 6aafe7d0a1c..ca272541072 100644 --- a/torchvision/csrc/cpu/decoder/decoder.cpp +++ b/torchvision/csrc/cpu/decoder/decoder.cpp @@ -1,6 +1,5 @@ #include "decoder.h" #include -#include #include #include #include @@ -150,8 +149,8 @@ bool Decoder::enableLogLevel(int level) const { } void Decoder::logCallback(int level, const std::string& message) { - LOG(INFO) << folly::sformat( - "Msg, uuid={} level={} msg={}", params_.loggingUuid, level, message); + LOG(INFO) << + "Msg, uuid=" << params_.loggingUuid << " level=" << level << " msg=" << message; } /* static */ @@ -223,9 +222,8 @@ bool Decoder::init( cleanUp(); if ((params.uri.empty() || in) && (!params.uri.empty() || !in)) { - LOG(ERROR) << folly::sformat( - "uuid={} either external URI gets provided or explicit input callback", - params_.loggingUuid); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " either external URI gets provided or explicit input callback"; return false; } @@ -233,8 +231,8 @@ bool Decoder::init( params_ = params; if (!(inputCtx_ = avformat_alloc_context())) { - LOG(ERROR) << folly::sformat( - "uuid={} cannot allocate format context", params_.loggingUuid); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " cannot allocate format context"; return false; } @@ -247,8 +245,8 @@ bool Decoder::init( params_.timeoutMs, params_.maxSeekableBytes, params_.isImage ? &type : nullptr)) < 0) { - LOG(ERROR) << folly::sformat( - "uuid={} can't initiate seekable buffer", params_.loggingUuid); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " can't initiate seekable buffer"; cleanUp(); return false; } @@ -276,10 +274,8 @@ bool Decoder::init( uint8_t* avioCtxBuffer = (uint8_t*)av_malloc(avioCtxBufferSize + kIoPaddingSize); if (!avioCtxBuffer) { - LOG(ERROR) << folly::sformat( - "uuid={} av_malloc cannot allocate {} bytes", - params_.loggingUuid, - avioCtxBufferSize); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " av_malloc cannot allocate " << avioCtxBufferSize << " bytes"; cleanUp(); return false; } @@ -292,8 +288,8 @@ bool Decoder::init( &Decoder::readFunction, nullptr, result == 1 ? &Decoder::seekFunction : nullptr))) { - LOG(ERROR) << folly::sformat( - "uuid={} avio_alloc_context failed", params_.loggingUuid); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " avio_alloc_context failed"; av_free(avioCtxBuffer); cleanUp(); return false; @@ -331,10 +327,8 @@ bool Decoder::init( guard = std::make_unique([&f, this]() { auto timeout = std::chrono::milliseconds(params_.timeoutMs); if (std::future_status::timeout == f.wait_for(timeout)) { - LOG(ERROR) << folly::sformat( - "uuid={} cannot open stream within {} ms", - params_.loggingUuid, - params_.timeoutMs); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " cannot open stream within " << params_.timeoutMs << " ms"; interrupted_ = true; } }); @@ -356,10 +350,8 @@ bool Decoder::init( } if (result < 0 || interrupted_) { - LOG(ERROR) << folly::sformat( - "uuid={} avformat_open_input failed, error={}", - params_.loggingUuid, - Util::generateErrorDesc(result)); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " avformat_open_input failed, error=" << Util::generateErrorDesc(result); cleanUp(); return false; } @@ -367,17 +359,15 @@ bool Decoder::init( result = avformat_find_stream_info(inputCtx_, nullptr); if (result < 0) { - LOG(ERROR) << folly::sformat( - "uuid={} avformat_find_stream_info failed, error={}", - params_.loggingUuid, - Util::generateErrorDesc(result)); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " avformat_find_stream_info failed, error=" << Util::generateErrorDesc(result); cleanUp(); return false; } if (!openStreams(metadata)) { - LOG(ERROR) << folly::sformat( - "uuid={} cannot activate streams", params_.loggingUuid); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " cannot activate streams"; cleanUp(); return false; } @@ -433,8 +423,8 @@ bool Decoder::openStreams(std::vector* metadata) { params_.loggingUuid); CHECK(stream); if (stream->openCodec(metadata) < 0) { - LOG(ERROR) << folly::sformat( - "uuid={} open codec failed, stream_idx={}", params_.loggingUuid, i); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " open codec failed, stream_idx=" << i; return false; } streams_.emplace(i, std::move(stream)); @@ -534,18 +524,15 @@ int Decoder::getFrame(size_t workingTimeInMs) { bool hasMsg = false; // packet either got consumed completely or not at all if ((result = processPacket(stream, &avPacket, &gotFrame, &hasMsg)) < 0) { - LOG(ERROR) << folly::sformat( - "uuid={} processPacket failed with code={}", - params_.loggingUuid, - result); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " processPacket failed with code=" << result; break; } if (!gotFrame && params_.maxProcessNoBytes != 0 && ++numConsecutiveNoBytes > params_.maxProcessNoBytes) { - LOG(ERROR) << folly::sformat( - "uuid={} exceeding max amount of consecutive no bytes", - params_.loggingUuid); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " exceeding max amount of consecutive no bytes"; break; } if (result > 0) { @@ -559,9 +546,8 @@ int Decoder::getFrame(size_t workingTimeInMs) { if (result < 0) { if (params_.maxPackageErrors != 0 && // check errors ++decodingErrors >= params_.maxPackageErrors) { // reached the limit - LOG(ERROR) << folly::sformat( - "uuid={} exceeding max amount of consecutive package errors", - params_.loggingUuid); + LOG(ERROR) << + "uuid=" << params_.loggingUuid << " exceeding max amount of consecutive package errors"; break; } } else { From 97bbaff4c60ebacb0e1a484d064ec3dc46b53ad4 Mon Sep 17 00:00:00 2001 From: Brian Hirsh Date: Wed, 2 Dec 2020 11:09:12 -0800 Subject: [PATCH 104/357] Updating all call-sites of the legacy dispatcher registration API in fbcode to the new API. (#48178) Summary: Pull Request resolved: https://github.com/pytorch/pytorch/pull/48178 I migrated all call sites that used the legacy dispatcher registration API (RegisterOperators()) to use the new API (TORCH_LIBRARY...). I found all call-sites by running `fbgs RegisterOperators()`. This includes several places, including other OSS code (nestedtensor, torchtext, torchvision). A few things to call out: For simple ops that only had one registered kernel without a dispatch key, I replaced them with: ``` TORCH_LIBRARY_FRAGMENT(ns, m) { m.def("opName", fn_name); } ``` For ops that registered to a specific dispatch key / had multiple kernels registered, I registered the common kernel (math/cpu) directly inside a `TORCH_LIBRARY_FRAGMENT` block, and registered any additional kernels from other files (e.g. cuda) in a separate `TORCH_LIBRARY_IMPL` block. ``` // cpu file TORCH_LIBRARY_FRAGMENT(ns, m) { m.def("opName(schema_inputs) -> schema_outputs"); m.impl("opName", torch::dispatch(c10::DispatchKey::CPU, TORCH_FN(cpu_kernel))); } // cuda file TORCH_LIBRARY_IMPL(ns, CUDA, m) { m.impl("opName", torch::dispatch(c10::DispatchKey::CUDA, TORCH_FN(cuda_kernel))); } ``` Special cases: I found a few ops that used a (legacy) `CPUTensorId`/`CUDATensorId` dispatch key. Updated those to use CPU/CUDA- this seems safe because the keys are aliased to one another in `DispatchKey.h` There were a handful of ops that registered a functor (function class) to the legacy API. As far as I could tell we don't allow this case in the new API, mainly because you can accomplish the same thing more cleanly with lambdas. Rather than delete the class I wrote a wrapper function on top of the class, which I passed to the new API. There were a handful of ops that were registered only to a CUDA dispatch key. I put them inside a TORCH_LIBRARY_FRAGMENT block, and used a `def()` and `impl()` call like in case two above. Test Plan: Imported from OSS Reviewed By: ezyang Differential Revision: D25056090 Pulled By: bdhirsh fbshipit-source-id: 8f868b45f545e5da2f21924046e786850eba70d9 --- .../csrc/cpu/video_reader/VideoReader.cpp | 15 +++++-------- torchvision/csrc/vision.cpp | 22 +++++++++---------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/torchvision/csrc/cpu/video_reader/VideoReader.cpp b/torchvision/csrc/cpu/video_reader/VideoReader.cpp index 3a184716b4d..7bbf8aa916e 100644 --- a/torchvision/csrc/cpu/video_reader/VideoReader.cpp +++ b/torchvision/csrc/cpu/video_reader/VideoReader.cpp @@ -669,12 +669,9 @@ torch::List probeVideoFromFile(std::string videoPath) { } // namespace video_reader -static auto registry = torch::RegisterOperators() - .op("video_reader::read_video_from_memory", - &video_reader::readVideoFromMemory) - .op("video_reader::read_video_from_file", - &video_reader::readVideoFromFile) - .op("video_reader::probe_video_from_memory", - &video_reader::probeVideoFromMemory) - .op("video_reader::probe_video_from_file", - &video_reader::probeVideoFromFile); +TORCH_LIBRARY_FRAGMENT(video_reader, m) { + m.def("read_video_from_memory", video_reader::readVideoFromMemory); + m.def("read_video_from_file", video_reader::readVideoFromFile); + m.def("probe_video_from_memory", video_reader::probeVideoFromMemory); + m.def("probe_video_from_file", video_reader::probeVideoFromFile); +} diff --git a/torchvision/csrc/vision.cpp b/torchvision/csrc/vision.cpp index ed8d4134831..5940191fdfc 100644 --- a/torchvision/csrc/vision.cpp +++ b/torchvision/csrc/vision.cpp @@ -39,14 +39,14 @@ int64_t _cuda_version() { #endif } -static auto registry = - torch::RegisterOperators() - .op("torchvision::nms", &nms) - .op("torchvision::roi_align(Tensor input, Tensor rois, float spatial_scale, int pooled_height, int pooled_width, int sampling_ratio, bool aligned) -> Tensor", - &roi_align) - .op("torchvision::roi_pool", &roi_pool) - .op("torchvision::_new_empty_tensor_op", &new_empty_tensor) - .op("torchvision::ps_roi_align", &ps_roi_align) - .op("torchvision::ps_roi_pool", &ps_roi_pool) - .op("torchvision::deform_conv2d", &deform_conv2d) - .op("torchvision::_cuda_version", &_cuda_version); +TORCH_LIBRARY_FRAGMENT(torchvision, m) { + m.def("nms", nms); + m.def("roi_align(Tensor input, Tensor rois, float spatial_scale, int pooled_height, int pooled_width, int sampling_ratio, bool aligned) -> Tensor", + &roi_align); + m.def("roi_pool", roi_pool); + m.def("_new_empty_tensor_op", new_empty_tensor); + m.def("ps_roi_align", ps_roi_align); + m.def("ps_roi_pool", ps_roi_pool); + m.def("deform_conv2d", deform_conv2d); + m.def("_cuda_version", _cuda_version); +} From 6ee5dcee564f4b8abfc0a1870149b2df1ae26e53 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Fri, 4 Dec 2020 09:16:54 -0800 Subject: [PATCH 105/357] Update fbcode to latest version of torchvision (#3079) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: � Pull Request resolved: https://github.com/pytorch/vision/pull/3079 Reviewed By: datumbox Differential Revision: D25247734 Pulled By: fmassa fbshipit-source-id: 5fcdec4e891c5c101a365e14a44a55469646f3a7 --- .circleci/config.yml | 1745 ++++++++++++++--- .circleci/config.yml.in | 569 ++++-- .circleci/regenerate.py | 101 +- .circleci/smoke_test/docker/Dockerfile | 36 + .../unittest/linux/scripts/environment.yml | 18 + .circleci/unittest/linux/scripts/install.sh | 29 + .../unittest/linux/scripts/post_process.sh | 8 + .circleci/unittest/linux/scripts/run_test.sh | 10 + .circleci/unittest/linux/scripts/setup_env.sh | 39 + .../unittest/windows/scripts/environment.yml | 18 + .circleci/unittest/windows/scripts/install.sh | 31 + .../windows/scripts/install_conda.bat | 1 + .../unittest/windows/scripts/post_process.sh | 8 + .../unittest/windows/scripts/run_test.sh | 10 + .../unittest/windows/scripts/setup_env.sh | 39 + .../windows/scripts/vc_env_helper.bat | 39 + .gitattributes | 7 + .gitignore | 5 + .travis.yml | 34 +- CMakeLists.txt | 109 +- CODE_OF_CONDUCT.md | 76 + README.rst | 64 +- cmake/TorchVisionConfig.cmake.in | 43 + docs/requirements.txt | 2 +- docs/source/conf.py | 19 +- docs/source/datasets.rst | 177 +- docs/source/index.rst | 35 + docs/source/io.rst | 58 +- docs/source/models.rst | 40 +- docs/source/ops.rst | 18 +- docs/source/transforms.rst | 100 +- docs/source/utils.rst | 1 + examples/cpp/hello_world/CMakeLists.txt | 16 + examples/cpp/hello_world/README.rst | 19 + examples/cpp/hello_world/main.cpp | 23 + examples/python/README.md | 18 + examples/python/tensor_transforms.ipynb | 388 ++++ examples/python/video_api.ipynb | 772 ++++++++ hubconf.py | 8 +- mypy.ini | 65 + packaging/build_cmake.sh | 101 + packaging/build_conda.sh | 2 +- packaging/build_wheel.sh | 46 +- packaging/conda/build_vision.sh | 12 +- packaging/pkg_helpers.bash | 94 +- packaging/torchvision/conda_build_config.yaml | 2 + packaging/torchvision/meta.yaml | 14 +- packaging/vs2017/meta.yaml | 21 - packaging/wheel/relocate.py | 417 ++++ packaging/windows/build_vision.bat | 4 +- packaging/windows/cuda102.bat | 59 + packaging/windows/internal/build_cmake.bat | 3 + packaging/windows/internal/build_conda.bat | 2 +- .../windows/internal/build_cpp_example.bat | 3 + packaging/windows/internal/build_frcnn.bat | 3 + packaging/windows/internal/build_wheels.bat | 4 +- packaging/windows/internal/cuda_install.bat | 44 + .../windows/internal/nightly_defaults.bat | 4 +- packaging/windows/internal/test.bat | 2 +- .../windows/internal/vc_install_helper.sh | 2 +- packaging/windows/internal/vs2017_install.ps1 | 2 +- packaging/windows/internal/vs_install.bat | 22 +- packaging/windows/templates/auth_task.yml | 2 +- packaging/windows/templates/build_task.yml | 14 +- references/classification/README.md | 47 +- .../classification/train_quantization.py | 11 +- references/detection/README.md | 25 +- references/detection/engine.py | 7 +- references/detection/train.py | 4 +- references/segmentation/README.md | 33 + references/segmentation/train.py | 31 +- references/segmentation/transforms.py | 2 +- references/segmentation/utils.py | 1 - references/video_classification/README.md | 34 + references/video_classification/train.py | 24 +- references/video_classification/transforms.py | 126 +- setup.cfg | 2 +- setup.py | 301 ++- test/assets/damaged_jpeg/TensorFlow-LICENSE | 13 + test/assets/damaged_jpeg/bad_huffman.jpg | Bin 0 -> 15416 bytes test/assets/damaged_jpeg/corrupt.jpg | Bin 0 -> 1552 bytes test/assets/damaged_jpeg/corrupt34_2.jpg | Bin 0 -> 755 bytes test/assets/damaged_jpeg/corrupt34_3.jpg | Bin 0 -> 5505 bytes test/assets/damaged_jpeg/corrupt34_4.jpg | Bin 0 -> 5092 bytes .../encode_jpeg/grace_hopper_517x606.jpg | Bin 0 -> 73746 bytes .../jpeg_write/grace_hopper_517x606_pil.jpg | Bin 0 -> 60002 bytes test/assets/fakedata/draw_boxes_util.png | Bin 0 -> 490 bytes test/assets/fakedata/logos/cmyk_pytorch.jpg | Bin 0 -> 3530 bytes test/assets/fakedata/logos/gray_pytorch.jpg | Bin 0 -> 1437 bytes test/assets/fakedata/logos/gray_pytorch.png | Bin 0 -> 433 bytes .../fakedata/logos/grayalpha_pytorch.png | Bin 0 -> 590 bytes .../assets/fakedata/logos/palette_pytorch.png | Bin 0 -> 1151 bytes test/assets/fakedata/logos/rgb_pytorch.jpg | Bin 0 -> 2126 bytes test/assets/fakedata/logos/rgb_pytorch.png | Bin 0 -> 575 bytes .../fakedata/logos/rgbalpha_pytorch.png | Bin 0 -> 2901 bytes test/assets/gaussian_blur_opencv_results.pt | Bin 0 -> 49135 bytes ...ppi_Michel_cartwheel_f_cm_np2_le_med_6.avi | Bin 0 -> 357888 bytes test/common_utils.py | 158 +- ...er.test_fasterrcnn_resnet50_fpn_expect.pkl | Bin 3326 -> 4109 bytes ....test_keypointrcnn_resnet50_fpn_expect.pkl | Bin 30725 -> 11755 bytes ...ster.test_maskrcnn_resnet50_fpn_expect.pkl | Bin 1005 -> 4705 bytes ...ter.test_retinanet_resnet50_fpn_expect.pkl | Bin 0 -> 9677 bytes test/fakedata_generation.py | 183 +- test/test_cpp_models.py | 6 +- test/test_datasets.py | 163 +- test/test_datasets_download.py | 208 ++ test/test_datasets_utils.py | 10 +- test/test_datasets_video_utils.py | 10 + test/test_datasets_video_utils_opt.py | 4 +- test/test_functional_tensor.py | 950 ++++++++- test/test_hub.py | 12 +- test/test_image.py | 282 +++ test/test_io.py | 34 +- test/test_io_opt.py | 3 +- test/test_models.py | 376 ++-- test/test_models_detection_anchor_utils.py | 61 + .../test_models_detection_negative_samples.py | 9 + test/test_models_detection_utils.py | 41 + test/test_onnx.py | 79 +- test/test_ops.py | 404 +++- test/test_transforms.py | 501 ++++- test/test_transforms_tensor.py | 605 ++++++ test/test_utils.py | 17 + test/test_video.py | 407 ++++ test/tracing/frcnn/CMakeLists.txt | 13 + test/tracing/frcnn/test_frcnn_tracing.cpp | 65 + test/tracing/frcnn/trace_model.py | 14 + torchvision/__init__.py | 15 +- torchvision/csrc/DeformConv.h | 364 +++- torchvision/csrc/PSROIAlign.h | 232 ++- torchvision/csrc/PSROIPool.h | 213 +- torchvision/csrc/ROIAlign.h | 240 ++- torchvision/csrc/ROIPool.h | 208 +- torchvision/csrc/autocast.h | 5 + torchvision/csrc/cpu/DeformConv_cpu.cpp | 569 ++++-- torchvision/csrc/cpu/PSROIAlign_cpu.cpp | 104 +- torchvision/csrc/cpu/PSROIPool_cpu.cpp | 80 +- torchvision/csrc/cpu/ROIAlign_cpu.cpp | 169 +- torchvision/csrc/cpu/ROIPool_cpu.cpp | 130 +- torchvision/csrc/cpu/decoder/decoder.cpp | 47 +- torchvision/csrc/cpu/decoder/decoder.h | 5 + torchvision/csrc/cpu/decoder/defs.h | 3 +- .../csrc/cpu/decoder/seekable_buffer.cpp | 4 +- torchvision/csrc/cpu/decoder/stream.cpp | 30 +- .../csrc/cpu/decoder/subtitle_stream.cpp | 3 +- torchvision/csrc/cpu/decoder/util.cpp | 4 +- torchvision/csrc/cpu/image/image.cpp | 22 + torchvision/csrc/cpu/image/image.h | 11 + torchvision/csrc/cpu/image/image_read_mode.h | 9 + torchvision/csrc/cpu/image/jpegcommon.cpp | 19 + torchvision/csrc/cpu/image/jpegcommon.h | 23 + torchvision/csrc/cpu/image/read_image_cpu.cpp | 28 + torchvision/csrc/cpu/image/read_image_cpu.h | 8 + .../csrc/cpu/image/read_write_file_cpu.cpp | 92 + .../csrc/cpu/image/read_write_file_cpu.h | 9 + torchvision/csrc/cpu/image/readjpeg_cpu.cpp | 153 ++ torchvision/csrc/cpu/image/readjpeg_cpu.h | 8 + torchvision/csrc/cpu/image/readpng_cpu.cpp | 165 ++ torchvision/csrc/cpu/image/readpng_cpu.h | 8 + torchvision/csrc/cpu/image/writejpeg_cpu.cpp | 105 + torchvision/csrc/cpu/image/writejpeg_cpu.h | 5 + torchvision/csrc/cpu/image/writepng_cpu.cpp | 176 ++ torchvision/csrc/cpu/image/writepng_cpu.h | 7 + torchvision/csrc/cpu/nms_cpu.cpp | 34 +- torchvision/csrc/cpu/video/Video.cpp | 321 +++ torchvision/csrc/cpu/video/Video.h | 60 + torchvision/csrc/cpu/video/register.cpp | 18 + .../csrc/cpu/video_reader/VideoReader.cpp | 50 +- torchvision/csrc/cpu/vision_cpu.h | 184 +- torchvision/csrc/cuda/DeformConv_cuda.cu | 621 ++++-- torchvision/csrc/cuda/PSROIAlign_cuda.cu | 116 +- torchvision/csrc/cuda/PSROIPool_cuda.cu | 94 +- torchvision/csrc/cuda/ROIAlign_cuda.cu | 113 +- torchvision/csrc/cuda/ROIPool_cuda.cu | 90 +- torchvision/csrc/cuda/cuda_helpers.h | 5 + torchvision/csrc/cuda/nms_cuda.cu | 49 +- torchvision/csrc/cuda/vision_cuda.h | 185 +- torchvision/csrc/empty_tensor_op.h | 24 +- torchvision/csrc/macros.h | 24 + torchvision/csrc/models/alexnet.h | 2 +- torchvision/csrc/models/densenet.cpp | 12 +- torchvision/csrc/models/densenet.h | 20 +- torchvision/csrc/models/googlenet.h | 4 +- torchvision/csrc/models/inception.cpp | 10 +- torchvision/csrc/models/inception.h | 22 +- torchvision/csrc/models/mnasnet.cpp | 5 +- torchvision/csrc/models/mnasnet.h | 13 +- torchvision/csrc/models/mobilenet.cpp | 6 +- torchvision/csrc/models/mobilenet.h | 2 +- torchvision/csrc/models/modelsimpl.h | 10 +- torchvision/csrc/models/resnet.cpp | 4 +- torchvision/csrc/models/resnet.h | 34 +- torchvision/csrc/models/shufflenetv2.h | 8 +- torchvision/csrc/models/squeezenet.cpp | 1 - torchvision/csrc/models/squeezenet.h | 6 +- torchvision/csrc/models/vgg.cpp | 5 +- torchvision/csrc/models/vgg.h | 36 +- torchvision/csrc/nms.h | 38 +- torchvision/csrc/vision.cpp | 108 +- torchvision/csrc/vision.h | 13 + torchvision/datasets/__init__.py | 3 +- torchvision/datasets/caltech.py | 53 +- torchvision/datasets/celeba.py | 30 +- torchvision/datasets/cifar.py | 25 +- torchvision/datasets/cityscapes.py | 29 +- torchvision/datasets/coco.py | 31 +- torchvision/datasets/fakedata.py | 18 +- torchvision/datasets/flickr.py | 39 +- torchvision/datasets/folder.py | 102 +- torchvision/datasets/hmdb51.py | 75 +- torchvision/datasets/imagenet.py | 27 +- torchvision/datasets/lsun.py | 43 +- torchvision/datasets/mnist.py | 115 +- torchvision/datasets/omniglot.py | 27 +- torchvision/datasets/phototour.py | 39 +- torchvision/datasets/places365.py | 170 ++ torchvision/datasets/samplers/clip_sampler.py | 39 +- torchvision/datasets/sbd.py | 29 +- torchvision/datasets/sbu.py | 17 +- torchvision/datasets/semeion.py | 17 +- torchvision/datasets/stl10.py | 30 +- torchvision/datasets/svhn.py | 25 +- torchvision/datasets/ucf101.py | 4 +- torchvision/datasets/usps.py | 17 +- torchvision/datasets/utils.py | 107 +- torchvision/datasets/video_utils.py | 52 +- torchvision/datasets/vision.py | 27 +- torchvision/datasets/voc.py | 53 +- torchvision/extension.py | 57 +- torchvision/io/__init__.py | 161 ++ torchvision/io/_video_opt.py | 50 +- torchvision/io/image.py | 268 +++ torchvision/io/video.py | 255 +-- torchvision/models/_utils.py | 4 +- torchvision/models/alexnet.py | 7 +- torchvision/models/densenet.py | 117 +- torchvision/models/detection/__init__.py | 1 + torchvision/models/detection/_utils.py | 44 +- torchvision/models/detection/anchor_utils.py | 158 ++ .../models/detection/backbone_utils.py | 89 +- torchvision/models/detection/faster_rcnn.py | 48 +- .../models/detection/generalized_rcnn.py | 33 +- torchvision/models/detection/image_list.py | 6 +- torchvision/models/detection/keypoint_rcnn.py | 47 +- torchvision/models/detection/mask_rcnn.py | 40 +- torchvision/models/detection/retinanet.py | 617 ++++++ torchvision/models/detection/roi_heads.py | 46 +- torchvision/models/detection/rpn.py | 168 +- torchvision/models/detection/transform.py | 22 +- torchvision/models/googlenet.py | 94 +- torchvision/models/inception.py | 117 +- torchvision/models/mnasnet.py | 60 +- torchvision/models/mobilenet.py | 53 +- torchvision/models/quantization/googlenet.py | 3 +- torchvision/models/quantization/inception.py | 22 +- torchvision/models/resnet.py | 114 +- torchvision/models/segmentation/deeplabv3.py | 2 +- torchvision/models/shufflenetv2.py | 49 +- torchvision/models/squeezenet.py | 26 +- torchvision/models/vgg.py | 53 +- torchvision/models/video/README.md | 60 + torchvision/ops/__init__.py | 11 +- torchvision/ops/_box_convert.py | 83 + torchvision/ops/_register_onnx_ops.py | 8 +- torchvision/ops/_utils.py | 10 +- torchvision/ops/boxes.py | 130 +- torchvision/ops/deform_conv.py | 77 +- torchvision/ops/feature_pyramid_network.py | 80 +- torchvision/ops/focal_loss.py | 49 + torchvision/ops/misc.py | 152 +- torchvision/ops/new_empty_tensor.py | 3 +- torchvision/ops/poolers.py | 72 +- torchvision/ops/ps_roi_align.py | 24 +- torchvision/ops/ps_roi_pool.py | 18 +- torchvision/ops/roi_align.py | 24 +- torchvision/ops/roi_pool.py | 16 +- torchvision/transforms/_functional_video.py | 2 +- torchvision/transforms/_transforms_video.py | 2 +- torchvision/transforms/functional.py | 1042 ++++++---- torchvision/transforms/functional_pil.py | 605 ++++++ torchvision/transforms/functional_tensor.py | 1042 +++++++++- torchvision/transforms/transforms.py | 1187 +++++++---- torchvision/utils.py | 106 +- 283 files changed, 20307 insertions(+), 5143 deletions(-) create mode 100644 .circleci/smoke_test/docker/Dockerfile create mode 100644 .circleci/unittest/linux/scripts/environment.yml create mode 100755 .circleci/unittest/linux/scripts/install.sh create mode 100755 .circleci/unittest/linux/scripts/post_process.sh create mode 100755 .circleci/unittest/linux/scripts/run_test.sh create mode 100755 .circleci/unittest/linux/scripts/setup_env.sh create mode 100644 .circleci/unittest/windows/scripts/environment.yml create mode 100644 .circleci/unittest/windows/scripts/install.sh create mode 100644 .circleci/unittest/windows/scripts/install_conda.bat create mode 100644 .circleci/unittest/windows/scripts/post_process.sh create mode 100644 .circleci/unittest/windows/scripts/run_test.sh create mode 100644 .circleci/unittest/windows/scripts/setup_env.sh create mode 100644 .circleci/unittest/windows/scripts/vc_env_helper.bat create mode 100644 CODE_OF_CONDUCT.md create mode 100644 cmake/TorchVisionConfig.cmake.in create mode 100644 examples/cpp/hello_world/CMakeLists.txt create mode 100644 examples/cpp/hello_world/README.rst create mode 100644 examples/cpp/hello_world/main.cpp create mode 100644 examples/python/README.md create mode 100644 examples/python/tensor_transforms.ipynb create mode 100644 examples/python/video_api.ipynb create mode 100644 mypy.ini create mode 100755 packaging/build_cmake.sh create mode 100644 packaging/wheel/relocate.py create mode 100644 packaging/windows/cuda102.bat create mode 100644 packaging/windows/internal/build_cmake.bat create mode 100644 packaging/windows/internal/build_cpp_example.bat create mode 100644 packaging/windows/internal/build_frcnn.bat create mode 100644 references/segmentation/README.md create mode 100644 references/video_classification/README.md create mode 100644 test/assets/damaged_jpeg/TensorFlow-LICENSE create mode 100644 test/assets/damaged_jpeg/bad_huffman.jpg create mode 100644 test/assets/damaged_jpeg/corrupt.jpg create mode 100644 test/assets/damaged_jpeg/corrupt34_2.jpg create mode 100644 test/assets/damaged_jpeg/corrupt34_3.jpg create mode 100644 test/assets/damaged_jpeg/corrupt34_4.jpg create mode 100644 test/assets/encode_jpeg/grace_hopper_517x606.jpg create mode 100644 test/assets/encode_jpeg/jpeg_write/grace_hopper_517x606_pil.jpg create mode 100644 test/assets/fakedata/draw_boxes_util.png create mode 100644 test/assets/fakedata/logos/cmyk_pytorch.jpg create mode 100644 test/assets/fakedata/logos/gray_pytorch.jpg create mode 100644 test/assets/fakedata/logos/gray_pytorch.png create mode 100644 test/assets/fakedata/logos/grayalpha_pytorch.png create mode 100644 test/assets/fakedata/logos/palette_pytorch.png create mode 100644 test/assets/fakedata/logos/rgb_pytorch.jpg create mode 100644 test/assets/fakedata/logos/rgb_pytorch.png create mode 100644 test/assets/fakedata/logos/rgbalpha_pytorch.png create mode 100644 test/assets/gaussian_blur_opencv_results.pt create mode 100644 test/assets/videos/hmdb51_Turnk_r_Pippi_Michel_cartwheel_f_cm_np2_le_med_6.avi create mode 100644 test/expect/ModelTester.test_retinanet_resnet50_fpn_expect.pkl create mode 100644 test/test_datasets_download.py create mode 100644 test/test_image.py create mode 100644 test/test_models_detection_anchor_utils.py create mode 100644 test/test_transforms_tensor.py create mode 100644 test/test_video.py create mode 100644 test/tracing/frcnn/CMakeLists.txt create mode 100644 test/tracing/frcnn/test_frcnn_tracing.cpp create mode 100644 test/tracing/frcnn/trace_model.py create mode 100644 torchvision/csrc/autocast.h create mode 100644 torchvision/csrc/cpu/image/image.cpp create mode 100644 torchvision/csrc/cpu/image/image.h create mode 100644 torchvision/csrc/cpu/image/image_read_mode.h create mode 100644 torchvision/csrc/cpu/image/jpegcommon.cpp create mode 100644 torchvision/csrc/cpu/image/jpegcommon.h create mode 100644 torchvision/csrc/cpu/image/read_image_cpu.cpp create mode 100644 torchvision/csrc/cpu/image/read_image_cpu.h create mode 100644 torchvision/csrc/cpu/image/read_write_file_cpu.cpp create mode 100644 torchvision/csrc/cpu/image/read_write_file_cpu.h create mode 100644 torchvision/csrc/cpu/image/readjpeg_cpu.cpp create mode 100644 torchvision/csrc/cpu/image/readjpeg_cpu.h create mode 100644 torchvision/csrc/cpu/image/readpng_cpu.cpp create mode 100644 torchvision/csrc/cpu/image/readpng_cpu.h create mode 100644 torchvision/csrc/cpu/image/writejpeg_cpu.cpp create mode 100644 torchvision/csrc/cpu/image/writejpeg_cpu.h create mode 100644 torchvision/csrc/cpu/image/writepng_cpu.cpp create mode 100644 torchvision/csrc/cpu/image/writepng_cpu.h create mode 100644 torchvision/csrc/cpu/video/Video.cpp create mode 100644 torchvision/csrc/cpu/video/Video.h create mode 100644 torchvision/csrc/cpu/video/register.cpp create mode 100644 torchvision/csrc/macros.h create mode 100644 torchvision/datasets/places365.py create mode 100644 torchvision/io/image.py create mode 100644 torchvision/models/detection/anchor_utils.py create mode 100644 torchvision/models/detection/retinanet.py create mode 100644 torchvision/models/video/README.md create mode 100644 torchvision/ops/_box_convert.py create mode 100644 torchvision/ops/focal_loss.py create mode 100644 torchvision/transforms/functional_pil.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 0d62d00e410..92e0b7891e3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -64,6 +64,7 @@ binary_common: &binary_common cu_version: description: "CUDA version to build against, in CU format (e.g., cpu or cu100)" type: string + default: "cpu" unicode_abi: description: "Python 2.7 wheel only: whether or not we are cp27mu (default: no)" type: string @@ -78,6 +79,11 @@ binary_common: &binary_common UNICODE_ABI: << parameters.unicode_abi >> CU_VERSION: << parameters.cu_version >> +smoke_test_common: &smoke_test_common + <<: *binary_common + docker: + - image: torchvision/smoke_test:latest + jobs: circleci_consistency: docker: @@ -90,6 +96,42 @@ jobs: python .circleci/regenerate.py git diff --exit-code || (echo ".circleci/config.yml not in sync with config.yml.in! Run .circleci/regenerate.py to update config"; exit 1) + python_lint: + docker: + - image: circleci/python:3.7 + steps: + - checkout + - run: + command: | + pip install --user --progress-bar off flake8 typing + flake8 --config=setup.cfg . + + python_type_check: + docker: + - image: circleci/python:3.7 + steps: + - checkout + - run: + command: | + sudo apt-get update -y + sudo apt install -y libturbojpeg-dev + pip install --user --progress-bar off numpy mypy + pip install --user --progress-bar off --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html + pip install --user --progress-bar off --editable . + mypy --config-file mypy.ini + + clang_format: + docker: + - image: circleci/python:3.7 + steps: + - checkout + - run: + command: | + curl https://oss-clang-format.s3.us-east-2.amazonaws.com/linux64/clang-format-linux64 -o clang-format + chmod +x clang-format + sudo mv clang-format /opt/clang-format + ./travis-scripts/run-clang-format/run-clang-format.py -r torchvision/csrc --clang-format-executable /opt/clang-format + binary_linux_wheel: <<: *binary_common docker: @@ -97,6 +139,7 @@ jobs: resource_class: 2xlarge+ steps: - checkout_merge + - designate_upload_channel - run: packaging/build_wheel.sh - store_artifacts: path: dist @@ -112,6 +155,7 @@ jobs: resource_class: 2xlarge+ steps: - checkout_merge + - designate_upload_channel - run: packaging/build_conda.sh - store_artifacts: path: /opt/conda/conda-bld/linux-64 @@ -122,110 +166,12 @@ jobs: - store_test_results: path: build_results/ - binary_linux_conda_cuda: - <<: *binary_common - machine: - image: ubuntu-1604:201903-01 - resource_class: gpu.medium - steps: - - checkout_merge - - run: - name: Setup environment - command: | - set -ex - - curl -L https://packagecloud.io/circleci/trusty/gpgkey | sudo apt-key add - - curl -L https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add - - - sudo apt-get update - - sudo apt-get install \ - apt-transport-https \ - ca-certificates \ - curl \ - gnupg-agent \ - software-properties-common - - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - - - sudo add-apt-repository \ - "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) \ - stable" - - sudo apt-get update - export DOCKER_VERSION="5:19.03.2~3-0~ubuntu-xenial" - sudo apt-get install docker-ce=${DOCKER_VERSION} docker-ce-cli=${DOCKER_VERSION} containerd.io=1.2.6-3 - - # Add the package repositories - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list - - export NVIDIA_CONTAINER_VERSION="1.0.3-1" - sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit=${NVIDIA_CONTAINER_VERSION} - sudo systemctl restart docker - - DRIVER_FN="NVIDIA-Linux-x86_64-440.59.run" - wget "https://s3.amazonaws.com/ossci-linux/nvidia_driver/$DRIVER_FN" - sudo /bin/bash "$DRIVER_FN" -s --no-drm || (sudo cat /var/log/nvidia-installer.log && false) - nvidia-smi - - - run: - name: Pull docker image - command: | - set -ex - export DOCKER_IMAGE=pytorch/conda-cuda - echo Pulling docker image $DOCKER_IMAGE - docker pull $DOCKER_IMAGE >/dev/null - - - run: - name: Build and run tests - command: | - set -ex - - cd ${HOME}/project/ - - export DOCKER_IMAGE=pytorch/conda-cuda - export VARS_TO_PASS="-e PYTHON_VERSION -e BUILD_VERSION -e PYTORCH_VERSION -e UNICODE_ABI -e CU_VERSION" - - docker run --gpus all --ipc=host -v $(pwd):/remote -w /remote ${VARS_TO_PASS} ${DOCKER_IMAGE} ./packaging/build_conda.sh - binary_win_conda: <<: *binary_common executor: windows-cpu steps: - checkout_merge - - run: - command: | - set -ex - source packaging/windows/internal/vc_install_helper.sh - eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" - conda activate base - conda install -yq conda-build "conda-package-handling!=1.5.0" - packaging/build_conda.sh - - store_test_results: - path: build_results/ - - binary_win_conda_cuda: - <<: *binary_common - executor: windows-gpu - steps: - - checkout_merge - - run: - command: | - set -ex - source packaging/windows/internal/vc_install_helper.sh - eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" - conda activate base - conda install -yq conda-build "conda-package-handling!=1.5.0" - packaging/build_conda.sh - - binary_win_conda_release: - <<: *binary_common - executor: windows-cpu - steps: - - checkout_merge + - designate_upload_channel - run: name: Build conda packages command: | @@ -246,11 +192,12 @@ jobs: - store_test_results: path: build_results/ - binary_win_wheel_release: + binary_win_wheel: <<: *binary_common executor: windows-cpu steps: - checkout_merge + - designate_upload_channel - run: name: Build wheel packages command: | @@ -270,9 +217,10 @@ jobs: binary_macos_wheel: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" steps: - checkout_merge + - designate_upload_channel - run: # Cannot easily deduplicate this as source'ing activate # will set environment variables which we need to propagate @@ -292,9 +240,10 @@ jobs: binary_macos_conda: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" steps: - checkout_merge + - designate_upload_channel - run: command: | curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh @@ -352,6 +301,381 @@ jobs: aws s3 cp "$pkg" "s3://pytorch/whl/${UPLOAD_CHANNEL}/<< parameters.subfolder >>" --acl public-read done + smoke_test_linux_conda: + <<: *smoke_test_common + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + name: install binaries + command: | + set -x + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + conda install -v -y -c pytorch-nightly pytorch + conda install -v -y $(ls ~/workspace/torchvision*.tar.bz2) + - run: + name: smoke test + command: | + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + python -c "import torchvision" + + smoke_test_linux_pip: + <<: *smoke_test_common + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + name: install binaries + command: | + set -x + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + pip install $(ls ~/workspace/torchvision*.whl) --pre -f https://download.pytorch.org/whl/nightly/torch_nightly.html + - run: + name: smoke test + command: | + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + python -c "import torchvision" + + smoke_test_docker_image_build: + machine: + image: ubuntu-1604:201903-01 + resource_class: large + environment: + image_name: torchvision/smoke_test + steps: + - checkout + - designate_upload_channel + - run: + name: Build and push Docker image + no_output_timeout: "1h" + command: | + set +x + echo "${DOCKER_HUB_TOKEN}" | docker login --username "${DOCKER_HUB_USERNAME}" --password-stdin + set -x + cd .circleci/smoke_test/docker && docker build . -t ${image_name}:${CIRCLE_WORKFLOW_ID} + docker tag ${image_name}:${CIRCLE_WORKFLOW_ID} ${image_name}:latest + docker push ${image_name}:${CIRCLE_WORKFLOW_ID} + docker push ${image_name}:latest + + smoke_test_win_conda: + <<: *binary_common + executor: + name: windows-cpu + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + name: install binaries + command: | + set -x + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda env remove -n python${PYTHON_VERSION} || true + conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} + conda activate python${PYTHON_VERSION} + conda install Pillow + conda install -v -y -c pytorch-nightly pytorch + conda install -v -y $(ls ~/workspace/torchvision*.tar.bz2) + - run: + name: smoke test + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate python${PYTHON_VERSION} + python -c "import torchvision" + + smoke_test_win_pip: + <<: *binary_common + executor: + name: windows-cpu + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + name: install binaries + command: | + set -x + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda env remove -n python${PYTHON_VERSION} || true + conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} + conda activate python${PYTHON_VERSION} + pip install $(ls ~/workspace/torchvision*.whl) --pre -f https://download.pytorch.org/whl/nightly/torch_nightly.html + - run: + name: smoke test + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate python${PYTHON_VERSION} + python -c "import torchvision" + + unittest_linux_cpu: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda102" + resource_class: 2xlarge+ + steps: + - checkout + - designate_upload_channel + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - restore_cache: + + keys: + - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + + key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + + paths: + - conda + - env + - run: + name: Install torchvision + command: .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_linux_gpu: + <<: *binary_common + machine: + image: ubuntu-1604-cuda-10.1:201909-23 + resource_class: gpu.small + environment: + image_name: "pytorch/manylinux-cuda101" + PYTHON_VERSION: << parameters.python_version >> + steps: + - checkout + - designate_upload_channel + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - run: + name: Setup + command: docker run -e PYTHON_VERSION -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + + key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + + paths: + - conda + - env + - run: + name: Install torchvision + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD -e UPLOAD_CHANNEL "${image_name}" .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post Process + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_windows_cpu: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout + - designate_upload_channel + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - restore_cache: + + keys: + - env-v2-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + + - run: + name: Setup + command: .circleci/unittest/windows/scripts/setup_env.sh + - save_cache: + + key: env-v2-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + + paths: + - conda + - env + - run: + name: Install torchvision + command: .circleci/unittest/windows/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/windows/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/windows/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_windows_gpu: + <<: *binary_common + executor: + name: windows-gpu + environment: + CUDA_VERSION: "10.1" + PYTHON_VERSION: << parameters.python_version >> + steps: + - checkout + - designate_upload_channel + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - run: + name: Setup + command: .circleci/unittest/windows/scripts/setup_env.sh + - save_cache: + + key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + + paths: + - conda + - env + - run: + name: Install torchvision + command: .circleci/unittest/windows/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/windows/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/windows/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_macos_cpu: + <<: *binary_common + macos: + xcode: "9.4.1" + resource_class: large + steps: + - checkout + - designate_upload_channel + - run: + name: Install wget + command: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget + # Disable brew auto update which is very slow + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - restore_cache: + + keys: + - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + + key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + + paths: + - conda + - env + - run: + name: Install torchvision + command: .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + cmake_linux_cpu: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda102" + resource_class: 2xlarge+ + steps: + - checkout_merge + - designate_upload_channel + - run: + name: Setup conda + command: .circleci/unittest/linux/scripts/setup_env.sh + - run: packaging/build_cmake.sh + + cmake_linux_gpu: + <<: *binary_common + machine: + image: ubuntu-1604-cuda-10.1:201909-23 + resource_class: gpu.small + environment: + PYTHON_VERSION: << parameters.python_version >> + PYTORCH_VERSION: << parameters.pytorch_version >> + UNICODE_ABI: << parameters.unicode_abi >> + CU_VERSION: << parameters.cu_version >> + steps: + - checkout_merge + - designate_upload_channel + - run: + name: Setup conda + command: docker run -e CU_VERSION -e PYTHON_VERSION -e UNICODE_ABI -e PYTORCH_VERSION -t --gpus all -v $PWD:$PWD -w $PWD << parameters.wheel_docker_image >> .circleci/unittest/linux/scripts/setup_env.sh + - run: + name: Build torchvision C++ distribution and test + command: docker run -e CU_VERSION -e PYTHON_VERSION -e UNICODE_ABI -e PYTORCH_VERSION -e UPLOAD_CHANNEL -t --gpus all -v $PWD:$PWD -w $PWD << parameters.wheel_docker_image >> packaging/build_cmake.sh + + cmake_macos_cpu: + <<: *binary_common + macos: + xcode: "9.4.1" + steps: + - checkout_merge + - designate_upload_channel + - run: + command: | + curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh + sh conda.sh -b + source $HOME/miniconda3/bin/activate + conda install -yq conda-build cmake + packaging/build_cmake.sh + + cmake_windows_cpu: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout_merge + - designate_upload_channel + - run: + command: | + set -ex + source packaging/windows/internal/vc_install_helper.sh + packaging/build_cmake.sh + + cmake_windows_gpu: + <<: *binary_common + executor: + name: windows-gpu + steps: + - checkout_merge + - designate_upload_channel + - run: + command: | + set -ex + source packaging/windows/internal/vc_install_helper.sh + packaging/windows/internal/cuda_install.bat + packaging/build_cmake.sh workflows: build: @@ -377,6 +701,11 @@ workflows: name: binary_linux_wheel_py3.6_cu102 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_wheel: + cu_version: cu110 + name: binary_linux_wheel_py3.6_cu110 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda110 - binary_linux_wheel: cu_version: cpu name: binary_linux_wheel_py3.7_cpu @@ -397,6 +726,11 @@ workflows: name: binary_linux_wheel_py3.7_cu102 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_wheel: + cu_version: cu110 + name: binary_linux_wheel_py3.7_cu110 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda110 - binary_linux_wheel: cu_version: cpu name: binary_linux_wheel_py3.8_cpu @@ -417,6 +751,11 @@ workflows: name: binary_linux_wheel_py3.8_cu102 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_wheel: + cu_version: cu110 + name: binary_linux_wheel_py3.8_cu110 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda110 - binary_macos_wheel: cu_version: cpu name: binary_macos_wheel_py3.6_cpu @@ -432,84 +771,104 @@ workflows: name: binary_macos_wheel_py3.8_cpu python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 - - binary_win_wheel_release: + - binary_win_wheel: cu_version: cpu filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_wheel_py3.6_cpu python_version: '3.6' - - binary_win_wheel_release: - cu_version: cu92 - filters: - branches: - only: master - name: binary_win_wheel_py3.6_cu92 - python_version: '3.6' - - binary_win_wheel_release: + - binary_win_wheel: cu_version: cu101 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_wheel_py3.6_cu101 python_version: '3.6' - - binary_win_wheel_release: + - binary_win_wheel: cu_version: cu102 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_wheel_py3.6_cu102 python_version: '3.6' - - binary_win_wheel_release: - cu_version: cpu + - binary_win_wheel: + cu_version: cu110 filters: branches: only: master - name: binary_win_wheel_py3.7_cpu - python_version: '3.7' - - binary_win_wheel_release: - cu_version: cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: binary_win_wheel_py3.6_cu110 + python_version: '3.6' + - binary_win_wheel: + cu_version: cpu filters: branches: only: master - name: binary_win_wheel_py3.7_cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: binary_win_wheel_py3.7_cpu python_version: '3.7' - - binary_win_wheel_release: + - binary_win_wheel: cu_version: cu101 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_wheel_py3.7_cu101 python_version: '3.7' - - binary_win_wheel_release: + - binary_win_wheel: cu_version: cu102 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_wheel_py3.7_cu102 python_version: '3.7' - - binary_win_wheel_release: - cu_version: cpu - name: binary_win_wheel_py3.8_cpu - python_version: '3.8' - - binary_win_wheel_release: - cu_version: cu92 + - binary_win_wheel: + cu_version: cu110 filters: branches: only: master - name: binary_win_wheel_py3.8_cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: binary_win_wheel_py3.7_cu110 + python_version: '3.7' + - binary_win_wheel: + cu_version: cpu + name: binary_win_wheel_py3.8_cpu python_version: '3.8' - - binary_win_wheel_release: + - binary_win_wheel: cu_version: cu101 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_wheel_py3.8_cu101 python_version: '3.8' - - binary_win_wheel_release: + - binary_win_wheel: cu_version: cu102 + filters: + branches: + only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_wheel_py3.8_cu102 python_version: '3.8' + - binary_win_wheel: + cu_version: cu110 + name: binary_win_wheel_py3.8_cu110 + python_version: '3.8' - binary_linux_conda: cu_version: cpu name: binary_linux_conda_py3.6_cpu @@ -530,6 +889,11 @@ workflows: name: binary_linux_conda_py3.6_cu102 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_conda: + cu_version: cu110 + name: binary_linux_conda_py3.6_cu110 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda110 - binary_linux_conda: cu_version: cpu name: binary_linux_conda_py3.7_cpu @@ -550,6 +914,11 @@ workflows: name: binary_linux_conda_py3.7_cu102 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_conda: + cu_version: cu110 + name: binary_linux_conda_py3.7_cu110 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda110 - binary_linux_conda: cu_version: cpu name: binary_linux_conda_py3.8_cpu @@ -570,6 +939,11 @@ workflows: name: binary_linux_conda_py3.8_cu102 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 + - binary_linux_conda: + cu_version: cu110 + name: binary_linux_conda_py3.8_cu110 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda110 - binary_macos_conda: cu_version: cpu name: binary_macos_conda_py3.6_cpu @@ -585,105 +959,228 @@ workflows: name: binary_macos_conda_py3.8_cpu python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 - - binary_win_conda_release: + - binary_win_conda: cu_version: cpu filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_conda_py3.6_cpu python_version: '3.6' - - binary_win_conda_release: - cu_version: cu92 - filters: - branches: - only: master - name: binary_win_conda_py3.6_cu92 - python_version: '3.6' - - binary_win_conda_release: + - binary_win_conda: cu_version: cu101 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_conda_py3.6_cu101 python_version: '3.6' - - binary_win_conda_release: + - binary_win_conda: cu_version: cu102 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_conda_py3.6_cu102 python_version: '3.6' - - binary_win_conda_release: - cu_version: cpu + - binary_win_conda: + cu_version: cu110 filters: branches: only: master - name: binary_win_conda_py3.7_cpu - python_version: '3.7' - - binary_win_conda_release: - cu_version: cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: binary_win_conda_py3.6_cu110 + python_version: '3.6' + - binary_win_conda: + cu_version: cpu filters: branches: only: master - name: binary_win_conda_py3.7_cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: binary_win_conda_py3.7_cpu python_version: '3.7' - - binary_win_conda_release: + - binary_win_conda: cu_version: cu101 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_conda_py3.7_cu101 python_version: '3.7' - - binary_win_conda_release: + - binary_win_conda: cu_version: cu102 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_conda_py3.7_cu102 python_version: '3.7' - - binary_win_conda_release: - cu_version: cpu - name: binary_win_conda_py3.8_cpu - python_version: '3.8' - - binary_win_conda_release: - cu_version: cu92 + - binary_win_conda: + cu_version: cu110 filters: branches: only: master - name: binary_win_conda_py3.8_cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: binary_win_conda_py3.7_cu110 + python_version: '3.7' + - binary_win_conda: + cu_version: cpu + name: binary_win_conda_py3.8_cpu python_version: '3.8' - - binary_win_conda_release: + - binary_win_conda: cu_version: cu101 filters: branches: only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_conda_py3.8_cu101 python_version: '3.8' - - binary_win_conda_release: + - binary_win_conda: cu_version: cu102 + filters: + branches: + only: master + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: binary_win_conda_py3.8_cu102 python_version: '3.8' - - binary_linux_conda_cuda: - name: torchvision_linux_py3.8_cu102_cuda - python_version: "3.8" - cu_version: "cu102" - binary_win_conda: - name: torchvision_win_py3.6_cpu - python_version: "3.6" - cu_version: "cpu" - - binary_win_conda_cuda: - name: torchvision_win_py3.6_cu101 - python_version: "3.6" - cu_version: "cu101" + cu_version: cu110 + name: binary_win_conda_py3.8_cu110 + python_version: '3.8' + - python_lint + - python_type_check + - clang_format + + unittest: + jobs: + - unittest_linux_cpu: + cu_version: cpu + name: unittest_linux_cpu_py3.6 + python_version: '3.6' + - unittest_linux_cpu: + cu_version: cpu + name: unittest_linux_cpu_py3.7 + python_version: '3.7' + - unittest_linux_cpu: + cu_version: cpu + name: unittest_linux_cpu_py3.8 + python_version: '3.8' + - unittest_linux_gpu: + cu_version: cu101 + filters: + branches: + only: + - master + - nightly + name: unittest_linux_gpu_py3.6 + python_version: '3.6' + - unittest_linux_gpu: + cu_version: cu101 + filters: + branches: + only: + - master + - nightly + name: unittest_linux_gpu_py3.7 + python_version: '3.7' + - unittest_linux_gpu: + cu_version: cu101 + name: unittest_linux_gpu_py3.8 + python_version: '3.8' + - unittest_windows_cpu: + cu_version: cpu + name: unittest_windows_cpu_py3.6 + python_version: '3.6' + - unittest_windows_cpu: + cu_version: cpu + name: unittest_windows_cpu_py3.7 + python_version: '3.7' + - unittest_windows_cpu: + cu_version: cpu + name: unittest_windows_cpu_py3.8 + python_version: '3.8' + - unittest_windows_gpu: + cu_version: cu101 + filters: + branches: + only: + - master + - nightly + name: unittest_windows_gpu_py3.6 + python_version: '3.6' + - unittest_windows_gpu: + cu_version: cu101 + filters: + branches: + only: + - master + - nightly + name: unittest_windows_gpu_py3.7 + python_version: '3.7' + - unittest_windows_gpu: + cu_version: cu101 + name: unittest_windows_gpu_py3.8 + python_version: '3.8' + - unittest_macos_cpu: + cu_version: cpu + name: unittest_macos_cpu_py3.6 + python_version: '3.6' + - unittest_macos_cpu: + cu_version: cpu + name: unittest_macos_cpu_py3.7 + python_version: '3.7' + - unittest_macos_cpu: + cu_version: cpu + name: unittest_macos_cpu_py3.8 + python_version: '3.8' + + cmake: + jobs: + - cmake_linux_cpu: + cu_version: cpu + name: cmake_linux_cpu + python_version: '3.8' + - cmake_linux_gpu: + cu_version: cu101 + name: cmake_linux_gpu + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda101 + - cmake_windows_cpu: + cu_version: cpu + name: cmake_windows_cpu + python_version: '3.8' + - cmake_windows_gpu: + cu_version: cu101 + name: cmake_windows_gpu + python_version: '3.8' + - cmake_macos_cpu: + cu_version: cpu + name: cmake_macos_cpu + python_version: '3.8' nightly: jobs: - circleci_consistency + - python_lint + - python_type_check + - clang_format - binary_linux_wheel: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.6_cpu python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 @@ -696,13 +1193,24 @@ workflows: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.6_cpu_upload requires: - - nightly_binary_linux_wheel_py3.6_cpu - subfolder: cpu/ + - nightly_binary_linux_wheel_py3.6_cpu + subfolder: cpu/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.6_cpu_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_linux_wheel_py3.6_cpu_upload - binary_linux_wheel: cu_version: cu92 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.6_cu92 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda92 @@ -717,11 +1225,22 @@ workflows: requires: - nightly_binary_linux_wheel_py3.6_cu92 subfolder: cu92/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.6_cu92_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_linux_wheel_py3.6_cu92_upload - binary_linux_wheel: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.6_cu101 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda101 @@ -736,11 +1255,22 @@ workflows: requires: - nightly_binary_linux_wheel_py3.6_cu101 subfolder: cu101/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.6_cu101_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_linux_wheel_py3.6_cu101_upload - binary_linux_wheel: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.6_cu102 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 @@ -755,11 +1285,52 @@ workflows: requires: - nightly_binary_linux_wheel_py3.6_cu102 subfolder: cu102/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.6_cu102_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_linux_wheel_py3.6_cu102_upload + - binary_linux_wheel: + cu_version: cu110 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_cu110 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda110 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_cu110_upload + requires: + - nightly_binary_linux_wheel_py3.6_cu110 + subfolder: cu110/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.6_cu110_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_linux_wheel_py3.6_cu110_upload - binary_linux_wheel: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.7_cpu python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 @@ -774,11 +1345,22 @@ workflows: requires: - nightly_binary_linux_wheel_py3.7_cpu subfolder: cpu/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.7_cpu_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_linux_wheel_py3.7_cpu_upload - binary_linux_wheel: cu_version: cu92 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.7_cu92 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda92 @@ -793,11 +1375,22 @@ workflows: requires: - nightly_binary_linux_wheel_py3.7_cu92 subfolder: cu92/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.7_cu92_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_linux_wheel_py3.7_cu92_upload - binary_linux_wheel: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.7_cu101 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda101 @@ -812,11 +1405,22 @@ workflows: requires: - nightly_binary_linux_wheel_py3.7_cu101 subfolder: cu101/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.7_cu101_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_linux_wheel_py3.7_cu101_upload - binary_linux_wheel: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.7_cu102 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 @@ -831,11 +1435,52 @@ workflows: requires: - nightly_binary_linux_wheel_py3.7_cu102 subfolder: cu102/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.7_cu102_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_linux_wheel_py3.7_cu102_upload + - binary_linux_wheel: + cu_version: cu110 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_cu110 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda110 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_cu110_upload + requires: + - nightly_binary_linux_wheel_py3.7_cu110 + subfolder: cu110/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.7_cu110_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_linux_wheel_py3.7_cu110_upload - binary_linux_wheel: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.8_cpu python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 @@ -850,11 +1495,22 @@ workflows: requires: - nightly_binary_linux_wheel_py3.8_cpu subfolder: cpu/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.8_cpu_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_linux_wheel_py3.8_cpu_upload - binary_linux_wheel: cu_version: cu92 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.8_cu92 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda92 @@ -869,11 +1525,22 @@ workflows: requires: - nightly_binary_linux_wheel_py3.8_cu92 subfolder: cu92/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.8_cu92_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_linux_wheel_py3.8_cu92_upload - binary_linux_wheel: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.8_cu101 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda101 @@ -888,11 +1555,22 @@ workflows: requires: - nightly_binary_linux_wheel_py3.8_cu101 subfolder: cu101/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.8_cu101_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_linux_wheel_py3.8_cu101_upload - binary_linux_wheel: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_wheel_py3.8_cu102 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 @@ -907,11 +1585,52 @@ workflows: requires: - nightly_binary_linux_wheel_py3.8_cu102 subfolder: cu102/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.8_cu102_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_linux_wheel_py3.8_cu102_upload + - binary_linux_wheel: + cu_version: cu110 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_cu110 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda110 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_cu110_upload + requires: + - nightly_binary_linux_wheel_py3.8_cu110 + subfolder: cu110/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.8_cu110_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_linux_wheel_py3.8_cu110_upload - binary_macos_wheel: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_wheel_py3.6_cpu python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 @@ -931,6 +1650,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_wheel_py3.7_cpu python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 @@ -950,6 +1671,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_wheel_py3.8_cpu python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 @@ -964,11 +1687,13 @@ workflows: requires: - nightly_binary_macos_wheel_py3.8_cpu subfolder: '' - - binary_win_wheel_release: + - binary_win_wheel: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_wheel_py3.6_cpu python_version: '3.6' - binary_wheel_upload: @@ -982,29 +1707,22 @@ workflows: requires: - nightly_binary_win_wheel_py3.6_cpu subfolder: cpu/ - - binary_win_wheel_release: - cu_version: cu92 + - smoke_test_win_pip: filters: branches: - only: nightly - name: nightly_binary_win_wheel_py3.6_cu92 + only: + - nightly + name: nightly_binary_win_wheel_py3.6_cpu_smoke_test_pip python_version: '3.6' - - binary_wheel_upload: - context: org-member - filters: - branches: - only: nightly - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.6_cu92_upload requires: - - nightly_binary_win_wheel_py3.6_cu92 - subfolder: cu92/ - - binary_win_wheel_release: + - nightly_binary_win_wheel_py3.6_cpu_upload + - binary_win_wheel: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_wheel_py3.6_cu101 python_version: '3.6' - binary_wheel_upload: @@ -1018,11 +1736,22 @@ workflows: requires: - nightly_binary_win_wheel_py3.6_cu101 subfolder: cu101/ - - binary_win_wheel_release: + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.6_cu101_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_win_wheel_py3.6_cu101_upload + - binary_win_wheel: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_wheel_py3.6_cu102 python_version: '3.6' - binary_wheel_upload: @@ -1036,13 +1765,24 @@ workflows: requires: - nightly_binary_win_wheel_py3.6_cu102 subfolder: cu102/ - - binary_win_wheel_release: - cu_version: cpu + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.6_cu102_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_win_wheel_py3.6_cu102_upload + - binary_win_wheel: + cu_version: cu110 filters: branches: only: nightly - name: nightly_binary_win_wheel_py3.7_cpu - python_version: '3.7' + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.6_cu110 + python_version: '3.6' - binary_wheel_upload: context: org-member filters: @@ -1050,16 +1790,27 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.7_cpu_upload + name: nightly_binary_win_wheel_py3.6_cu110_upload requires: - - nightly_binary_win_wheel_py3.7_cpu - subfolder: cpu/ - - binary_win_wheel_release: - cu_version: cu92 + - nightly_binary_win_wheel_py3.6_cu110 + subfolder: cu110/ + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.6_cu110_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_win_wheel_py3.6_cu110_upload + - binary_win_wheel: + cu_version: cpu filters: branches: only: nightly - name: nightly_binary_win_wheel_py3.7_cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.7_cpu python_version: '3.7' - binary_wheel_upload: context: org-member @@ -1068,15 +1819,26 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.7_cu92_upload + name: nightly_binary_win_wheel_py3.7_cpu_upload requires: - - nightly_binary_win_wheel_py3.7_cu92 - subfolder: cu92/ - - binary_win_wheel_release: + - nightly_binary_win_wheel_py3.7_cpu + subfolder: cpu/ + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.7_cpu_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_win_wheel_py3.7_cpu_upload + - binary_win_wheel: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_wheel_py3.7_cu101 python_version: '3.7' - binary_wheel_upload: @@ -1090,11 +1852,22 @@ workflows: requires: - nightly_binary_win_wheel_py3.7_cu101 subfolder: cu101/ - - binary_win_wheel_release: + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.7_cu101_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_win_wheel_py3.7_cu101_upload + - binary_win_wheel: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_wheel_py3.7_cu102 python_version: '3.7' - binary_wheel_upload: @@ -1108,13 +1881,24 @@ workflows: requires: - nightly_binary_win_wheel_py3.7_cu102 subfolder: cu102/ - - binary_win_wheel_release: - cu_version: cpu + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.7_cu102_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_win_wheel_py3.7_cu102_upload + - binary_win_wheel: + cu_version: cu110 filters: branches: only: nightly - name: nightly_binary_win_wheel_py3.8_cpu - python_version: '3.8' + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.7_cu110 + python_version: '3.7' - binary_wheel_upload: context: org-member filters: @@ -1122,16 +1906,27 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.8_cpu_upload + name: nightly_binary_win_wheel_py3.7_cu110_upload requires: - - nightly_binary_win_wheel_py3.8_cpu - subfolder: cpu/ - - binary_win_wheel_release: - cu_version: cu92 + - nightly_binary_win_wheel_py3.7_cu110 + subfolder: cu110/ + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.7_cu110_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_win_wheel_py3.7_cu110_upload + - binary_win_wheel: + cu_version: cpu filters: branches: only: nightly - name: nightly_binary_win_wheel_py3.8_cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.8_cpu python_version: '3.8' - binary_wheel_upload: context: org-member @@ -1140,15 +1935,26 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.8_cu92_upload + name: nightly_binary_win_wheel_py3.8_cpu_upload requires: - - nightly_binary_win_wheel_py3.8_cu92 - subfolder: cu92/ - - binary_win_wheel_release: + - nightly_binary_win_wheel_py3.8_cpu + subfolder: cpu/ + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.8_cpu_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_win_wheel_py3.8_cpu_upload + - binary_win_wheel: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_wheel_py3.8_cu101 python_version: '3.8' - binary_wheel_upload: @@ -1162,11 +1968,22 @@ workflows: requires: - nightly_binary_win_wheel_py3.8_cu101 subfolder: cu101/ - - binary_win_wheel_release: + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.8_cu101_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_win_wheel_py3.8_cu101_upload + - binary_win_wheel: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_wheel_py3.8_cu102 python_version: '3.8' - binary_wheel_upload: @@ -1180,11 +1997,51 @@ workflows: requires: - nightly_binary_win_wheel_py3.8_cu102 subfolder: cu102/ + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.8_cu102_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_win_wheel_py3.8_cu102_upload + - binary_win_wheel: + cu_version: cu110 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.8_cu110 + python_version: '3.8' + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_wheel_py3.8_cu110_upload + requires: + - nightly_binary_win_wheel_py3.8_cu110 + subfolder: cu110/ + - smoke_test_win_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_win_wheel_py3.8_cu110_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_win_wheel_py3.8_cu110_upload - binary_linux_conda: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.6_cpu python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 @@ -1198,11 +2055,22 @@ workflows: name: nightly_binary_linux_conda_py3.6_cpu_upload requires: - nightly_binary_linux_conda_py3.6_cpu + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.6_cpu_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_linux_conda_py3.6_cpu_upload - binary_linux_conda: cu_version: cu92 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.6_cu92 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda92 @@ -1216,11 +2084,22 @@ workflows: name: nightly_binary_linux_conda_py3.6_cu92_upload requires: - nightly_binary_linux_conda_py3.6_cu92 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.6_cu92_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_linux_conda_py3.6_cu92_upload - binary_linux_conda: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.6_cu101 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda101 @@ -1234,11 +2113,22 @@ workflows: name: nightly_binary_linux_conda_py3.6_cu101_upload requires: - nightly_binary_linux_conda_py3.6_cu101 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.6_cu101_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_linux_conda_py3.6_cu101_upload - binary_linux_conda: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.6_cu102 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 @@ -1252,11 +2142,51 @@ workflows: name: nightly_binary_linux_conda_py3.6_cu102_upload requires: - nightly_binary_linux_conda_py3.6_cu102 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.6_cu102_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_linux_conda_py3.6_cu102_upload + - binary_linux_conda: + cu_version: cu110 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cu110 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-cuda110 + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.6_cu110_upload + requires: + - nightly_binary_linux_conda_py3.6_cu110 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.6_cu110_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_linux_conda_py3.6_cu110_upload - binary_linux_conda: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.7_cpu python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 @@ -1270,11 +2200,22 @@ workflows: name: nightly_binary_linux_conda_py3.7_cpu_upload requires: - nightly_binary_linux_conda_py3.7_cpu + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.7_cpu_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_linux_conda_py3.7_cpu_upload - binary_linux_conda: cu_version: cu92 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.7_cu92 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda92 @@ -1288,11 +2229,22 @@ workflows: name: nightly_binary_linux_conda_py3.7_cu92_upload requires: - nightly_binary_linux_conda_py3.7_cu92 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.7_cu92_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_linux_conda_py3.7_cu92_upload - binary_linux_conda: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.7_cu101 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda101 @@ -1306,11 +2258,22 @@ workflows: name: nightly_binary_linux_conda_py3.7_cu101_upload requires: - nightly_binary_linux_conda_py3.7_cu101 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.7_cu101_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_linux_conda_py3.7_cu101_upload - binary_linux_conda: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.7_cu102 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 @@ -1324,11 +2287,51 @@ workflows: name: nightly_binary_linux_conda_py3.7_cu102_upload requires: - nightly_binary_linux_conda_py3.7_cu102 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.7_cu102_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_linux_conda_py3.7_cu102_upload + - binary_linux_conda: + cu_version: cu110 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cu110 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-cuda110 + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.7_cu110_upload + requires: + - nightly_binary_linux_conda_py3.7_cu110 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.7_cu110_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_linux_conda_py3.7_cu110_upload - binary_linux_conda: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.8_cpu python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 @@ -1342,11 +2345,22 @@ workflows: name: nightly_binary_linux_conda_py3.8_cpu_upload requires: - nightly_binary_linux_conda_py3.8_cpu + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.8_cpu_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_linux_conda_py3.8_cpu_upload - binary_linux_conda: cu_version: cu92 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.8_cu92 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda92 @@ -1360,11 +2374,22 @@ workflows: name: nightly_binary_linux_conda_py3.8_cu92_upload requires: - nightly_binary_linux_conda_py3.8_cu92 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.8_cu92_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_linux_conda_py3.8_cu92_upload - binary_linux_conda: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.8_cu101 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda101 @@ -1378,11 +2403,22 @@ workflows: name: nightly_binary_linux_conda_py3.8_cu101_upload requires: - nightly_binary_linux_conda_py3.8_cu101 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.8_cu101_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_linux_conda_py3.8_cu101_upload - binary_linux_conda: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_linux_conda_py3.8_cu102 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 @@ -1396,11 +2432,51 @@ workflows: name: nightly_binary_linux_conda_py3.8_cu102_upload requires: - nightly_binary_linux_conda_py3.8_cu102 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.8_cu102_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_linux_conda_py3.8_cu102_upload + - binary_linux_conda: + cu_version: cu110 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cu110 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-cuda110 + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_conda_py3.8_cu110_upload + requires: + - nightly_binary_linux_conda_py3.8_cu110 + - smoke_test_linux_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_conda_py3.8_cu110_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_linux_conda_py3.8_cu110_upload - binary_macos_conda: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_conda_py3.6_cpu python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 @@ -1419,6 +2495,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_conda_py3.7_cpu python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 @@ -1437,6 +2515,8 @@ workflows: filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_macos_conda_py3.8_cpu python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 @@ -1450,11 +2530,13 @@ workflows: name: nightly_binary_macos_conda_py3.8_cpu_upload requires: - nightly_binary_macos_conda_py3.8_cpu - - binary_win_conda_release: + - binary_win_conda: cu_version: cpu filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_conda_py3.6_cpu python_version: '3.6' - binary_conda_upload: @@ -1467,28 +2549,22 @@ workflows: name: nightly_binary_win_conda_py3.6_cpu_upload requires: - nightly_binary_win_conda_py3.6_cpu - - binary_win_conda_release: - cu_version: cu92 + - smoke_test_win_conda: filters: branches: - only: nightly - name: nightly_binary_win_conda_py3.6_cu92 + only: + - nightly + name: nightly_binary_win_conda_py3.6_cpu_smoke_test_conda python_version: '3.6' - - binary_conda_upload: - context: org-member - filters: - branches: - only: nightly - tags: - only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.6_cu92_upload requires: - - nightly_binary_win_conda_py3.6_cu92 - - binary_win_conda_release: + - nightly_binary_win_conda_py3.6_cpu_upload + - binary_win_conda: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_conda_py3.6_cu101 python_version: '3.6' - binary_conda_upload: @@ -1501,11 +2577,22 @@ workflows: name: nightly_binary_win_conda_py3.6_cu101_upload requires: - nightly_binary_win_conda_py3.6_cu101 - - binary_win_conda_release: + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.6_cu101_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_win_conda_py3.6_cu101_upload + - binary_win_conda: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_conda_py3.6_cu102 python_version: '3.6' - binary_conda_upload: @@ -1518,13 +2605,24 @@ workflows: name: nightly_binary_win_conda_py3.6_cu102_upload requires: - nightly_binary_win_conda_py3.6_cu102 - - binary_win_conda_release: - cu_version: cpu + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.6_cu102_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_win_conda_py3.6_cu102_upload + - binary_win_conda: + cu_version: cu110 filters: branches: only: nightly - name: nightly_binary_win_conda_py3.7_cpu - python_version: '3.7' + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.6_cu110 + python_version: '3.6' - binary_conda_upload: context: org-member filters: @@ -1532,15 +2630,26 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.7_cpu_upload + name: nightly_binary_win_conda_py3.6_cu110_upload requires: - - nightly_binary_win_conda_py3.7_cpu - - binary_win_conda_release: - cu_version: cu92 + - nightly_binary_win_conda_py3.6_cu110 + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.6_cu110_smoke_test_conda + python_version: '3.6' + requires: + - nightly_binary_win_conda_py3.6_cu110_upload + - binary_win_conda: + cu_version: cpu filters: branches: only: nightly - name: nightly_binary_win_conda_py3.7_cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.7_cpu python_version: '3.7' - binary_conda_upload: context: org-member @@ -1549,14 +2658,25 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.7_cu92_upload + name: nightly_binary_win_conda_py3.7_cpu_upload + requires: + - nightly_binary_win_conda_py3.7_cpu + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.7_cpu_smoke_test_conda + python_version: '3.7' requires: - - nightly_binary_win_conda_py3.7_cu92 - - binary_win_conda_release: + - nightly_binary_win_conda_py3.7_cpu_upload + - binary_win_conda: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_conda_py3.7_cu101 python_version: '3.7' - binary_conda_upload: @@ -1569,11 +2689,22 @@ workflows: name: nightly_binary_win_conda_py3.7_cu101_upload requires: - nightly_binary_win_conda_py3.7_cu101 - - binary_win_conda_release: + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.7_cu101_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_win_conda_py3.7_cu101_upload + - binary_win_conda: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_conda_py3.7_cu102 python_version: '3.7' - binary_conda_upload: @@ -1586,13 +2717,24 @@ workflows: name: nightly_binary_win_conda_py3.7_cu102_upload requires: - nightly_binary_win_conda_py3.7_cu102 - - binary_win_conda_release: - cu_version: cpu + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.7_cu102_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_win_conda_py3.7_cu102_upload + - binary_win_conda: + cu_version: cu110 filters: branches: only: nightly - name: nightly_binary_win_conda_py3.8_cpu - python_version: '3.8' + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.7_cu110 + python_version: '3.7' - binary_conda_upload: context: org-member filters: @@ -1600,15 +2742,26 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.8_cpu_upload + name: nightly_binary_win_conda_py3.7_cu110_upload requires: - - nightly_binary_win_conda_py3.8_cpu - - binary_win_conda_release: - cu_version: cu92 + - nightly_binary_win_conda_py3.7_cu110 + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.7_cu110_smoke_test_conda + python_version: '3.7' + requires: + - nightly_binary_win_conda_py3.7_cu110_upload + - binary_win_conda: + cu_version: cpu filters: branches: only: nightly - name: nightly_binary_win_conda_py3.8_cu92 + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.8_cpu python_version: '3.8' - binary_conda_upload: context: org-member @@ -1617,14 +2770,25 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.8_cu92_upload + name: nightly_binary_win_conda_py3.8_cpu_upload + requires: + - nightly_binary_win_conda_py3.8_cpu + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.8_cpu_smoke_test_conda + python_version: '3.8' requires: - - nightly_binary_win_conda_py3.8_cu92 - - binary_win_conda_release: + - nightly_binary_win_conda_py3.8_cpu_upload + - binary_win_conda: cu_version: cu101 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_conda_py3.8_cu101 python_version: '3.8' - binary_conda_upload: @@ -1637,11 +2801,22 @@ workflows: name: nightly_binary_win_conda_py3.8_cu101_upload requires: - nightly_binary_win_conda_py3.8_cu101 - - binary_win_conda_release: + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.8_cu101_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_win_conda_py3.8_cu101_upload + - binary_win_conda: cu_version: cu102 filters: branches: only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_conda_py3.8_cu102 python_version: '3.8' - binary_conda_upload: @@ -1653,4 +2828,52 @@ workflows: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: nightly_binary_win_conda_py3.8_cu102_upload requires: - - nightly_binary_win_conda_py3.8_cu102 \ No newline at end of file + - nightly_binary_win_conda_py3.8_cu102 + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.8_cu102_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_win_conda_py3.8_cu102_upload + - binary_win_conda: + cu_version: cu110 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.8_cu110 + python_version: '3.8' + - binary_conda_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_win_conda_py3.8_cu110_upload + requires: + - nightly_binary_win_conda_py3.8_cu110 + - smoke_test_win_conda: + filters: + branches: + only: + - nightly + name: nightly_binary_win_conda_py3.8_cu110_smoke_test_conda + python_version: '3.8' + requires: + - nightly_binary_win_conda_py3.8_cu110_upload + docker_build: + triggers: + - schedule: + cron: "0 10 * * 0" + filters: + branches: + only: + - master + jobs: + - smoke_test_docker_image_build: + context: org-member diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index e8f03474ce9..50f7041afab 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -64,6 +64,7 @@ binary_common: &binary_common cu_version: description: "CUDA version to build against, in CU format (e.g., cpu or cu100)" type: string + default: "cpu" unicode_abi: description: "Python 2.7 wheel only: whether or not we are cp27mu (default: no)" type: string @@ -78,6 +79,11 @@ binary_common: &binary_common UNICODE_ABI: << parameters.unicode_abi >> CU_VERSION: << parameters.cu_version >> +smoke_test_common: &smoke_test_common + <<: *binary_common + docker: + - image: torchvision/smoke_test:latest + jobs: circleci_consistency: docker: @@ -90,6 +96,42 @@ jobs: python .circleci/regenerate.py git diff --exit-code || (echo ".circleci/config.yml not in sync with config.yml.in! Run .circleci/regenerate.py to update config"; exit 1) + python_lint: + docker: + - image: circleci/python:3.7 + steps: + - checkout + - run: + command: | + pip install --user --progress-bar off flake8 typing + flake8 --config=setup.cfg . + + python_type_check: + docker: + - image: circleci/python:3.7 + steps: + - checkout + - run: + command: | + sudo apt-get update -y + sudo apt install -y libturbojpeg-dev + pip install --user --progress-bar off numpy mypy + pip install --user --progress-bar off --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html + pip install --user --progress-bar off --editable . + mypy --config-file mypy.ini + + clang_format: + docker: + - image: circleci/python:3.7 + steps: + - checkout + - run: + command: | + curl https://oss-clang-format.s3.us-east-2.amazonaws.com/linux64/clang-format-linux64 -o clang-format + chmod +x clang-format + sudo mv clang-format /opt/clang-format + ./travis-scripts/run-clang-format/run-clang-format.py -r torchvision/csrc --clang-format-executable /opt/clang-format + binary_linux_wheel: <<: *binary_common docker: @@ -97,6 +139,7 @@ jobs: resource_class: 2xlarge+ steps: - checkout_merge + - designate_upload_channel - run: packaging/build_wheel.sh - store_artifacts: path: dist @@ -112,6 +155,7 @@ jobs: resource_class: 2xlarge+ steps: - checkout_merge + - designate_upload_channel - run: packaging/build_conda.sh - store_artifacts: path: /opt/conda/conda-bld/linux-64 @@ -122,110 +166,12 @@ jobs: - store_test_results: path: build_results/ - binary_linux_conda_cuda: - <<: *binary_common - machine: - image: ubuntu-1604:201903-01 - resource_class: gpu.medium - steps: - - checkout_merge - - run: - name: Setup environment - command: | - set -ex - - curl -L https://packagecloud.io/circleci/trusty/gpgkey | sudo apt-key add - - curl -L https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add - - - sudo apt-get update - - sudo apt-get install \ - apt-transport-https \ - ca-certificates \ - curl \ - gnupg-agent \ - software-properties-common - - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - - - sudo add-apt-repository \ - "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) \ - stable" - - sudo apt-get update - export DOCKER_VERSION="5:19.03.2~3-0~ubuntu-xenial" - sudo apt-get install docker-ce=${DOCKER_VERSION} docker-ce-cli=${DOCKER_VERSION} containerd.io=1.2.6-3 - - # Add the package repositories - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list - - export NVIDIA_CONTAINER_VERSION="1.0.3-1" - sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit=${NVIDIA_CONTAINER_VERSION} - sudo systemctl restart docker - - DRIVER_FN="NVIDIA-Linux-x86_64-440.59.run" - wget "https://s3.amazonaws.com/ossci-linux/nvidia_driver/$DRIVER_FN" - sudo /bin/bash "$DRIVER_FN" -s --no-drm || (sudo cat /var/log/nvidia-installer.log && false) - nvidia-smi - - - run: - name: Pull docker image - command: | - set -ex - export DOCKER_IMAGE=pytorch/conda-cuda - echo Pulling docker image $DOCKER_IMAGE - docker pull $DOCKER_IMAGE >/dev/null - - - run: - name: Build and run tests - command: | - set -ex - - cd ${HOME}/project/ - - export DOCKER_IMAGE=pytorch/conda-cuda - export VARS_TO_PASS="-e PYTHON_VERSION -e BUILD_VERSION -e PYTORCH_VERSION -e UNICODE_ABI -e CU_VERSION" - - docker run --gpus all --ipc=host -v $(pwd):/remote -w /remote ${VARS_TO_PASS} ${DOCKER_IMAGE} ./packaging/build_conda.sh - binary_win_conda: <<: *binary_common executor: windows-cpu steps: - checkout_merge - - run: - command: | - set -ex - source packaging/windows/internal/vc_install_helper.sh - eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" - conda activate base - conda install -yq conda-build "conda-package-handling!=1.5.0" - packaging/build_conda.sh - - store_test_results: - path: build_results/ - - binary_win_conda_cuda: - <<: *binary_common - executor: windows-gpu - steps: - - checkout_merge - - run: - command: | - set -ex - source packaging/windows/internal/vc_install_helper.sh - eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" - conda activate base - conda install -yq conda-build "conda-package-handling!=1.5.0" - packaging/build_conda.sh - - binary_win_conda_release: - <<: *binary_common - executor: windows-cpu - steps: - - checkout_merge + - designate_upload_channel - run: name: Build conda packages command: | @@ -246,11 +192,12 @@ jobs: - store_test_results: path: build_results/ - binary_win_wheel_release: + binary_win_wheel: <<: *binary_common executor: windows-cpu steps: - checkout_merge + - designate_upload_channel - run: name: Build wheel packages command: | @@ -270,9 +217,10 @@ jobs: binary_macos_wheel: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" steps: - checkout_merge + - designate_upload_channel - run: # Cannot easily deduplicate this as source'ing activate # will set environment variables which we need to propagate @@ -292,9 +240,10 @@ jobs: binary_macos_conda: <<: *binary_common macos: - xcode: "9.0" + xcode: "9.4.1" steps: - checkout_merge + - designate_upload_channel - run: command: | curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh @@ -352,28 +301,416 @@ jobs: aws s3 cp "$pkg" "s3://pytorch/whl/${UPLOAD_CHANNEL}/<< parameters.subfolder >>" --acl public-read done + smoke_test_linux_conda: + <<: *smoke_test_common + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + name: install binaries + command: | + set -x + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + conda install -v -y -c pytorch-nightly pytorch + conda install -v -y $(ls ~/workspace/torchvision*.tar.bz2) + - run: + name: smoke test + command: | + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + python -c "import torchvision" + + smoke_test_linux_pip: + <<: *smoke_test_common + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + name: install binaries + command: | + set -x + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + pip install $(ls ~/workspace/torchvision*.whl) --pre -f https://download.pytorch.org/whl/nightly/torch_nightly.html + - run: + name: smoke test + command: | + source /usr/local/etc/profile.d/conda.sh && conda activate python${PYTHON_VERSION} + python -c "import torchvision" + + smoke_test_docker_image_build: + machine: + image: ubuntu-1604:201903-01 + resource_class: large + environment: + image_name: torchvision/smoke_test + steps: + - checkout + - designate_upload_channel + - run: + name: Build and push Docker image + no_output_timeout: "1h" + command: | + set +x + echo "${DOCKER_HUB_TOKEN}" | docker login --username "${DOCKER_HUB_USERNAME}" --password-stdin + set -x + cd .circleci/smoke_test/docker && docker build . -t ${image_name}:${CIRCLE_WORKFLOW_ID} + docker tag ${image_name}:${CIRCLE_WORKFLOW_ID} ${image_name}:latest + docker push ${image_name}:${CIRCLE_WORKFLOW_ID} + docker push ${image_name}:latest + + smoke_test_win_conda: + <<: *binary_common + executor: + name: windows-cpu + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + name: install binaries + command: | + set -x + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda env remove -n python${PYTHON_VERSION} || true + conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} + conda activate python${PYTHON_VERSION} + conda install Pillow + conda install -v -y -c pytorch-nightly pytorch + conda install -v -y $(ls ~/workspace/torchvision*.tar.bz2) + - run: + name: smoke test + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate python${PYTHON_VERSION} + python -c "import torchvision" + + smoke_test_win_pip: + <<: *binary_common + executor: + name: windows-cpu + steps: + - attach_workspace: + at: ~/workspace + - designate_upload_channel + - run: + name: install binaries + command: | + set -x + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda env remove -n python${PYTHON_VERSION} || true + conda create -yn python${PYTHON_VERSION} python=${PYTHON_VERSION} + conda activate python${PYTHON_VERSION} + pip install $(ls ~/workspace/torchvision*.whl) --pre -f https://download.pytorch.org/whl/nightly/torch_nightly.html + - run: + name: smoke test + command: | + eval "$('/C/tools/miniconda3/Scripts/conda.exe' 'shell.bash' 'hook')" + conda activate python${PYTHON_VERSION} + python -c "import torchvision" + + unittest_linux_cpu: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda102" + resource_class: 2xlarge+ + steps: + - checkout + - designate_upload_channel + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - restore_cache: + {% raw %} + keys: + - env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + {% endraw %} + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + {% endraw %} + paths: + - conda + - env + - run: + name: Install torchvision + command: .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_linux_gpu: + <<: *binary_common + machine: + image: ubuntu-1604-cuda-10.1:201909-23 + resource_class: gpu.small + environment: + image_name: "pytorch/manylinux-cuda101" + PYTHON_VERSION: << parameters.python_version >> + steps: + - checkout + - designate_upload_channel + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - run: + name: Setup + command: docker run -e PYTHON_VERSION -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v2-linux-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + {% endraw %} + paths: + - conda + - env + - run: + name: Install torchvision + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD -e UPLOAD_CHANNEL "${image_name}" .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post Process + command: docker run -t --gpus all -v $PWD:$PWD -w $PWD "${image_name}" .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_windows_cpu: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout + - designate_upload_channel + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - restore_cache: + {% raw %} + keys: + - env-v2-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + {% endraw %} + - run: + name: Setup + command: .circleci/unittest/windows/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v2-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + {% endraw %} + paths: + - conda + - env + - run: + name: Install torchvision + command: .circleci/unittest/windows/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/windows/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/windows/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_windows_gpu: + <<: *binary_common + executor: + name: windows-gpu + environment: + CUDA_VERSION: "10.1" + PYTHON_VERSION: << parameters.python_version >> + steps: + - checkout + - designate_upload_channel + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - run: + name: Setup + command: .circleci/unittest/windows/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + {% endraw %} + paths: + - conda + - env + - run: + name: Install torchvision + command: .circleci/unittest/windows/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/windows/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/windows/scripts/post_process.sh + - store_test_results: + path: test-results + + unittest_macos_cpu: + <<: *binary_common + macos: + xcode: "9.4.1" + resource_class: large + steps: + - checkout + - designate_upload_channel + - run: + name: Install wget + command: HOMEBREW_NO_AUTO_UPDATE=1 brew install wget + # Disable brew auto update which is very slow + - run: + name: Generate cache key + # This will refresh cache on Sundays, nightly build should generate new cache. + command: echo "$(date +"%Y-%U")" > .circleci-weekly + - restore_cache: + {% raw %} + keys: + - env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + {% endraw %} + - run: + name: Setup + command: .circleci/unittest/linux/scripts/setup_env.sh + - save_cache: + {% raw %} + key: env-v3-macos-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/linux/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} + {% endraw %} + paths: + - conda + - env + - run: + name: Install torchvision + command: .circleci/unittest/linux/scripts/install.sh + - run: + name: Run tests + command: .circleci/unittest/linux/scripts/run_test.sh + - run: + name: Post process + command: .circleci/unittest/linux/scripts/post_process.sh + - store_test_results: + path: test-results + + cmake_linux_cpu: + <<: *binary_common + docker: + - image: "pytorch/manylinux-cuda102" + resource_class: 2xlarge+ + steps: + - checkout_merge + - designate_upload_channel + - run: + name: Setup conda + command: .circleci/unittest/linux/scripts/setup_env.sh + - run: packaging/build_cmake.sh + + cmake_linux_gpu: + <<: *binary_common + machine: + image: ubuntu-1604-cuda-10.1:201909-23 + resource_class: gpu.small + environment: + PYTHON_VERSION: << parameters.python_version >> + PYTORCH_VERSION: << parameters.pytorch_version >> + UNICODE_ABI: << parameters.unicode_abi >> + CU_VERSION: << parameters.cu_version >> + steps: + - checkout_merge + - designate_upload_channel + - run: + name: Setup conda + command: docker run -e CU_VERSION -e PYTHON_VERSION -e UNICODE_ABI -e PYTORCH_VERSION -t --gpus all -v $PWD:$PWD -w $PWD << parameters.wheel_docker_image >> .circleci/unittest/linux/scripts/setup_env.sh + - run: + name: Build torchvision C++ distribution and test + command: docker run -e CU_VERSION -e PYTHON_VERSION -e UNICODE_ABI -e PYTORCH_VERSION -e UPLOAD_CHANNEL -t --gpus all -v $PWD:$PWD -w $PWD << parameters.wheel_docker_image >> packaging/build_cmake.sh + + cmake_macos_cpu: + <<: *binary_common + macos: + xcode: "9.4.1" + steps: + - checkout_merge + - designate_upload_channel + - run: + command: | + curl -o conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh + sh conda.sh -b + source $HOME/miniconda3/bin/activate + conda install -yq conda-build cmake + packaging/build_cmake.sh + + cmake_windows_cpu: + <<: *binary_common + executor: + name: windows-cpu + steps: + - checkout_merge + - designate_upload_channel + - run: + command: | + set -ex + source packaging/windows/internal/vc_install_helper.sh + packaging/build_cmake.sh + + cmake_windows_gpu: + <<: *binary_common + executor: + name: windows-gpu + steps: + - checkout_merge + - designate_upload_channel + - run: + command: | + set -ex + source packaging/windows/internal/vc_install_helper.sh + packaging/windows/internal/cuda_install.bat + packaging/build_cmake.sh workflows: build: {%- if True %} jobs: - circleci_consistency - {{ workflows(windows_latest_only=True) }} - - binary_linux_conda_cuda: - name: torchvision_linux_py3.8_cu102_cuda - python_version: "3.8" - cu_version: "cu102" - - binary_win_conda: - name: torchvision_win_py3.6_cpu - python_version: "3.6" - cu_version: "cpu" - - binary_win_conda_cuda: - name: torchvision_win_py3.6_cu101 - python_version: "3.6" - cu_version: "cu101" + {{ build_workflows(windows_latest_only=True) }} + - python_lint + - python_type_check + - clang_format + + unittest: + jobs: + {{ unittest_workflows() }} + + cmake: + jobs: + {{ cmake_workflows() }} nightly: {%- endif %} jobs: - circleci_consistency - {{ workflows(prefix="nightly_", filter_branch="nightly", upload=True) }} + - python_lint + - python_type_check + - clang_format + {{ build_workflows(prefix="nightly_", filter_branch="nightly", upload=True) }} + docker_build: + triggers: + - schedule: + cron: "0 10 * * 0" + filters: + branches: + only: + - master + jobs: + - smoke_test_docker_image_build: + context: org-member diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 1e929242974..43f87d93246 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -19,12 +19,18 @@ import os.path -def workflows(prefix='', filter_branch=None, upload=False, indentation=6, windows_latest_only=False): +PYTHON_VERSIONS = ["3.6", "3.7", "3.8"] + + +def build_workflows(prefix='', filter_branch=None, upload=False, indentation=6, windows_latest_only=False): w = [] for btype in ["wheel", "conda"]: for os_type in ["linux", "macos", "win"]: - python_versions = ["3.6", "3.7", "3.8"] - cu_versions = (["cpu", "cu92", "cu101", "cu102"] if os_type == "linux" or os_type == "win" else ["cpu"]) + python_versions = PYTHON_VERSIONS + cu_versions_dict = {"linux": ["cpu", "cu92", "cu101", "cu102", "cu110"], + "win": ["cpu", "cu101", "cu102", "cu110"], + "macos": ["cpu"]} + cu_versions = cu_versions_dict[os_type] for python_version in python_versions: for cu_version in cu_versions: for unicode in ([False, True] if btype == "wheel" and python_version == "2.7" else [False]): @@ -52,6 +58,9 @@ def workflow_pair(btype, os_type, python_version, cu_version, unicode, prefix='' if upload: w.append(generate_upload_workflow(base_workflow_name, os_type, btype, cu_version, filter_branch=filter_branch)) + if filter_branch == 'nightly' and os_type in ['linux', 'win']: + pydistro = 'pip' if btype == 'wheel' else 'conda' + w.append(generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version, os_type)) return w @@ -60,6 +69,7 @@ def workflow_pair(btype, os_type, python_version, cu_version, unicode, prefix='' "cu92": "pytorch/manylinux-cuda92", "cu101": "pytorch/manylinux-cuda101", "cu102": "pytorch/manylinux-cuda102", + "cu110": "pytorch/manylinux-cuda110", } @@ -86,12 +96,25 @@ def generate_base_workflow(base_workflow_name, python_version, cu_version, d["wheel_docker_image"] = get_manylinux_image(cu_version) if filter_branch is not None: - d["filters"] = {"branches": {"only": filter_branch}} + d["filters"] = { + "branches": { + "only": filter_branch + }, + "tags": { + # Using a raw string here to avoid having to escape + # anything + "only": r"/v[0-9]+(\.[0-9]+)*-rc[0-9]+/" + } + } - w = f"binary_{os_type}_{btype}_release" if os_type == "win" else f"binary_{os_type}_{btype}" + w = f"binary_{os_type}_{btype}" return {w: d} +def gen_filter_branch_tree(*branches): + return {"branches": {"only": [b for b in branches]}} + + def generate_upload_workflow(base_workflow_name, os_type, btype, cu_version, *, filter_branch=None): d = { "name": f"{base_workflow_name}_upload", @@ -117,18 +140,84 @@ def generate_upload_workflow(base_workflow_name, os_type, btype, cu_version, *, return {f"binary_{btype}_upload": d} +def generate_smoketest_workflow(pydistro, base_workflow_name, filter_branch, python_version, os_type): + + required_build_suffix = "_upload" + required_build_name = base_workflow_name + required_build_suffix + + smoke_suffix = f"smoke_test_{pydistro}" + d = { + "name": f"{base_workflow_name}_{smoke_suffix}", + "requires": [required_build_name], + "python_version": python_version, + } + + if filter_branch: + d["filters"] = gen_filter_branch_tree(filter_branch) + + return {"smoke_test_{os_type}_{pydistro}".format(os_type=os_type, pydistro=pydistro): d} + + def indent(indentation, data_list): return ("\n" + " " * indentation).join( yaml.dump(data_list, default_flow_style=False).splitlines()) +def unittest_workflows(indentation=6): + jobs = [] + for os_type in ["linux", "windows", "macos"]: + for device_type in ["cpu", "gpu"]: + if os_type == "macos" and device_type == "gpu": + continue + for i, python_version in enumerate(PYTHON_VERSIONS): + job = { + "name": f"unittest_{os_type}_{device_type}_py{python_version}", + "python_version": python_version, + } + + if device_type == 'gpu': + if python_version != "3.8": + job['filters'] = gen_filter_branch_tree('master', 'nightly') + job['cu_version'] = 'cu101' + else: + job['cu_version'] = 'cpu' + + jobs.append({f"unittest_{os_type}_{device_type}": job}) + + return indent(indentation, jobs) + + +def cmake_workflows(indentation=6): + jobs = [] + python_version = '3.8' + for os_type in ['linux', 'windows', 'macos']: + # Skip OSX CUDA + device_types = ['cpu', 'gpu'] if os_type != 'macos' else ['cpu'] + for device in device_types: + job = { + 'name': f'cmake_{os_type}_{device}', + 'python_version': python_version + } + + job['cu_version'] = 'cu101' if device == 'gpu' else 'cpu' + if device == 'gpu' and os_type == 'linux': + job['wheel_docker_image'] = 'pytorch/manylinux-cuda101' + jobs.append({f'cmake_{os_type}_{device}': job}) + return indent(indentation, jobs) + + if __name__ == "__main__": d = os.path.dirname(__file__) env = jinja2.Environment( loader=jinja2.FileSystemLoader(d), lstrip_blocks=True, autoescape=False, + keep_trailing_newline=True, ) with open(os.path.join(d, 'config.yml'), 'w') as f: - f.write(env.get_template('config.yml.in').render(workflows=workflows)) + f.write(env.get_template('config.yml.in').render( + build_workflows=build_workflows, + unittest_workflows=unittest_workflows, + cmake_workflows=cmake_workflows, + )) diff --git a/.circleci/smoke_test/docker/Dockerfile b/.circleci/smoke_test/docker/Dockerfile new file mode 100644 index 00000000000..c5082c5971e --- /dev/null +++ b/.circleci/smoke_test/docker/Dockerfile @@ -0,0 +1,36 @@ +# this Dockerfile is for torchvision smoke test, it will be created periodically via CI system +# if you need to do it locally, follow below steps once you have Docker installed +# assuming you're within the directory where this Dockerfile located +# $ docker build . -t torchvision/smoketest + +# if you want to push to aws ecr, make sure you have the rights to write to ECR, then run +# $ eval $(aws ecr get-login --region us-east-1 --no-include-email) +# $ export MYTAG=localbuild ## you can choose whatever tag you like +# $ docker tag torchvision/smoketest 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchvision/smoke_test:${MYTAG} +# $ docker push 308535385114.dkr.ecr.us-east-1.amazonaws.com/torchvision/smoke_test:${MYTAG} + +FROM ubuntu:latest + +RUN apt-get -qq update && apt-get -qq -y install curl bzip2 libsox-fmt-all \ + && curl -sSL https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -o /tmp/miniconda.sh \ + && bash /tmp/miniconda.sh -bfp /usr/local \ + && rm -rf /tmp/miniconda.sh \ + && conda install -y python=3 \ + && conda update conda \ + && apt-get -qq -y remove curl bzip2 \ + && apt-get -qq -y autoremove \ + && apt-get autoclean \ + && rm -rf /var/lib/apt/lists/* /var/log/dpkg.log \ + && conda clean --all --yes + +ENV PATH /opt/conda/bin:$PATH + +RUN conda create -y --name python3.6 python=3.6 +RUN conda create -y --name python3.7 python=3.7 +RUN conda create -y --name python3.8 python=3.8 +SHELL [ "/bin/bash", "-c" ] +RUN echo "source /usr/local/etc/profile.d/conda.sh" >> ~/.bashrc +RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.6 && conda install -y numpy Pillow +RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.7 && conda install -y numpy Pillow +RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.8 && conda install -y numpy Pillow +CMD [ "/bin/bash"] diff --git a/.circleci/unittest/linux/scripts/environment.yml b/.circleci/unittest/linux/scripts/environment.yml new file mode 100644 index 00000000000..b2d5efdf533 --- /dev/null +++ b/.circleci/unittest/linux/scripts/environment.yml @@ -0,0 +1,18 @@ +channels: + - pytorch + - defaults +dependencies: + - numpy + - pytest + - pytest-cov + - codecov + - pip + - libpng + - jpeg + - ffmpeg=4.2 + - ca-certificates + - pip: + - future + - pillow>=4.1.1 + - scipy + - av diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh new file mode 100755 index 00000000000..2de17f12744 --- /dev/null +++ b/.circleci/unittest/linux/scripts/install.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash + +unset PYTORCH_VERSION +# For unittest, nightly PyTorch is used as the following section, +# so no need to set PYTORCH_VERSION. +# In fact, keeping PYTORCH_VERSION forces us to hardcode PyTorch version in config. + +set -e + +eval "$(./conda/bin/conda shell.bash hook)" +conda activate ./env + +if [ "${CU_VERSION:-}" == cpu ] ; then + cudatoolkit="cpuonly" +else + if [[ ${#CU_VERSION} -eq 4 ]]; then + CUDA_VERSION="${CU_VERSION:2:1}.${CU_VERSION:3:1}" + elif [[ ${#CU_VERSION} -eq 5 ]]; then + CUDA_VERSION="${CU_VERSION:2:2}.${CU_VERSION:4:1}" + fi + echo "Using CUDA $CUDA_VERSION as determined by CU_VERSION" + version="$(python -c "print('.'.join(\"${CUDA_VERSION}\".split('.')[:2]))")" + cudatoolkit="cudatoolkit=${version}" +fi +printf "Installing PyTorch with %s\n" "${cudatoolkit}" +conda install -y -c "pytorch-${UPLOAD_CHANNEL}" pytorch "${cudatoolkit}" + +printf "* Installing torchvision\n" +python setup.py develop diff --git a/.circleci/unittest/linux/scripts/post_process.sh b/.circleci/unittest/linux/scripts/post_process.sh new file mode 100755 index 00000000000..a84a0dea55e --- /dev/null +++ b/.circleci/unittest/linux/scripts/post_process.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +eval "$(./conda/bin/conda shell.bash hook)" +conda activate ./env + +codecov diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh new file mode 100755 index 00000000000..419b9eb562c --- /dev/null +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e + +eval "$(./conda/bin/conda shell.bash hook)" +conda activate ./env + +export PYTORCH_TEST_WITH_SLOW='1' +python -m torch.utils.collect_env +pytest --cov=torchvision --junitxml=test-results/junit.xml -v --durations 20 test --ignore=test/test_datasets_download.py diff --git a/.circleci/unittest/linux/scripts/setup_env.sh b/.circleci/unittest/linux/scripts/setup_env.sh new file mode 100755 index 00000000000..44ee98b91d0 --- /dev/null +++ b/.circleci/unittest/linux/scripts/setup_env.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# This script is for setting up environment in which unit test is ran. +# To speed up the CI time, the resulting environment is cached. +# +# Do not install PyTorch and torchvision here, otherwise they also get cached. + +set -e + +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +root_dir="$(git rev-parse --show-toplevel)" +conda_dir="${root_dir}/conda" +env_dir="${root_dir}/env" + +cd "${root_dir}" + +case "$(uname -s)" in + Darwin*) os=MacOSX;; + *) os=Linux +esac + +# 1. Install conda at ./conda +if [ ! -d "${conda_dir}" ]; then + printf "* Installing conda\n" + wget -O miniconda.sh "http://repo.continuum.io/miniconda/Miniconda3-latest-${os}-x86_64.sh" + bash ./miniconda.sh -b -f -p "${conda_dir}" +fi +eval "$(${conda_dir}/bin/conda shell.bash hook)" + +# 2. Create test environment at ./env +if [ ! -d "${env_dir}" ]; then + printf "* Creating a test environment\n" + conda create --prefix "${env_dir}" -y python="$PYTHON_VERSION" +fi +conda activate "${env_dir}" + +# 3. Install Conda dependencies +printf "* Installing dependencies (except PyTorch)\n" +conda env update --file "${this_dir}/environment.yml" --prune diff --git a/.circleci/unittest/windows/scripts/environment.yml b/.circleci/unittest/windows/scripts/environment.yml new file mode 100644 index 00000000000..9f4348ebb26 --- /dev/null +++ b/.circleci/unittest/windows/scripts/environment.yml @@ -0,0 +1,18 @@ +channels: + - pytorch + - defaults +dependencies: + - numpy + - pytest + - pytest-cov + - codecov + - pip + - libpng + - jpeg + - ca-certificates + - pip: + - future + - pillow>=4.1.1 + - scipy==1.4.1 + - av + - dataclasses diff --git a/.circleci/unittest/windows/scripts/install.sh b/.circleci/unittest/windows/scripts/install.sh new file mode 100644 index 00000000000..bdf2a869fe1 --- /dev/null +++ b/.circleci/unittest/windows/scripts/install.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +unset PYTORCH_VERSION +# For unittest, nightly PyTorch is used as the following section, +# so no need to set PYTORCH_VERSION. +# In fact, keeping PYTORCH_VERSION forces us to hardcode PyTorch version in config. + +set -e + +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" +conda activate ./env + +if [ "${CU_VERSION:-}" == cpu ] ; then + cudatoolkit="cpuonly" +else + if [[ ${#CU_VERSION} -eq 4 ]]; then + CUDA_VERSION="${CU_VERSION:2:1}.${CU_VERSION:3:1}" + elif [[ ${#CU_VERSION} -eq 5 ]]; then + CUDA_VERSION="${CU_VERSION:2:2}.${CU_VERSION:4:1}" + fi + echo "Using CUDA $CUDA_VERSION as determined by CU_VERSION" + version="$(python -c "print('.'.join(\"${CUDA_VERSION}\".split('.')[:2]))")" + cudatoolkit="cudatoolkit=${version}" +fi +printf "Installing PyTorch with %s\n" "${cudatoolkit}" +conda install -y -c "pytorch-${UPLOAD_CHANNEL}" pytorch "${cudatoolkit}" + +printf "* Installing torchvision\n" +"$this_dir/vc_env_helper.bat" python setup.py develop diff --git a/.circleci/unittest/windows/scripts/install_conda.bat b/.circleci/unittest/windows/scripts/install_conda.bat new file mode 100644 index 00000000000..6612fba56f6 --- /dev/null +++ b/.circleci/unittest/windows/scripts/install_conda.bat @@ -0,0 +1 @@ +start /wait "" "%miniconda_exe%" /S /InstallationType=JustMe /RegisterPython=0 /AddToPath=0 /D=%tmp_conda% \ No newline at end of file diff --git a/.circleci/unittest/windows/scripts/post_process.sh b/.circleci/unittest/windows/scripts/post_process.sh new file mode 100644 index 00000000000..b132113194b --- /dev/null +++ b/.circleci/unittest/windows/scripts/post_process.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" +conda activate ./env + +codecov diff --git a/.circleci/unittest/windows/scripts/run_test.sh b/.circleci/unittest/windows/scripts/run_test.sh new file mode 100644 index 00000000000..96d9cbd6b2d --- /dev/null +++ b/.circleci/unittest/windows/scripts/run_test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e + +eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" +conda activate ./env + +export PYTORCH_TEST_WITH_SLOW='1' +python -m torch.utils.collect_env +pytest --cov=torchvision --junitxml=test-results/junit.xml -v --durations 20 test --ignore=test/test_datasets_download.py diff --git a/.circleci/unittest/windows/scripts/setup_env.sh b/.circleci/unittest/windows/scripts/setup_env.sh new file mode 100644 index 00000000000..b0b70631112 --- /dev/null +++ b/.circleci/unittest/windows/scripts/setup_env.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# This script is for setting up environment in which unit test is ran. +# To speed up the CI time, the resulting environment is cached. +# +# Do not install PyTorch and torchvision here, otherwise they also get cached. + +set -e + +this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +root_dir="$(git rev-parse --show-toplevel)" +conda_dir="${root_dir}/conda" +env_dir="${root_dir}/env" + +cd "${root_dir}" + +# 1. Install conda at ./conda +if [ ! -d "${conda_dir}" ]; then + printf "* Installing conda\n" + export tmp_conda="$(echo $conda_dir | tr '/' '\\')" + export miniconda_exe="$(echo $root_dir | tr '/' '\\')\\miniconda.exe" + curl --output miniconda.exe https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -O + "$this_dir/install_conda.bat" + unset tmp_conda + unset miniconda_exe +fi + +eval "$(${conda_dir}/Scripts/conda.exe 'shell.bash' 'hook')" + +# 2. Create test environment at ./env +if [ ! -d "${env_dir}" ]; then + printf "* Creating a test environment\n" + conda create --prefix "${env_dir}" -y python="$PYTHON_VERSION" +fi +conda activate "${env_dir}" + +# 3. Install Conda dependencies +printf "* Installing dependencies (except PyTorch)\n" +conda env update --file "${this_dir}/environment.yml" --prune diff --git a/.circleci/unittest/windows/scripts/vc_env_helper.bat b/.circleci/unittest/windows/scripts/vc_env_helper.bat new file mode 100644 index 00000000000..9410135677a --- /dev/null +++ b/.circleci/unittest/windows/scripts/vc_env_helper.bat @@ -0,0 +1,39 @@ +@echo on + +set VC_VERSION_LOWER=16 +set VC_VERSION_UPPER=17 + +for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -legacy -products * -version [%VC_VERSION_LOWER%^,%VC_VERSION_UPPER%^) -property installationPath`) do ( + if exist "%%i" if exist "%%i\VC\Auxiliary\Build\vcvarsall.bat" ( + set "VS15INSTALLDIR=%%i" + set "VS15VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat" + goto vswhere + ) +) + +:vswhere +if "%VSDEVCMD_ARGS%" == "" ( + call "%VS15VCVARSALL%" x64 || exit /b 1 +) else ( + call "%VS15VCVARSALL%" x64 %VSDEVCMD_ARGS% || exit /b 1 +) + +@echo on + +set DISTUTILS_USE_SDK=1 + +set args=%1 +shift +:start +if [%1] == [] goto done +set args=%args% %1 +shift +goto start + +:done +if "%args%" == "" ( + echo Usage: vc_env_helper.bat [command] [args] + echo e.g. vc_env_helper.bat cl /c test.cpp +) + +%args% || exit /b 1 diff --git a/.gitattributes b/.gitattributes index a476e7afb59..22d0452f8d7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,8 @@ *.pkl binary +# Jupyter notebook + +# For text count +# *.ipynb text + +# To ignore it use below +*.ipynb linguist-documentation diff --git a/.gitignore b/.gitignore index 5f483c84327..3c7e579c23c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,8 @@ htmlcov *.swp *.swo gen.yml +.mypy_cache +.vscode/ +.idea/ +*.orig +*-checkpoint.ipynb diff --git a/.travis.yml b/.travis.yml index d08225c29bb..49b6e4ab517 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,31 +1,19 @@ language: python -dist: xenial -matrix: +os: + - linux + +dist: bionic + +jobs: include: - - env: FORMAT_CHECK - language: cpp - addons: - apt: - sources: - - llvm-toolchain-xenial-7 - packages: - - clang-7 - - clang-format-7 - before_install: skip - install: skip - script: ./travis-scripts/run-clang-format/run-clang-format.py -r torchvision/csrc - - env: LINT_CHECK - python: "3.6" - install: pip install flake8 typing - script: flake8 .circleci - after_success: [] - python: "3.6" env: IMAGE_BACKEND=Pillow-SIMD - python: "3.6" before_install: - sudo apt-get update + - sudo apt-get install -y libpng-dev libjpeg-turbo8-dev - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; - bash miniconda.sh -b -p $HOME/miniconda - export PATH="$HOME/miniconda/bin:$PATH" @@ -34,7 +22,7 @@ before_install: # Useful for debugging any issues with conda - conda info -a - - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION pytorch scipy -c pytorch-nightly + - conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION cpuonly pytorch scipy -c pytorch-nightly - source activate test-environment - | if [[ "$IMAGE_BACKEND" == "Pillow-SIMD" ]]; then @@ -42,16 +30,14 @@ before_install: fi - pip install future - pip install pytest pytest-cov codecov - - pip install mock - pip install typing - | if [[ $TRAVIS_PYTHON_VERSION == 3.6 ]]; then pip install -q --user typing-extensions==3.6.6 - pip install -q --user -i https://test.pypi.org/simple/ ort-nightly==1.2.0.dev202005021 + pip install -q --user -i https://test.pypi.org/simple/ ort-nightly==1.5.2.dev202010191 fi - conda install av -c conda-forge - install: # Using pip instead of setup.py ensures we install a non-compressed version of the package # (as opposed to an egg), which is necessary to collect coverage. @@ -68,7 +54,7 @@ install: cd - script: - - pytest --cov-config .coveragerc --cov torchvision --cov $TV_INSTALL_PATH -k 'not TestVideoReader and not TestVideoTransforms' test + - pytest --cov-config .coveragerc --cov torchvision --cov $TV_INSTALL_PATH -k 'not TestVideo and not TestVideoReader and not TestVideoTransforms and not TestIO' test --ignore=test/test_datasets_download.py - pytest test/test_hub.py after_success: diff --git a/CMakeLists.txt b/CMakeLists.txt index d5655ad7ef7..81ca559d530 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,28 +1,105 @@ -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.1) project(torchvision) set(CMAKE_CXX_STANDARD 14) -enable_language(CUDA) +set(TORCHVISION_VERSION 0.7.0) -add_definitions(-D__CUDA_NO_HALF_OPERATORS__) +option(WITH_CUDA "Enable CUDA support" OFF) + +if(WITH_CUDA) + enable_language(CUDA) + add_definitions(-D__CUDA_NO_HALF_OPERATORS__) + add_definitions(-DWITH_CUDA) + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr") +endif() + +find_package(Python3 COMPONENTS Development) find_package(Torch REQUIRED) -find_package(pybind11 REQUIRED) +find_package(PNG REQUIRED) +find_package(JPEG REQUIRED) -include_directories(${PYTHON_INCLUDE_DIR}) +function(CUDA_CONVERT_FLAGS EXISTING_TARGET) + get_property(old_flags TARGET ${EXISTING_TARGET} PROPERTY INTERFACE_COMPILE_OPTIONS) + if(NOT "${old_flags}" STREQUAL "") + string(REPLACE ";" "," CUDA_flags "${old_flags}") + set_property(TARGET ${EXISTING_TARGET} PROPERTY INTERFACE_COMPILE_OPTIONS + "$<$>:${old_flags}>$<$>:-Xcompiler=${CUDA_flags}>" + ) + endif() +endfunction() file(GLOB HEADERS torchvision/csrc/*.h) -file(GLOB CPU_HEADERS torchvision/csrc/cpu/vision_cpu.h) -file(GLOB CPU_SOURCES torchvision/csrc/cuda/*.h torchvision/csrc/cpu/*.cpp) -file(GLOB CUDA_HEADERS torchvision/csrc/cuda/vision_cuda.h) -file(GLOB CUDA_SOURCES torchvision/csrc/cuda/*.h torchvision/csrc/cuda/*.cu) +# Image extension +file(GLOB IMAGE_HEADERS torchvision/csrc/cpu/image/*.h) +file(GLOB IMAGE_SOURCES torchvision/csrc/cpu/image/*.cpp) +file(GLOB OPERATOR_SOURCES torchvision/csrc/cpu/*.h torchvision/csrc/cpu/*.cpp ${IMAGE_HEADERS} ${IMAGE_SOURCES} ${HEADERS} torchvision/csrc/*.cpp) +if(WITH_CUDA) + file(GLOB OPERATOR_SOURCES ${OPERATOR_SOURCES} torchvision/csrc/cuda/*.h torchvision/csrc/cuda/*.cu) +endif() file(GLOB MODELS_HEADERS torchvision/csrc/models/*.h) file(GLOB MODELS_SOURCES torchvision/csrc/models/*.h torchvision/csrc/models/*.cpp) -add_library (${PROJECT_NAME} SHARED ${MODELS_SOURCES} ${CPU_SOURCES} ${CUDA_SOURCES}) -target_link_libraries(${PROJECT_NAME} PUBLIC "${TORCH_LIBRARIES}") +if(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4819") + if(WITH_CUDA) + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=/wd4819") + foreach(diag cc_clobber_ignored integer_sign_change useless_using_declaration + set_but_not_used field_without_dll_interface + base_class_has_different_dll_interface + dll_interface_conflict_none_assumed + dll_interface_conflict_dllexport_assumed + implicit_return_from_non_void_function + unsigned_compare_with_zero + declared_but_not_referenced + bad_friend_decl) + string(APPEND CMAKE_CUDA_FLAGS " -Xcudafe --diag_suppress=${diag}") + endforeach() + CUDA_CONVERT_FLAGS(torch_cpu) + CUDA_CONVERT_FLAGS(torch_cuda) + endif() +endif() + +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +add_library(${PROJECT_NAME} SHARED ${MODELS_SOURCES} ${OPERATOR_SOURCES} ${IMAGE_SOURCES}) +target_link_libraries(${PROJECT_NAME} PRIVATE ${TORCH_LIBRARIES} ${PNG_LIBRARY} ${JPEG_LIBRARIES} Python3::Python) +set_target_properties(${PROJECT_NAME} PROPERTIES + EXPORT_NAME TorchVision + INSTALL_RPATH ${TORCH_INSTALL_PREFIX}/lib) + +include_directories(torchvision/csrc ${JPEG_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS}) + +set(TORCHVISION_CMAKECONFIG_INSTALL_DIR "share/cmake/TorchVision" CACHE STRING "install path for TorchVisionConfig.cmake") + +configure_package_config_file(cmake/TorchVisionConfig.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/TorchVisionConfig.cmake" + INSTALL_DESTINATION ${TORCHVISION_CMAKECONFIG_INSTALL_DIR}) + +write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/TorchVisionConfigVersion.cmake + VERSION ${TORCHVISION_VERSION} + COMPATIBILITY AnyNewerVersion) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/TorchVisionConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/TorchVisionConfigVersion.cmake + DESTINATION ${TORCHVISION_CMAKECONFIG_INSTALL_DIR}) + +install(TARGETS ${PROJECT_NAME} + EXPORT TorchVisionTargets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + +install(EXPORT TorchVisionTargets + NAMESPACE TorchVision:: + DESTINATION ${TORCHVISION_CMAKECONFIG_INSTALL_DIR}) -install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) -install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}) -install(FILES ${CPU_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/cpu) -install(FILES ${CUDA_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/cuda) -install(FILES ${MODELS_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/${PROJECT_NAME}/models) +install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}) +install(FILES + torchvision/csrc/cpu/vision_cpu.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/cpu) +if(WITH_CUDA) + install(FILES + torchvision/csrc/cuda/vision_cuda.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/cuda) +endif() +install(FILES ${MODELS_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/models) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..b91e23b17c0 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic +address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a +professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies within all project spaces, and it also applies when +an individual is representing the project or its community in public spaces. +Examples of representing a project or community include using an official +project e-mail address, posting via an official social media account, or acting +as an appointed representative at an online or offline event. Representation of +a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at . All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/README.rst b/README.rst index 718ff01c898..d9daec6183f 100644 --- a/README.rst +++ b/README.rst @@ -20,7 +20,35 @@ The torchvision package consists of popular datasets, model architectures, and c Installation ============ -TorchVision requires PyTorch 1.2 or newer. +We recommend Anaconda as Python package management system. Please refer to `pytorch.org `_ +for the detail of PyTorch (``torch``) installation. The following is the corresponding ``torchvision`` versions and +supported Python versions. + ++--------------------------+--------------------------+---------------------------------+ +| ``torch`` | ``torchvision`` | ``python`` | ++==========================+==========================+=================================+ +| ``master`` / ``nightly`` | ``master`` / ``nightly`` | ``>=3.6`` | ++--------------------------+--------------------------+---------------------------------+ +| ``1.7.0`` | ``0.8.0`` | ``>=3.6`` | ++--------------------------+--------------------------+---------------------------------+ +| ``1.6.0`` | ``0.7.0`` | ``>=3.6`` | ++--------------------------+--------------------------+---------------------------------+ +| ``1.5.1`` | ``0.6.1`` | ``>=3.5`` | ++--------------------------+--------------------------+---------------------------------+ +| ``1.5.0`` | ``0.6.0`` | ``>=3.5`` | ++--------------------------+--------------------------+---------------------------------+ +| ``1.4.0`` | ``0.5.0`` | ``==2.7``, ``>=3.5``, ``<=3.8`` | ++--------------------------+--------------------------+---------------------------------+ +| ``1.3.1`` | ``0.4.2`` | ``==2.7``, ``>=3.5``, ``<=3.7`` | ++--------------------------+--------------------------+---------------------------------+ +| ``1.3.0`` | ``0.4.1`` | ``==2.7``, ``>=3.5``, ``<=3.7`` | ++--------------------------+--------------------------+---------------------------------+ +| ``1.2.0`` | ``0.4.0`` | ``==2.7``, ``>=3.5``, ``<=3.7`` | ++--------------------------+--------------------------+---------------------------------+ +| ``1.1.0`` | ``0.3.0`` | ``==2.7``, ``>=3.5``, ``<=3.7`` | ++--------------------------+--------------------------+---------------------------------+ +| ``<=1.0.1`` | ``0.2.2`` | ``==2.7``, ``>=3.5``, ``<=3.7`` | ++--------------------------+--------------------------+---------------------------------+ Anaconda: @@ -56,13 +84,23 @@ Torchvision currently supports the following image backends: * `accimage`_ - if installed can be activated by calling :code:`torchvision.set_image_backend('accimage')` +* `libpng`_ - can be installed via conda :code:`conda install libpng` or any of the package managers for debian-based and RHEL-based Linux distributions. + +* `libjpeg`_ - can be installed via conda :code:`conda install jpeg` or any of the package managers for debian-based and RHEL-based Linux distributions. `libjpeg-turbo`_ can be used as well. + +**Notes:** ``libpng`` and ``libjpeg`` must be available at compilation time in order to be available. Make sure that it is available on the standard library locations, +otherwise, add the include and library paths in the environment variables ``TORCHVISION_INCLUDE`` and ``TORCHVISION_LIBRARY``, respectively. + +.. _libpng : http://www.libpng.org/pub/png/libpng.html .. _Pillow : https://python-pillow.org/ .. _Pillow-SIMD : https://github.com/uploadcare/pillow-simd .. _accimage: https://github.com/pytorch/accimage +.. _libjpeg: http://ijg.org/ +.. _libjpeg-turbo: https://libjpeg-turbo.org/ C++ API ======= -TorchVision also offers a C++ API that contains C++ equivalent of python models. +TorchVision also offers a C++ API that contains C++ equivalent of python models. Installation From source: @@ -70,13 +108,31 @@ Installation From source: mkdir build cd build + # Add -DWITH_CUDA=on support for the CUDA if needed cmake .. - make + make make install +Once installed, the library can be accessed in cmake (after properly configuring ``CMAKE_PREFIX_PATH``) via the :code:`TorchVision::TorchVision` target: + +.. code:: rest + + find_package(TorchVision REQUIRED) + target_link_libraries(my-target PUBLIC TorchVision::TorchVision) + +The ``TorchVision`` package will also automatically look for the ``Torch`` package and add it as a dependency to ``my-target``, +so make sure that it is also available to cmake via the ``CMAKE_PREFIX_PATH``. + +For an example setup, take a look at ``examples/cpp/hello_world``. + +TorchVision Operators +--------------------- +In order to get the torchvision operators registered with torch (eg. for the JIT), all you need to do is to ensure that you +:code:`#include ` in your project. + Documentation ============= -You can find the API documentation on the pytorch website: http://pytorch.org/docs/master/torchvision/ +You can find the API documentation on the pytorch website: https://pytorch.org/docs/stable/torchvision/index.html Contributing ============ diff --git a/cmake/TorchVisionConfig.cmake.in b/cmake/TorchVisionConfig.cmake.in new file mode 100644 index 00000000000..42a3d566166 --- /dev/null +++ b/cmake/TorchVisionConfig.cmake.in @@ -0,0 +1,43 @@ +# TorchVisionConfig.cmake +# -------------------- +# +# Exported targets:: Vision +# + +@PACKAGE_INIT@ + +set(PN TorchVision) + +# location of include/torchvision +set(${PN}_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@") + +set(${PN}_LIBRARY "") +set(${PN}_DEFINITIONS USING_${PN}) + +check_required_components(${PN}) + + +if(NOT (CMAKE_VERSION VERSION_LESS 3.0)) +#----------------------------------------------------------------------------- +# Don't include targets if this file is being picked up by another +# project which has already built this as a subproject +#----------------------------------------------------------------------------- +if(NOT TARGET ${PN}::TorchVision) +include("${CMAKE_CURRENT_LIST_DIR}/${PN}Targets.cmake") + +if(NOT TARGET torch_library) +find_package(Torch REQUIRED) +endif() +if(NOT TARGET Python3::Python) +find_package(Python3 COMPONENTS Development) +endif() + +set_target_properties(TorchVision::TorchVision PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${${PN}_INCLUDE_DIR}" INTERFACE_LINK_LIBRARIES "torch;Python3::Python" ) + + +if(@WITH_CUDA@) + target_compile_definitions(TorchVision::TorchVision INTERFACE WITH_CUDA) +endif() + +endif() +endif() diff --git a/docs/requirements.txt b/docs/requirements.txt index 014f642d0eb..f649853cd03 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,3 +1,3 @@ sphinx==1.7.3 sphinxcontrib-googleanalytics --e git://github.com/snide/sphinx_rtd_theme.git#egg=sphinx_rtd_theme +-e git+git://github.com/pytorch/pytorch_sphinx_theme.git#egg=pytorch_sphinx_theme diff --git a/docs/source/conf.py b/docs/source/conf.py index fdb36238ff9..47f37c4fe25 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -22,7 +22,7 @@ # sys.path.insert(0, os.path.abspath('.')) import torch import torchvision -import sphinx_rtd_theme +import pytorch_sphinx_theme # -- General configuration ------------------------------------------------ @@ -104,8 +104,8 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] +html_theme = 'pytorch_sphinx_theme' +html_theme_path = [pytorch_sphinx_theme.get_html_theme_path()] # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -115,6 +115,7 @@ 'collapse_navigation': False, 'display_version': True, 'logo_only': True, + 'pytorch_project': 'docs', } html_logo = '_static/img/pytorch-logo-dark.svg' @@ -125,12 +126,12 @@ html_static_path = ['_static'] # html_style_path = 'css/pytorch_theme.css' -html_context = { - 'css_files': [ - 'https://fonts.googleapis.com/css?family=Lato', - '_static/css/pytorch_theme.css' - ], -} +# html_context = { +# 'css_files': [ +# 'https://fonts.googleapis.com/css?family=Lato', +# '_static/css/pytorch_theme.css' +# ], +# } # -- Options for HTMLHelp output ------------------------------------------ diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index 040962edc6a..fa04aded1ea 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -24,36 +24,31 @@ All the datasets have almost similar API. They all have two common arguments: .. currentmodule:: torchvision.datasets +CelebA +~~~~~~ -MNIST -~~~~~ - -.. autoclass:: MNIST - -Fashion-MNIST -~~~~~~~~~~~~~ - -.. autoclass:: FashionMNIST - -KMNIST -~~~~~~~~~~~~~ - -.. autoclass:: KMNIST +.. autoclass:: CelebA + :members: __getitem__ + :special-members: -EMNIST -~~~~~~ +CIFAR +~~~~~ -.. autoclass:: EMNIST +.. autoclass:: CIFAR10 + :members: __getitem__ + :special-members: -QMNIST -~~~~~~ +.. autoclass:: CIFAR100 -.. autoclass:: QMNIST +Cityscapes +~~~~~~~~~~ -FakeData -~~~~~~~~ +.. note :: + Requires Cityscape to be downloaded. -.. autoclass:: FakeData +.. autoclass:: Cityscapes + :members: __getitem__ + :special-members: COCO ~~~~ @@ -79,28 +74,53 @@ Detection :members: __getitem__ :special-members: -LSUN -~~~~ +DatasetFolder +~~~~~~~~~~~~~ -.. autoclass:: LSUN +.. autoclass:: DatasetFolder :members: __getitem__ :special-members: -ImageFolder -~~~~~~~~~~~ -.. autoclass:: ImageFolder +EMNIST +~~~~~~ + +.. autoclass:: EMNIST + +FakeData +~~~~~~~~ + +.. autoclass:: FakeData + +Fashion-MNIST +~~~~~~~~~~~~~ + +.. autoclass:: FashionMNIST + +Flickr +~~~~~~ + +.. autoclass:: Flickr8k :members: __getitem__ :special-members: -DatasetFolder -~~~~~~~~~~~~~ +.. autoclass:: Flickr30k + :members: __getitem__ + :special-members: -.. autoclass:: DatasetFolder +HMDB51 +~~~~~~~ + +.. autoclass:: HMDB51 :members: __getitem__ :special-members: +ImageFolder +~~~~~~~~~~~ +.. autoclass:: ImageFolder + :members: __getitem__ + :special-members: ImageNet ~~~~~~~~~~~ @@ -110,87 +130,86 @@ ImageNet .. note :: This requires `scipy` to be installed +Kinetics-400 +~~~~~~~~~~~~ -CIFAR -~~~~~ - -.. autoclass:: CIFAR10 +.. autoclass:: Kinetics400 :members: __getitem__ :special-members: -.. autoclass:: CIFAR100 +KMNIST +~~~~~~~~~~~~~ -STL10 -~~~~~ +.. autoclass:: KMNIST +LSUN +~~~~ -.. autoclass:: STL10 +.. autoclass:: LSUN :members: __getitem__ :special-members: -SVHN +MNIST ~~~~~ +.. autoclass:: MNIST -.. autoclass:: SVHN - :members: __getitem__ - :special-members: +Omniglot +~~~~~~ + +.. autoclass:: Omniglot PhotoTour ~~~~~~~~~ - .. autoclass:: PhotoTour :members: __getitem__ :special-members: -SBU -~~~ - +Places365 +~~~~~~~~~ -.. autoclass:: SBU +.. autoclass:: Places365 :members: __getitem__ :special-members: -Flickr +QMNIST ~~~~~~ +.. autoclass:: QMNIST -.. autoclass:: Flickr8k - :members: __getitem__ - :special-members: +SBD +~~~~~~ -.. autoclass:: Flickr30k +.. autoclass:: SBDataset :members: __getitem__ :special-members: -VOC -~~~~~~ - +SBU +~~~ -.. autoclass:: VOCSegmentation +.. autoclass:: SBU :members: __getitem__ :special-members: -.. autoclass:: VOCDetection +STL10 +~~~~~ + +.. autoclass:: STL10 :members: __getitem__ :special-members: -Cityscapes -~~~~~~~~~~ - -.. note :: - Requires Cityscape to be downloaded. +SVHN +~~~~~ -.. autoclass:: Cityscapes +.. autoclass:: SVHN :members: __getitem__ :special-members: -SBD -~~~~~~ - +UCF101 +~~~~~~~ -.. autoclass:: SBDataset +.. autoclass:: UCF101 :members: __getitem__ :special-members: @@ -201,26 +220,14 @@ USPS :members: __getitem__ :special-members: +VOC +~~~~~~ -Kinetics-400 -~~~~~~~~~~~~ - -.. autoclass:: Kinetics400 +.. autoclass:: VOCSegmentation :members: __getitem__ :special-members: - -HMDB51 -~~~~~~~ - -.. autoclass:: HMDB51 +.. autoclass:: VOCDetection :members: __getitem__ :special-members: - -UCF101 -~~~~~~~ - -.. autoclass:: UCF101 - :members: __getitem__ - :special-members: diff --git a/docs/source/index.rst b/docs/source/index.rst index 9de82b6e7fc..d4aefafed1d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,5 +1,28 @@ torchvision =========== +This library is part of the `PyTorch +`_ project. PyTorch is an open source +machine learning framework. + +Features described in this documentation are classified by release status: + + *Stable:* These features will be maintained long-term and there should generally + be no major performance limitations or gaps in documentation. + We also expect to maintain backwards compatibility (although + breaking changes can happen and notice will be given one release ahead + of time). + + *Beta:* Features are tagged as Beta because the API may change based on + user feedback, because the performance needs to improve, or because + coverage across operators is not yet complete. For Beta features, we are + committing to seeing the feature through to the Stable classification. + We are not, however, committing to backwards compatibility. + + *Prototype:* These features are typically not available as part of + binary distributions like PyPI or Conda, except sometimes behind run-time + flags, and are at an early stage for feedback and testing. + + The :mod:`torchvision` package consists of popular datasets, model architectures, and common image transformations for computer vision. @@ -17,3 +40,15 @@ architectures, and common image transformations for computer vision. .. automodule:: torchvision :members: + +.. toctree:: + :maxdepth: 1 + :caption: PyTorch Libraries + + PyTorch + torchaudio + torchtext + torchvision + TorchElastic + TorchServe + PyTorch on XLA Devices diff --git a/docs/source/io.rst b/docs/source/io.rst index e7aeedc0716..1d776369e84 100644 --- a/docs/source/io.rst +++ b/docs/source/io.rst @@ -4,7 +4,8 @@ torchvision.io .. currentmodule:: torchvision.io The :mod:`torchvision.io` package provides functions for performing IO -operations. They are currently specific to reading and writing video. +operations. They are currently specific to reading and writing video and +images. Video ----- @@ -14,3 +15,58 @@ Video .. autofunction:: read_video_timestamps .. autofunction:: write_video + + +Fine-grained video API +------------------- + +In addition to the :mod:`read_video` function, we provide a high-performance +lower-level API for more fine-grained control compared to the :mod:`read_video` function. +It does all this whilst fully supporting torchscript. + +.. autoclass:: VideoReader + :members: __next__, get_metadata, set_current_stream, seek + + +Example of inspecting a video: + +.. code:: python + + import torchvision + video_path = "path to a test video" + # Constructor allocates memory and a threaded decoder + # instance per video. At the moment it takes two arguments: + # path to the video file, and a wanted stream. + reader = torchvision.io.VideoReader(video_path, "video") + + # The information about the video can be retrieved using the + # `get_metadata()` method. It returns a dictionary for every stream, with + # duration and other relevant metadata (often frame rate) + reader_md = reader.get_metadata() + + # metadata is structured as a dict of dicts with following structure + # {"stream_type": {"attribute": [attribute per stream]}} + # + # following would print out the list of frame rates for every present video stream + print(reader_md["video"]["fps"]) + + # we explicitly select the stream we would like to operate on. In + # the constructor we select a default video stream, but + # in practice, we can set whichever stream we would like + video.set_current_stream("video:0") + + +Image +----- + +.. autofunction:: read_image + +.. autofunction:: decode_image + +.. autofunction:: encode_jpeg + +.. autofunction:: write_jpeg + +.. autofunction:: encode_png + +.. autofunction:: write_png diff --git a/docs/source/models.rst b/docs/source/models.rst index 0ca9b35483d..66ebf0e211d 100644 --- a/docs/source/models.rst +++ b/docs/source/models.rst @@ -71,7 +71,7 @@ This directory can be set using the `TORCH_MODEL_ZOO` environment variable. See Some models use modules which have different training and evaluation behavior, such as batch normalization. To switch between these modes, use ``model.train()`` or ``model.eval()`` as appropriate. See -:meth:`~torch.nn.Module.train` or :meth:`~torch.nn.Module.eval` for details. +:meth:`~torch.nn.Module.train` or :meth:`~torch.nn.Module.eval` for details. All pre-trained models expect input images normalized in the same way, i.e. mini-batches of 3-channel RGB images of shape (3 x H x W), @@ -86,6 +86,28 @@ You can use the following transform to normalize:: An example of such normalization can be found in the imagenet example `here `_ +The process for obtaining the values of `mean` and `std` is roughly equivalent +to:: + + import torch + from torchvision import datasets, transforms as T + + transform = T.Compose([T.Resize(256), T.CenterCrop(224), T.ToTensor()]) + dataset = datasets.ImageNet(".", split="train", transform=transform) + + means = [] + stds = [] + for img in subset(dataset): + means.append(torch.mean(img)) + stds.append(torch.std(img)) + + mean = torch.mean(torch.tensor(means)) + std = torch.mean(torch.tensor(stds)) + +Unfortunately, the concrete `subset` that was used is lost. For more +information see `this discussion `_ +or `these experiments `_. + ImageNet 1-crop error rates (224x224) ================================ ============= ============= @@ -183,11 +205,19 @@ Inception v3 .. autofunction:: inception_v3 +.. note :: + This requires `scipy` to be installed + + GoogLeNet ------------ .. autofunction:: googlenet +.. note :: + This requires `scipy` to be installed + + ShuffleNet v2 ------------- @@ -320,6 +350,7 @@ the instances set of COCO train2017 and evaluated on COCO val2017. Network box AP mask AP keypoint AP ================================ ======= ======== =========== Faster R-CNN ResNet-50 FPN 37.0 - - +RetinaNet ResNet-50 FPN 36.4 - - Mask R-CNN ResNet-50 FPN 37.9 34.6 - ================================ ======= ======== =========== @@ -375,6 +406,7 @@ precision-recall. Network train time (s / it) test time (s / it) memory (GB) ============================== =================== ================== =========== Faster R-CNN ResNet-50 FPN 0.2288 0.0590 5.2 +RetinaNet ResNet-50 FPN 0.2514 0.0939 4.1 Mask R-CNN ResNet-50 FPN 0.2728 0.0903 5.4 Keypoint R-CNN ResNet-50 FPN 0.3789 0.1242 6.8 ============================== =================== ================== =========== @@ -386,6 +418,12 @@ Faster R-CNN .. autofunction:: torchvision.models.detection.fasterrcnn_resnet50_fpn +RetinaNet +------------ + +.. autofunction:: torchvision.models.detection.retinanet_resnet50_fpn + + Mask R-CNN ---------- diff --git a/docs/source/ops.rst b/docs/source/ops.rst index ec87d02556e..cdebe9721c3 100644 --- a/docs/source/ops.rst +++ b/docs/source/ops.rst @@ -6,12 +6,28 @@ torchvision.ops :mod:`torchvision.ops` implements operators that are specific for Computer Vision. .. note:: - Those operators currently do not support TorchScript. + All operators have native support for TorchScript. .. autofunction:: nms +.. autofunction:: batched_nms +.. autofunction:: remove_small_boxes +.. autofunction:: clip_boxes_to_image +.. autofunction:: box_convert +.. autofunction:: box_area +.. autofunction:: box_iou +.. autofunction:: generalized_box_iou .. autofunction:: roi_align +.. autofunction:: ps_roi_align .. autofunction:: roi_pool +.. autofunction:: ps_roi_pool +.. autofunction:: deform_conv2d +.. autofunction:: sigmoid_focal_loss .. autoclass:: RoIAlign +.. autoclass:: PSRoIAlign .. autoclass:: RoIPool +.. autoclass:: PSRoIPool +.. autoclass:: DeformConv2d +.. autoclass:: MultiScaleRoIAlign +.. autoclass:: FeaturePyramidNetwork diff --git a/docs/source/transforms.rst b/docs/source/transforms.rst index 2e0c6cefb8d..517ede35dbf 100644 --- a/docs/source/transforms.rst +++ b/docs/source/transforms.rst @@ -9,77 +9,151 @@ Functional transforms give fine-grained control over the transformations. This is useful if you have to build a more complex transformation pipeline (e.g. in the case of segmentation tasks). +All transformations accept PIL Image, Tensor Image or batch of Tensor Images as input. Tensor Image is a tensor with +``(C, H, W)`` shape, where ``C`` is a number of channels, ``H`` and ``W`` are image height and width. Batch of +Tensor Images is a tensor of ``(B, C, H, W)`` shape, where ``B`` is a number of images in the batch. Deterministic or +random transformations applied on the batch of Tensor Images identically transform all the images of the batch. + +.. warning:: + + Since v0.8.0 all random transformations are using torch default random generator to sample random parameters. + It is a backward compatibility breaking change and user should set the random state as following: + + .. code:: python + + # Previous versions + # import random + # random.seed(12) + + # Now + import torch + torch.manual_seed(17) + + Please, keep in mind that the same seed for torch random generator and Python random generator will not + produce the same results. + + +Scriptable transforms +--------------------- + +In order to script the transformations, please use ``torch.nn.Sequential`` instead of :class:`Compose`. + +.. code:: python + + transforms = torch.nn.Sequential( + transforms.CenterCrop(10), + transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)), + ) + scripted_transforms = torch.jit.script(transforms) + +Make sure to use only scriptable transformations, i.e. that work with ``torch.Tensor`` and does not require +`lambda` functions or ``PIL.Image``. + +For any custom transformations to be used with ``torch.jit.script``, they should be derived from ``torch.nn.Module``. + + +Compositions of transforms +-------------------------- + .. autoclass:: Compose -Transforms on PIL Image ------------------------ +Transforms on PIL Image and torch.\*Tensor +------------------------------------------ .. autoclass:: CenterCrop + :members: .. autoclass:: ColorJitter + :members: .. autoclass:: FiveCrop + :members: .. autoclass:: Grayscale + :members: .. autoclass:: Pad + :members: .. autoclass:: RandomAffine + :members: .. autoclass:: RandomApply -.. autoclass:: RandomChoice - .. autoclass:: RandomCrop + :members: .. autoclass:: RandomGrayscale + :members: .. autoclass:: RandomHorizontalFlip - -.. autoclass:: RandomOrder + :members: .. autoclass:: RandomPerspective + :members: .. autoclass:: RandomResizedCrop + :members: .. autoclass:: RandomRotation + :members: .. autoclass:: RandomSizedCrop + :members: .. autoclass:: RandomVerticalFlip + :members: .. autoclass:: Resize + :members: .. autoclass:: Scale + :members: .. autoclass:: TenCrop + :members: -Transforms on torch.\*Tensor +.. autoclass:: GaussianBlur + :members: + +Transforms on PIL Image only ---------------------------- +.. autoclass:: RandomChoice + +.. autoclass:: RandomOrder + + +Transforms on torch.\*Tensor only +--------------------------------- + .. autoclass:: LinearTransformation + :members: .. autoclass:: Normalize - :members: __call__ - :special-members: + :members: .. autoclass:: RandomErasing + :members: + +.. autoclass:: ConvertImageDtype + Conversion Transforms --------------------- .. autoclass:: ToPILImage - :members: __call__ - :special-members: + :members: .. autoclass:: ToTensor - :members: __call__ - :special-members: + :members: + Generic Transforms ------------------ .. autoclass:: Lambda + :members: Functional Transforms diff --git a/docs/source/utils.rst b/docs/source/utils.rst index ad2fc91c897..0ae450487e3 100644 --- a/docs/source/utils.rst +++ b/docs/source/utils.rst @@ -7,3 +7,4 @@ torchvision.utils .. autofunction:: save_image +.. autofunction:: draw_bounding_boxes \ No newline at end of file diff --git a/examples/cpp/hello_world/CMakeLists.txt b/examples/cpp/hello_world/CMakeLists.txt new file mode 100644 index 00000000000..3244efb392b --- /dev/null +++ b/examples/cpp/hello_world/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.10) +project(hello-world) + +# The first thing do is to tell cmake to find the TorchVision library. +# The package pulls in all the necessary torch libraries, +# so there is no need to also add `find_package(Torch)` here. +find_package(TorchVision REQUIRED) + +add_executable(hello-world main.cpp) + +# We now need to link the TorchVision library to our executable. +# We can do that by using the TorchVision::TorchVision target, +# which also adds all the necessary torch dependencies. +target_compile_features(hello-world PUBLIC cxx_range_for) +target_link_libraries(hello-world TorchVision::TorchVision) +set_property(TARGET hello-world PROPERTY CXX_STANDARD 14) diff --git a/examples/cpp/hello_world/README.rst b/examples/cpp/hello_world/README.rst new file mode 100644 index 00000000000..aa5427a6f1c --- /dev/null +++ b/examples/cpp/hello_world/README.rst @@ -0,0 +1,19 @@ +Hello World! +============ + +This is a minimal example of getting TorchVision to work in C++ with CMake. + + +In order to successfully compile this example, make sure you have both ``LibTorch`` and +``TorchVision`` installed. +Once both dependencies are sorted, we can start the CMake fun: + +1) Create a ``build`` directory inside the current one. +2) from within the ``build`` directory, run the following commands: + - | ``cmake -DCMAKE_PREFIX_PATH=";" ..`` + | where ```` and ```` are the paths to the libtorch and torchvision installations. + - ``cmake --build .`` + +| That's it! +| You should now have a ``hello-world`` executable in your ``build`` folder. + Running it will output a (fairly long) tensor of random values to your terminal. \ No newline at end of file diff --git a/examples/cpp/hello_world/main.cpp b/examples/cpp/hello_world/main.cpp new file mode 100644 index 00000000000..445924dd0e3 --- /dev/null +++ b/examples/cpp/hello_world/main.cpp @@ -0,0 +1,23 @@ +#include +#include + +int main() +{ + auto model = vision::models::ResNet18(); + model->eval(); + + // Create a random input tensor and run it through the model. + auto in = torch::rand({1, 3, 10, 10}); + auto out = model->forward(in); + + std::cout << out.sizes(); + + if (torch::cuda::is_available()) { + // Move model and inputs to GPU + model->to(torch::kCUDA); + auto gpu_in = in.to(torch::kCUDA); + auto gpu_out = model->forward(gpu_in); + + std::cout << gpu_out.sizes(); + } +} diff --git a/examples/python/README.md b/examples/python/README.md new file mode 100644 index 00000000000..9cd02bcb326 --- /dev/null +++ b/examples/python/README.md @@ -0,0 +1,18 @@ +# Python examples + +- [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pytorch/vision/blob/master/examples/python/tensor_transforms.ipynb) +[Examples of Tensor Images transformations](https://github.com/pytorch/vision/blob/master/examples/python/tensor_transforms.ipynb) +- [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pytorch/vision/blob/master/examples/python/video_api.ipynb) +[Example of VideoAPI](https://github.com/pytorch/vision/blob/master/examples/python/video_api.ipynb) + + +Prior to v0.8.0, transforms in torchvision have traditionally been PIL-centric and presented multiple limitations due to +that. Now, since v0.8.0, transforms implementations are Tensor and PIL compatible and we can achieve the following new +features: +- transform multi-band torch tensor images (with more than 3-4 channels) +- torchscript transforms together with your model for deployment +- support for GPU acceleration +- batched transformation such as for videos +- read and decode data directly as torch tensor with torchscript support (for PNG and JPEG image formats) + +Furthermore, previously we used to provide a very high-level API for video decoding which left little control to the user. We're now expanding that API (and replacing it in the future) with a lower-level API that allows the user a frame-based access to a video. diff --git a/examples/python/tensor_transforms.ipynb b/examples/python/tensor_transforms.ipynb new file mode 100644 index 00000000000..7bb5741947c --- /dev/null +++ b/examples/python/tensor_transforms.ipynb @@ -0,0 +1,388 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "vjAC2mZnb4nz" + }, + "source": [ + "# Image transformations\n", + "\n", + "This notebook shows new features of torchvision image transformations. \n", + "\n", + "Prior to v0.8.0, transforms in torchvision have traditionally been PIL-centric and presented multiple limitations due to that. Now, since v0.8.0, transforms implementations are Tensor and PIL compatible and we can achieve the following new \n", + "features:\n", + "- transform multi-band torch tensor images (with more than 3-4 channels) \n", + "- torchscript transforms together with your model for deployment\n", + "- support for GPU acceleration\n", + "- batched transformation such as for videos\n", + "- read and decode data directly as torch tensor with torchscript support (for PNG and JPEG image formats)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "id": "btaDWPDbgIyW", + "outputId": "8a83d408-f643-42da-d247-faf3a1bd3ae0" + }, + "outputs": [], + "source": [ + "import torch, torchvision\n", + "torch.__version__, torchvision.__version__" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9Vj9draNb4oA" + }, + "source": [ + "## Transforms on CPU/CUDA tensor images\n", + "\n", + "Let's show how to apply transformations on images opened directly as a torch tensors.\n", + "Now, torchvision provides image reading functions for PNG and JPG images with torchscript support. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Epp3hCy0b4oD" + }, + "outputs": [], + "source": [ + "from torchvision.datasets.utils import download_url\n", + "\n", + "download_url(\"https://farm1.static.flickr.com/152/434505223_8d1890e1e2.jpg\", \".\", \"test-image.jpg\")\n", + "download_url(\"https://farm3.static.flickr.com/2142/1896267403_24939864ba.jpg\", \".\", \"test-image2.jpg\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Y-m7lYDPb4oK" + }, + "outputs": [], + "source": [ + "import matplotlib.pylab as plt\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 303 + }, + "id": "5bi8Q7L3b4oc", + "outputId": "e5de5c73-e16d-4992-ebee-94c7ddf0bf54" + }, + "outputs": [], + "source": [ + "from torchvision.io.image import read_image\n", + "\n", + "tensor_image = read_image(\"test-image.jpg\")\n", + "\n", + "print(\"tensor image info: \", tensor_image.shape, tensor_image.dtype)\n", + "\n", + "plt.imshow(tensor_image.numpy().transpose((1, 2, 0)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def to_rgb_image(tensor):\n", + " \"\"\"Helper method to get RGB numpy array for plotting\"\"\"\n", + " np_img = tensor.cpu().numpy().transpose((1, 2, 0))\n", + " m1, m2 = np_img.min(axis=(0, 1)), np_img.max(axis=(0, 1))\n", + " return (255.0 * (np_img - m1) / (m2 - m1)).astype(\"uint8\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 322 + }, + "id": "PgWpjxQ3b4pF", + "outputId": "e9a138e8-b45c-4f75-d849-3b41de0e5472" + }, + "outputs": [], + "source": [ + "import torchvision.transforms as T\n", + "\n", + "# to fix random seed is now:\n", + "torch.manual_seed(12)\n", + "\n", + "transforms = T.Compose([\n", + " T.RandomCrop(224),\n", + " T.RandomHorizontalFlip(p=0.3),\n", + " T.ConvertImageDtype(torch.float),\n", + " T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n", + "])\n", + "\n", + "out_image = transforms(tensor_image)\n", + "print(\"output tensor image info: \", out_image.shape, out_image.dtype)\n", + "\n", + "plt.imshow(to_rgb_image(out_image))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "LmYQB4cxb4pI" + }, + "source": [ + "Tensor images can be on GPU" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 322 + }, + "id": "S6syYJGEb4pN", + "outputId": "86bddb64-e648-45f2-c216-790d43cfc26d" + }, + "outputs": [], + "source": [ + "out_image = transforms(tensor_image.to(\"cuda\"))\n", + "print(\"output tensor image info: \", out_image.shape, out_image.dtype, out_image.device)\n", + "\n", + "plt.imshow(to_rgb_image(out_image))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "jg9TQd7ajfyn" + }, + "source": [ + "## Scriptable transforms for easier deployment via torchscript\n", + "\n", + "Next, we show how to combine input transformations and model's forward pass and use `torch.jit.script` to obtain a single scripted module.\n", + "\n", + "**Note:** we have to use only scriptable transformations that should be derived from `torch.nn.Module`. \n", + "Since v0.8.0, all transformations are scriptable except `Compose`, `RandomChoice`, `RandomOrder`, `Lambda` and those applied on PIL images.\n", + "The transformations like `Compose` are kept for backward compatibility and can be easily replaced by existing torch modules, like `nn.Sequential`.\n", + "\n", + "Let's define a module `Predictor` that transforms input tensor and applies ImageNet pretrained resnet18 model on it." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "NSDOJ3RajfvO" + }, + "outputs": [], + "source": [ + "import torch\n", + "import torch.nn as nn\n", + "import torchvision.transforms as T\n", + "from torchvision.io.image import read_image\n", + "from torchvision.models import resnet18\n", + "\n", + "\n", + "class Predictor(nn.Module):\n", + "\n", + " def __init__(self):\n", + " super().__init__()\n", + " self.resnet18 = resnet18(pretrained=True).eval()\n", + " self.transforms = nn.Sequential(\n", + " T.Resize([256, ]), # We use single int value inside a list due to torchscript type restrictions\n", + " T.CenterCrop(224),\n", + " T.ConvertImageDtype(torch.float),\n", + " T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n", + " )\n", + "\n", + " def forward(self, x: torch.Tensor) -> torch.Tensor:\n", + " with torch.no_grad():\n", + " x = self.transforms(x)\n", + " y_pred = self.resnet18(x)\n", + " return y_pred.argmax(dim=1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZZKDovqej5vA" + }, + "source": [ + "Now, let's define scripted and non-scripted instances of `Predictor` and apply on multiple tensor images of the same size" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "GBBMSo7vjfr0" + }, + "outputs": [], + "source": [ + "from torchvision.io.image import read_image\n", + "\n", + "predictor = Predictor().to(\"cuda\")\n", + "scripted_predictor = torch.jit.script(predictor).to(\"cuda\")\n", + "\n", + "\n", + "tensor_image1 = read_image(\"test-image.jpg\")\n", + "tensor_image2 = read_image(\"test-image2.jpg\")\n", + "batch = torch.stack([tensor_image1[:, -320:, :], tensor_image2[:, -320:, :]]).to(\"cuda\")\n", + "\n", + "res1 = scripted_predictor(batch)\n", + "res2 = predictor(batch)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 501 + }, + "id": "Dmi9r_p-oKsk", + "outputId": "b9c55e7d-5db1-4975-c485-fecc4075bf47" + }, + "outputs": [], + "source": [ + "import json\n", + "from torchvision.datasets.utils import download_url\n", + "\n", + "\n", + "download_url(\"https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json\", \".\", \"imagenet_class_index.json\")\n", + "\n", + "\n", + "with open(\"imagenet_class_index.json\", \"r\") as h:\n", + " labels = json.load(h)\n", + "\n", + "\n", + "plt.figure(figsize=(12, 7))\n", + "for i, p in enumerate(res1):\n", + " plt.subplot(1, 2, i + 1)\n", + " plt.title(\"Scripted predictor:\\n{label})\".format(label=labels[str(p.item())]))\n", + " plt.imshow(batch[i, ...].cpu().numpy().transpose((1, 2, 0)))\n", + "\n", + "\n", + "plt.figure(figsize=(12, 7))\n", + "for i, p in enumerate(res2):\n", + " plt.subplot(1, 2, i + 1)\n", + " plt.title(\"Original predictor:\\n{label})\".format(label=labels[str(p.item())]))\n", + " plt.imshow(batch[i, ...].cpu().numpy().transpose((1, 2, 0)))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "7IYsjzpFqcK8" + }, + "source": [ + "We save and reload scripted predictor in Python or C++ and use it for inference:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 52 + }, + "id": "0kk9LLw5jfol", + "outputId": "05ea6db7-7fcf-4b74-a763-5f117c14cc00" + }, + "outputs": [], + "source": [ + "scripted_predictor.save(\"scripted_predictor.pt\")\n", + "\n", + "scripted_predictor = torch.jit.load(\"scripted_predictor.pt\")\n", + "res1 = scripted_predictor(batch)\n", + "\n", + "for i, p in enumerate(res1):\n", + " print(\"Scripted predictor: {label})\".format(label=labels[str(p.item())]))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Data reading and decoding functions also support torch script and therefore can be part of the model as well:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class AnotherPredictor(Predictor):\n", + "\n", + " def forward(self, path: str) -> int:\n", + " with torch.no_grad():\n", + " x = read_image(path).unsqueeze(0)\n", + " x = self.transforms(x)\n", + " y_pred = self.resnet18(x)\n", + " return int(y_pred.argmax(dim=1).item())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "-cMwTs3Yjffy" + }, + "outputs": [], + "source": [ + "scripted_predictor2 = torch.jit.script(AnotherPredictor())\n", + "\n", + "res = scripted_predictor2(\"test-image.jpg\")\n", + "\n", + "print(\"Scripted another predictor: {label})\".format(label=labels[str(res)]))" + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "collapsed_sections": [], + "name": "torchvision_scriptable_transforms.ipynb", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/python/video_api.ipynb b/examples/python/video_api.ipynb new file mode 100644 index 00000000000..724de2f0a12 --- /dev/null +++ b/examples/python/video_api.ipynb @@ -0,0 +1,772 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Welcome to torchvision's new video API\n", + "\n", + "Here, we're going to examine the capabilities of the new video API, together with the examples on how to build datasets and more. \n", + "\n", + "### Table of contents\n", + "1. Introduction: building a new video object and examining the properties\n", + "2. Building a sample `read_video` function\n", + "3. Building an example dataset (can be applied to e.g. kinetics400)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('1.8.0a0+7580962', '0.8.0a0+4db3dc6')" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import torch, torchvision\n", + "torch.__version__, torchvision.__version__" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading https://github.com/pytorch/vision/blob/master/test/assets/videos/WUzgd7C1pWA.mp4?raw=true to ./WUzgd7C1pWA.mp4\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100.4%" + ] + } + ], + "source": [ + "# download the sample video\n", + "from torchvision.datasets.utils import download_url\n", + "download_url(\"https://github.com/pytorch/vision/blob/master/test/assets/videos/WUzgd7C1pWA.mp4?raw=true\", \".\", \"WUzgd7C1pWA.mp4\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. Introduction: building a new video object and examining the properties\n", + "\n", + "First we select a video to test the object out. For the sake of argument we're using one from Kinetics400 dataset. To create it, we need to define the path and the stream we want to use. See inline comments for description. " + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "import torch, torchvision\n", + "\"\"\"\n", + "chosen video statistics:\n", + "WUzgd7C1pWA.mp4\n", + " - source: kinetics-400\n", + " - video: H-264 - MPEG-4 AVC (part 10) (avc1)\n", + " - fps: 29.97\n", + " - audio: MPEG AAC audio (mp4a)\n", + " - sample rate: 48K Hz\n", + "\"\"\"\n", + "video_path = \"./WUzgd7C1pWA.mp4\"\n", + "\n", + "\"\"\"\n", + "streams are defined in a similar fashion as torch devices. We encode them as strings in a form\n", + "of `stream_type:stream_id` where stream_type is a string and stream_id a long int. \n", + "\n", + "The constructor accepts passing a stream_type only, in which case the stream is auto-discovered.\n", + "\"\"\"\n", + "stream = \"video\"\n", + "\n", + "\n", + "\n", + "video = torchvision.io.VideoReader(video_path, stream)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, let's get the metadata for our particular video:" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'video': {'duration': [10.9109], 'fps': [29.97002997002997]},\n", + " 'audio': {'duration': [10.9], 'framerate': [48000.0]}}" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "video.get_metadata()" + ] + }, + { + "source": [ + "Here we can see that video has two streams - a video and an audio stream. \n", + "Currently available stream types include ``['video', 'audio']``.\n", + "Each descriptor consists of two parts: stream type (e.g. 'video') and\n", + "a unique stream id (which are determined by video encoding).\n", + "In this way, if the video contaner contains multiple\n", + "streams of the same type, users can acces the one they want.\n", + "If only stream type is passed, the decoder auto-detects first stream\n", + "of that type and returns it.\n", + "\n", + "Let's read all the frames from the video stream.\n", + "By default, the return value of `next(video_reader)` is a dict containing the following fields.\n", + "\n", + "The return fields are \n", + "- `data` containing a torch.tensor\n", + "- `pts` containing a float timestamp of this particular frame. " + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PTS for first five frames [0.0, 0.033367, 0.066733, 0.1001, 0.133467]\n", + "Total number of frames: 327\n", + "We can expect approx: 327.0\n", + "Tensor size: torch.Size([3, 256, 340])\n" + ] + } + ], + "source": [ + "# first we select the video stream \n", + "metadata = video.get_metadata()\n", + "video.set_current_stream(\"video:0\")\n", + "\n", + "frames = [] # we are going to save the frames here.\n", + "ptss = [] # pts is a presentation timestamp in seconds (float) of each frame\n", + "for frame in video:\n", + " frames.append(frame['data'])\n", + " ptss.append(frame['pts'])\n", + "\n", + "print(\"PTS for first five frames \", ptss[:5])\n", + "print(\"Total number of frames: \", len(frames))\n", + "approx_nf = metadata['video']['duration'][0] * metadata['video']['fps'][0]\n", + "print(\"We can expect approx: \", approx_nf)\n", + "print(\"Tensor size: \", frames[0].size())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that selecting zero video stream is equivalent to selecting video stream automatically. I.e. `video:0` and `video` will end up with same results in this case. \n", + "\n", + "Let's try this for audio. Note that presentation timestamps are different so aligment has to be done carefully. " + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "PTS for first five frames [0.0, 0.021332999999999998, 0.042667, 0.064, 0.08533299999999999]\n", + "Total number of frames: 511\n", + "Approx total number of datapoints we can expect: 523200.0\n", + "Read data size: 523264\n" + ] + } + ], + "source": [ + "metadata = video.get_metadata()\n", + "video.set_current_stream(\"audio\")\n", + "\n", + "frames = [] # we are going to save the frames here.\n", + "ptss = [] # pts is a presentation timestamp in seconds (float) of each frame\n", + "for frame in video:\n", + " frames.append(frame['data'])\n", + " ptss.append(frame['pts'])\n", + "\n", + "print(\"PTS for first five frames \", ptss[:5])\n", + "print(\"Total number of frames: \", len(frames))\n", + "approx_nf = metadata['audio']['duration'][0] * metadata['audio']['framerate'][0]\n", + "print(\"Approx total number of datapoints we can expect: \", approx_nf)\n", + "print(\"Read data size: \", frames[0].size(0) * len(frames))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "But what if we only want to read certain time segment of the video?\n", + "\n", + "That can be done easily using the combination of our seek function, and the fact that each call to next returns the presentation timestamp of the returned frame in seconds. Given that our implementation relies on python iterators, we can leverage `itertools` to simplify the process and make it more pythonic. \n", + "\n", + "For example, if we wanted to read ten frames from second second:" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total number of frames: 10\n" + ] + } + ], + "source": [ + "import itertools\n", + "video.set_current_stream(\"video\")\n", + "\n", + "frames = [] # we are going to save the frames here.\n", + "\n", + "# we seek into a second second of the video\n", + "# and use islice to get 10 frames since\n", + "for frame, pts in itertools.islice(video.seek(2), 10):\n", + " frames.append(frame)\n", + " \n", + "print(\"Total number of frames: \", len(frames))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or if we wanted to read from 2nd to 5th second:" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total number of frames: 90\n", + "We can expect approx: 89.91008991008991\n", + "Tensor size: torch.Size([3, 256, 340])\n" + ] + } + ], + "source": [ + "video.set_current_stream(\"video\")\n", + "\n", + "frames = [] # we are going to save the frames here.\n", + "\n", + "# we seek into a second second of the video\n", + "video = video.seek(2)\n", + "# then we utilize the itertools takewhile to get the \n", + "# correct number of frames\n", + "for frame in itertools.takewhile(lambda x: x['pts'] <= 5, video):\n", + " frames.append(frame['data'])\n", + "\n", + "print(\"Total number of frames: \", len(frames))\n", + "approx_nf = (5-2) * video.get_metadata()['video']['fps'][0]\n", + "print(\"We can expect approx: \", approx_nf)\n", + "print(\"Tensor size: \", frames[0].size())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Building a sample `read_video` function\n", + "\n", + "We can utilize the methods above to build the read video function that follows the same API to the existing `read_video` function " + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "metadata": {}, + "outputs": [], + "source": [ + "def example_read_video(video_object, start=0, end=None, read_video=True, read_audio=True):\n", + "\n", + " if end is None:\n", + " end = float(\"inf\")\n", + " if end < start:\n", + " raise ValueError(\n", + " \"end time should be larger than start time, got \"\n", + " \"start time={} and end time={}\".format(s, e)\n", + " )\n", + " \n", + " video_frames = torch.empty(0)\n", + " video_pts = []\n", + " if read_video:\n", + " video_object.set_current_stream(\"video\")\n", + " frames = []\n", + " for frame in itertools.takewhile(lambda x: x['pts'] <= end, video_object.seek(start)):\n", + " frames.append(frame['data'])\n", + " video_pts.append(frame['pts'])\n", + " if len(frames) > 0:\n", + " video_frames = torch.stack(frames, 0)\n", + "\n", + " audio_frames = torch.empty(0)\n", + " audio_pts = []\n", + " if read_audio:\n", + " video_object.set_current_stream(\"audio\")\n", + " frames = []\n", + " for frame in itertools.takewhile(lambda x: x['pts'] <= end, video_object.seek(start)):\n", + " frames.append(frame['data'])\n", + " video_pts.append(frame['pts'])\n", + " if len(frames) > 0:\n", + " audio_frames = torch.cat(frames, 0)\n", + "\n", + " return video_frames, audio_frames, (video_pts, audio_pts), video_object.get_metadata()" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "torch.Size([327, 3, 256, 340]) torch.Size([523264, 1])\n" + ] + } + ], + "source": [ + "vf, af, info, meta = example_read_video(video)\n", + "# total number of frames should be 327 for video and 523264 datapoints for audio\n", + "print(vf.size(), af.size())" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "torch.Size([523264, 1])" + ] + }, + "execution_count": 57, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# you can also get the sequence of audio frames as well\n", + "af.size()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. Building an example randomly sampled dataset (can be applied to training dataest of kinetics400)\n", + "\n", + "Cool, so now we can use the same principle to make the sample dataset. We suggest trying out iterable dataset for this purpose. \n", + "\n", + "Here, we are going to build\n", + "\n", + "a. an example dataset that reads randomly selected 10 frames of video" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [], + "source": [ + "# make sample dataest\n", + "import os\n", + "os.makedirs(\"./dataset\", exist_ok=True)\n", + "os.makedirs(\"./dataset/1\", exist_ok=True)\n", + "os.makedirs(\"./dataset/2\", exist_ok=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "18.4%" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading https://github.com/pytorch/vision/blob/master/test/assets/videos/WUzgd7C1pWA.mp4?raw=true to ./dataset/1/WUzgd7C1pWA.mp4\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100.4%" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading https://github.com/pytorch/vision/blob/master/test/assets/videos/RATRACE_wave_f_nm_np1_fr_goo_37.avi?raw=true to ./dataset/1/RATRACE_wave_f_nm_np1_fr_goo_37.avi\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "102.5%" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading https://github.com/pytorch/vision/blob/master/test/assets/videos/SOX5yA1l24A.mp4?raw=true to ./dataset/2/SOX5yA1l24A.mp4\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100.9%" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading https://github.com/pytorch/vision/blob/master/test/assets/videos/v_SoccerJuggling_g23_c01.avi?raw=true to ./dataset/2/v_SoccerJuggling_g23_c01.avi\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "101.5%" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloading https://github.com/pytorch/vision/blob/master/test/assets/videos/v_SoccerJuggling_g24_c01.avi?raw=true to ./dataset/2/v_SoccerJuggling_g24_c01.avi\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "101.3%" + ] + } + ], + "source": [ + "# download the videos \n", + "from torchvision.datasets.utils import download_url\n", + "download_url(\"https://github.com/pytorch/vision/blob/master/test/assets/videos/WUzgd7C1pWA.mp4?raw=true\", \"./dataset/1\", \"WUzgd7C1pWA.mp4\")\n", + "download_url(\"https://github.com/pytorch/vision/blob/master/test/assets/videos/RATRACE_wave_f_nm_np1_fr_goo_37.avi?raw=true\", \"./dataset/1\", \"RATRACE_wave_f_nm_np1_fr_goo_37.avi\")\n", + "download_url(\"https://github.com/pytorch/vision/blob/master/test/assets/videos/SOX5yA1l24A.mp4?raw=true\", \"./dataset/2\", \"SOX5yA1l24A.mp4\")\n", + "download_url(\"https://github.com/pytorch/vision/blob/master/test/assets/videos/v_SoccerJuggling_g23_c01.avi?raw=true\", \"./dataset/2\", \"v_SoccerJuggling_g23_c01.avi\")\n", + "download_url(\"https://github.com/pytorch/vision/blob/master/test/assets/videos/v_SoccerJuggling_g24_c01.avi?raw=true\", \"./dataset/2\", \"v_SoccerJuggling_g24_c01.avi\")" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [], + "source": [ + "# housekeeping and utilities\n", + "import os\n", + "import random\n", + "\n", + "import torch\n", + "from torchvision.datasets.folder import make_dataset\n", + "from torchvision import transforms as t\n", + "\n", + "def _find_classes(dir):\n", + " classes = [d.name for d in os.scandir(dir) if d.is_dir()]\n", + " classes.sort()\n", + " class_to_idx = {cls_name: i for i, cls_name in enumerate(classes)}\n", + " return classes, class_to_idx\n", + "\n", + "def get_samples(root, extensions=(\".mp4\", \".avi\")):\n", + " _, class_to_idx = _find_classes(root)\n", + " return make_dataset(root, class_to_idx, extensions=extensions)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are going to define the dataset and some basic arguments. We asume the structure of the FolderDataset, and add the following parameters:\n", + " \n", + "1. frame transform: with this API, we can chose to apply transforms on every frame of the video\n", + "2. videotransform: equally, we can also apply transform to a 4D tensor\n", + "3. length of the clip: do we want a single or multiple frames?\n", + "\n", + "Note that we actually add `epoch size` as using `IterableDataset` class allows us to naturally oversample clips or images from each video if needed. " + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [], + "source": [ + "class RandomDataset(torch.utils.data.IterableDataset):\n", + " def __init__(self, root, epoch_size=None, frame_transform=None, video_transform=None, clip_len=16):\n", + " super(RandomDataset).__init__()\n", + " \n", + " self.samples = get_samples(root)\n", + " \n", + " # allow for temporal jittering\n", + " if epoch_size is None:\n", + " epoch_size = len(self.samples)\n", + " self.epoch_size = epoch_size\n", + " \n", + " self.clip_len = clip_len # length of a clip in frames\n", + " self.frame_transform = frame_transform # transform for every frame individually\n", + " self.video_transform = video_transform # transform on a video sequence\n", + "\n", + " def __iter__(self):\n", + " for i in range(self.epoch_size):\n", + " # get random sample\n", + " path, target = random.choice(self.samples)\n", + " # get video object\n", + " vid = torchvision.io.VideoReader(path, \"video\")\n", + " metadata = vid.get_metadata()\n", + " video_frames = [] # video frame buffer \n", + " # seek and return frames\n", + " \n", + " max_seek = metadata[\"video\"]['duration'][0] - (self.clip_len / metadata[\"video\"]['fps'][0])\n", + " start = random.uniform(0., max_seek)\n", + " for frame in itertools.islice(vid.seek(start), self.clip_len):\n", + " video_frames.append(self.frame_transform(frame['data']))\n", + " current_pts = frame['pts']\n", + " # stack it into a tensor\n", + " video = torch.stack(video_frames, 0)\n", + " if self.video_transform:\n", + " video = self.video_transform(video)\n", + " output = {\n", + " 'path': path,\n", + " 'video': video,\n", + " 'target': target,\n", + " 'start': start,\n", + " 'end': current_pts}\n", + " yield output" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Given a path of videos in a folder structure, i.e:\n", + "```\n", + "dataset:\n", + " -class 1:\n", + " file 0\n", + " file 1\n", + " ...\n", + " - class 2:\n", + " file 0\n", + " file 1\n", + " ...\n", + " - ...\n", + "```\n", + "We can generate a dataloader and test the dataset. \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [], + "source": [ + "from torchvision import transforms as t\n", + "transforms = [t.Resize((112, 112))]\n", + "frame_transform = t.Compose(transforms)\n", + "\n", + "ds = RandomDataset(\"./dataset\", epoch_size=None, frame_transform=frame_transform)" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [], + "source": [ + "from torch.utils.data import DataLoader\n", + "loader = DataLoader(ds, batch_size=12)\n", + "d = {\"video\":[], 'start':[], 'end':[], 'tensorsize':[]}\n", + "for b in loader:\n", + " for i in range(len(b['path'])):\n", + " d['video'].append(b['path'][i])\n", + " d['start'].append(b['start'][i].item())\n", + " d['end'].append(b['end'][i].item())\n", + " d['tensorsize'].append(b['video'][i].size())" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'video': ['./dataset/2/SOX5yA1l24A.mp4',\n", + " './dataset/1/RATRACE_wave_f_nm_np1_fr_goo_37.avi',\n", + " './dataset/2/v_SoccerJuggling_g23_c01.avi',\n", + " './dataset/2/SOX5yA1l24A.mp4',\n", + " './dataset/2/v_SoccerJuggling_g24_c01.avi'],\n", + " 'start': [2.9344678384893816,\n", + " 1.6827470772443045,\n", + " 3.9380918322335887,\n", + " 8.400625043794742,\n", + " 0.9696198736175933],\n", + " 'end': [3.4367669999999997,\n", + " 2.1999999999999997,\n", + " 4.471133,\n", + " 8.9089,\n", + " 1.5014999999999998],\n", + " 'tensorsize': [torch.Size([16, 3, 112, 112]),\n", + " torch.Size([16, 3, 112, 112]),\n", + " torch.Size([16, 3, 112, 112]),\n", + " torch.Size([16, 3, 112, 112]),\n", + " torch.Size([16, 3, 112, 112])]}" + ] + }, + "execution_count": 64, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "d" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Visualisation:\n", + " \n", + "example of visualsed video" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pylab as plt\n", + "%matplotlib inline\n", + "\n", + "plt.figure(figsize=(12, 12))\n", + "for i in range(16):\n", + " plt.subplot(4, 4, i + 1)\n", + " plt.imshow(b[\"video\"][0, i, ...].permute(1, 2, 0))\n", + " plt.axis(\"off\")" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [], + "source": [ + "## Cleanup\n", + "import os, shutil\n", + "os.remove(\"./WUzgd7C1pWA.mp4\")\n", + "shutil.rmtree(\"./dataset\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.5-final" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file diff --git a/hubconf.py b/hubconf.py index f43f922e89c..79c22bd938b 100644 --- a/hubconf.py +++ b/hubconf.py @@ -1,6 +1,7 @@ # Optional list of dependencies required by the package dependencies = ['torch'] +# classification from torchvision.models.alexnet import alexnet from torchvision.models.densenet import densenet121, densenet169, densenet201, densenet161 from torchvision.models.inception import inception_v3 @@ -8,7 +9,12 @@ resnext50_32x4d, resnext101_32x8d, wide_resnet50_2, wide_resnet101_2 from torchvision.models.squeezenet import squeezenet1_0, squeezenet1_1 from torchvision.models.vgg import vgg11, vgg13, vgg16, vgg19, vgg11_bn, vgg13_bn, vgg16_bn, vgg19_bn -from torchvision.models.segmentation import fcn_resnet101, deeplabv3_resnet101 from torchvision.models.googlenet import googlenet from torchvision.models.shufflenetv2 import shufflenet_v2_x0_5, shufflenet_v2_x1_0 from torchvision.models.mobilenet import mobilenet_v2 +from torchvision.models.mnasnet import mnasnet0_5, mnasnet0_75, mnasnet1_0, \ + mnasnet1_3 + +# segmentation +from torchvision.models.segmentation import fcn_resnet50, fcn_resnet101, \ + deeplabv3_resnet50, deeplabv3_resnet101 diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 00000000000..b35ee60d907 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,65 @@ +[mypy] + +files = torchvision +show_error_codes = True +pretty = True + +[mypy-torchvision.io._video_opt.*] + +ignore_errors = True + +[mypy-torchvision.io.*] + +ignore_errors = True + +[mypy-torchvision.models.densenet.*] + +ignore_errors=True + +[mypy-torchvision.models.detection.*] + +ignore_errors = True + +[mypy-torchvision.models.quantization.*] + +ignore_errors = True + +[mypy-torchvision.ops.*] + +ignore_errors = True + +[mypy-torchvision.transforms.*] + +ignore_errors = True + +[mypy-PIL.*] + +ignore_missing_imports = True + +[mypy-numpy.*] + +ignore_missing_imports = True + +[mypy-scipy.*] + +ignore_missing_imports = True + +[mypy-pycocotools.*] + +ignore_missing_imports = True + +[mypy-lmdb.*] + +ignore_missing_imports = True + +[mypy-pandas.*] + +ignore_missing_imports = True + +[mypy-accimage.*] + +ignore_missing_imports = True + +[mypy-av.*] + +ignore_missing_imports = True diff --git a/packaging/build_cmake.sh b/packaging/build_cmake.sh new file mode 100755 index 00000000000..15b25b78d47 --- /dev/null +++ b/packaging/build_cmake.sh @@ -0,0 +1,101 @@ +#!/bin/bash +set -ex + +if [[ "$(uname)" != Darwin && "$OSTYPE" != "msys" ]]; then + eval "$(./conda/bin/conda shell.bash hook)" + conda activate ./env +fi + +script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +. "$script_dir/pkg_helpers.bash" + +export BUILD_TYPE=conda +setup_env 0.9.0 +export SOURCE_ROOT_DIR="$PWD" +setup_conda_pytorch_constraint +setup_conda_cudatoolkit_plain_constraint + +if [[ "$OSTYPE" == "msys" ]]; then + conda install -yq conda-build cmake pillow future + pip install dataclasses +fi + +setup_visual_studio_constraint +setup_junit_results_folder + +conda install -yq pytorch=$PYTORCH_VERSION $CONDA_CUDATOOLKIT_CONSTRAINT $CONDA_CPUONLY_FEATURE -c "pytorch-${UPLOAD_CHANNEL}" +TORCH_PATH=$(dirname $(python -c "import torch; print(torch.__file__)")) + +if [[ "$(uname)" == Darwin || "$OSTYPE" == "msys" ]]; then + conda install -yq libpng jpeg +else + yum install -y libpng-devel libjpeg-turbo-devel +fi + +mkdir cpp_build +pushd cpp_build + +# Generate libtorchvision files +cmake .. -DTorch_DIR=$TORCH_PATH/share/cmake/Torch -DWITH_CUDA=$CMAKE_USE_CUDA + +# Compile and install libtorchvision +if [[ "$OSTYPE" == "msys" ]]; then + "$script_dir/windows/internal/vc_env_helper.bat" "$script_dir/windows/internal/build_cmake.bat" + CONDA_PATH=$(dirname $(which python)) + cp -r "C:/Program Files (x86)/torchvision/include/torchvision" $CONDA_PATH/include +else + make + make install + + if [[ "$(uname)" == Darwin ]]; then + CONDA_PATH=$(dirname $(dirname $(which python))) + cp -r /usr/local/include/torchvision $CONDA_PATH/include/ + export C_INCLUDE_PATH=/usr/local/include + export CPLUS_INCLUDE_PATH=/usr/local/include + fi +fi + +popd + +# Install torchvision locally +python setup.py develop + +# Trace, compile and run project that uses Faster-RCNN +pushd test/tracing/frcnn +mkdir build + +# Trace model +python trace_model.py +cp fasterrcnn_resnet50_fpn.pt build + +cd build +cmake .. -DTorch_DIR=$TORCH_PATH/share/cmake/Torch -DWITH_CUDA=$CMAKE_USE_CUDA +if [[ "$OSTYPE" == "msys" ]]; then + "$script_dir/windows/internal/vc_env_helper.bat" "$script_dir/windows/internal/build_frcnn.bat" + mv fasterrcnn_resnet50_fpn.pt Release + cd Release + export PATH=$(cygpath "C:/Program Files (x86)/torchvision/bin"):$(cygpath $TORCH_PATH)/lib:$PATH +else + make +fi + +# Run traced program +./test_frcnn_tracing + +# Compile and run the CPP example +popd +cd examples/cpp/hello_world + +mkdir build +cd build +cmake .. -DTorch_DIR=$TORCH_PATH/share/cmake/Torch + +if [[ "$OSTYPE" == "msys" ]]; then + "$script_dir/windows/internal/vc_env_helper.bat" "$script_dir/windows/internal/build_cpp_example.bat" + cd Release +else + make +fi + +# Run CPP example +./hello-world diff --git a/packaging/build_conda.sh b/packaging/build_conda.sh index 9ec011d7d75..fa155359935 100755 --- a/packaging/build_conda.sh +++ b/packaging/build_conda.sh @@ -5,7 +5,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" . "$script_dir/pkg_helpers.bash" export BUILD_TYPE=conda -setup_env 0.6.0 +setup_env 0.9.0 export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint setup_conda_cudatoolkit_constraint diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index 93c6998211a..371c4e71a12 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -5,15 +5,55 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" . "$script_dir/pkg_helpers.bash" export BUILD_TYPE=wheel -setup_env 0.6.0 +setup_env 0.9.0 setup_wheel_python pip_install numpy pyyaml future ninja -# TODO remove after https://github.com/pytorch/pytorch/pull/27282 gets merged -pip_install six setup_pip_pytorch_version python setup.py clean + +# Copy binaries to be included in the wheel distribution +if [[ "$(uname)" == Darwin || "$OSTYPE" == "msys" ]]; then + python_exec="$(which python)" + bin_path=$(dirname $python_exec) + env_path=$(dirname $bin_path) + if [[ "$(uname)" == Darwin ]]; then + # Install delocate to relocate the required binaries + pip_install delocate + else + cp "$bin_path/Library/bin/libpng16.dll" torchvision + cp "$bin_path/Library/bin/libjpeg.dll" torchvision + fi +else + # Install auditwheel to get some inspection utilities + pip_install auditwheel + + # Point to custom libraries + export LD_LIBRARY_PATH=$(pwd)/ext_libraries/lib:$LD_LIBRARY_PATH + export TORCHVISION_INCLUDE=$(pwd)/ext_libraries/include + export TORCHVISION_LIBRARY=$(pwd)/ext_libraries/lib +fi + +download_copy_ffmpeg + if [[ "$OSTYPE" == "msys" ]]; then IS_WHEEL=1 "$script_dir/windows/internal/vc_env_helper.bat" python setup.py bdist_wheel else IS_WHEEL=1 python setup.py bdist_wheel fi + + +if [[ "$(uname)" == Darwin ]]; then + pushd dist/ + python_exec="$(which python)" + bin_path=$(dirname $python_exec) + env_path=$(dirname $bin_path) + for whl in *.whl; do + DYLD_LIBRARY_PATH="$env_path/lib/:$DYLD_LIBRARY_PATH" delocate-wheel -v $whl + done +else + if [[ "$OSTYPE" == "msys" ]]; then + "$script_dir/windows/internal/vc_env_helper.bat" python $script_dir/wheel/relocate.py + else + LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH" python $script_dir/wheel/relocate.py + fi +fi diff --git a/packaging/conda/build_vision.sh b/packaging/conda/build_vision.sh index 29784739c79..b326012cf22 100755 --- a/packaging/conda/build_vision.sh +++ b/packaging/conda/build_vision.sh @@ -89,7 +89,7 @@ export tmp_conda="${WIN_PACKAGE_WORK_DIR}\\conda" export miniconda_exe="${WIN_PACKAGE_WORK_DIR}\\miniconda.exe" rm -rf "$tmp_conda" rm -f "$miniconda_exe" -curl -sSk https://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe -o "$miniconda_exe" +curl -sSk https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -o "$miniconda_exe" "$SOURCE_DIR/install_conda.bat" && rm "$miniconda_exe" pushd $tmp_conda export PATH="$(pwd):$(pwd)/Library/usr/bin:$(pwd)/Library/bin:$(pwd)/Scripts:$(pwd)/bin:$PATH" @@ -108,7 +108,9 @@ if [[ "$desired_cuda" == 'cpu' ]]; then else export CONDA_CPUONLY_FEATURE="" . ./switch_cuda_version.sh $desired_cuda - if [[ "$desired_cuda" == "10.1" ]]; then + if [[ "$desired_cuda" == "10.2" ]]; then + export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=10.2,<10.3 # [not osx]" + elif [[ "$desired_cuda" == "10.1" ]]; then export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=10.1,<10.2 # [not osx]" elif [[ "$desired_cuda" == "10.0" ]]; then export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=10.0,<10.1 # [not osx]" @@ -125,7 +127,7 @@ else fi if [[ -z "$PYTORCH_VERSION" ]]; then - export CONDA_CHANNEL_FLAGS="-c pytorch-nightly" + export CONDA_CHANNEL_FLAGS="-c pytorch-nightly -c pytorch" export PYTORCH_VERSION="$(conda search --json 'pytorch[channel=pytorch-nightly]' | \ python -c "import os, sys, json, re; cuver = '$cuver'; \ cuver = cuver.replace('cu', 'cuda') if cuver != 'cpu' else cuver; \ @@ -162,9 +164,9 @@ for py_ver in "${DESIRED_PYTHON[@]}"; do mkdir "$output_folder" if [[ "$py_ver" == 3.5 ]]; then - export CONDA_TYPING_CONSTRAINT="- typing" + export CONDA_TYPING_CONSTRAINT="- typing" else - export CONDA_TYPING_CONSTRAINT="" + export CONDA_TYPING_CONSTRAINT="" fi export VSTOOLCHAIN_PACKAGE=vs2017 diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index ad5a9038fdd..5d967cb18df 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -49,6 +49,17 @@ setup_cuda() { # Now work out the CUDA settings case "$CU_VERSION" in + cu110) + if [[ "$OSTYPE" == "msys" ]]; then + export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.0" + else + export CUDA_HOME=/usr/local/cuda-11.0/ + fi + export FORCE_CUDA=1 + # Hard-coding gencode flags is temporary situation until + # https://github.com/pytorch/pytorch/pull/23408 lands + export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_80,code=sm_80 -gencode=arch=compute_50,code=compute_50" + ;; cu102) if [[ "$OSTYPE" == "msys" ]]; then export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2" @@ -121,7 +132,7 @@ setup_build_version() { # Set build version based on tag if on tag if [[ -n "${CIRCLE_TAG}" ]]; then # Strip tag - export BUILD_VERSION="$(echo "${CIRCLE_TAG}" | sed -e 's/^v//' -e 's/-.*$//')" + export BUILD_VERSION="$(echo "${CIRCLE_TAG}" | sed -e 's/^v//' -e 's/-.*$//')${VERSION_SUFFIX}" fi } @@ -170,7 +181,11 @@ setup_wheel_python() { conda env remove -n "env$PYTHON_VERSION" || true conda create -yn "env$PYTHON_VERSION" python="$PYTHON_VERSION" conda activate "env$PYTHON_VERSION" + # Install libpng from Anaconda (defaults) + conda install libpng jpeg -y else + # Install native CentOS libJPEG, LAME, freetype and GnuTLS + yum install -y libjpeg-turbo-devel lame freetype gnutls case "$PYTHON_VERSION" in 2.7) if [[ -n "$UNICODE_ABI" ]]; then @@ -188,7 +203,13 @@ setup_wheel_python() { exit 1 ;; esac - export PATH="/opt/python/$python_abi/bin:$PATH" + # Download all the dependencies required to compile image and video_reader + # extensions + + mkdir -p ext_libraries + pushd ext_libraries + popd + export PATH="/opt/python/$python_abi/bin:$(pwd)/ext_libraries/bin:$PATH" fi } @@ -213,8 +234,8 @@ setup_pip_pytorch_version() { fi else pip_install "torch==$PYTORCH_VERSION$PYTORCH_VERSION_SUFFIX" \ - -f https://download.pytorch.org/whl/torch_stable.html \ - -f https://download.pytorch.org/whl/nightly/torch_nightly.html + -f "https://download.pytorch.org/whl/${CU_VERSION}/torch_stable.html" \ + -f "https://download.pytorch.org/whl/${UPLOAD_CHANNEL}/${CU_VERSION}/torch_${UPLOAD_CHANNEL}.html" fi } @@ -224,7 +245,7 @@ setup_pip_pytorch_version() { # You MUST have populated PYTORCH_VERSION_SUFFIX before hand. setup_conda_pytorch_constraint() { if [[ -z "$PYTORCH_VERSION" ]]; then - export CONDA_CHANNEL_FLAGS="-c pytorch-nightly" + export CONDA_CHANNEL_FLAGS="-c pytorch-nightly -c pytorch" export PYTORCH_VERSION="$(conda search --json 'pytorch[channel=pytorch-nightly]' | \ python -c "import os, sys, json, re; cuver = os.environ.get('CU_VERSION'); \ cuver_1 = cuver.replace('cu', 'cuda') if cuver != 'cpu' else cuver; \ @@ -239,7 +260,7 @@ setup_conda_pytorch_constraint() { exit 1 fi else - export CONDA_CHANNEL_FLAGS="-c pytorch -c pytorch-nightly" + export CONDA_CHANNEL_FLAGS="-c pytorch -c pytorch-${UPLOAD_CHANNEL}" fi if [[ "$CU_VERSION" == cpu ]]; then export CONDA_PYTORCH_BUILD_CONSTRAINT="- pytorch==$PYTORCH_VERSION${PYTORCH_VERSION_SUFFIX}" @@ -260,6 +281,9 @@ setup_conda_cudatoolkit_constraint() { export CONDA_CUDATOOLKIT_CONSTRAINT="" else case "$CU_VERSION" in + cu110) + export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=11.0,<11.1 # [not osx]" + ;; cu102) export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=10.2,<10.3 # [not osx]" ;; @@ -284,6 +308,39 @@ setup_conda_cudatoolkit_constraint() { fi } +setup_conda_cudatoolkit_plain_constraint() { + export CONDA_CPUONLY_FEATURE="" + export CMAKE_USE_CUDA=1 + if [[ "$(uname)" == Darwin ]]; then + export CONDA_CUDATOOLKIT_CONSTRAINT="" + export CMAKE_USE_CUDA=0 + else + case "$CU_VERSION" in + cu102) + export CONDA_CUDATOOLKIT_CONSTRAINT="cudatoolkit=10.2" + ;; + cu101) + export CONDA_CUDATOOLKIT_CONSTRAINT="cudatoolkit=10.1" + ;; + cu100) + export CONDA_CUDATOOLKIT_CONSTRAINT="cudatoolkit=10.0" + ;; + cu92) + export CONDA_CUDATOOLKIT_CONSTRAINT="cudatoolkit=9.2" + ;; + cpu) + export CONDA_CUDATOOLKIT_CONSTRAINT="" + export CONDA_CPUONLY_FEATURE="cpuonly" + export CMAKE_USE_CUDA=0 + ;; + *) + echo "Unrecognized CU_VERSION=$CU_VERSION" + exit 1 + ;; + esac + fi +} + # Build the proper compiler package before building the final package setup_visual_studio_constraint() { if [[ "$OSTYPE" == "msys" ]]; then @@ -298,3 +355,28 @@ setup_junit_results_folder() { export CONDA_PYTORCH_BUILD_RESULTS_DIRECTORY="${SOURCE_ROOT_DIR}/build_results/results.xml" fi } + + +download_copy_ffmpeg() { + if [[ "$OSTYPE" == "msys" ]]; then + # conda install -yq ffmpeg=4.2 -c pytorch + # curl -L -q https://anaconda.org/pytorch/ffmpeg/4.3/download/win-64/ffmpeg-4.3-ha925a31_0.tar.bz2 --output ffmpeg-4.3-ha925a31_0.tar.bz2 + # bzip2 --decompress --stdout ffmpeg-4.3-ha925a31_0.tar.bz2 | tar -x --file=- + # cp Library/bin/*.dll ../torchvision + echo "FFmpeg is disabled currently on Windows" + else + if [[ "$(uname)" == Darwin ]]; then + conda install -yq ffmpeg=4.2 -c pytorch + conda install -yq wget + else + # pushd ext_libraries + # wget -q https://anaconda.org/pytorch/ffmpeg/4.2/download/linux-64/ffmpeg-4.2-hf484d3e_0.tar.bz2 + # tar -xjvf ffmpeg-4.2-hf484d3e_0.tar.bz2 + # rm -rf ffmpeg-4.2-hf484d3e_0.tar.bz2 + # ldconfig + # which ffmpeg + # popd + echo "FFmpeg is disabled currently on Linux" + fi + fi +} diff --git a/packaging/torchvision/conda_build_config.yaml b/packaging/torchvision/conda_build_config.yaml index 5188bb0ebec..257515c8b70 100644 --- a/packaging/torchvision/conda_build_config.yaml +++ b/packaging/torchvision/conda_build_config.yaml @@ -1,3 +1,5 @@ +channel_sources: + - pytorch-nightly,pytorch,defaults blas_impl: - mkl # [x86_64] c_compiler: diff --git a/packaging/torchvision/meta.yaml b/packaging/torchvision/meta.yaml index 104ce2af846..fadd9b47f72 100644 --- a/packaging/torchvision/meta.yaml +++ b/packaging/torchvision/meta.yaml @@ -8,6 +8,9 @@ source: requirements: build: - {{ compiler('c') }} # [win] + - libpng + - jpeg + - ffmpeg =4.2 # [not win] host: - python @@ -18,6 +21,9 @@ requirements: run: - python + - libpng + - ffmpeg =4.2 # [not win] + - jpeg - pillow >=4.1.1 - numpy >=1.11 {{ environ.get('CONDA_PYTORCH_CONSTRAINT') }} @@ -25,11 +31,12 @@ requirements: build: string: py{{py}}_{{ environ['CU_VERSION'] }} - script: python setup.py install --single-version-externally-managed --record=record.txt # [not win] + script: python setup.py install --single-version-externally-managed --record=record.txt script_env: - CUDA_HOME - FORCE_CUDA - NVCC_FLAGS + - BUILD_VERSION features: {{ environ.get('CONDA_CPUONLY_FEATURE') }} @@ -43,12 +50,9 @@ test: requires: - pytest - scipy - - mock - - av + - av =8.0.1 - ca-certificates {{ environ.get('CONDA_TYPING_CONSTRAINT') }} - commands: - pytest . --verbose --junitxml={{ environ.get("CONDA_PYTORCH_BUILD_RESULTS_DIRECTORY", "build/test_results.xml" )}} about: diff --git a/packaging/vs2017/meta.yaml b/packaging/vs2017/meta.yaml index 34f4860ba85..1f569525ee1 100644 --- a/packaging/vs2017/meta.yaml +++ b/packaging/vs2017/meta.yaml @@ -19,27 +19,6 @@ outputs: # VS 2017 is binary-compatible with VS 2015/vc14. Tools are "v141". strong: - vc{{ vcfeature }} - run_exports: - - vc {{ vcver }} about: summary: Activation and version verification of MSVC {{ vcver }} (VS {{ vsyear }}) compiler license: BSD 3-clause - - name: vs{{ vsyear }}_runtime - script: install_runtime.bat - - name: vc - version: {{ vcver }} - track_features: - - vc{{ vcfeature }} - requirements: - run: - - {{ pin_subpackage('vs' ~ vsyear ~ '_runtime') }} - about: - home: https://github.com/conda/conda/wiki/VC-features - license: Modified BSD License (3-clause) - license_family: BSD - summary: A meta-package to track VC features. - description: | - This metapackage is used to activate vc features without - depending on Python. - doc_url: https://github.com/conda/conda/wiki/VC-features - dev_url: https://github.com/conda/conda/wiki/VC-features diff --git a/packaging/wheel/relocate.py b/packaging/wheel/relocate.py new file mode 100644 index 00000000000..dd2c5d2a4ce --- /dev/null +++ b/packaging/wheel/relocate.py @@ -0,0 +1,417 @@ +# -*- coding: utf-8 -*- + +"""Helper script to package wheels and relocate binaries.""" + +# Standard library imports +import os +import io +import sys +import glob +import shutil +import zipfile +import hashlib +import platform +import subprocess +import os.path as osp +from base64 import urlsafe_b64encode + +# Third party imports +if sys.platform == 'linux': + from auditwheel.lddtree import lddtree +from wheel.bdist_wheel import get_abi_tag + + +ALLOWLIST = { + 'libgcc_s.so.1', 'libstdc++.so.6', 'libm.so.6', + 'libdl.so.2', 'librt.so.1', 'libc.so.6', + 'libnsl.so.1', 'libutil.so.1', 'libpthread.so.0', + 'libresolv.so.2', 'libX11.so.6', 'libXext.so.6', + 'libXrender.so.1', 'libICE.so.6', 'libSM.so.6', + 'libGL.so.1', 'libgobject-2.0.so.0', 'libgthread-2.0.so.0', + 'libglib-2.0.so.0', 'ld-linux-x86-64.so.2', 'ld-2.17.so' +} + +WINDOWS_ALLOWLIST = { + 'MSVCP140.dll', 'KERNEL32.dll', + 'VCRUNTIME140_1.dll', 'VCRUNTIME140.dll', + 'api-ms-win-crt-heap-l1-1-0.dll', + 'api-ms-win-crt-runtime-l1-1-0.dll', + 'api-ms-win-crt-stdio-l1-1-0.dll', + 'api-ms-win-crt-filesystem-l1-1-0.dll', + 'api-ms-win-crt-string-l1-1-0.dll', + 'api-ms-win-crt-environment-l1-1-0.dll', + 'api-ms-win-crt-math-l1-1-0.dll', + 'api-ms-win-crt-convert-l1-1-0.dll' +} + + +HERE = osp.dirname(osp.abspath(__file__)) +PACKAGE_ROOT = osp.dirname(osp.dirname(HERE)) +PLATFORM_ARCH = platform.machine() +PYTHON_VERSION = sys.version_info + + +def read_chunks(file, size=io.DEFAULT_BUFFER_SIZE): + """Yield pieces of data from a file-like object until EOF.""" + while True: + chunk = file.read(size) + if not chunk: + break + yield chunk + + +def rehash(path, blocksize=1 << 20): + """Return (hash, length) for path using hashlib.sha256()""" + h = hashlib.sha256() + length = 0 + with open(path, 'rb') as f: + for block in read_chunks(f, size=blocksize): + length += len(block) + h.update(block) + digest = 'sha256=' + urlsafe_b64encode( + h.digest() + ).decode('latin1').rstrip('=') + # unicode/str python2 issues + return (digest, str(length)) # type: ignore + + +def unzip_file(file, dest): + """Decompress zip `file` into directory `dest`.""" + with zipfile.ZipFile(file, 'r') as zip_ref: + zip_ref.extractall(dest) + + +def is_program_installed(basename): + """ + Return program absolute path if installed in PATH. + Otherwise, return None + On macOS systems, a .app is considered installed if + it exists. + """ + if (sys.platform == 'darwin' and basename.endswith('.app') and + osp.exists(basename)): + return basename + + for path in os.environ["PATH"].split(os.pathsep): + abspath = osp.join(path, basename) + if osp.isfile(abspath): + return abspath + + +def find_program(basename): + """ + Find program in PATH and return absolute path + Try adding .exe or .bat to basename on Windows platforms + (return None if not found) + """ + names = [basename] + if os.name == 'nt': + # Windows platforms + extensions = ('.exe', '.bat', '.cmd', '.dll') + if not basename.endswith(extensions): + names = [basename + ext for ext in extensions] + [basename] + for name in names: + path = is_program_installed(name) + if path: + return path + + +def patch_new_path(library_path, new_dir): + library = osp.basename(library_path) + name, *rest = library.split('.') + rest = '.'.join(rest) + hash_id = hashlib.sha256(library_path.encode('utf-8')).hexdigest()[:8] + new_name = '.'.join([name, hash_id, rest]) + return osp.join(new_dir, new_name) + + +def find_dll_dependencies(dumpbin, binary): + out = subprocess.run([dumpbin, "/dependents", binary], + stdout=subprocess.PIPE) + out = out.stdout.strip().decode('utf-8') + start_index = out.find('dependencies:') + len('dependencies:') + end_index = out.find('Summary') + dlls = out[start_index:end_index].strip() + dlls = dlls.split(os.linesep) + dlls = [dll.strip() for dll in dlls] + return dlls + + +def relocate_elf_library(patchelf, output_dir, output_library, binary): + """ + Relocate an ELF shared library to be packaged on a wheel. + + Given a shared library, find the transitive closure of its dependencies, + rename and copy them into the wheel while updating their respective rpaths. + """ + + print('Relocating {0}'.format(binary)) + binary_path = osp.join(output_library, binary) + + ld_tree = lddtree(binary_path) + tree_libs = ld_tree['libs'] + + binary_queue = [(n, binary) for n in ld_tree['needed']] + binary_paths = {binary: binary_path} + binary_dependencies = {} + + while binary_queue != []: + library, parent = binary_queue.pop(0) + library_info = tree_libs[library] + print(library) + + if library_info['path'] is None: + print('Omitting {0}'.format(library)) + continue + + if library in ALLOWLIST: + # Omit glibc/gcc/system libraries + print('Omitting {0}'.format(library)) + continue + + parent_dependencies = binary_dependencies.get(parent, []) + parent_dependencies.append(library) + binary_dependencies[parent] = parent_dependencies + + if library in binary_paths: + continue + + binary_paths[library] = library_info['path'] + binary_queue += [(n, library) for n in library_info['needed']] + + print('Copying dependencies to wheel directory') + new_libraries_path = osp.join(output_dir, 'torchvision.libs') + os.makedirs(new_libraries_path) + + new_names = {binary: binary_path} + + for library in binary_paths: + if library != binary: + library_path = binary_paths[library] + new_library_path = patch_new_path(library_path, new_libraries_path) + print('{0} -> {1}'.format(library, new_library_path)) + shutil.copyfile(library_path, new_library_path) + new_names[library] = new_library_path + + print('Updating dependency names by new files') + for library in binary_paths: + if library != binary: + if library not in binary_dependencies: + continue + library_dependencies = binary_dependencies[library] + new_library_name = new_names[library] + for dep in library_dependencies: + new_dep = osp.basename(new_names[dep]) + print('{0}: {1} -> {2}'.format(library, dep, new_dep)) + subprocess.check_output( + [ + patchelf, + '--replace-needed', + dep, + new_dep, + new_library_name + ], + cwd=new_libraries_path) + + print('Updating library rpath') + subprocess.check_output( + [ + patchelf, + '--set-rpath', + "$ORIGIN", + new_library_name + ], + cwd=new_libraries_path) + + subprocess.check_output( + [ + patchelf, + '--print-rpath', + new_library_name + ], + cwd=new_libraries_path) + + print("Update library dependencies") + library_dependencies = binary_dependencies[binary] + for dep in library_dependencies: + new_dep = osp.basename(new_names[dep]) + print('{0}: {1} -> {2}'.format(binary, dep, new_dep)) + subprocess.check_output( + [ + patchelf, + '--replace-needed', + dep, + new_dep, + binary + ], + cwd=output_library) + + print('Update library rpath') + subprocess.check_output( + [ + patchelf, + '--set-rpath', + "$ORIGIN:$ORIGIN/../torchvision.libs", + binary_path + ], + cwd=output_library + ) + + +def relocate_dll_library(dumpbin, output_dir, output_library, binary): + """ + Relocate a DLL/PE shared library to be packaged on a wheel. + + Given a shared library, find the transitive closure of its dependencies, + rename and copy them into the wheel. + """ + print('Relocating {0}'.format(binary)) + binary_path = osp.join(output_library, binary) + + library_dlls = find_dll_dependencies(dumpbin, binary_path) + binary_queue = [(dll, binary) for dll in library_dlls] + binary_paths = {binary: binary_path} + binary_dependencies = {} + + while binary_queue != []: + library, parent = binary_queue.pop(0) + if library in WINDOWS_ALLOWLIST or library.startswith('api-ms-win'): + print('Omitting {0}'.format(library)) + continue + + library_path = find_program(library) + if library_path is None: + print('{0} not found'.format(library)) + continue + + if osp.basename(osp.dirname(library_path)) == 'system32': + continue + + print('{0}: {1}'.format(library, library_path)) + parent_dependencies = binary_dependencies.get(parent, []) + parent_dependencies.append(library) + binary_dependencies[parent] = parent_dependencies + + if library in binary_paths: + continue + + binary_paths[library] = library_path + downstream_dlls = find_dll_dependencies(dumpbin, library_path) + binary_queue += [(n, library) for n in downstream_dlls] + + print('Copying dependencies to wheel directory') + package_dir = osp.join(output_dir, 'torchvision') + for library in binary_paths: + if library != binary: + library_path = binary_paths[library] + new_library_path = osp.join(package_dir, library) + print('{0} -> {1}'.format(library, new_library_path)) + shutil.copyfile(library_path, new_library_path) + + +def compress_wheel(output_dir, wheel, wheel_dir, wheel_name): + """Create RECORD file and compress wheel distribution.""" + print('Update RECORD file in wheel') + dist_info = glob.glob(osp.join(output_dir, '*.dist-info'))[0] + record_file = osp.join(dist_info, 'RECORD') + + with open(record_file, 'w') as f: + for root, _, files in os.walk(output_dir): + for this_file in files: + full_file = osp.join(root, this_file) + rel_file = osp.relpath(full_file, output_dir) + if full_file == record_file: + f.write('{0},,\n'.format(rel_file)) + else: + digest, size = rehash(full_file) + f.write('{0},{1},{2}\n'.format(rel_file, digest, size)) + + print('Compressing wheel') + base_wheel_name = osp.join(wheel_dir, wheel_name) + shutil.make_archive(base_wheel_name, 'zip', output_dir) + os.remove(wheel) + shutil.move('{0}.zip'.format(base_wheel_name), wheel) + shutil.rmtree(output_dir) + + +def patch_linux(): + # Get patchelf location + patchelf = find_program('patchelf') + if patchelf is None: + raise FileNotFoundError('Patchelf was not found in the system, please' + ' make sure that is available on the PATH.') + + # Find wheel + print('Finding wheels...') + wheels = glob.glob(osp.join(PACKAGE_ROOT, 'dist', '*.whl')) + output_dir = osp.join(PACKAGE_ROOT, 'dist', '.wheel-process') + + image_binary = 'image.so' + video_binary = 'video_reader.so' + torchvision_binaries = [image_binary, video_binary] + for wheel in wheels: + if osp.exists(output_dir): + shutil.rmtree(output_dir) + + os.makedirs(output_dir) + + print('Unzipping wheel...') + wheel_file = osp.basename(wheel) + wheel_dir = osp.dirname(wheel) + print('{0}'.format(wheel_file)) + wheel_name, _ = osp.splitext(wheel_file) + unzip_file(wheel, output_dir) + + print('Finding ELF dependencies...') + output_library = osp.join(output_dir, 'torchvision') + for binary in torchvision_binaries: + if osp.exists(osp.join(output_library, binary)): + relocate_elf_library( + patchelf, output_dir, output_library, binary) + + compress_wheel(output_dir, wheel, wheel_dir, wheel_name) + + +def patch_win(): + # Get dumpbin location + dumpbin = find_program('dumpbin') + if dumpbin is None: + raise FileNotFoundError('Dumpbin was not found in the system, please' + ' make sure that is available on the PATH.') + + # Find wheel + print('Finding wheels...') + wheels = glob.glob(osp.join(PACKAGE_ROOT, 'dist', '*.whl')) + output_dir = osp.join(PACKAGE_ROOT, 'dist', '.wheel-process') + + image_binary = 'image.pyd' + video_binary = 'video_reader.pyd' + torchvision_binaries = [image_binary, video_binary] + for wheel in wheels: + if osp.exists(output_dir): + shutil.rmtree(output_dir) + + os.makedirs(output_dir) + + print('Unzipping wheel...') + wheel_file = osp.basename(wheel) + wheel_dir = osp.dirname(wheel) + print('{0}'.format(wheel_file)) + wheel_name, _ = osp.splitext(wheel_file) + unzip_file(wheel, output_dir) + + print('Finding DLL/PE dependencies...') + output_library = osp.join(output_dir, 'torchvision') + for binary in torchvision_binaries: + if osp.exists(osp.join(output_library, binary)): + relocate_dll_library( + dumpbin, output_dir, output_library, binary) + + compress_wheel(output_dir, wheel, wheel_dir, wheel_name) + + +if __name__ == '__main__': + if sys.platform == 'linux': + patch_linux() + elif sys.platform == 'win32': + patch_win() diff --git a/packaging/windows/build_vision.bat b/packaging/windows/build_vision.bat index 995c43905cb..46b0874c8d8 100644 --- a/packaging/windows/build_vision.bat +++ b/packaging/windows/build_vision.bat @@ -52,7 +52,7 @@ set "tmp_conda=%CONDA_HOME%" set "miniconda_exe=%CD%\miniconda.exe" rmdir /s /q conda del miniconda.exe -curl -k https://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe -o "%miniconda_exe%" +curl -k https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -o "%miniconda_exe%" call ..\conda\install_conda.bat IF ERRORLEVEL 1 exit /b 1 set "ORIG_PATH=%PATH%" @@ -64,7 +64,7 @@ FOR %%v IN (%DESIRED_PYTHON%) DO ( set PYTHON_VERSION_STR=%%v set PYTHON_VERSION_STR=!PYTHON_VERSION_STR:.=! conda remove -n py!PYTHON_VERSION_STR! --all -y || rmdir %CONDA_HOME%\envs\py!PYTHON_VERSION_STR! /s - conda create -n py!PYTHON_VERSION_STR! -y -q -c defaults -c conda-forge numpy>=1.11 mkl>=2018 python=%%v ca-certificates scipy av + conda create -n py!PYTHON_VERSION_STR! -y -q -c defaults -c conda-forge numpy>=1.11 mkl>=2018 python=%%v ca-certificates scipy ) :: Uncomment for stable releases diff --git a/packaging/windows/cuda102.bat b/packaging/windows/cuda102.bat new file mode 100644 index 00000000000..93dd5a77dfd --- /dev/null +++ b/packaging/windows/cuda102.bat @@ -0,0 +1,59 @@ +@echo off + +IF NOT "%BUILD_VISION%" == "" ( + set MODULE_NAME=vision +) ELSE ( + set MODULE_NAME=pytorch +) + +IF NOT EXIST "setup.py" IF NOT EXIST "%MODULE_NAME%" ( + call internal\clone.bat + cd .. + IF ERRORLEVEL 1 goto eof +) ELSE ( + call internal\clean.bat +) + +call internal\check_deps.bat +IF ERRORLEVEL 1 goto eof + +REM Check for optional components + +set NO_CUDA= +set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 + +IF "%NVTOOLSEXT_PATH%"=="" ( + echo NVTX ^(Visual Studio Extension ^for CUDA^) ^not installed, failing + exit /b 1 + goto optcheck +) + +IF "%CUDA_PATH_V10_2%"=="" ( + echo CUDA 10.2 not found, failing + exit /b 1 +) ELSE ( + IF "%BUILD_VISION%" == "" ( + set TORCH_CUDA_ARCH_LIST=3.5;5.0+PTX;6.0;6.1;7.0;7.5 + set TORCH_NVCC_FLAGS=-Xfatbin -compress-all + ) ELSE ( + set NVCC_FLAGS=-D__CUDA_NO_HALF_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_50,code=compute_50 + ) + + set "CUDA_PATH=%CUDA_PATH_V10_2%" + set "PATH=%CUDA_PATH_V10_2%\bin;%PATH%" +) + +:optcheck + +IF "%BUILD_VISION%" == "" ( + call internal\check_opts.bat + IF ERRORLEVEL 1 goto eof + + call internal\copy.bat + IF ERRORLEVEL 1 goto eof +) + +call internal\setup.bat +IF ERRORLEVEL 1 goto eof + +:eof diff --git a/packaging/windows/internal/build_cmake.bat b/packaging/windows/internal/build_cmake.bat new file mode 100644 index 00000000000..e7b609d2dee --- /dev/null +++ b/packaging/windows/internal/build_cmake.bat @@ -0,0 +1,3 @@ +@echo on +msbuild "-p:Configuration=Release" torchvision.vcxproj +msbuild "-p:Configuration=Release" INSTALL.vcxproj diff --git a/packaging/windows/internal/build_conda.bat b/packaging/windows/internal/build_conda.bat index e66d5596298..18f0bf13467 100644 --- a/packaging/windows/internal/build_conda.bat +++ b/packaging/windows/internal/build_conda.bat @@ -1,4 +1,4 @@ -if "%VC_YEAR%" == "2017" set VSDEVCMD_ARGS=-vcvars_ver=14.11 +if "%VC_YEAR%" == "2017" set VSDEVCMD_ARGS=-vcvars_ver=14.13 if "%VC_YEAR%" == "2017" powershell packaging/windows/internal/vs2017_install.ps1 if errorlevel 1 exit /b 1 diff --git a/packaging/windows/internal/build_cpp_example.bat b/packaging/windows/internal/build_cpp_example.bat new file mode 100644 index 00000000000..7ab711c3999 --- /dev/null +++ b/packaging/windows/internal/build_cpp_example.bat @@ -0,0 +1,3 @@ +@echo on +set CL=/I"C:\Program Files (x86)\torchvision\include" +msbuild "-p:Configuration=Release" hello-world.vcxproj diff --git a/packaging/windows/internal/build_frcnn.bat b/packaging/windows/internal/build_frcnn.bat new file mode 100644 index 00000000000..276e158409b --- /dev/null +++ b/packaging/windows/internal/build_frcnn.bat @@ -0,0 +1,3 @@ +@echo on +set CL=/I"C:\Program Files (x86)\torchvision\include" +msbuild "-p:Configuration=Release" test_frcnn_tracing.vcxproj diff --git a/packaging/windows/internal/build_wheels.bat b/packaging/windows/internal/build_wheels.bat index eea6db2b6ea..a321c3ce6e7 100644 --- a/packaging/windows/internal/build_wheels.bat +++ b/packaging/windows/internal/build_wheels.bat @@ -1,11 +1,11 @@ -if "%VC_YEAR%" == "2017" set VSDEVCMD_ARGS=-vcvars_ver=14.11 +if "%VC_YEAR%" == "2017" set VSDEVCMD_ARGS=-vcvars_ver=14.13 if "%VC_YEAR%" == "2017" powershell packaging/windows/internal/vs2017_install.ps1 if errorlevel 1 exit /b 1 call packaging/windows/internal/cuda_install.bat if errorlevel 1 exit /b 1 -call packaging/windows/internal/nightly_defaults.bat Conda +call packaging/windows/internal/nightly_defaults.bat Wheels if errorlevel 1 exit /b 1 call packaging/windows/build_vision.bat %CUDA_VERSION% %TORCHVISION_BUILD_VERSION% %TORCHVISION_BUILD_NUMBER% diff --git a/packaging/windows/internal/cuda_install.bat b/packaging/windows/internal/cuda_install.bat index 35b4da115cc..b6b26c0c54c 100644 --- a/packaging/windows/internal/cuda_install.bat +++ b/packaging/windows/internal/cuda_install.bat @@ -17,6 +17,8 @@ set CUDA_VERSION_STR=%CUDA_VER_MAJOR%.%CUDA_VER_MINOR% if %CUDA_VER% EQU 92 goto cuda92 if %CUDA_VER% EQU 100 goto cuda100 if %CUDA_VER% EQU 101 goto cuda101 +if %CUDA_VER% EQU 102 goto cuda102 +if %CUDA_VER% EQU 110 goto cuda110 echo CUDA %CUDA_VERSION_STR% is not supported exit /b 1 @@ -71,6 +73,40 @@ if not exist "%SRC_DIR%\temp_build\cudnn-10.1-windows10-x64-v7.6.4.38.zip" ( goto cuda_common +:cuda102 + +if not exist "%SRC_DIR%\temp_build\cuda_10.2.89_441.22_win10.exe" ( + curl -k -L https://ossci-windows.s3.amazonaws.com/cuda_10.2.89_441.22_win10.exe --output "%SRC_DIR%\temp_build\cuda_10.2.89_441.22_win10.exe" + if errorlevel 1 exit /b 1 + set "CUDA_SETUP_FILE=%SRC_DIR%\temp_build\cuda_10.2.89_441.22_win10.exe" + set "ARGS=nvcc_10.2 cuobjdump_10.2 nvprune_10.2 cupti_10.2 cublas_10.2 cublas_dev_10.2 cudart_10.2 cufft_10.2 cufft_dev_10.2 curand_10.2 curand_dev_10.2 cusolver_10.2 cusolver_dev_10.2 cusparse_10.2 cusparse_dev_10.2 nvgraph_10.2 nvgraph_dev_10.2 npp_10.2 npp_dev_10.2 nvrtc_10.2 nvrtc_dev_10.2 nvml_dev_10.2" +) + +if not exist "%SRC_DIR%\temp_build\cudnn-10.2-windows10-x64-v7.6.5.32.zip" ( + curl -k -L https://ossci-windows.s3.amazonaws.com/cudnn-10.2-windows10-x64-v7.6.5.32.zip --output "%SRC_DIR%\temp_build\cudnn-10.2-windows10-x64-v7.6.5.32.zip" + if errorlevel 1 exit /b 1 + set "CUDNN_SETUP_FILE=%SRC_DIR%\temp_build\cudnn-10.2-windows10-x64-v7.6.5.32.zip" +) + +goto cuda_common + +:cuda110 + +if not exist "%SRC_DIR%\temp_build\cuda_11.0.2_451.48_win10.exe" ( + curl -k -L https://ossci-windows.s3.amazonaws.com/cuda_11.0.2_451.48_win10.exe --output "%SRC_DIR%\temp_build\cuda_11.0.2_451.48_win10.exe" + if errorlevel 1 exit /b 1 + set "CUDA_SETUP_FILE=%SRC_DIR%\temp_build\cuda_11.0.2_451.48_win10.exe" + set "ARGS=nvcc_11.0 cuobjdump_11.0 nvprune_11.0 nvprof_11.0 cupti_11.0 cublas_11.0 cublas_dev_11.0 cudart_11.0 cufft_11.0 cufft_dev_11.0 curand_11.0 curand_dev_11.0 cusolver_11.0 cusolver_dev_11.0 cusparse_11.0 cusparse_dev_11.0 npp_11.0 npp_dev_11.0 nvrtc_11.0 nvrtc_dev_11.0 nvml_dev_11.0" +) + +if not exist "%SRC_DIR%\temp_build\cudnn-11.0-windows-x64-v8.0.4.30.zip" ( + curl -k -L https://ossci-windows.s3.amazonaws.com/cudnn-11.0-windows-x64-v8.0.4.30.zip --output "%SRC_DIR%\temp_build\cudnn-11.0-windows-x64-v8.0.4.30.zip" + if errorlevel 1 exit /b 1 + set "CUDNN_SETUP_FILE=%SRC_DIR%\temp_build\cudnn-11.0-windows-x64-v8.0.4.30.zip" +) + +goto cuda_common + :cuda_common if not exist "%SRC_DIR%\temp_build\NvToolsExt.7z" ( @@ -78,6 +114,11 @@ if not exist "%SRC_DIR%\temp_build\NvToolsExt.7z" ( if errorlevel 1 exit /b 1 ) +if not exist "%SRC_DIR%\temp_build\gpu_driver_dlls.7z" ( + curl -k -L "https://drive.google.com/u/0/uc?id=1injUyo3lnarMgWyRcXqKg4UGnN0ysmuq&export=download" --output "%SRC_DIR%\temp_build\gpu_driver_dlls.zip" + if errorlevel 1 exit /b 1 +) + echo Installing CUDA toolkit... 7z x %CUDA_SETUP_FILE% -o"%SRC_DIR%\temp_build\cuda" pushd "%SRC_DIR%\temp_build\cuda" @@ -113,5 +154,8 @@ xcopy /Y "%SRC_DIR%\temp_build\cudnn\cuda\bin\*.*" "%ProgramFiles%\NVIDIA GPU Co xcopy /Y "%SRC_DIR%\temp_build\cudnn\cuda\lib\x64\*.*" "%ProgramFiles%\NVIDIA GPU Computing Toolkit\CUDA\v%CUDA_VERSION_STR%\lib\x64" xcopy /Y "%SRC_DIR%\temp_build\cudnn\cuda\include\*.*" "%ProgramFiles%\NVIDIA GPU Computing Toolkit\CUDA\v%CUDA_VERSION_STR%\include" +echo Installing GPU driver DLLs +7z x %SRC_DIR%\temp_build\gpu_driver_dlls.zip -o"C:\Windows\System32" + echo Cleaning temp files rd /s /q "%SRC_DIR%\temp_build" || ver > nul diff --git a/packaging/windows/internal/nightly_defaults.bat b/packaging/windows/internal/nightly_defaults.bat index 5a65781e600..68f04fdbccf 100644 --- a/packaging/windows/internal/nightly_defaults.bat +++ b/packaging/windows/internal/nightly_defaults.bat @@ -144,10 +144,10 @@ if "%CUDA_VERSION%" == "cpu" ( :: pytorch-nightly==1.0.0.dev20180908 :: or in manylinux like :: torch_nightly-1.0.0.dev20180908-cp27-cp27m-linux_x86_64.whl -if "%TORCHVISION_BUILD_VERSION%" == "" set TORCHVISION_BUILD_VERSION=0.6.0.dev%NIGHTLIES_DATE_COMPACT% +if "%TORCHVISION_BUILD_VERSION%" == "" set TORCHVISION_BUILD_VERSION=0.9.0.dev%NIGHTLIES_DATE_COMPACT% if "%~1" == "Wheels" ( - if not "%CUDA_VERSION%" == "101" ( + if not "%CUDA_VERSION%" == "102" ( set TORCHVISION_BUILD_VERSION=%TORCHVISION_BUILD_VERSION%+%_DESIRED_CUDA% ) ) diff --git a/packaging/windows/internal/test.bat b/packaging/windows/internal/test.bat index 2f51f79aac9..472f2ca05da 100644 --- a/packaging/windows/internal/test.bat +++ b/packaging/windows/internal/test.bat @@ -8,7 +8,7 @@ set PYTHON_VERSION=%PYTHON_PREFIX:py=cp% if "%BUILD_VISION%" == "" ( pip install future pytest coverage hypothesis protobuf ) ELSE ( - pip install future pytest "pillow>=4.1.1" mock + pip install future pytest "pillow>=4.1.1" ) for /F "delims=" %%i in ('where /R %SRC_DIR%\output *%MODULE_NAME%*%PYTHON_VERSION%*.whl') do pip install "%%i" diff --git a/packaging/windows/internal/vc_install_helper.sh b/packaging/windows/internal/vc_install_helper.sh index 9910677acac..cdae18065b9 100644 --- a/packaging/windows/internal/vc_install_helper.sh +++ b/packaging/windows/internal/vc_install_helper.sh @@ -4,7 +4,7 @@ set -ex if [[ "$CU_VERSION" == "cu92" ]]; then export VC_YEAR=2017 - export VSDEVCMD_ARGS="-vcvars_ver=14.11" + export VSDEVCMD_ARGS="-vcvars_ver=14.13" powershell packaging/windows/internal/vs2017_install.ps1 elif [[ "$CU_VERSION" == "cu100" ]]; then export VC_YEAR=2017 diff --git a/packaging/windows/internal/vs2017_install.ps1 b/packaging/windows/internal/vs2017_install.ps1 index 6bbb1deb310..3e953de1ab7 100644 --- a/packaging/windows/internal/vs2017_install.ps1 +++ b/packaging/windows/internal/vs2017_install.ps1 @@ -1,6 +1,6 @@ $VS_DOWNLOAD_LINK = "https://aka.ms/vs/15/release/vs_buildtools.exe" $VS_INSTALL_ARGS = @("--nocache","--quiet","--wait", "--add Microsoft.VisualStudio.Workload.VCTools", - "--add Microsoft.VisualStudio.Component.VC.Tools.14.11", + "--add Microsoft.VisualStudio.Component.VC.Tools.14.13", "--add Microsoft.Component.MSBuild", "--add Microsoft.VisualStudio.Component.Roslyn.Compiler", "--add Microsoft.VisualStudio.Component.TextTemplating", diff --git a/packaging/windows/internal/vs_install.bat b/packaging/windows/internal/vs_install.bat index e6589092372..348a5e33166 100644 --- a/packaging/windows/internal/vs_install.bat +++ b/packaging/windows/internal/vs_install.bat @@ -1,28 +1,14 @@ @echo off -set VS_DOWNLOAD_LINK=https://aka.ms/vs/15/release/vs_buildtools.exe -REM IF "%VS_LATEST%" == "1" ( -REM set VS_INSTALL_ARGS= --nocache --norestart --quiet --wait --add Microsoft.VisualStudio.Workload.VCTools -REM set VSDEVCMD_ARGS= -REM ) ELSE ( -set VS_INSTALL_ARGS=--nocache --quiet --wait --add Microsoft.VisualStudio.Workload.VCTools ^ - --add Microsoft.VisualStudio.Component.VC.Tools.14.11 ^ - --add Microsoft.Component.MSBuild ^ - --add Microsoft.VisualStudio.Component.Roslyn.Compiler ^ - --add Microsoft.VisualStudio.Component.TextTemplating ^ - --add Microsoft.VisualStudio.Component.VC.CoreIde ^ - --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest ^ - --add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Core ^ - --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 ^ - --add Microsoft.VisualStudio.Component.VC.Tools.14.11 ^ - --add Microsoft.VisualStudio.ComponentGroup.NativeDesktop.Win81 +set VS_DOWNLOAD_LINK=https://aka.ms/vs/15/release/vs_enterprise.exe +set VS_INSTALL_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise +set VS_INSTALL_ARGS=--nocache --quiet --wait --add Microsoft.VisualStudio.Component.VC.Tools.14.11 set VSDEVCMD_ARGS=-vcvars_ver=14.11 -REM ) curl -k -L %VS_DOWNLOAD_LINK% --output vs_installer.exe if errorlevel 1 exit /b 1 -start /wait .\vs_installer.exe %VS_INSTALL_ARGS% +start /wait vs_installer.exe modify --installPath "%VS_INSTALL_PATH%" %VS_INSTALL_ARGS% if not errorlevel 0 exit /b 1 if errorlevel 1 if not errorlevel 3010 exit /b 1 if errorlevel 3011 exit /b 1 diff --git a/packaging/windows/templates/auth_task.yml b/packaging/windows/templates/auth_task.yml index ece66412ff4..7554ffaac1d 100644 --- a/packaging/windows/templates/auth_task.yml +++ b/packaging/windows/templates/auth_task.yml @@ -6,7 +6,7 @@ jobs: - group: 'peterjc-vsts-token' pool: - vmImage: 'win1803' + vmImage: 'vs2017-win2016' steps: - checkout: self diff --git a/packaging/windows/templates/build_task.yml b/packaging/windows/templates/build_task.yml index 8e52749b338..17452477b82 100644 --- a/packaging/windows/templates/build_task.yml +++ b/packaging/windows/templates/build_task.yml @@ -83,10 +83,22 @@ jobs: PY3.8_101: DESIRED_PYTHON: 3.8 CUDA_VERSION: 101 + PY3.5_102: + DESIRED_PYTHON: 3.5 + CUDA_VERSION: 102 + PY3.6_102: + DESIRED_PYTHON: 3.6 + CUDA_VERSION: 102 + PY3.7_102: + DESIRED_PYTHON: 3.7 + CUDA_VERSION: 102 + PY3.8_102: + DESIRED_PYTHON: 3.8 + CUDA_VERSION: 102 pool: ${{ if eq(parameters.msagent, 'true') }}: - vmImage: 'win1803' + vmImage: 'vs2017-win2016' ${{ if eq(parameters.msagent, 'false') }}: name: 'release' diff --git a/references/classification/README.md b/references/classification/README.md index acc2b0b4ed0..bd00f2c7dd8 100644 --- a/references/classification/README.md +++ b/references/classification/README.md @@ -4,7 +4,31 @@ This folder contains reference training scripts for image classification. They serve as a log of how to train specific models, as provide baseline training and evaluation scripts to quickly bootstrap research. -Except otherwise noted, all models have been trained on 8x V100 GPUs. +Except otherwise noted, all models have been trained on 8x V100 GPUs with +the following parameters: + +| Parameter | value | +| ------------------------ | ------ | +| `--batch_size` | `32` | +| `--epochs` | `90` | +| `--lr` | `0.1` | +| `--momentum` | `0.9` | +| `--wd`, `--weight-decay` | `1e-4` | +| `--lr-step-size` | `30` | +| `--lr-gamma` | `0.1` | + +### AlexNet and VGG + +Since `AlexNet` and the original `VGG` architectures do not include batch +normalization, the default initial learning rate `--lr 0.1` is to high. + +``` +python main.py --model $MODEL --lr 1e-2 +``` + +Here `$MODEL` is one of `alexnet`, `vgg11`, `vgg13`, `vgg16` or `vgg19`. Note +that `vgg11_bn`, `vgg13_bn`, `vgg16_bn`, and `vgg19_bn` include batch +normalization and thus are trained with the default parameters. ### ResNext-50 32x4d ``` @@ -40,6 +64,27 @@ python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py\ ``` ## Quantized +### INT8 models +We add INT8 quantized models to follow the quantization support added in PyTorch 1.3. + +Obtaining a pre-trained quantized model can be obtained with a few lines of code: +``` +model = torchvision.models.quantization.mobilenet_v2(pretrained=True, quantize=True) +model.eval() +# run the model with quantized inputs and weights +out = model(torch.rand(1, 3, 224, 224)) +``` +We provide pre-trained quantized weights for the following models: + +| Model | Acc@1 | Acc@5 | +|:-----------------:|:------:|:------:| +| MobileNet V2 | 71.658 | 90.150 | +| ShuffleNet V2: | 68.360 | 87.582 | +| ResNet 18 | 69.494 | 88.882 | +| ResNet 50 | 75.920 | 92.814 | +| ResNext 101 32x8d | 78.986 | 94.480 | +| Inception V3 | 77.176 | 93.354 | +| GoogleNet | 69.826 | 89.404 | ### Parameters used for generating quantized models: diff --git a/references/classification/train_quantization.py b/references/classification/train_quantization.py index e59b8d4a64e..a054dbda91c 100644 --- a/references/classification/train_quantization.py +++ b/references/classification/train_quantization.py @@ -58,6 +58,9 @@ def main(args): model.qconfig = torch.quantization.get_default_qat_qconfig(args.backend) torch.quantization.prepare_qat(model, inplace=True) + if args.distributed and args.sync_bn: + model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(model) + optimizer = torch.optim.SGD( model.parameters(), lr=args.lr, momentum=args.momentum, weight_decay=args.weight_decay) @@ -129,7 +132,7 @@ def main(args): print('Evaluate QAT model') evaluate(model, criterion, data_loader_test, device=device) - quantized_eval_model = copy.deepcopy(model) + quantized_eval_model = copy.deepcopy(model_without_ddp) quantized_eval_model.eval() quantized_eval_model.to(torch.device('cpu')) torch.quantization.convert(quantized_eval_model, inplace=True) @@ -223,6 +226,12 @@ def parse_args(): It also serializes the transforms", action="store_true", ) + parser.add_argument( + "--sync-bn", + dest="sync_bn", + help="Use sync batch norm", + action="store_true", + ) parser.add_argument( "--test-only", dest="test_only", diff --git a/references/detection/README.md b/references/detection/README.md index 7aec36aefa3..f89e8149a71 100644 --- a/references/detection/README.md +++ b/references/detection/README.md @@ -1,10 +1,24 @@ # Object detection reference training scripts This folder contains reference training scripts for object detection. -They serve as a log of how to train specific models, as provide baseline +They serve as a log of how to train specific models, to provide baseline training and evaluation scripts to quickly bootstrap research. -Except otherwise noted, all models have been trained on 8x V100 GPUs. +To execute the example commands below you must install the following: + +``` +cython +pycocotools +matplotlib +``` + +You must modify the following flags: + +`--data-path=/path/to/coco/dataset` + +`--nproc_per_node=` + +Except otherwise noted, all models have been trained on 8x V100 GPUs. ### Faster R-CNN ``` @@ -13,6 +27,13 @@ python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py\ --lr-steps 16 22 --aspect-ratio-group-factor 3 ``` +### RetinaNet +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py\ + --dataset coco --model retinanet_resnet50_fpn --epochs 26\ + --lr-steps 16 22 --aspect-ratio-group-factor 3 --lr 0.01 +``` + ### Mask R-CNN ``` diff --git a/references/detection/engine.py b/references/detection/engine.py index 86c25d9c486..9f34336b0cc 100644 --- a/references/detection/engine.py +++ b/references/detection/engine.py @@ -81,13 +81,12 @@ def evaluate(model, data_loader, device): iou_types = _get_iou_types(model) coco_evaluator = CocoEvaluator(coco, iou_types) - for image, targets in metric_logger.log_every(data_loader, 100, header): - image = list(img.to(device) for img in image) - targets = [{k: v.to(device) for k, v in t.items()} for t in targets] + for images, targets in metric_logger.log_every(data_loader, 100, header): + images = list(img.to(device) for img in images) torch.cuda.synchronize() model_time = time.time() - outputs = model(image) + outputs = model(images) outputs = [{k: v.to(cpu_device) for k, v in t.items()} for t in outputs] model_time = time.time() - model_time diff --git a/references/detection/train.py b/references/detection/train.py index 722f4b4f72c..00d94fd1636 100644 --- a/references/detection/train.py +++ b/references/detection/train.py @@ -108,14 +108,14 @@ def main(args): # lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=args.lr_step_size, gamma=args.lr_gamma) lr_scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=args.lr_steps, gamma=args.lr_gamma) - + if args.resume: checkpoint = torch.load(args.resume, map_location='cpu') model_without_ddp.load_state_dict(checkpoint['model']) optimizer.load_state_dict(checkpoint['optimizer']) lr_scheduler.load_state_dict(checkpoint['lr_scheduler']) args.start_epoch = checkpoint['epoch'] + 1 - + if args.test_only: evaluate(model, data_loader_test, device=device) return diff --git a/references/segmentation/README.md b/references/segmentation/README.md new file mode 100644 index 00000000000..34db88c7a3a --- /dev/null +++ b/references/segmentation/README.md @@ -0,0 +1,33 @@ +# Semantic segmentation reference training scripts + +This folder contains reference training scripts for semantic segmentation. +They serve as a log of how to train specific models, as provide baseline +training and evaluation scripts to quickly bootstrap research. + +All models have been trained on 8x V100 GPUs. + +You must modify the following flags: + +`--data-path=/path/to/dataset` + +`--nproc_per_node=` + +## fcn_resnet50 +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py --lr 0.02 --dataset coco -b 4 --model fcn_resnet50 --aux-loss +``` + +## fcn_resnet101 +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py --lr 0.02 --dataset coco -b 4 --model fcn_resnet101 --aux-loss +``` + +## deeplabv3_resnet50 +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py --lr 0.02 --dataset coco -b 4 --model deeplabv3_resnet50 --aux-loss +``` + +## deeplabv3_resnet101 +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py --lr 0.02 --dataset coco -b 4 --model deeplabv3_resnet101 --aux-loss +``` diff --git a/references/segmentation/train.py b/references/segmentation/train.py index b1173d5323a..e82e5bda651 100644 --- a/references/segmentation/train.py +++ b/references/segmentation/train.py @@ -12,13 +12,13 @@ import utils -def get_dataset(name, image_set, transform): +def get_dataset(dir_path, name, image_set, transform): def sbd(*args, **kwargs): return torchvision.datasets.SBDataset(*args, mode='segmentation', **kwargs) paths = { - "voc": ('/datasets01/VOC/060817/', torchvision.datasets.VOCSegmentation, 21), - "voc_aug": ('/datasets01/SBDD/072318/', sbd, 21), - "coco": ('/datasets01/COCO/022719/', get_coco, 21) + "voc": (dir_path, torchvision.datasets.VOCSegmentation, 21), + "voc_aug": (dir_path, sbd, 21), + "coco": (dir_path, get_coco, 21) } p, ds_fn, num_classes = paths[name] @@ -101,8 +101,8 @@ def main(args): device = torch.device(args.device) - dataset, num_classes = get_dataset(args.dataset, "train", get_transform(train=True)) - dataset_test, _ = get_dataset(args.dataset, "val", get_transform(train=False)) + dataset, num_classes = get_dataset(args.data_path, args.dataset, "train", get_transform(train=True)) + dataset_test, _ = get_dataset(args.data_path, args.dataset, "val", get_transform(train=False)) if args.distributed: train_sampler = torch.utils.data.distributed.DistributedSampler(dataset) @@ -128,10 +128,6 @@ def main(args): if args.distributed: model = torch.nn.SyncBatchNorm.convert_sync_batchnorm(model) - if args.resume: - checkpoint = torch.load(args.resume, map_location='cpu') - model.load_state_dict(checkpoint['model']) - model_without_ddp = model if args.distributed: model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.gpu]) @@ -157,8 +153,15 @@ def main(args): optimizer, lambda x: (1 - x / (len(data_loader) * args.epochs)) ** 0.9) + if args.resume: + checkpoint = torch.load(args.resume, map_location='cpu') + model_without_ddp.load_state_dict(checkpoint['model']) + optimizer.load_state_dict(checkpoint['optimizer']) + lr_scheduler.load_state_dict(checkpoint['lr_scheduler']) + args.start_epoch = checkpoint['epoch'] + 1 + start_time = time.time() - for epoch in range(args.epochs): + for epoch in range(args.start_epoch, args.epochs): if args.distributed: train_sampler.set_epoch(epoch) train_one_epoch(model, criterion, optimizer, data_loader, lr_scheduler, device, epoch, args.print_freq) @@ -168,6 +171,7 @@ def main(args): { 'model': model_without_ddp.state_dict(), 'optimizer': optimizer.state_dict(), + 'lr_scheduler': lr_scheduler.state_dict(), 'epoch': epoch, 'args': args }, @@ -182,7 +186,8 @@ def parse_args(): import argparse parser = argparse.ArgumentParser(description='PyTorch Segmentation Training') - parser.add_argument('--dataset', default='voc', help='dataset') + parser.add_argument('--data-path', default='/datasets01/COCO/022719/', help='dataset path') + parser.add_argument('--dataset', default='coco', help='dataset name') parser.add_argument('--model', default='fcn_resnet101', help='model') parser.add_argument('--aux-loss', action='store_true', help='auxiliar loss') parser.add_argument('--device', default='cuda', help='device') @@ -201,6 +206,8 @@ def parse_args(): parser.add_argument('--print-freq', default=10, type=int, help='print frequency') parser.add_argument('--output-dir', default='.', help='path where to save') parser.add_argument('--resume', default='', help='resume from checkpoint') + parser.add_argument('--start-epoch', default=0, type=int, metavar='N', + help='start epoch') parser.add_argument( "--test-only", dest="test_only", diff --git a/references/segmentation/transforms.py b/references/segmentation/transforms.py index bce4bfbe639..4fe5a5ad147 100644 --- a/references/segmentation/transforms.py +++ b/references/segmentation/transforms.py @@ -78,7 +78,7 @@ def __call__(self, image, target): class ToTensor(object): def __call__(self, image, target): image = F.to_tensor(image) - target = torch.as_tensor(np.asarray(target), dtype=torch.int64) + target = torch.as_tensor(np.array(target), dtype=torch.int64) return image, target diff --git a/references/segmentation/utils.py b/references/segmentation/utils.py index d9251b72b9f..b67c18052fb 100644 --- a/references/segmentation/utils.py +++ b/references/segmentation/utils.py @@ -1,6 +1,5 @@ from collections import defaultdict, deque import datetime -import math import time import torch import torch.distributed as dist diff --git a/references/video_classification/README.md b/references/video_classification/README.md new file mode 100644 index 00000000000..ef7db6dcd90 --- /dev/null +++ b/references/video_classification/README.md @@ -0,0 +1,34 @@ +# Video Classification + +We present a simple training script that can be used for replicating the result of [resenet-based video models](https://research.fb.com/wp-content/uploads/2018/04/a-closer-look-at-spatiotemporal-convolutions-for-action-recognition.pdf). All models are trained on [Kinetics400 dataset](https://deepmind.com/research/open-source/kinetics), a benchmark dataset for human-action recognition. The accuracy is reported on the traditional validation split. + +## Data preparation + +If you already have downloaded [Kinetics400 dataset](https://deepmind.com/research/open-source/kinetics), +please proceed directly to the next section. + +To download videos, one can use https://github.com/Showmax/kinetics-downloader. Please note that the dataset can take up upwards of 400GB, depending on the quality setting during download. + +## Training + +We assume the training and validation AVI videos are stored at `/data/kinectics400/train` and +`/data/kinectics400/val`. For training we suggest starting with the hyperparameters reported in the [paper](https://research.fb.com/wp-content/uploads/2018/04/a-closer-look-at-spatiotemporal-convolutions-for-action-recognition.pdf), in order to match the performance of said models. Clip sampling strategy is a particularly important parameter during training, and we suggest using random temporal jittering during training - in other words sampling multiple training clips from each video with random start times during at every epoch. This functionality is built into our training script, and optimal hyperparameters are set by default. + +### Multiple GPUs + +Run the training on a single node with 8 GPUs: +```bash +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py --data-path=/data/kinectics400 --train-dir=train --val-dir=val --batch-size=16 --cache-dataset --sync-bn --apex +``` + +**Note:** all our models were trained on 8 nodes with 8 V100 GPUs each for a total of 64 GPUs. Expected training time for 64 GPUs is 24 hours, depending on the storage solution. +**Note 2:** hyperparameters for exact replication of our training can be found [here](https://github.com/pytorch/vision/blob/master/torchvision/models/video/README.md). Some hyperparameters such as learning rate are scaled linearly in proportion to the number of GPUs. + +### Single GPU + +**Note:** training on a single gpu can be extremely slow. + + +```bash +python train.py --data-path=/data/kinectics400 --train-dir=train --val-dir=val --batch-size=8 --cache-dataset +``` diff --git a/references/video_classification/train.py b/references/video_classification/train.py index e71c03f174f..3b5d8d8d206 100644 --- a/references/video_classification/train.py +++ b/references/video_classification/train.py @@ -7,13 +7,13 @@ from torch import nn import torchvision import torchvision.datasets.video_utils -from torchvision import transforms +from torchvision import transforms as T from torchvision.datasets.samplers import DistributedSampler, UniformClipSampler, RandomClipSampler import utils from scheduler import WarmupMultiStepLR -import transforms as T +from transforms import ConvertBHWCtoBCHW, ConvertBCHWtoCBHW try: from apex import amp @@ -119,11 +119,13 @@ def main(args): st = time.time() cache_path = _get_cache_path(traindir) transform_train = torchvision.transforms.Compose([ - T.ToFloatTensorInZeroOne(), + ConvertBHWCtoBCHW(), + T.ConvertImageDtype(torch.float32), T.Resize((128, 171)), T.RandomHorizontalFlip(), normalize, - T.RandomCrop((112, 112)) + T.RandomCrop((112, 112)), + ConvertBCHWtoCBHW() ]) if args.cache_dataset and os.path.exists(cache_path): @@ -139,7 +141,8 @@ def main(args): frames_per_clip=args.clip_len, step_between_clips=1, transform=transform_train, - frame_rate=15 + frame_rate=15, + extensions=('avi', 'mp4', ) ) if args.cache_dataset: print("Saving dataset_train to {}".format(cache_path)) @@ -152,10 +155,12 @@ def main(args): cache_path = _get_cache_path(valdir) transform_test = torchvision.transforms.Compose([ - T.ToFloatTensorInZeroOne(), + ConvertBHWCtoBCHW(), + T.ConvertImageDtype(torch.float32), T.Resize((128, 171)), normalize, - T.CenterCrop((112, 112)) + T.CenterCrop((112, 112)), + ConvertBCHWtoCBHW() ]) if args.cache_dataset and os.path.exists(cache_path): @@ -171,7 +176,8 @@ def main(args): frames_per_clip=args.clip_len, step_between_clips=1, transform=transform_test, - frame_rate=15 + frame_rate=15, + extensions=('avi', 'mp4',) ) if args.cache_dataset: print("Saving dataset_test to {}".format(cache_path)) @@ -265,7 +271,7 @@ def main(args): def parse_args(): import argparse - parser = argparse.ArgumentParser(description='PyTorch Classification Training') + parser = argparse.ArgumentParser(description='PyTorch Video Classification Training') parser.add_argument('--data-path', default='/datasets01_101/kinetics/070618/', help='dataset') parser.add_argument('--train-dir', default='train_avi-480p', help='name of train dir') diff --git a/references/video_classification/transforms.py b/references/video_classification/transforms.py index 9435450c4b3..27f6c75450a 100644 --- a/references/video_classification/transforms.py +++ b/references/video_classification/transforms.py @@ -1,122 +1,18 @@ import torch -import random +import torch.nn as nn -def crop(vid, i, j, h, w): - return vid[..., i:(i + h), j:(j + w)] +class ConvertBHWCtoBCHW(nn.Module): + """Convert tensor from (B, H, W, C) to (B, C, H, W) + """ + def forward(self, vid: torch.Tensor) -> torch.Tensor: + return vid.permute(0, 3, 1, 2) -def center_crop(vid, output_size): - h, w = vid.shape[-2:] - th, tw = output_size - i = int(round((h - th) / 2.)) - j = int(round((w - tw) / 2.)) - return crop(vid, i, j, th, tw) +class ConvertBCHWtoCBHW(nn.Module): + """Convert tensor from (B, C, H, W) to (C, B, H, W) + """ - -def hflip(vid): - return vid.flip(dims=(-1,)) - - -# NOTE: for those functions, which generally expect mini-batches, we keep them -# as non-minibatch so that they are applied as if they were 4d (thus image). -# this way, we only apply the transformation in the spatial domain -def resize(vid, size, interpolation='bilinear'): - # NOTE: using bilinear interpolation because we don't work on minibatches - # at this level - scale = None - if isinstance(size, int): - scale = float(size) / min(vid.shape[-2:]) - size = None - return torch.nn.functional.interpolate( - vid, size=size, scale_factor=scale, mode=interpolation, align_corners=False) - - -def pad(vid, padding, fill=0, padding_mode="constant"): - # NOTE: don't want to pad on temporal dimension, so let as non-batch - # (4d) before padding. This works as expected - return torch.nn.functional.pad(vid, padding, value=fill, mode=padding_mode) - - -def to_normalized_float_tensor(vid): - return vid.permute(3, 0, 1, 2).to(torch.float32) / 255 - - -def normalize(vid, mean, std): - shape = (-1,) + (1,) * (vid.dim() - 1) - mean = torch.as_tensor(mean).reshape(shape) - std = torch.as_tensor(std).reshape(shape) - return (vid - mean) / std - - -# Class interface - -class RandomCrop(object): - def __init__(self, size): - self.size = size - - @staticmethod - def get_params(vid, output_size): - """Get parameters for ``crop`` for a random crop. - """ - h, w = vid.shape[-2:] - th, tw = output_size - if w == tw and h == th: - return 0, 0, h, w - i = random.randint(0, h - th) - j = random.randint(0, w - tw) - return i, j, th, tw - - def __call__(self, vid): - i, j, h, w = self.get_params(vid, self.size) - return crop(vid, i, j, h, w) - - -class CenterCrop(object): - def __init__(self, size): - self.size = size - - def __call__(self, vid): - return center_crop(vid, self.size) - - -class Resize(object): - def __init__(self, size): - self.size = size - - def __call__(self, vid): - return resize(vid, self.size) - - -class ToFloatTensorInZeroOne(object): - def __call__(self, vid): - return to_normalized_float_tensor(vid) - - -class Normalize(object): - def __init__(self, mean, std): - self.mean = mean - self.std = std - - def __call__(self, vid): - return normalize(vid, self.mean, self.std) - - -class RandomHorizontalFlip(object): - def __init__(self, p=0.5): - self.p = p - - def __call__(self, vid): - if random.random() < self.p: - return hflip(vid) - return vid - - -class Pad(object): - def __init__(self, padding, fill=0): - self.padding = padding - self.fill = fill - - def __call__(self, vid): - return pad(vid, self.padding, self.fill) + def forward(self, vid: torch.Tensor) -> torch.Tensor: + return vid.permute(1, 0, 2, 3) diff --git a/setup.cfg b/setup.cfg index 5b77b5fbce3..19f6d24056a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,5 +9,5 @@ max-line-length = 120 [flake8] max-line-length = 120 -ignore = F401,E402,F403,W503,W504 +ignore = F401,E402,F403,W503,W504,F821 exclude = venv diff --git a/setup.py b/setup.py index 0f7c5676e75..82c93be87cd 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,8 @@ import os import io -import re import sys from setuptools import setup, find_packages -from pkg_resources import get_distribution, DistributionNotFound +from pkg_resources import parse_version, get_distribution, DistributionNotFound import subprocess import distutils.command.clean import distutils.spawn @@ -12,6 +11,7 @@ import torch from torch.utils.cpp_extension import BuildExtension, CppExtension, CUDAExtension, CUDA_HOME +from torch.utils.hipify import hipify_python def read(*names, **kwargs): @@ -29,7 +29,7 @@ def get_dist(pkgname): return None -version = '0.6.0a0' +version = '0.9.0a0' sha = 'Unknown' package_name = 'torchvision' @@ -44,7 +44,6 @@ def get_dist(pkgname): version = os.getenv('BUILD_VERSION') elif sha != 'Unknown': version += '+' + sha[:7] -print("Building wheel {}-{}".format(package_name, version)) def write_version_file(): @@ -57,10 +56,6 @@ def write_version_file(): f.write(" cuda = _check_cuda_version()\n") -write_version_file() - -readme = open('README.rst').read() - pytorch_dep = 'torch' if os.getenv('PYTORCH_VERSION'): pytorch_dep += "==" + os.getenv('PYTORCH_VERSION') @@ -75,13 +70,93 @@ def write_version_file(): requirements.append(pillow_req + pillow_ver) +def find_library(name, vision_include): + this_dir = os.path.dirname(os.path.abspath(__file__)) + build_prefix = os.environ.get('BUILD_PREFIX', None) + is_conda_build = build_prefix is not None + + library_found = False + conda_installed = False + lib_folder = None + include_folder = None + library_header = '{0}.h'.format(name) + + # Lookup in TORCHVISION_INCLUDE or in the package file + package_path = [os.path.join(this_dir, 'torchvision')] + for folder in vision_include + package_path: + candidate_path = os.path.join(folder, library_header) + library_found = os.path.exists(candidate_path) + if library_found: + break + + if not library_found: + print('Running build on conda-build: {0}'.format(is_conda_build)) + if is_conda_build: + # Add conda headers/libraries + if os.name == 'nt': + build_prefix = os.path.join(build_prefix, 'Library') + include_folder = os.path.join(build_prefix, 'include') + lib_folder = os.path.join(build_prefix, 'lib') + library_header_path = os.path.join( + include_folder, library_header) + library_found = os.path.isfile(library_header_path) + conda_installed = library_found + else: + # Check if using Anaconda to produce wheels + conda = distutils.spawn.find_executable('conda') + is_conda = conda is not None + print('Running build on conda: {0}'.format(is_conda)) + if is_conda: + python_executable = sys.executable + py_folder = os.path.dirname(python_executable) + if os.name == 'nt': + env_path = os.path.join(py_folder, 'Library') + else: + env_path = os.path.dirname(py_folder) + lib_folder = os.path.join(env_path, 'lib') + include_folder = os.path.join(env_path, 'include') + library_header_path = os.path.join( + include_folder, library_header) + library_found = os.path.isfile(library_header_path) + conda_installed = library_found + + if not library_found: + if sys.platform == 'linux': + library_found = os.path.exists('/usr/include/{0}'.format( + library_header)) + library_found = library_found or os.path.exists( + '/usr/local/include/{0}'.format(library_header)) + + return library_found, conda_installed, include_folder, lib_folder + + def get_extensions(): this_dir = os.path.dirname(os.path.abspath(__file__)) extensions_dir = os.path.join(this_dir, 'torchvision', 'csrc') main_file = glob.glob(os.path.join(extensions_dir, '*.cpp')) source_cpu = glob.glob(os.path.join(extensions_dir, 'cpu', '*.cpp')) - source_cuda = glob.glob(os.path.join(extensions_dir, 'cuda', '*.cu')) + + is_rocm_pytorch = False + if torch.__version__ >= '1.5': + from torch.utils.cpp_extension import ROCM_HOME + is_rocm_pytorch = True if ((torch.version.hip is not None) and (ROCM_HOME is not None)) else False + + if is_rocm_pytorch: + hipify_python.hipify( + project_directory=this_dir, + output_directory=this_dir, + includes="torchvision/csrc/cuda/*", + show_detailed=True, + is_pytorch_extension=True, + ) + source_cuda = glob.glob(os.path.join(extensions_dir, 'hip', '*.hip')) + # Copy over additional files + shutil.copy("torchvision/csrc/cuda/cuda_helpers.h", "torchvision/csrc/hip/cuda_helpers.h") + shutil.copy("torchvision/csrc/cuda/vision_cuda.h", "torchvision/csrc/hip/vision_cuda.h") + + else: + source_cuda = glob.glob(os.path.join(extensions_dir, 'cuda', '*.cu')) sources = main_file + source_cpu extension = CppExtension @@ -100,26 +175,44 @@ def get_extensions(): define_macros = [] - extra_compile_args = {} - if (torch.cuda.is_available() and CUDA_HOME is not None) or os.getenv('FORCE_CUDA', '0') == '1': + extra_compile_args = { + 'cxx': [] + } + if (torch.cuda.is_available() and ((CUDA_HOME is not None) or is_rocm_pytorch)) \ + or os.getenv('FORCE_CUDA', '0') == '1': extension = CUDAExtension sources += source_cuda - define_macros += [('WITH_CUDA', None)] - nvcc_flags = os.getenv('NVCC_FLAGS', '') - if nvcc_flags == '': - nvcc_flags = [] + if not is_rocm_pytorch: + define_macros += [('WITH_CUDA', None)] + nvcc_flags = os.getenv('NVCC_FLAGS', '') + if nvcc_flags == '': + nvcc_flags = [] + else: + nvcc_flags = nvcc_flags.split(' ') else: - nvcc_flags = nvcc_flags.split(' ') - extra_compile_args = { - 'cxx': [], - 'nvcc': nvcc_flags, - } + define_macros += [('WITH_HIP', None)] + nvcc_flags = [] + extra_compile_args['nvcc'] = nvcc_flags if sys.platform == 'win32': define_macros += [('torchvision_EXPORTS', None)] - - extra_compile_args.setdefault('cxx', []) extra_compile_args['cxx'].append('/MP') + elif sys.platform == 'linux': + extra_compile_args['cxx'].append('-fopenmp') + + debug_mode = os.getenv('DEBUG', '0') == '1' + if debug_mode: + print("Compile in debug mode") + extra_compile_args['cxx'].append("-g") + extra_compile_args['cxx'].append("-O0") + if "nvcc" in extra_compile_args: + # we have to remove "-OX" and "-g" flag if exists and append + nvcc_flags = extra_compile_args["nvcc"] + extra_compile_args["nvcc"] = [ + f for f in nvcc_flags if not ("-O" in f or "-g" in f) + ] + extra_compile_args["nvcc"].append("-O0") + extra_compile_args["nvcc"].append("-g") sources = [os.path.join(extensions_dir, s) for s in sources] @@ -145,22 +238,116 @@ def get_extensions(): ) ) + # ------------------- Torchvision extra extensions ------------------------ + vision_include = os.environ.get('TORCHVISION_INCLUDE', None) + vision_library = os.environ.get('TORCHVISION_LIBRARY', None) + vision_include = (vision_include.split(os.pathsep) + if vision_include is not None else []) + vision_library = (vision_library.split(os.pathsep) + if vision_library is not None else []) + include_dirs += vision_include + library_dirs = vision_library + + # Image reading extension + image_macros = [] + image_include = [extensions_dir] + image_library = [] + image_link_flags = [] + + # Locating libPNG + libpng = distutils.spawn.find_executable('libpng-config') + pngfix = distutils.spawn.find_executable('pngfix') + png_found = libpng is not None or pngfix is not None + print('PNG found: {0}'.format(png_found)) + if png_found: + if libpng is not None: + # Linux / Mac + png_version = subprocess.run([libpng, '--version'], + stdout=subprocess.PIPE) + png_version = png_version.stdout.strip().decode('utf-8') + print('libpng version: {0}'.format(png_version)) + png_version = parse_version(png_version) + if png_version >= parse_version("1.6.0"): + print('Building torchvision with PNG image support') + png_lib = subprocess.run([libpng, '--libdir'], + stdout=subprocess.PIPE) + png_lib = png_lib.stdout.strip().decode('utf-8') + if 'disabled' not in png_lib: + image_library += [png_lib] + png_include = subprocess.run([libpng, '--I_opts'], + stdout=subprocess.PIPE) + png_include = png_include.stdout.strip().decode('utf-8') + _, png_include = png_include.split('-I') + print('libpng include path: {0}'.format(png_include)) + image_include += [png_include] + image_link_flags.append('png') + else: + print('libpng installed version is less than 1.6.0, ' + 'disabling PNG support') + png_found = False + else: + # Windows + png_lib = os.path.join( + os.path.dirname(os.path.dirname(pngfix)), 'lib') + png_include = os.path.join(os.path.dirname( + os.path.dirname(pngfix)), 'include', 'libpng16') + image_library += [png_lib] + image_include += [png_include] + image_link_flags.append('libpng') + + # Locating libjpeg + (jpeg_found, jpeg_conda, + jpeg_include, jpeg_lib) = find_library('jpeglib', vision_include) + + print('JPEG found: {0}'.format(jpeg_found)) + image_macros += [('PNG_FOUND', str(int(png_found)))] + image_macros += [('JPEG_FOUND', str(int(jpeg_found)))] + if jpeg_found: + print('Building torchvision with JPEG image support') + image_link_flags.append('jpeg') + if jpeg_conda: + image_library += [jpeg_lib] + image_include += [jpeg_include] + + image_path = os.path.join(extensions_dir, 'cpu', 'image') + image_src = glob.glob(os.path.join(image_path, '*.cpp')) + + if png_found or jpeg_found: + ext_modules.append(extension( + 'torchvision.image', + image_src, + include_dirs=image_include + include_dirs + [image_path], + library_dirs=image_library + library_dirs, + define_macros=image_macros, + libraries=image_link_flags, + extra_compile_args=extra_compile_args + )) + ffmpeg_exe = distutils.spawn.find_executable('ffmpeg') has_ffmpeg = ffmpeg_exe is not None + print("FFmpeg found: {}".format(has_ffmpeg)) if has_ffmpeg: ffmpeg_bin = os.path.dirname(ffmpeg_exe) ffmpeg_root = os.path.dirname(ffmpeg_bin) ffmpeg_include_dir = os.path.join(ffmpeg_root, 'include') + ffmpeg_library_dir = os.path.join(ffmpeg_root, 'lib') + print("ffmpeg include path: {}".format(ffmpeg_include_dir)) + print("ffmpeg library_dir: {}".format(ffmpeg_library_dir)) # TorchVision base decoder + video reader video_reader_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'video_reader') video_reader_src = glob.glob(os.path.join(video_reader_src_dir, "*.cpp")) base_decoder_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'decoder') base_decoder_src = glob.glob( - os.path.join(base_decoder_src_dir, "[!sync_decoder_test,!utils_test]*.cpp")) + os.path.join(base_decoder_src_dir, "*.cpp")) + # Torchvision video API + videoapi_src_dir = os.path.join(this_dir, 'torchvision', 'csrc', 'cpu', 'video') + videoapi_src = glob.glob(os.path.join(videoapi_src_dir, "*.cpp")) + # exclude tests + base_decoder_src = [x for x in base_decoder_src if '_test.cpp' not in x] - combined_src = video_reader_src + base_decoder_src + combined_src = video_reader_src + base_decoder_src + videoapi_src ext_modules.append( CppExtension( @@ -169,9 +356,11 @@ def get_extensions(): include_dirs=[ base_decoder_src_dir, video_reader_src_dir, + videoapi_src_dir, ffmpeg_include_dir, extensions_dir, ], + library_dirs=[ffmpeg_library_dir] + library_dirs, libraries=[ 'avcodec', 'avformat', @@ -179,8 +368,8 @@ def get_extensions(): 'swresample', 'swscale', ], - extra_compile_args=["-std=c++14"], - extra_link_args=["-std=c++14"], + extra_compile_args=["-std=c++14"] if os.name != 'nt' else ['/std:c++14', '/MP'], + extra_link_args=["-std=c++14" if os.name != 'nt' else '/std:c++14'], ) ) @@ -202,28 +391,38 @@ def run(self): distutils.command.clean.clean.run(self) -setup( - # Metadata - name=package_name, - version=version, - author='PyTorch Core Team', - author_email='soumith@pytorch.org', - url='https://github.com/pytorch/vision', - description='image and video datasets and models for torch deep learning', - long_description=readme, - license='BSD', - - # Package info - packages=find_packages(exclude=('test',)), - - zip_safe=False, - install_requires=requirements, - extras_require={ - "scipy": ["scipy"], - }, - ext_modules=get_extensions(), - cmdclass={ - 'build_ext': BuildExtension.with_options(no_python_abi_suffix=True), - 'clean': clean, - } -) +if __name__ == "__main__": + print("Building wheel {}-{}".format(package_name, version)) + + write_version_file() + + with open('README.rst') as f: + readme = f.read() + + setup( + # Metadata + name=package_name, + version=version, + author='PyTorch Core Team', + author_email='soumith@pytorch.org', + url='https://github.com/pytorch/vision', + description='image and video datasets and models for torch deep learning', + long_description=readme, + license='BSD', + + # Package info + packages=find_packages(exclude=('test',)), + package_data={ + package_name: ['*.dll', '*.dylib', '*.so'] + }, + zip_safe=False, + install_requires=requirements, + extras_require={ + "scipy": ["scipy"], + }, + ext_modules=get_extensions(), + cmdclass={ + 'build_ext': BuildExtension.with_options(no_python_abi_suffix=True), + 'clean': clean, + } + ) diff --git a/test/assets/damaged_jpeg/TensorFlow-LICENSE b/test/assets/damaged_jpeg/TensorFlow-LICENSE new file mode 100644 index 00000000000..c7563fe4e5b --- /dev/null +++ b/test/assets/damaged_jpeg/TensorFlow-LICENSE @@ -0,0 +1,13 @@ + Copyright 2019 The TensorFlow Authors. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/test/assets/damaged_jpeg/bad_huffman.jpg b/test/assets/damaged_jpeg/bad_huffman.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef5b6f12c5588e63f9573f921286141ec0af1335 GIT binary patch literal 15416 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 literal 0 HcmV?d00001 diff --git a/test/assets/damaged_jpeg/corrupt34_3.jpg b/test/assets/damaged_jpeg/corrupt34_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c1c2a9d1e1e9d942a982c4f53815d4af0ef8e92a GIT binary patch literal 5505 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 N%VYWIp?j>Re**2dQX2pO literal 0 HcmV?d00001 diff --git a/test/assets/encode_jpeg/grace_hopper_517x606.jpg b/test/assets/encode_jpeg/grace_hopper_517x606.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d2a427810f679db537236c5430873a81a62ef412 GIT binary patch literal 73746 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 literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/draw_boxes_util.png b/test/assets/fakedata/draw_boxes_util.png new file mode 100644 index 0000000000000000000000000000000000000000..e6b9286bf922d5dac64e5a083b902efa80bf857b GIT binary patch literal 490 zcmeAS@N?(olHy`uVBq!ia0vp^DIm)5Lqq9HXkK(J$-XJd7zm^-g?Fas5-}T~k&b z*%?=~|8%^4qjF?&sztnS_L|h}o2y^Rz0O&^>%8r?m3|C&=aq%I_`U21t+7s@TCgw6 z#){z>QxB^Iw}Du}+WT|9I{#f;*nY5X&o=edE_PlG?CWMO> z_5O0i^o-!_R9pbKkK*s{I#-Q_kPXn+mo+;W@Y2v zeycQ{_tuNV{U@u;w>KAVV(8~<*w_%8YJOBUy literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/logos/cmyk_pytorch.jpg b/test/assets/fakedata/logos/cmyk_pytorch.jpg new file mode 100644 index 0000000000000000000000000000000000000000..16ee8b2b4bc173ebb3079fc4d5e84738ba794d2d GIT binary patch literal 3530 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 Q|C2ob)9C!=)|xv0UlnhW_y7O^ literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/logos/gray_pytorch.jpg b/test/assets/fakedata/logos/gray_pytorch.jpg new file mode 100644 index 0000000000000000000000000000000000000000..60c9c7cf705e9081cd4ff5ba61235e5d83d7a4d9 GIT binary patch literal 1437 zcmYjQdpOg382`@9#&#N_hH11Ft%PE(%Pm`SDHS^@9HK;Wo6#i6t(c)i=y2Q;DwRv* zQsj2*AxdVgqTC`PAxrt4)#-W8dEfWH_w#(-_x*gH7aD|yf$UzI4Gq9x0KmivAR({< zC@CqV6as}rBBiBKG8l#5FlaPJNq#L>K~9D>q> z`NN-`ZvH|wu5H;Rx1ya{>g%`)fmtg!b}?$kV8t!w0sjWQ)l7s_hd_lB1bVaU$p12L z?K365CEORWGl~hbs|z|h5MZo6kE(ue63J$|jMw?)3sjO~9@07!Wdps;dfB-{sTCS8 zLj4+#f1WYm-WvAbU#37FO+}8gNBM;o!>;R06ytr0G9s_}rRb)Qet{cqcttqN&l(b< zwP@r0X4llO7GgQ4n~8=q&&vC(6&$VE$O{d+xJ0U(2yJ9?d&HxK+Y`C3WMYz=bCj>e zG$95BhV2o^S+2n(e8nCV&MS^)=N5;SyHj5aKc>|JrlY`onp_+JftC|@RL!R2XN5h& zmG0VhgL8E&f?4OY`op5?kfo#{%9~DXdUSkhTKg+*E(Ffca$Jwu=Fs|!D|0jgG?yQT zQc)0~29uM;EBP*m*eN&F`}_#ZT%nDHI+2D zY(~-tPtPvWNdH23IGe!rHAeO^G$N!E}Kb2U^KrDup*PFehQqOFt z%oXq?vnk1mi-3b?#EJE01kAmAyKa89KYobhr$)V76a#^L>_E*fH49P`o?+e97I*iB5vare@-pseBM0kB?wfxVdyhoS+uf&5v7h==)La^v3XkisGk*QwIb+ z*sfqM4PJ4aFwxH{({psYG)zUzt8-l5 z>{i0Q_V|+ewRGC=QsZ(+AgMcf!67zR1F@I;glP0F&KUx6VdW5b+MV)!2?F2jnQVjT zX=Z(NNYIvsEE`QFiGr1x2~x<=BRkH($Kq0#Ns4wDYvq_5P(8W?!t_U#d&()*rMw6o zVLeP%S6zV#7k#%W6U(UJ=(;&+#GY=GtTl!X^^NgupTHDe2Sb@h=X7*kz4KD4A~@)1 zYPmmey*)3_oI&~?XzY|_>i-w%6p!6wPTJTa3h+ov>A4rMN>n@WFf>WtyfqVvGnyDv n4gaFp=00V>F7B&q{PRZo`TC1+zyg8f+ds$t_^|(%A|&_+uN;lK literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/logos/gray_pytorch.png b/test/assets/fakedata/logos/gray_pytorch.png new file mode 100644 index 0000000000000000000000000000000000000000..412b931299ebcc6afa4d677c514e1c2b21681545 GIT binary patch literal 433 zcmV;i0Z#sjP)0ro^9)=28F~;SeD*4gD*!~G5If)rs8Wl*B;YfgVGXzLK zgF^`8kQW~_Mw!93@Bz6Rn3H1|7@{-q$B!Te1Amp;*~J-90J02~7=RQ*Oa`I|>FU{6 z1TwFSGUkBL3Uwm*pdk@tT9uTmDJZgH7u*>I5X%U)a;1}x0<;FN$J%3!b97QS_;UJFHV0qq*N-E bO8=ubnYTlDCaD3600000NkvXXu0mjft7Npb literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/logos/grayalpha_pytorch.png b/test/assets/fakedata/logos/grayalpha_pytorch.png new file mode 100644 index 0000000000000000000000000000000000000000..3e77d72b904b14aebc99ff98d0b8acfbcedf7603 GIT binary patch literal 590 zcmV-U0cL5JhDg06L+Clt2g2g?F%27fDK@gj7H}2#df8(Z}}8ypeT|-(4j+)=1Z*KZHOC zA%qY@2q7usr9~|d-W9aba2IK%;VjZl!&RiEhNDPZ4L6b28crhZHC#m2&~Ol0M*}WW z)cC^IQ3fhf)`%~qC()T3aG@j`f1e_(epp5{8psg^5?QX{1w>?h4Twk&8UPWSMmK|9 zqj76IPQy6;_R*=X7&6k6hC#$b!?NBhMSL`>kr#m5Ye6*hs6+~t0yT6>3K3t8N)59> zy4G4V)qlhy`P;HDYk35DPRtp>tj_i*LXq@M;Wim*Bxz3EFR@!867kDNDVi)N+sw#4 z*nC(c3Pjppy-8|h*Xj+m2!4dvqB0}BL6P2|NN-SNJOf(+h^o)Xqq?L^)Gc-`pG^s> zM)W1N2}{H+b}jo&$27JZfo*0ags{8+ipxnBX;*x#ig+gSxH3gV6?d(|J?*D7#(V_% z%R!8hj}9W}{;FFT8Sn9+Yryyx_UUh$&Z^7EYxc`tH|)ntu2G1-0Odd}H(UB9F;T9l zXPjCFmNvs$KE*I~);rT&WAr8K;Qxi=#&bL;&p(ClsREW2$+(yycU!iF)wqttAslTH zemPqA2av;(H7|%w4(!yYl|h|5VcYmPgp;_?33q&kpTn1C27LqIbfGY%)BX~J5JCtc cgb>mtKXGfO%i=ibiU0rr07*qoM6N<$g2L7Ww*UYD literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/logos/palette_pytorch.png b/test/assets/fakedata/logos/palette_pytorch.png new file mode 100644 index 0000000000000000000000000000000000000000..2108d1b315a73725115f22033954469a50718cb0 GIT binary patch literal 1151 zcmeAS@N?(olHy`uVBq!ia0vp^DImB|mLR^8|cRo5KAwfYwAt51Q zVPO#w5m8Z5F)=Z5ad8O=2}wywDJdywX=xc58Ch9bIXO9bd3gl|1w}gt-Bn%dghy1Kgh`uc{3hQ`LmrlzLm=H`}`me$tRwzjtR_V$jBj?T``uCA``?(UwR zp5ETxzP`Tx{{9IQCQO_-anhtolP6D}GG)rtsZ*y-n>Ky=^cgc|%$zxM)~s2xXV0E9 zXU^QYbLY*QH-G;81q&7|T)1%2qD6}rFJ7`_$TOXvSrKGty{Nk+qQlC_8mKR?A*C?*REZ= zckkY_XV2cfd-v_zw}1cs0|yQqJb3WXp+kocA3k#A$kC%mj~zR9{P^(`Cr+F^dGge$ zQ>Ra#K6B>G*|TTQojZ5_{P_zPE?m5L@zSMBmoHzwa^=d^t5>gGyLSEh^&2;C+`M`7 z)~#E&Z{NOi=g!@`ckkW1cmMwV2M-=ReE9IuqeqV)KYsG$$k{E1dg-FJ7e^mhs|3&^5@)cIC+sjHim%3}Mok{T)78djzFFitsZ+IOrlb?cdT3Trz;9>2euwBSgD zrq`*SDYKFnX_^}GB|FF%x*f6J>-MGWnELa1PQ~X0K%V`yzLK%|qN}c}IBPgC6d62S L{an^LB{Ts53B@u^ literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/logos/rgb_pytorch.jpg b/test/assets/fakedata/logos/rgb_pytorch.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d49e658b94ffb204533dc228d8a2a2f6b100637d GIT binary patch literal 2126 zcmbW1dpy+X9>;%kVJ@a5qh>H}BPK-|w^3-eO_P5u!IZj zu(zSw03Z+mfTRPEi~`31xU4KpRt64(!4L>I5{2G|l9NMWcPh%GamwmyIAv8;4Q&Hm z4XyonRaJu7-u(v+jg5`fbA~dKnMf^C5OUn+lC=(s%jGdXGtCd3UI(1 z@P>f20I&iGq5zUS1=OYYlmY!F;NJp)Ay64v7#x9=lLl&c0ALUV0)|3lWS~%KI!d|^ zKow+mY8qO}D$+b*T9?tp*wg|z-nyzy$+=gkZR8aYhd}PyjlnAK(a|OB)iX9RH6xiH zI(D35V{1pXclq|@Df;Q}T+e%d|977Y7a4&;!6Bhx;Sv9cPe^24yPkCOR$6*S=1;e? z3hxx%y;pqyK}mJZ!`er6^$m?rI8UEFZ|``~+4rV@U~p*o?a27Vuai^LA7^HH3yVvi zMawH+#H(9eAOP|^mUR9d>@QpjQZ6tQ3W375xIo}gsUZqb8BIgkomMoM=Ve7LVk{hO zomx=UhQJ#+3zfVAdXc-djmP&aY@z)|_TPcU{a<8%fc=MS1VBMR(&9lB05TxnOd{li z|8PxY@%!06Tim3++zU+V$!pzja=b%k!j23usP`&Zg!(4xcL`|P2`dWv8_=KaaeZ7J zzLDA0UrUex(JKY9tku@#?2SsRQGSn*9e=fJiszaZ-MZHEn6q(q&0%vWe@-;p>zg%I z!SePu*gmVGMX+l7Q36=;BClFEzjWO5YE93!Z>quXLOcI-xqgXLarVY;-lee}5@7Ni zYqNze0jwF5CCjCyXZU7$7n_59AdG}>3h3G~WTPRS7G-(xOx19i5ksPQS5z%WoJj_^lhg5$vNKeEo*p`lI`sfBX`;lmGUqAS~zG2uI7I;GW zmnJ5I_gr;86G(j+VAXy?Xf*Hf%(%A=b*ppKEBS9t=W+;G-ING=UP{G8OHRbko7A}Y z(Wl>z9FCZe&Ju$=@(}tm5i&fgfU%KshvOliO($PySz-!e z#CDjA2vugs?EIJQU!DybH#}t8yO~#qEV6IFTzc3`Lt0H^V1DI&SJUjHW2SwEQ~!kN zt2;(sUSwZkTQj0@7vol}*PKhS5FbgFGXo4?+BVk0k#|>0k-S+Rv!3tow@M5Ds~h_C9lFae0?UMiTWAxdtDCe(`>M6~wwVHJ=lsn}8_G(CgnPZ}I_O%_<11zQ9fGYQW4X>@@T3;oE zpCpedt+Puw5}>2dJ$vMAo>Txlf~@LB->5C+il}au!Sn&EWA|HOw5jz(imc zG8^t=QIml%W~wOhKp0Y`novM=4`VypWd_Q{2N4pSihx$F=IV=_((J|M&<|J82H@qIZ9f&HnAhE<8iQnv%Z=#VAE3P(l=+~Yg*fU zji}zpnb#D#3=b(r3a7c$Y?YZ@#1ThiIxf*BP>d`g%}`w!VEo6VbuKW#>lxoARRl8Bv#BoxMc^&yAd&$Ci)DZ6#<;tj|S zBzI$NNuXAP2JShp#xAn@g%!+haOA1c41?^cXP+c| RJo$4w`r4NMvO*+p{{<4)%02)9 literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/logos/rgb_pytorch.png b/test/assets/fakedata/logos/rgb_pytorch.png new file mode 100644 index 0000000000000000000000000000000000000000..c9d08e6c7da91991a780ded69d966fbd0c18eb5a GIT binary patch literal 575 zcmV-F0>J%=P)mlEGZGj7-Nhv#u#IaF~&Ub z`}JAfg#UT3ZorwgrlOmy&ZeT3tmdYokF5TtqKT|6OhpG-yO@e{SsR&(T3LIUib7f2 znTje|JDQ3TSx-%UeE*C;Ugi2tTyNdf{F~uOlZ7=kb3iOQS&ODRAd+PmaMjNnZUjJ9 zlUR+5Lc--_C1A-ayjS3rUX``c4B&cG-3=31RsxEw^1%(M0Zvu|%SvEb2`nptWhJnz z1eTScX5Ns^HuHuz#(W(4^W5BYWUP<8T=~wzvHVw=eSveE- z@vmU*u$W9x_LNA6ouqO*$_do4iT5CcyX{v$JfuD{;{F;oStf}>w4t0GG0jzx?!IRz zQ-)W1Qwl#ZaW_~0ufxGg%Bmjxm&rPqx3c N002ovPDHLkV1i6h2Xz1d literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/logos/rgbalpha_pytorch.png b/test/assets/fakedata/logos/rgbalpha_pytorch.png new file mode 100644 index 0000000000000000000000000000000000000000..5a9ff14ba5e9f57085acc05351fdb33b4015b9f7 GIT binary patch literal 2901 zcmV-b3##;qP)cC*6nyxixUewbaw<<82&eP(9m z{yxr!Ip>+*JokA!&jk_^5)u*;5)u*;5)u*;5)u*;5)u*;YJ$T{=hf@7OH$R&BM!LQ z37js6m(H6Nr0mB2prNJOxx|52?F3GTL)~*)Gmy=qxV%`Mcrdu^D#-GB*5U24-2{T{7XOv;X?9fw*%&U20B<3mN?@+J2D&KM@$NR|S}W z(NOk7?G0ydd+*XJVqoE+<@mvdjT-VgrZ%{MI zxR3z=!nm%^a6?hPJm!zZSTgw5cfWC(smDr9?Do2n0RT$e5c#QK1HK!2iyvkCM;A(TJ1zP$g1Q~gd?R7FT7WgL$#xhRcU z^>y@o-yndRT-jG#$k58RW{mQSm6kD8vdi0l<{P}yuw~yTm5f`_G34;ldG#{Fn`&J~ ze^>kJ83AuBs%|{IbY6WWV^>Uw0+b5uhI)^$tz{Y6?)H1qh8`WUf_h_?rUJV`EBGX- zn2>?)_S@2)Syk&Y0;aX0Dnv_*$Fyfw4Rp8PR;e5+Vt%l@V*!)C4p6<-6US0QXWS>nx~G4Q*<(4*rr#xXaMY%GMsGD6evzi&G&(T^&sftPUf31^{FXBWLaQ#tYJSxy<9Mn6u;k zeDnF~J9E}<&zR_+Bvb_htB1Nenq21MREQ;Al`(wL#GO{4bkdiza>#~!D?PQl>Sdtx z)b64U`PQ73Lmr(tv=&8?F?^9Fb=pgu2^pKe|GHSFcQ648y1R8p??G2NOqJFhy$2O^ zHOw^C2$)b*^fWH$d(}nkIA~nZ_i9nm6GZfqu{K>j*2dUzB1Dn8BE>v2YTdy^Af;z( zv3HC^4?#%j*{B|FRgq$zsYqSnBDNDDA>^v4nFR1eAz+Oypw=P{PFrR(8f-AQ8Key3dZa0GMebe)H0xL3`tl=?>Z( zHPBfo2$(t6)>w&Mh&9rps`V3}SOlOT0u}iv?wGDnk&g-@Cv1tU0;*bXjnuvnAAFX_ zWF~%21Xw}A^SI{fY0KexJYWTdh^H1jCgVfSiaTcPLf9b1pvXaj2n8F4xwvDx!iHgv z2!)BCD*y&Tj2HXM3St)$s+K?WnhrzxL?+95vbLTgu?rDPc|r71q!N6i{Eal^l>0k`8!=dO2lM_{dfuQJVbKEgqQS`K#fgozbIusQjb~x^su?tZ~ zmVjdu2SNpqVj>SZJMNgS@Sw9(Of=C45kSB(Wn|-y8M}~t-WyQp07pEumH!Q9h~cCp$cYeZX;;)g%PNpDrpfb+vlF+t z@I13LV@y-jo?NI3YiXB@xK4x!?3+2!Y}8{*RiU6;Dp{U6RTLlv-J)e4S9#H_z`p4s zwi6-eZ0|b)V3!|J=Ts1d$5@>0Zm-#~B-`EI=`j{Zop_G5Y1ddAW5-n!$ZqKbQcW-oG)t|+z55zd6D&2JwS`8eu;CvOEQrsdhLw(DKRKUK0_ZP%xm zmggfXEqx-4ihQg#zui@QXF^(cygy9PXZ(mWPz3-26Y*oNiUm%E;qE!DMEn>C9MwB~ zCJ^+Q)*bK1zCs_zY2{*p=;;wFM<%HRyd*@hVNDI(23`Yjh+sp;@FnFcEk~>zDG)vF zG7qOe#JOAceWHqWQROti*!>H`H{RYgca6(DPKMjN=B`N_zOmf>m4FGVSa+`DD{jvJ znaz}Xa>UA>R2eCGD+mlfFxb_8r|VqGG1%39XJGh&sBr@*U6&ZKvZt9+PrA;XL$VkNw2gSM&9b5M?>@5^LM=SKbQIZciCk#GoJlZ%FxYuD`n52>I~y(7(URt zt?v&m^BJdNgK5jrmbD{RHrJQAf1wz=7-Q(>I^VvY?Vh{BRW8}?xhv{?`+COE&ACZr z)EmZ#mCY?jXRdXX%S0-=eKFM4(WIo?Gln}Sdw*iU1Y6p-*jxmyYu(b@6G#016&;;E z^ezBDGDH-$5+A3|Fh;HPkkazTZM_wHTV2KXllr^nU*M75nl^mdWKsy9Uw11i;qL_5 zXuvzCdXfLL747F($TbT7IVrxMGVD**D}a)Wyp=sgH7i=T?L9P=c&AHMHu(CNbzJCq z`h5B;dJ6ExrBDS>5c!mVw*c-DLN8Hx02B=R#bOQsioTzQ7MfJO*{tXQq*H+_0_Ir+ zATQAa_wm#jM$Sr47}CmWTqdg8j_c61ZOsVinY1xCK3>zS>g@N=)cb} zuQr4re==5%gD`%+U229xOI3wa%p=7Ft0-8JwT(wxAEwt{3#a%Mu~8Fe5`!z+t})v)jk%?ecVHJ=vYwkDp~p4he~`fI(_?|1h8zCZWgHS0cA zTiu;r-BtUXsa7#$sGy*5;e!6ppJ+ibf|{8YZQJ#1m9=HF?#;4v?a;AIi6}w!1O5yS zF~A8*S2vnGJbSh#*>g0>*+l-Evq`or`J6u*IU&-u=-i`I*FITVbTO^6bn4Nud%I@F zH0u+gTZ?8Lo0$ksNR3Bm*}YHKRuP;~bwkKA^~mmo9zANL6UOI+O;<5w-9N)x(&b|;eSMD{sR zTqml}iPkn`+pujlEtV6#t;AyZoS3c?%jd-Qi^X>0*jQYj6VG+x`7_bt>6dWuH^U zb*lQDYJRa~PIVje`J5WAQ`6_v@{1*RYTH;HpHtU$>iL}dez6oz0~>4Ta~io$W1rK+ zFP742YGciOPIK33;d5I0#Zoz~Y^=4SSZb%ejdk!j9bKoB&*|(JOXGC0 zv93PHaUJ7xy7|S@I^AuohtKKhI=y^OZ@*YNr;m;G^*Q}qr@zk`;1^5p479O9K4-A& z4DmTb{bCuMVKz40=ZtV2*XNA%i)D01+1O~GGsbns`kZlou}sc*8=K&BCc4ffpEKDn zmf4wNV^e+3G}oE#b7uI(vN$tsY?jZN?K*RO&RoA(R%f1#&G$JATxX%r`O`0!%~@n) zi+#=#*IDXwmifi9JIifsh0j^(I;(unYQ$u|#^+u^V=mkBh|f8Sxoo>*KIb3IWm_HhIVUieZFAD+oWfkT#c7{&26OrBXMN5& z%;oc)_c<3Zm(O$2=Ul>E-v4Eva|Lrf$K-OZ+Rt{)=UjK48$RczUo5xtuZ`XEIk#Qs zj?cO47t7<^v$6X==Yi`y^f{0GVtJj%Hul8lJawICKIge#ET8kj#$NiISFZEg=e+TY z<#*oN*gK!|-gQ3soR5C70?sEJ`|NYRxXxFf^UW_-(D~2CzWbaXuJhC9{PK$xa(+w9 z1j#wtXa11UH6bt$DWhLrVH3)Nq=rT~jEt@ci+MO32|g_sG2typY6OHM%IKO%m`Ape z;MAffiUmoHif}X;T@xMi7&a1|TFk_>AgQqsjxD2W;$R-vMuJm|n|Kx^H9o=#WOPkJ z%oEv2aB2yY*n*@cK{%<5u1SV@avKRwEoo9%kkph2r;^b%sWDGuBf+VqOj-+)nhxRg zGP))M<{527QrjzL0%rEmTi8mQEEeSPSrN`AqieEbp2J3hU#g7BX+ctRA)H%A*W|%G zuZ;w!mN)qJz{rmzJ`ErM`S8C_Eh^WruVoLbS8upp@=5iTX8 zYf58Y#zrKyy<%BlIS;+hTFI2RAdjzra77tiQwj6RHWK_&l}!~3l3EqvYBIW}I_5qb z2~MqIYFLoenh4jD(KWR(uVW*@sa1`==CG;t5UwwyYZ_qQ&_;q&tC>a?B(*WZO=NUU zQ_P#$NN{R()7*ljwm`V0jIL>gd21U9PW72K79_PT!tG>qO?%8c*hp|{4b#zrq;^8M zvy86kf_YaP2~MqP91D_a5bh?UYr13J!$yKrYnh%FB()d9y=8PwAI$sONN{Rx)6asW z_D6VtjIJ4o`5+q!POW1GTaeTt2oIIfHN!9;ZX>~|bRrs*%l;q4#IO~bj>`>=i5kdY9q72f}}1)_)i&Kvk3FWHWHlL*etOisY?-FCZlVX zW4^*hf>WEAl@=s*6~e1!bj=#f*V;&MYE!e$f~5Y1@Ol|tvjOvsHWHlL%xtnCshbhr zBBN`zV!q8rf>WED?G_|;2f{mLbj>czciTvCY74W+f~4+6c%O`}*^l|(HWHlL(j2fL zsRt20B%^B%V}8U&f>T?WqZTCf7{dR^=$hl0pRkeO)Yj&t1xY=H@M#%ca|ZLXHWHlL z#+CAfsz8Vt&a+f>Ya?%N8W{3c^=qbj>x)uiJ>EwpY9Xyy>BL&TD7>wIGkb zh45_|U2_NXyEYR1Qtiz>3zB*t;RiCh<{{>fY$Q0flX+}GQlB9FR7Tf4!~D681gCa3 zFDyvvON3v^=$hA(7-^(Vr=WOU7M%!A~{(l1p`Y8E6lg#6QILdxixP?(3dk>F?T zX2MvI)UXJLlhHNdF^^y)!KvL%L<^D{3E{{xx+V(dQEenRwTFpjK~ke5979Ie#Kb(7 zjRdFmG_fs6Y8-^)%IKPSn8&w~;M86wfdxrTh;SkqU6UB|BsLP9+S??xAgRd^PA;Qs zQed9aMuJoOm{b-dH8sL%WOPkh%+uLOaB5$Z-h!lNKscj}uE~UXW*Z4k?Ps!BkkqUQ zXOmGbQZUb9BS>u<&SvC<=0Zkp%=7$DMqSyzK?6))3zC`-;rueXrU2#zZ6x@02bw|_ zB(*TYMPzhMQOt|kNO0;PQ`~~2mO!|qjIJq#d1)KbRG9@G9Bj&1k=(L~my^*oM3^o{jkB4mb6!NNxkf8_MXKMwmCY5x?9Krim5FZHjm^8C}yH^AdN1JX| zB)2=_J!EuEPt1GSh+pm))7y&V_CdU_jIQa2d4C)6%N=V5SdrX;h!2v{HG?r9Vk3UJ z=dNN#(@k-$+N%6U&_K?ld1(N^RM#vndcM%RqPe7ueLz1RdZ z!HVQgM0}Eru9=Ma6dUo&oouFBk=$vBPnXd(GcccNBYwG4%q%OCI~(yiGP-6i=JRaC zFL$b$Z$)w!AihvW*Zhh3A{&w1_KJ&vOFZNUo@SO>ktbM&_;MLtvjX##HsbeU)6FU? zlDiu5H8Q$pE#~WN#4mS-`OAvru19=>jIP;;`6e6j%bjU9Tanx?h;NnAHQO-XZX@YaU?!&_?`n7nw&^B=<4mPh@n>Q_P>)h+pnv^W2K$zCiq?jIMcw`D+{T%UxpL zSdrYfh`*E3HSaP1U?YCHOU*|slKTnq&oa8^3+7*K#4mT5`DR6O|3mz{jIQ~C`A-}1 z%Uy1MS&`h|hzEtVxqry$Ga+R3&s||cT9MpPh=-QZHDNFhYa@QoyV8WSBDvuak07IK zB4QrNM*MPDnaEZoHwxlWWpqt6%%j_gU+!uX!;0j_L_C&^u8EC#92@b=U1Q=}k=%HQ z$CuGH2{2D+BYwGSO(H9jn;7vVGP))y=E-ctFL#|uZbfoaAf8f2*QCNcwT<}Y{$BYwH-O-3t{n+fsEGP))U=2>mTFL#5xs<^?myJkn zd&S(qJRb6dxY6XbB2SPH@%%E%MGfW!ZN%@zHkm?JB)2f)MP!t#8qAB?h+pnjQ{0N= zmO#9ujB;6nd1)K*%iU(mSdrYah?kR5E^9EaU?YCH+f79)l3NM!$}-Aj4dzvCL~`3J zRs&Y|kRN!5@mY~4sDXG*8C_Eg^V&Az_hLIu9V?Ps7x8*Bx~4wn4Q#|Ocb92sMRFS< z-dIN0G{L;7jris6HqER^Zga$2$SBt|n76VKzuY~hwH3*2gLqpRUDFQp_BP^|yVrEE zBDozA?l@}D3>*uFR~H8+)-w+70F$K z_);0=Y6kP=HsY5%+N`i5xhoN0C8J!;V7|si{Bp;bwN@l|9pZnZ?F-++_7e( z70KO%_+}a9Y6kPIHsY5%&TO+Hx!V!nA){Q)V7|*n{Bp;e-Bu)b58``el&cxc_uGhH z?gaC<70Eq-_(2)vY6kPeHsY5%(HyZNxknK{CZk-FW_&YUX=yOw-cnVBqQFEUVeoD+Al5u^*SpQ zFf>swsKNll5`*wU;eg?Zp@9*A5s49ik${njQGro_QHimD(SXs3@qsabF^Nflv4F9O zDS>f-af!O=;sN6mb<-sPCM4>nO9V_z%#Y_x0!&IQ0!#)>?jhIR%_fBvIUG_Vo=Qe3 z_F$gIMuHEWgIi2mE0UWI@$@oEwFmQzHewH*l6bL9z|6#Qz%0P5#LB>I!0g1Dz#PDw z#CpJ7z}&>fz&yab#1_DO!2E$&09cUN7MX>Bg^7CH7XcO}_D5zhU~!^PuE*sf3Rsd@ z2UrSNny5!}8DLqW*7M5&%M-P7UjbN=s5SaZz{4CL@b%@!3b%FJWxqdu$=&$NYvwQ5^yq6kGm7_xIQ6@@94YGnVO|IS`t0=SO8V<6CvOwxmkad(L(och|r>vB&8e}77y-P`@<2LkklmE0as>z3OL-;NaghC#_fngJ9H4xWz8d5Z<%e|F zAV)lD{|64sqrhXtFu;F+$B7YvCx9o3(SWCbr-^!!I|Do$i06RkiF)R{0K7=lBk&UN zvWIPDyIp}?rO0->2Dwg=?REol(@*||+@i>qybZZSku7-_a*rZg@;>ANMYiNa$Rmnu z$;Xf_HPgaC#l7R3P*3K*JL z3K#|$mZ(cWIAD09E&&mM5sA74L;^-8>JktI7?s!rFBA@eOV-s}= zhy#pE)XaFm_(aW208B{K#Uc?fv5c+$f8W8)ZIVc+kx43}{})cfnPeh%)lDw{^qCYg z%C#Tnsca;8fevp{TaeT=2&a`%F8wf1ZzI8}5ljXPlA00WOftGAGv--rBsevq$!bAT zvmu;aM%U!PJg1EWr$#clEJ$i@g!9Pgn!K3jvytG`$R@u9NiBeIK^a|B2=l@=5}X>v z6tN(wMG-D0qic#|UcyF#Q=^)a79_P4!lh+&O&QF~+DLF}G*ixkq?Sjxf{d=IhQF2Wd?yAT=>aTS`%>j6vE{ zO1Y*3q$8!gd@%{qnNmgieUPq{8d4R57)o8KjX}Co8o8ziq$j1hd^riyo6<%)evrPD zj#3wc^rtvd9fJ&{$koLl$Y6?GT?~N?^^;+c;grEr8H2bKx!xEF8AXv-9}O8pkyjrJ z8Ap*<9}k(}Cleu)DDr+LL#9yV)u%$HQRLO9LuOFqYG)>77DcXhW<%ysW7A>>brTvTCn^tfk1R zy$)2od`#4p_X+SRQCHq)z~@B0O?v@+Nz~i4SHRaqy-j-q zd`r~Zw0FSwM7>S>0Q^YQJF-u}&qTc=`vUw*)Gro(1O7+UlEZi452D_?{RI9ZYRTa@ zFi3uw#;!8$^$UQ1$p4krBT>KV7ZMnXs9)*}4GcrnukVEgh9l}1^}+)q5cMm05rL72 z`sKUGz$irhnq5?2G@^cYE;=wqAjSm7BI;M?Vgut4^-FSbf$@m?b-4Jz1VsJfTS8zW zqJEn#F)&FWCIu!V>X+G)15*(7YilWisfZy_RZ0y^LktH@3rt6h3``HqK#T#*2+Tx` z3(O46LQDkA3d}}K4$KbBK}-Y83Cu;z2+R%4L(B%u3(QB%1K@fmMhd zfK`Fjh+Tozfj(jnU=3hRVqah_U~S?cU>%_SK{x!})bA421J)132Ec~Iv3PhRU}NGW zU=v_d;&fm$U~}ReU<+VN;zD36VCz6^18hrNj?8wz_QW;74#1AY4Zu#o&cv<2F2JtD zT|ftDi2H%vfZd7uWttwqo<#lDOfO(>qJBN553ny$zX#I~*q^9hco_g3NYrn(3<3@& z>Q`8X0EZIwyDGzg!--lj9szWT+Wr^`97WXj$7tXfqP9QA0>=@x{V^UmfvD||iNHxj zZGTJ#P9bXhV=8bOQQIHWfisBO{+J1zMb!4kY~UQCwm;?q=MlC2F(0^qsO^u1z(0xF z{#XQD9EeMRONrVOSq5BA)Sk!+;7X$QE>;0o6Sa4-2Dp}}y^D3gzXEYRa05{r8XJL| zh}zKD4BSH0hQ?OlHlj8(wgYz%wRf=-xQnR0i`~FIMD5w_1@0sELPKLe@Nc4aISv31 z61DSx2zZ#NE&e0GqeSiH9|QhF)TaG$;0dC3=T8Dp5w#6}8hD1N{r0oKb3|>dp9fwb zY6txy@Dfp5<(Gk1h}sjs3cN`#q;%C6;f%pRWlBnI{SHRaqZ418vz9nk^_Z{#(QD5i- z@FP*5^Aqs1hwN6*GGDAnq2epz-(-{yFy`NF#9l(`;qU|alcFp@rimgB>*NQ>d}-4n3$+XQxafOq8?4jfXRuvlT!dw z5_Ko10;VSFfs+Q9)Yynv1P<<2t&tw?Sm#0$$P zKdFd$Q5*5goo|X+k=){lmyl6@R1x!1Hex@SVrgI*5BbIxn6g&n3CbZ}UPk#@Ma(PO zh~JAXG?lDKZe_%)$S6OohT@OZD1Xut~+&s z^@w`F)dx24u&tDC8bTUTq;%65(u5+Vo2HOv6e;30hqRzb5w9hr6-A18ts!kFQp9Tu zX-APFUVBIfiWKoWLOM~Th}Rj?h0@VAT_Fxd%4i1CjUr{V?vNf7DVp_!^r8%wFVR8z zP^4(q7t)U+MYH~p0Td~k4TKD$NYQLCWC%ryWV4jDm_E$>1`Qe?}If{dof zmLCHdOOc}4ILLU46wM|;CQ_tmHVHDBB1N+)kf{_YnoWaD_mdfrnG`9b&4SFPNEvMo zWUeP(iEJKlKGWpM7eE$LMzK8itOkOkc|}C(VHNfDYB!tK(ic{Nd_~l^^cwhv zsBh^l@EuXBxbJ}e9Ug6(JE7orwyzXHDzwbS|^@Ht2aHeDDsBQ`LZVi269E$w zwThbrn3Skh++@JyM6Kec0H!2r6*mDa--M=_k1$xhc{+%mc|wk=|iGNPdd+ z4hujEQlxiS2vV3Ly~84qq7>;J7K0S0$Ynfr+Wk(fARf=48RD)Ef$YqBQQiCF^QB6oKimXPpA$2IS8r6l=qsVGh zAJTv#t5HKpBZ{m>jUi1avKlpoG^5CB)Ev@+BCAnLNGpo0My(-jD6$&0g|wr{YSbRm zfg-C>M@T1%tVW$7T_}>%72;4N$3VJKWX0+Z=|Pb#))Uf;B3rCCqz^^5SYJp#Kj{w{ zK#^@Y5Hg4&+i);s2t~HxP{=TfY{TJ@5fs^mE@UJ{w&5tqXo_sZF_5to*@ojF<0-NY zCqO1rWcy5lOs2^8nF5(gk?k`LGMyqT`V7cSimd3fAhRj5qR)ZMrO1jt4>F%3EBXS+ zLW->De?k^{;;rb5flG+Gd@cnpBkJBwMt|RJ7`4@0K zQCG?hz>P#*DK`N(6LqEB0^CZ}m2w+!J5e)t0Cy5Ka~E(oQPwliMpoV0Ny0(n))yB7E#yK+rT?ST~qG@?-6xP zy$^gq)HU@X@DWkh)W^UlL|s##0-q6eO??i0LDV(%CGZtdJEO0GZ;09%eG7a?)XwO8 z;0L01Mn3{S5w$b=8Tf^$ozbtrZ$#~k{s;U{)XwM+;7_7s+qhWwyiP{+r2MkZt&S(T+#6XM$j7-$dXcS;nqIO230izSOGa3UJ zlc=51Sisms?Tp3&#wBWJG#)TMQ9GjvfC-7(8BGLCOw`V35@1rIc1Du{lM}TwngW=T zsGZSNz|=(TjHUsmC2D6h9WXsnJEIwZ8Hw5%%>>L$)Xr!YU{<1bMzaC46SXs%1DKPj zozYyt+(hk+<^kp31 zjwEVlbQEwjQ9Gk!fMbc;865{4Pt?xn1mMI#oCKUq)XwM>;8db^MyCO%6SXrs12~hI z9$(j<1)NRP%sIfhMD3x@1I{O=!owE;7ZUY3{{$`~>T@mzE(ye?z-2^zq2<68L~Yit z1g;`#eS9@=4N>dkYk}*C+L!$cxSrSoJ=6`rjYRFsZUSy5YF~B>a4S*!vfF^$iQ1Rl z0o+N{zU(gGZld;O_W<`2wJ*C5xSyzf*}s7Yh}wud2s}j8PTFDM5u$d|jslMnwUhP_ z@HkOBX(xauiP}j!1w2jEPTCpZS)z8*&H>L8wUc%Mc#)``v`fItMD3(q0bUKnYryM7 z?RMM%-Xv;!?O)(6qBhNL1Md*^2)PTqN7N(aKJWoix6(u4Bch%e9s{2c^~~@T_>8D$ zhUdT+L_L4L1im8b`SUgK4N=dZZ-MWKdj5P5{6N(6=SSctqMkoL1HTaU{P`95ji~3( z|A60#dj9+Y{7KaF=P%%IqMkp4BH;Q{MqGdDRtfQD0*nESNz~I?EMRP+p4Q?3;}Z3>77rMo zsAsSQz=T9SgCzncCh8e12{36OCIcoX>Oq?Vn3AXmZ7N`DqMoeM0MionS}`3kJyEX} zGXOIZ^{C4P%uLjqrYyj$M7?Rs2Fy;>o2DGVoJ76T&jrj))I0q=z`R7gf6oWZPt^PO z0>FYqy?-wREKJmzcoASxqTbXO0~ROhO??SqNuu7=mjae1>iv5eU|FKxzn24+C+hus z1z<&@-oIA@RwnBGdlg_+qTat(16C*M{ksoXgQ)lKHG#E=djDP_XIIsVmSS>ak>i-H5t9y90Z8*jB1@Jt4g)Ql0A!=|hp~Twh2( zift-G22i9jIS?|4B9+O(kRcSQOb&$%qex|PIAjDxDw8f`BtrJMJki? zAoD%(Dw7L<3yE5p{1do{sFlgZz$L_J_+f^nz-7ePz~#Ud#00>Vz*WSgz}3JtL_J@v z1+F9N`RXs=`as+O+(^^|Zxe7cQ4hQ=z^z36MB9MdJ!~tRaR+24MK1D+@9cDMk%NYp)h33!>Pd-e+ODpB|BHQ;rk?%5l_n?&8S{{n9jb-PqOL@bflr9K5KJ0=@@+AnHo=5%`IyE751*mq7dq{6^H}=|A9iqApKAfInsY|8^*In_m)Y zWPZzt4rTik@`EYzuN{bpOGX)S$(R-x0vM8*2^b0(nwT9J1{ju@2N(_*o>&kV0T_{3 z3>XO*nOGVa1sIiB0T>M!omdqZ0~nK76Br8^+e7De_~T@gVUj(yUDYNl1}q zZ6ZiwiZpAJK$23VHJc2QoFc8+6p)k@Y0ajBq^3w~HVq^#MOw4zAn7U6n#};oNRifT zCP-$Av}UtFvQnfqn+=kkBCXjRken20&E|sSrbufx4 zNMVXJ8jC=RQl!yX3{u=rNkn$9H^$L)R6nXVZkjj2i z1yYqF@2481Iz?XH2dP1kSFZ`FMUjh%+K@UFxtOR6sYj8EiTaQR6uFpa2x&x-i;2dN zCKS1tXbNdYk&B7ukQNlVm}m)UMUjh%){r(7xtM4RX-AQZiT02V6uFq_20nR1rk~0rDpQuaD0^mZTE;)Y!7ZG)J zSqxl4)YWAva2ZiA)|UfU5cTF~C2$o{Z+=z-*AVsQXDx6YQEz_!0dns<;8vpE{A>emC+f}54&Y9r-skKB?k4Je&K}@iqTYw^1MVm4&ClP!14O+K zKL|WT)aK=3;1QxWFOLF`5w&^w5AZlqo0lhmCyCm;JOw;W)aKE z)aGR@U~Hl`FXI5?619054;ViX695wuwRxEcn3$-|%Ot?0L~ULs112YG^D+f6B~hD~ zseq{iF%2*+QJa_Pfa!_ayvzX1NYv(KCSYcwHZQXPvl6v=nGKkosLjh9z??*FUgiSk zCTjCC4=^uLo0s{3`H9-REC4J>)aGR&U}2&b--`f?61DhV3|O3~WzZ79l0+@Omjae1 zYVo}cuq;uF@8y8yiCTQG0IW#V;(H}vWug|}s{pGKwfJ5QSe>ZFcOS3@QH$?2fwhQQ ze6J0xL)7AXU0^+;7T@aw8xXbl-VoS`sKxijz$Qd3zBdIn3&iHY7DTPcw*}`SVh+1cF59~nHI(tW8r$Fos>_XJydsm=C)H=HXb|Y$?y*sc6u?0E@J%PQ5 zZGpXkeTZ6-?+ffl)b?S2-~ghw4+jDV5w(3d7&wHe?ZctKVMJ{o4hN1PYWvUyjwEXP za1?MfQQL=OfMbc;J{$)ePt?ZP1mHxXwht!(Clj@OI0ZPBsO`gP!0AM7AI<>IBx?I` z7H~FE+lO<2bBWqMoClmw)K1|7;6kEy3jYKyBI*y~Ee0+j>JQ>A1ui3MPjNYL1yO$x zZzXV5Ag%_kA?i=(tp%QCqW1zb9yUjT$B25^`~y5r z)WhZk@FYPg-5po~+fS5sk!b5%^A@C7V_xoeu6QUkVPl3;f zIq~r4z!$`Pz?Z;R#KOSWz&FGaz_-A6f%qQyfmj}yAAz5URe+y?Ux+n;UxD9L0+LMBQ<}fWJMoKL;5U85f^2+KbP&QtJo-2}zM!M<_^Wid4PAK*Ca_>J<(W zo+4GR2#|;rsd`0%M5aj9D+(kkMXFxWAkisO^@;(BNs+o!EJ$pM)Sco$;!>pU6b}-g zB2}gYkc1SeG9`i}rbv}32_z{+s!Yis$thB0N&!hpkt$OvNNS2ynbJVgQl!e14w9ZC zTRsCMBSp4+CP-$AZ22sZtQ4s-WrJj=NR=rEBqv3xOt~PrDN<$11IbH~DpNj4em^My zDM*pJQz1xUiqxHoK#F?e)s%_>i!)80yac2qMV_h@q%=j!Q)M7!DYDDTLCRBPmsNmN zq{uF-1gT7sM^%ATrPy*Jq&mfx6CpJywwws5MX}{XNF9po=(>=46kAS&G@#gWBBT+; zmJ=aOD6*rQLYh%zM>mJGpvaDH328;KJoJGvvJ6Giq#XGj-{ zEhj=8iY+HXx>0O75z>QV%ZZR)p0Jz<>_ha*iNJnDubc=RK=jIqz(GW>oCq8eh(m$H zh+1PD4je($8lwvwNz}JA3OJgmZ)ps0EK%RmIN*S4 z|IMByuQ?~dM&`VX`je2dXkNghF3O0dU*rkY_Fikw~l zh1{aZ+4VN$4n@wccOmyEa(2BBc|eh~>qE#Rikw{^L!MCN?D`b)j3Q^(=a3f^IlI1u zyrRh2^)=)TMb55oA@3-1c6|@|K#{ZSN606NoLxUdzEI@s`W5nxB4^kCAm1r+cKreQ zNs+VbFUW6Cyt8Xi6kMChh{B+r%0d7`67^IT3K%*N!vMnuVmM%U58KLSj{u42Cy^kL z{Uiz`Dn)ipG)Q!c?3x&mm=xJHu^_Q2vTNc%;!F9O)^MwitL&ckdzeJHK`z}DY9$QK+;lV*QA4_r^v3!0Lkcyw`(#1GZS^!WC3O+ z>aNKK%udu*CI>JlQ5Te4z}!S#Q1Srt5_Lhz2h2~@1*HJ6AW;{TLcqdAT~LYuiw0sb zU~!_p`4YgAM1Aw6fTaVm46rOwKT$bgd7^%z3c!j){X~_3m5KU^ssO7J^%GSCRwwEw z@&RiQb&0GAtVPr%vNo^|QJ2WNzJr%&*p8@6WP4x-qArmgft`rDM0N&tA?gy@73dIki8R1& zL|r1g1A7EwPhc;iuA9AqeFCvBuwNkd2M!3tfxtmTU3LcphY)qy9SR&q)Ma-#a0F48 zT^Bf#sLSps;Ao;QyJLW3iMs5L1CA%^vO57dk*M9qNx;cO?KVyUP9NTLe$3MQs6QV<@Z0y zp&Zn~EVmFzew{VKD`k{lWR3Z18_{3sWK%nuH5MdwEyC+$l;2H*`Fb0%ztKtCl^cK? ziQ2B*1l&y2cI6h})C0e1)D9^hW0wk!7m_Y<{U`8V)DARYuB zB5DuwFz^UbdzeRo$B5d){0DfPs6EURz>`GnVV(k>CTb7!4Dc*bdzj~d=ZV_Gya2pN z)E?#~;ANurFs}fw619hU4S1cXJ4rCfgb|#Bk&VZ zdzhbrUjp$f@LM4M2mBt0KY%}p+5-Ir{OzIl+u06IG(l1I@7y2qPx+i>E zIf?q5xq!Ke`j+wl^AhzFc#-a67{GX2OLk- zqizClB2kaJNx;cO-5pbaQ;B-iO#@CR>QOfXIFqPH-7MhjK%4`dOVmSg9&kQUkB|kx zg+$H#6S#<|Z+#@8^+bL6 z2H-}bULtG)ZYJs_!WQ6GVqg3U_HDrJ#6iFvz@0>W^Sgk%iF!4#2e_B0%lSUweqsoj z$WN*O4-mrw4+0Mnb%8z%JVMk3`Y7-iQ5WccfX9itK%W4fBe5G5_P}-3%o^4gWYi(c!#KW6nBC5 zh*ql@EuWa zoZbUJ5cS6CBk&VZKjvrP7oy%ceFc6a>Q_4d1AZs!jnfa{Pomy9{Q~|b>OE3WG!!aj z#I>T{BZUBlBXfLm#k4Al3xd z3dGvLIz+85+JAqd&(tI8p;#Z-fT*wD5ZH*QM_prJ6QUkH_frA2ZFmMP_55=LtVMKk-;lL3@eM>HIB+;vF z0!Ihp7~t4I90wdv)XzQvIFYC?GzmDFsBdWsa4J#%B1{8LC+a7f0h~$H4KfQjo2Y-| z<^bmswF){9IG?Ch&;`JSL|wK21TG@#0=*cxgs2PjQs6S8F3`(?D~P%xtOTwi>H@tQ zxQ3_;^jhFLqAt*X0oN0Cf!+Yz7>JvIn~7ez6S$SAYw|qFxD{0G=f3mB1UHu<;45MeY>?N$H-Y#T z_>QP|J@0`ZhU~E9U__$cUPS^%ChF}~6kt^1a%|*i!01H1 zy@~;hNz~h`Sismsy%mZBj7!uzsd&KnM7@(r08B{q>Yu>GM6dn{OiJ|XpTOjSm;#uR zsKuOAz|=%7yrco9CF-4iI$-)h%mBi1OAQl1^CVKTxU{RvJP%&U}qQ0dPz>-9-{s}Bi^y;6$vP7@` z2`o?a>Yu=hM6dn{tW5OkpTMd_ul@u{*FwAoc|IB6{^tU>~Aa{{;3U>Z|t$4j}4LHxM|8=+!@g zLx^7e6F7|M)jxqFh+h2@IFjhqKY^o(Ui}j|mgv<#f#Zo@{S!Em=+!@glLK)Ia4J#v z(KO(6qLw;m0A~_)7taFD4#YXYxkNn_=K<#j;sW48qF4U}E+TsMPv8=w?xUr^Wkfys zF9)t5di77>Dq;sLD64^Mh`PS71+ELkzkutB`tS|Fjl`~a&P~A0M7=!N0^CZ}D}imm z?L@s2*a6&0^y;6$-9%lW_W<`2b%EXo+)woCpTGk|ul@-H>WUcsUTS0Iw4Dg{}dw6ZK=> z0Ny0(e*YJEi{{+4xdi77>2clR11b!mw$NUWZLiFmNz;8sa{t5g}{Drd558zLt zSN{b5CVKTx`O>ZY3uI)(^`~M8U`V3gAB6&jCh84N7+_eU-r$4-h7ZIDz=%ZM#gTxK z12GCPD$%Qd0;3c4eZ~OBBYu=bM6dn{OdNKY-9*#*_k< z4#YCRvVm9*Se~dyNCjX;qF4U}RwjD&PheG|SN{Z7CwlcyV2wbm39J=}wSjerUi}kT zkLcAufenaW{S(-T=+!@gO^9Co6WEOC)jxqPh+h2@*ox@YKY?wCUi}l;j_B1tfgOlm z{S(-U=+!@gU5H-&6X*n@0d^zmKI#taLDX_zPhhV=><#Qg)cxKU*pH}(Vt?QOq8^F^ zfrA2ZFmOm94h0S)>I)4Ajv(q^1Q$4x=+!@gqXTgaaBLus1CA$p^-thLqF4U}PA2MG zngX0k^y;6$=|r#o37kpv>Yu>b#C=$L<^bmsz4|9`KGCax0v8f>)&3K>i0IWnflG*9 z{S&y1s3-sBz!gNV{s~+ah^v8X0&y*H9nq_Q0@nxP2H-}buG*V`n~7fi6S$SAtM)eF z_CVYL+)31>d>3$cAnpO~4a9xG{ek#5@BmS-1P%fZ5p^*=3_L>AMgJ)97}2YL0*@2D z`X}%t(W`#~PZPcRC-5v$uLRBk&l5A^3h)B(A~75A67Vw7tA7Ho621B-@H)|}e*$k3 zz4|Bc7O|XOe**6iz4|BcULf8FJ_y8zz(;}j82E&!<86iF$kW1Nf7uw^zS_ zzlnN#6%-TKpECN_KY<~MdV3WL7@FwSKY?M1Ui}joo~ZX75r7eidV3WK7@4TIS5bgb ziOcaZqXDB6*8pPxV-hz2V*z6m^;RejFfLK=x#9ui2Vw$XLZaStB?2ZU>YGmjOd5#E zfXRvaiBbSl67>_M0;VSFCrSfMOVm%44w#;(pC|(`BT+w5CSYcwzWFS`tVFHoW&>s? zYDG5(Fegzfy19V4iCT%u1I$bG>Yu>;M6E9s02U-_?V=E{Fj4DEMSw+#T3;##EKbz= zQVC#5qSlv60ZS9LzElQSmZaYzb^d z)V_*hR*&Wz}sC%;~ zuoqGHW^Z60qVCPUzM2u;Ff2th1!gzMvrcziJgj%D+h_octTj{`a4# zK@ozQnHFu^^=y^3XDidKU6;;fN`wijk3Tsh*e5!_piM0~od((eRjc@i{m1`2mH&%K zH|>A@;S;xP*1cJlt{po5???MTvwRoK@6U00(|ok|wyISO6DE_Fk|bp2|4GLCk^jek l_VXe!_Ul9*C%^P0C}_O*|LqSGRjU{}jI|K*ADgea{|`0WK$8Ff literal 0 HcmV?d00001 diff --git a/test/assets/videos/hmdb51_Turnk_r_Pippi_Michel_cartwheel_f_cm_np2_le_med_6.avi b/test/assets/videos/hmdb51_Turnk_r_Pippi_Michel_cartwheel_f_cm_np2_le_med_6.avi new file mode 100644 index 0000000000000000000000000000000000000000..979cd3901af54b2ed8e15922f94d88a34704aba3 GIT binary patch literal 357888 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 z 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 z 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%0AgRXs4 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

f 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 literal 0 HcmV?d00001 diff --git a/test/common_utils.py b/test/common_utils.py index 9dbd04f4217..fbfc64bd76b 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -7,13 +7,17 @@ import sys import io import torch -import errno +import warnings import __main__ +import random from numbers import Number from torch._six import string_classes from collections import OrderedDict +import numpy as np +from PIL import Image + @contextlib.contextmanager def get_tmp_dir(src=None, **kwargs): @@ -27,6 +31,12 @@ def get_tmp_dir(src=None, **kwargs): shutil.rmtree(tmp_dir) +def set_rng_seed(seed): + torch.manual_seed(seed) + random.seed(seed) + np.random.seed(seed) + + ACCEPT = os.getenv('EXPECTTEST_ACCEPT') TEST_WITH_SLOW = os.getenv('PYTORCH_TEST_WITH_SLOW', '0') == '1' # TEST_WITH_SLOW = True # TODO: Delete this line once there is a PYTORCH_TEST_WITH_SLOW aware CI job @@ -85,68 +95,64 @@ def is_iterable(obj): class TestCase(unittest.TestCase): precision = 1e-5 - def assertExpected(self, output, subname=None, prec=None): - r""" - Test that a python value matches the recorded contents of a file - derived from the name of this test and subname. The value must be - pickable with `torch.save`. This file - is placed in the 'expect' directory in the same directory - as the test script. You can automatically update the recorded test - output using --accept. - - If you call this multiple times in a single function, you must - give a unique subname each time. - """ - def remove_prefix(text, prefix): + def _get_expected_file(self, subname=None, strip_suffix=None): + def remove_prefix_suffix(text, prefix, suffix): if text.startswith(prefix): - return text[len(prefix):] + text = text[len(prefix):] + if suffix is not None and text.endswith(suffix): + text = text[:len(text) - len(suffix)] return text # NB: we take __file__ from the module that defined the test # class, so we place the expect directory where the test script # lives, NOT where test/common_utils.py lives. module_id = self.__class__.__module__ - munged_id = remove_prefix(self.id(), module_id + ".") + munged_id = remove_prefix_suffix(self.id(), module_id + ".", strip_suffix) test_file = os.path.realpath(sys.modules[module_id].__file__) expected_file = os.path.join(os.path.dirname(test_file), "expect", munged_id) - subname_output = "" if subname: expected_file += "_" + subname - subname_output = " ({})".format(subname) expected_file += "_expect.pkl" - expected = None - def accept_output(update_type): - print("Accepting {} for {}{}:\n\n{}".format(update_type, munged_id, subname_output, output)) - torch.save(output, expected_file) - MAX_PICKLE_SIZE = 50 * 1000 # 50 KB - binary_size = os.path.getsize(expected_file) - self.assertTrue(binary_size <= MAX_PICKLE_SIZE) + if not ACCEPT and not os.path.exists(expected_file): + raise RuntimeError( + ("No expect file exists for {}; to accept the current output, run:\n" + "python {} {} --accept").format(os.path.basename(expected_file), __main__.__file__, munged_id)) - try: - expected = torch.load(expected_file) - except IOError as e: - if e.errno != errno.ENOENT: - raise - elif ACCEPT: - return accept_output("output") - else: - raise RuntimeError( - ("I got this output for {}{}:\n\n{}\n\n" - "No expect file exists; to accept the current output, run:\n" - "python {} {} --accept").format(munged_id, subname_output, output, __main__.__file__, munged_id)) + return expected_file + + def assertExpected(self, output, subname=None, prec=None, strip_suffix=None): + r""" + Test that a python value matches the recorded contents of a file + derived from the name of this test and subname. The value must be + pickable with `torch.save`. This file + is placed in the 'expect' directory in the same directory + as the test script. You can automatically update the recorded test + output using --accept. + + If you call this multiple times in a single function, you must + give a unique subname each time. + + strip_suffix allows different tests that expect similar numerics, e.g. + "test_xyz_cuda" and "test_xyz_cpu", to use the same pickled data. + test_xyz_cuda would pass strip_suffix="_cuda", test_xyz_cpu would pass + strip_suffix="_cpu", and they would both use a data file name based on + "test_xyz". + """ + expected_file = self._get_expected_file(subname, strip_suffix) if ACCEPT: - equal = False - try: - equal = self.assertEqual(output, expected, prec=prec) - except Exception: - equal = False - if not equal: - return accept_output("updated output") + filename = {os.path.basename(expected_file)} + print("Accepting updated output for {}:\n\n{}".format(filename, output)) + torch.save(output, expected_file) + MAX_PICKLE_SIZE = 50 * 1000 # 50 KB + binary_size = os.path.getsize(expected_file) + if binary_size > MAX_PICKLE_SIZE: + raise RuntimeError("The output for {}, is larger than 50kb".format(filename)) else: + expected = torch.load(expected_file) self.assertEqual(output, expected, prec=prec) def assertEqual(self, x, y, prec=None, message='', allow_inf=False): @@ -266,14 +272,21 @@ def assertTensorsEqual(a, b): else: super(TestCase, self).assertEqual(x, y, message) - def checkModule(self, nn_module, args, unwrapper=None, skip=False): + def check_jit_scriptable(self, nn_module, args, unwrapper=None, skip=False): """ Check that a nn.Module's results in TorchScript match eager and that it can be exported """ if not TEST_WITH_SLOW or skip: # TorchScript is not enabled, skip these tests - return + msg = "The check_jit_scriptable test for {} was skipped. " \ + "This test checks if the module's results in TorchScript " \ + "match eager and that it can be exported. To run these " \ + "tests make sure you set the environment variable " \ + "PYTORCH_TEST_WITH_SLOW=1 and that the test is not " \ + "manually skipped.".format(nn_module.__class__.__name__) + warnings.warn(msg, RuntimeWarning) + return None sm = torch.jit.script(nn_module) @@ -285,7 +298,7 @@ def checkModule(self, nn_module, args, unwrapper=None, skip=False): if unwrapper: script_out = unwrapper(script_out) - self.assertEqual(eager_out, script_out) + self.assertEqual(eager_out, script_out, prec=1e-4) self.assertExportImportModule(sm, args) return sm @@ -321,3 +334,54 @@ def freeze_rng_state(): if torch.cuda.is_available(): torch.cuda.set_rng_state(cuda_rng_state) torch.set_rng_state(rng_state) + + +class TransformsTester(unittest.TestCase): + + def _create_data(self, height=3, width=3, channels=3, device="cpu"): + tensor = torch.randint(0, 255, (channels, height, width), dtype=torch.uint8, device=device) + pil_img = Image.fromarray(tensor.permute(1, 2, 0).contiguous().cpu().numpy()) + return tensor, pil_img + + def _create_data_batch(self, height=3, width=3, channels=3, num_samples=4, device="cpu"): + batch_tensor = torch.randint( + 0, 255, + (num_samples, channels, height, width), + dtype=torch.uint8, + device=device + ) + return batch_tensor + + def compareTensorToPIL(self, tensor, pil_image, msg=None): + np_pil_image = np.array(pil_image) + if np_pil_image.ndim == 2: + np_pil_image = np_pil_image[:, :, None] + pil_tensor = torch.as_tensor(np_pil_image.transpose((2, 0, 1))) + if msg is None: + msg = "tensor:\n{} \ndid not equal PIL tensor:\n{}".format(tensor, pil_tensor) + self.assertTrue(tensor.cpu().equal(pil_tensor), msg) + + def approxEqualTensorToPIL(self, tensor, pil_image, tol=1e-5, msg=None, agg_method="mean"): + np_pil_image = np.array(pil_image) + if np_pil_image.ndim == 2: + np_pil_image = np_pil_image[:, :, None] + pil_tensor = torch.as_tensor(np_pil_image.transpose((2, 0, 1))).to(tensor) + # error value can be mean absolute error, max abs error + err = getattr(torch, agg_method)(torch.abs(tensor - pil_tensor)).item() + self.assertTrue( + err < tol, + msg="{}: err={}, tol={}: \n{}\nvs\n{}".format(msg, err, tol, tensor[0, :10, :10], pil_tensor[0, :10, :10]) + ) + + +def cycle_over(objs): + for idx, obj in enumerate(objs): + yield obj, objs[:idx] + objs[idx + 1:] + + +def int_dtypes(): + return torch.testing.integral_types() + + +def float_dtypes(): + return torch.testing.floating_types() diff --git a/test/expect/ModelTester.test_fasterrcnn_resnet50_fpn_expect.pkl b/test/expect/ModelTester.test_fasterrcnn_resnet50_fpn_expect.pkl index 3e4fc8ec64157f8ef6fc6e23d88b074217a4b10a..3085bf36e60b8dd3d688b9beee2567821825e218 100644 GIT binary patch literal 4109 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 literal 30725 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 Ip|8yC|9ZFpI{*Lx diff --git a/test/expect/ModelTester.test_maskrcnn_resnet50_fpn_expect.pkl b/test/expect/ModelTester.test_maskrcnn_resnet50_fpn_expect.pkl index c05342100a36b9f4973c1e154edcd379d94e8e9b..d8ee673ab607bf6ce7ef60bc36d7ca3aad3cb86e 100644 GIT binary patch literal 4705 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 diff --git a/test/expect/ModelTester.test_retinanet_resnet50_fpn_expect.pkl b/test/expect/ModelTester.test_retinanet_resnet50_fpn_expect.pkl new file mode 100644 index 0000000000000000000000000000000000000000..8bd32f5be885f34a66b4ef8ace00f144e61c6d16 GIT binary patch literal 9677 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 literal 0 HcmV?d00001 diff --git a/test/fakedata_generation.py b/test/fakedata_generation.py index dbbe01c06eb..e17a4309cdc 100644 --- a/test/fakedata_generation.py +++ b/test/fakedata_generation.py @@ -7,6 +7,12 @@ import torch from common_utils import get_tmp_dir import pickle +import random +from itertools import cycle +from torchvision.io.video import write_video +import unittest.mock +import hashlib +from distutils import dir_util @contextlib.contextmanager @@ -253,14 +259,187 @@ def _make_mat(file): yield root + @contextlib.contextmanager def voc_root(): with get_tmp_dir() as tmp_dir: voc_dir = os.path.join(tmp_dir, 'VOCdevkit', - 'VOC2012','ImageSets','Main') + 'VOC2012', 'ImageSets', 'Main') os.makedirs(voc_dir) - train_file = os.path.join(voc_dir,'train.txt') + train_file = os.path.join(voc_dir, 'train.txt') with open(train_file, 'w') as f: f.write('test') yield tmp_dir + + +@contextlib.contextmanager +def ucf101_root(): + with get_tmp_dir() as tmp_dir: + ucf_dir = os.path.join(tmp_dir, 'UCF-101') + video_dir = os.path.join(ucf_dir, 'video') + annotations = os.path.join(ucf_dir, 'annotations') + + os.makedirs(ucf_dir) + os.makedirs(video_dir) + os.makedirs(annotations) + + fold_files = [] + for split in {'train', 'test'}: + for fold in range(1, 4): + fold_file = '{:s}list{:02d}.txt'.format(split, fold) + fold_files.append(os.path.join(annotations, fold_file)) + + file_handles = [open(x, 'w') for x in fold_files] + file_iter = cycle(file_handles) + + for i in range(0, 2): + current_class = 'class_{0}'.format(i + 1) + class_dir = os.path.join(video_dir, current_class) + os.makedirs(class_dir) + for group in range(0, 3): + for clip in range(0, 4): + # Save sample file + clip_name = 'v_{0}_g{1}_c{2}.avi'.format( + current_class, group, clip) + clip_path = os.path.join(class_dir, clip_name) + length = random.randrange(10, 21) + this_clip = torch.randint( + 0, 256, (length * 25, 320, 240, 3), dtype=torch.uint8) + write_video(clip_path, this_clip, 25) + # Add to annotations + ann_file = next(file_iter) + ann_file.write('{0}\n'.format( + os.path.join(current_class, clip_name))) + # Close all file descriptors + for f in file_handles: + f.close() + yield (video_dir, annotations) + + +@contextlib.contextmanager +def places365_root(split="train-standard", small=False, extract_images=True): + VARIANTS = { + "train-standard": "standard", + "train-challenge": "challenge", + "val": "standard", + } + # {split: file} + DEVKITS = { + "train-standard": "filelist_places365-standard.tar", + "train-challenge": "filelist_places365-challenge.tar", + "val": "filelist_places365-standard.tar", + } + CATEGORIES = "categories_places365.txt" + # {split: file} + FILE_LISTS = { + "train-standard": "places365_train_standard.txt", + "train-challenge": "places365_train_challenge.txt", + "val": "places365_train_standard.txt", + } + # {(split, small): (archive, folder_default, folder_renamed)} + IMAGES = { + ("train-standard", False): ("train_large_places365standard.tar", "data_large", "data_large_standard"), + ("train-challenge", False): ("train_large_places365challenge.tar", "data_large", "data_large_challenge"), + ("val", False): ("val_large.tar", "val_large", "val_large"), + ("train-standard", True): ("train_256_places365standard.tar", "data_256", "data_256_standard"), + ("train-challenge", True): ("train_256_places365challenge.tar", "data_256", "data_256_challenge"), + ("val", True): ("val_256.tar", "val_256", "val_256"), + } + + # (class, idx) + CATEGORIES_CONTENT = (("/a/airfield", 0), ("/a/apartment_building/outdoor", 8), ("/b/badlands", 30)) + # (file, idx) + FILE_LIST_CONTENT = ( + ("Places365_val_00000001.png", 0), + *((f"{category}/Places365_train_00000001.png", idx) for category, idx in CATEGORIES_CONTENT), + ) + + def mock_target(attr, partial="torchvision.datasets.places365.Places365"): + return f"{partial}.{attr}" + + def mock_class_attribute(stack, attr, new): + mock = unittest.mock.patch(mock_target(attr), new_callable=unittest.mock.PropertyMock, return_value=new) + stack.enter_context(mock) + return mock + + def compute_md5(file): + with open(file, "rb") as fh: + return hashlib.md5(fh.read()).hexdigest() + + def make_txt(root, name, seq): + file = os.path.join(root, name) + with open(file, "w") as fh: + for string, idx in seq: + fh.write(f"{string} {idx}\n") + return name, compute_md5(file) + + def make_categories_txt(root, name): + return make_txt(root, name, CATEGORIES_CONTENT) + + def make_file_list_txt(root, name): + return make_txt(root, name, FILE_LIST_CONTENT) + + def make_image(file, size): + os.makedirs(os.path.dirname(file), exist_ok=True) + PIL.Image.fromarray(np.zeros((*size, 3), dtype=np.uint8)).save(file) + + def make_tar(root, name, *files, remove_files=True): + name = f"{os.path.splitext(name)[0]}.tar" + archive = os.path.join(root, name) + + with tarfile.open(archive, "w") as fh: + for file in files: + fh.add(os.path.join(root, file), arcname=file) + + if remove_files: + for file in [os.path.join(root, file) for file in files]: + if os.path.isdir(file): + dir_util.remove_tree(file) + else: + os.remove(file) + + return name, compute_md5(archive) + + def make_devkit_archive(stack, root, split): + archive = DEVKITS[split] + files = [] + + meta = make_categories_txt(root, CATEGORIES) + mock_class_attribute(stack, "_CATEGORIES_META", meta) + files.append(meta[0]) + + meta = {split: make_file_list_txt(root, FILE_LISTS[split])} + mock_class_attribute(stack, "_FILE_LIST_META", meta) + files.extend([item[0] for item in meta.values()]) + + meta = {VARIANTS[split]: make_tar(root, archive, *files)} + mock_class_attribute(stack, "_DEVKIT_META", meta) + + def make_images_archive(stack, root, split, small): + archive, folder_default, folder_renamed = IMAGES[(split, small)] + + image_size = (256, 256) if small else (512, random.randint(512, 1024)) + files, idcs = zip(*FILE_LIST_CONTENT) + images = [file.lstrip("/").replace("/", os.sep) for file in files] + for image in images: + make_image(os.path.join(root, folder_default, image), image_size) + + meta = {(split, small): make_tar(root, archive, folder_default)} + mock_class_attribute(stack, "_IMAGES_META", meta) + + return [(os.path.join(root, folder_renamed, image), idx) for image, idx in zip(images, idcs)] + + with contextlib.ExitStack() as stack, get_tmp_dir() as root: + make_devkit_archive(stack, root, split) + class_to_idx = dict(CATEGORIES_CONTENT) + classes = list(class_to_idx.keys()) + data = {"class_to_idx": class_to_idx, "classes": classes} + + if extract_images: + data["imgs"] = make_images_archive(stack, root, split, small) + else: + stack.enter_context(unittest.mock.patch(mock_target("download_images"))) + data["imgs"] = None + + yield root, data diff --git a/test/test_cpp_models.py b/test/test_cpp_models.py index b6654a0278d..6deb5d79739 100644 --- a/test/test_cpp_models.py +++ b/test/test_cpp_models.py @@ -25,7 +25,8 @@ def process_model(model, tensor, func, name): def read_image1(): - image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets', 'grace_hopper_517x606.jpg') + image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets', 'encode_jpeg', + 'grace_hopper_517x606.jpg') image = Image.open(image_path) image = image.resize((224, 224)) x = F.to_tensor(image) @@ -33,7 +34,8 @@ def read_image1(): def read_image2(): - image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets', 'grace_hopper_517x606.jpg') + image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets', 'encode_jpeg', + 'grace_hopper_517x606.jpg') image = Image.open(image_path) image = image.resize((299, 299)) x = F.to_tensor(image) diff --git a/test/test_datasets.py b/test/test_datasets.py index d2fa2d9885f..af092e1845d 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1,7 +1,7 @@ import sys import os import unittest -import mock +from unittest import mock import numpy as np import PIL from PIL import Image @@ -9,8 +9,10 @@ import torchvision from common_utils import get_tmp_dir from fakedata_generation import mnist_root, cifar_root, imagenet_root, \ - cityscapes_root, svhn_root, voc_root + cityscapes_root, svhn_root, voc_root, ucf101_root, places365_root import xml.etree.ElementTree as ET +from urllib.request import Request, urlopen +import itertools try: @@ -19,6 +21,12 @@ except ImportError: HAS_SCIPY = False +try: + import av + HAS_PYAV = True +except ImportError: + HAS_PYAV = False + class Tester(unittest.TestCase): def generic_classification_dataset_test(self, dataset, num_images=1): @@ -40,10 +48,12 @@ def test_imagefolder(self): with get_tmp_dir(src=os.path.join(FAKEDATA_DIR, 'imagefolder')) as root: classes = sorted(['a', 'b']) - class_a_image_files = [os.path.join(root, 'a', file) - for file in ('a1.png', 'a2.png', 'a3.png')] - class_b_image_files = [os.path.join(root, 'b', file) - for file in ('b1.png', 'b2.png', 'b3.png', 'b4.png')] + class_a_image_files = [ + os.path.join(root, 'a', file) for file in ('a1.png', 'a2.png', 'a3.png') + ] + class_b_image_files = [ + os.path.join(root, 'b', file) for file in ('b1.png', 'b2.png', 'b3.png', 'b4.png') + ] dataset = torchvision.datasets.ImageFolder(root, loader=lambda x: x) # test if all classes are present @@ -66,8 +76,8 @@ def test_imagefolder(self): self.assertEqual(imgs, outputs) # redo all tests with specified valid image files - dataset = torchvision.datasets.ImageFolder(root, loader=lambda x: x, - is_valid_file=lambda x: '3' in x) + dataset = torchvision.datasets.ImageFolder( + root, loader=lambda x: x, is_valid_file=lambda x: '3' in x) self.assertEqual(classes, sorted(dataset.classes)) class_a_idx = dataset.class_to_idx['a'] @@ -174,18 +184,18 @@ def test_cityscapes(self): for split in splits: for target_type in ['semantic', 'instance']: - dataset = torchvision.datasets.Cityscapes(root, split=split, - target_type=target_type, mode=mode) + dataset = torchvision.datasets.Cityscapes( + root, split=split, target_type=target_type, mode=mode) self.generic_segmentation_dataset_test(dataset, num_images=2) - color_dataset = torchvision.datasets.Cityscapes(root, split=split, - target_type='color', mode=mode) + color_dataset = torchvision.datasets.Cityscapes( + root, split=split, target_type='color', mode=mode) color_img, color_target = color_dataset[0] self.assertTrue(isinstance(color_img, PIL.Image.Image)) self.assertTrue(np.array(color_target).shape[2] == 4) - polygon_dataset = torchvision.datasets.Cityscapes(root, split=split, - target_type='polygon', mode=mode) + polygon_dataset = torchvision.datasets.Cityscapes( + root, split=split, target_type='polygon', mode=mode) polygon_img, polygon_target = polygon_dataset[0] self.assertTrue(isinstance(polygon_img, PIL.Image.Image)) self.assertTrue(isinstance(polygon_target, dict)) @@ -194,9 +204,8 @@ def test_cityscapes(self): # Test multiple target types targets_combo = ['semantic', 'polygon', 'color'] - multiple_types_dataset = torchvision.datasets.Cityscapes(root, split=split, - target_type=targets_combo, - mode=mode) + multiple_types_dataset = torchvision.datasets.Cityscapes( + root, split=split, target_type=targets_combo, mode=mode) output = multiple_types_dataset[0] self.assertTrue(isinstance(output, tuple)) self.assertTrue(len(output) == 2) @@ -239,13 +248,123 @@ def test_voc_parse_xml(self, mock_download_extract): dog """ - single_object_parsed = dataset.parse_voc_xml(ET.fromstring(single_object_xml - )) + + single_object_parsed = dataset.parse_voc_xml(ET.fromstring(single_object_xml)) multiple_object_parsed = dataset.parse_voc_xml(ET.fromstring(multiple_object_xml)) - self.assertEqual(single_object_parsed, {'annotation': {'object':[{'name': 'cat'}]}}) - self.assertEqual(multiple_object_parsed, {'annotation': - {'object':[{'name': 'cat'}, {'name': 'dog'}]}}) + self.assertEqual(single_object_parsed, {'annotation': {'object': [{'name': 'cat'}]}}) + self.assertEqual(multiple_object_parsed, + {'annotation': { + 'object': [{ + 'name': 'cat' + }, { + 'name': 'dog' + }] + }}) + + @unittest.skipIf(not HAS_PYAV, "PyAV unavailable") + def test_ucf101(self): + with ucf101_root() as (root, ann_root): + for split in {True, False}: + for fold in range(1, 4): + for length in {10, 15, 20}: + dataset = torchvision.datasets.UCF101( + root, ann_root, length, fold=fold, train=split) + self.assertGreater(len(dataset), 0) + + video, audio, label = dataset[0] + self.assertEqual(video.size(), (length, 320, 240, 3)) + self.assertEqual(audio.numel(), 0) + self.assertEqual(label, 0) + + video, audio, label = dataset[len(dataset) - 1] + self.assertEqual(video.size(), (length, 320, 240, 3)) + self.assertEqual(audio.numel(), 0) + self.assertEqual(label, 1) + + def test_places365(self): + for split, small in itertools.product(("train-standard", "train-challenge", "val"), (False, True)): + with places365_root(split=split, small=small) as places365: + root, data = places365 + + dataset = torchvision.datasets.Places365(root, split=split, small=small, download=True) + self.generic_classification_dataset_test(dataset, num_images=len(data["imgs"])) + + def test_places365_transforms(self): + expected_image = "image" + expected_target = "target" + + def transform(image): + return expected_image + + def target_transform(target): + return expected_target + + with places365_root() as places365: + root, data = places365 + + dataset = torchvision.datasets.Places365( + root, transform=transform, target_transform=target_transform, download=True + ) + actual_image, actual_target = dataset[0] + + self.assertEqual(actual_image, expected_image) + self.assertEqual(actual_target, expected_target) + + def test_places365_devkit_download(self): + for split in ("train-standard", "train-challenge", "val"): + with self.subTest(split=split): + with places365_root(split=split) as places365: + root, data = places365 + + dataset = torchvision.datasets.Places365(root, split=split, download=True) + + with self.subTest("classes"): + self.assertSequenceEqual(dataset.classes, data["classes"]) + + with self.subTest("class_to_idx"): + self.assertDictEqual(dataset.class_to_idx, data["class_to_idx"]) + + with self.subTest("imgs"): + self.assertSequenceEqual(dataset.imgs, data["imgs"]) + + def test_places365_devkit_no_download(self): + for split in ("train-standard", "train-challenge", "val"): + with self.subTest(split=split): + with places365_root(split=split, extract_images=False) as places365: + root, data = places365 + + with self.assertRaises(RuntimeError): + torchvision.datasets.Places365(root, split=split, download=False) + + def test_places365_images_download(self): + for split, small in itertools.product(("train-standard", "train-challenge", "val"), (False, True)): + with self.subTest(split=split, small=small): + with places365_root(split=split, small=small) as places365: + root, data = places365 + + dataset = torchvision.datasets.Places365(root, split=split, small=small, download=True) + + assert all(os.path.exists(item[0]) for item in dataset.imgs) + + def test_places365_images_download_preexisting(self): + split = "train-standard" + small = False + images_dir = "data_large_standard" + + with places365_root(split=split, small=small) as places365: + root, data = places365 + os.mkdir(os.path.join(root, images_dir)) + + with self.assertRaises(RuntimeError): + torchvision.datasets.Places365(root, split=split, small=small, download=True) + + def test_places365_repr_smoke(self): + with places365_root(extract_images=False) as places365: + root, data = places365 + + dataset = torchvision.datasets.Places365(root, download=True) + self.assertIsInstance(repr(dataset), str) if __name__ == '__main__': diff --git a/test/test_datasets_download.py b/test/test_datasets_download.py new file mode 100644 index 00000000000..c6e95ffe064 --- /dev/null +++ b/test/test_datasets_download.py @@ -0,0 +1,208 @@ +import contextlib +import itertools +import time +import unittest.mock +from datetime import datetime +from os import path +from urllib.error import HTTPError +from urllib.parse import urlparse +from urllib.request import urlopen, Request + +import pytest + +from torchvision import datasets +from torchvision.datasets.utils import download_url, check_integrity + +from common_utils import get_tmp_dir +from fakedata_generation import places365_root + + +def limit_requests_per_time(min_secs_between_requests=2.0): + last_requests = {} + + def outer_wrapper(fn): + def inner_wrapper(request, *args, **kwargs): + url = request.full_url if isinstance(request, Request) else request + + netloc = urlparse(url).netloc + last_request = last_requests.get(netloc) + if last_request is not None: + elapsed_secs = (datetime.now() - last_request).total_seconds() + delta = min_secs_between_requests - elapsed_secs + if delta > 0: + time.sleep(delta) + + response = fn(request, *args, **kwargs) + last_requests[netloc] = datetime.now() + + return response + + return inner_wrapper + + return outer_wrapper + + +urlopen = limit_requests_per_time()(urlopen) + + +@contextlib.contextmanager +def log_download_attempts( + urls_and_md5s=None, + patch=True, + download_url_target="torchvision.datasets.utils.download_url", + patch_auxiliaries=None, +): + if urls_and_md5s is None: + urls_and_md5s = set() + if patch_auxiliaries is None: + patch_auxiliaries = patch + + with contextlib.ExitStack() as stack: + download_url_mock = stack.enter_context( + unittest.mock.patch(download_url_target, wraps=None if patch else download_url) + ) + if patch_auxiliaries: + # download_and_extract_archive + stack.enter_context(unittest.mock.patch("torchvision.datasets.utils.extract_archive")) + try: + yield urls_and_md5s + finally: + for args, kwargs in download_url_mock.call_args_list: + url = args[0] + md5 = args[-1] if len(args) == 4 else kwargs.get("md5") + urls_and_md5s.add((url, md5)) + + +def retry(fn, times=1, wait=5.0): + msgs = [] + for _ in range(times + 1): + try: + return fn() + except AssertionError as error: + msgs.append(str(error)) + time.sleep(wait) + else: + raise AssertionError( + "\n".join( + ( + f"Assertion failed {times + 1} times with {wait:.1f} seconds intermediate wait time.\n", + *(f"{idx}: {error}" for idx, error in enumerate(msgs, 1)), + ) + ) + ) + + +@contextlib.contextmanager +def assert_server_response_ok(): + try: + yield + except HTTPError as error: + raise AssertionError(f"The server returned {error.code}: {error.reason}.") from error + + +def assert_url_is_accessible(url): + request = Request(url, headers=dict(method="HEAD")) + with assert_server_response_ok(): + urlopen(request) + + +def assert_file_downloads_correctly(url, md5): + with get_tmp_dir() as root: + file = path.join(root, path.basename(url)) + with assert_server_response_ok(): + with urlopen(url) as response, open(file, "wb") as fh: + fh.write(response.read()) + + assert check_integrity(file, md5=md5), "The MD5 checksums mismatch" + + +class DownloadConfig: + def __init__(self, url, md5=None, id=None): + self.url = url + self.md5 = md5 + self.id = id or url + + def __repr__(self): + return self.id + + +def make_download_configs(urls_and_md5s, name=None): + return [ + DownloadConfig(url, md5=md5, id=f"{name}, {url}" if name is not None else None) for url, md5 in urls_and_md5s + ] + + +def collect_download_configs(dataset_loader, name, **kwargs): + with contextlib.suppress(Exception), log_download_attempts(**kwargs) as urls_and_md5s: + dataset_loader() + return make_download_configs(urls_and_md5s, name) + + +def places365(): + with log_download_attempts(patch=False) as urls_and_md5s: + for split, small in itertools.product(("train-standard", "train-challenge", "val"), (False, True)): + with places365_root(split=split, small=small) as places365: + root, data = places365 + + datasets.Places365(root, split=split, small=small, download=True) + + return make_download_configs(urls_and_md5s, "Places365") + + +def caltech101(): + return collect_download_configs(lambda: datasets.Caltech101(".", download=True), "Caltech101") + + +def caltech256(): + return collect_download_configs(lambda: datasets.Caltech256(".", download=True), "Caltech256") + + +def cifar10(): + return collect_download_configs(lambda: datasets.CIFAR10(".", download=True), "CIFAR10") + + +def cifar100(): + return collect_download_configs(lambda: datasets.CIFAR10(".", download=True), "CIFAR100") + + +def voc(): + download_configs = [] + for year in ("2007", "2007-test", "2008", "2009", "2010", "2011", "2012"): + with contextlib.suppress(Exception), log_download_attempts( + download_url_target="torchvision.datasets.voc.download_url" + ) as urls_and_md5s: + datasets.VOCSegmentation(".", year=year, download=True) + download_configs.extend(make_download_configs(urls_and_md5s, f"VOC, {year}")) + return download_configs + + +def make_parametrize_kwargs(download_configs): + argvalues = [] + ids = [] + for config in download_configs: + argvalues.append((config.url, config.md5)) + ids.append(config.id) + + return dict(argnames=("url", "md5"), argvalues=argvalues, ids=ids) + + +@pytest.mark.parametrize( + **make_parametrize_kwargs( + itertools.chain( + places365(), + caltech101(), + caltech256(), + cifar10(), + cifar100(), + # The VOC download server is unstable. See https://github.com/pytorch/vision/issues/2953 for details. + # voc(), + ) + ) +) +def test_url_is_accessible(url, md5): + retry(lambda: assert_url_is_accessible(url)) + + +@pytest.mark.parametrize(**make_parametrize_kwargs(itertools.chain())) +def test_file_downloads_correctly(url, md5): + retry(lambda: assert_file_downloads_correctly(url, md5)) diff --git a/test/test_datasets_utils.py b/test/test_datasets_utils.py index ec9f7af2961..2c6599ce497 100644 --- a/test/test_datasets_utils.py +++ b/test/test_datasets_utils.py @@ -8,17 +8,13 @@ import gzip import warnings from torch._utils_internal import get_file_path_2 +from urllib.error import URLError from common_utils import get_tmp_dir -if sys.version_info < (3,): - from urllib2 import URLError -else: - from urllib.error import URLError - TEST_FILE = get_file_path_2( - os.path.dirname(os.path.abspath(__file__)), 'assets', 'grace_hopper_517x606.jpg') + os.path.dirname(os.path.abspath(__file__)), 'assets', 'encode_jpeg', 'grace_hopper_517x606.jpg') class Tester(unittest.TestCase): @@ -62,7 +58,6 @@ def test_download_url_retry_http(self): warnings.warn(msg, RuntimeWarning) raise unittest.SkipTest(msg) - @unittest.skipIf(sys.version_info < (3,), "Python2 doesn't raise error") def test_download_url_dont_exist(self): with get_tmp_dir() as temp_dir: url = "http://github.com/pytorch/vision/archive/this_doesnt_exist.zip" @@ -98,7 +93,6 @@ def test_extract_tar(self): self.assertEqual(data, 'this is the content') @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') - @unittest.skipIf(sys.version_info < (3,), "Extracting .tar.xz files is not supported under Python 2.x") def test_extract_tar_xz(self): for ext, mode in zip(['.tar.xz'], ['w:xz']): with get_tmp_dir() as temp_dir: diff --git a/test/test_datasets_video_utils.py b/test/test_datasets_video_utils.py index f038302e428..ed3dcfcbbef 100644 --- a/test/test_datasets_video_utils.py +++ b/test/test_datasets_video_utils.py @@ -119,6 +119,16 @@ def test_compute_clips_for_video(self): self.assertTrue(clips.equal(idxs)) self.assertTrue(idxs.flatten().equal(resampled_idxs)) + # case 3: frames aren't enough for a clip + num_frames = 32 + orig_fps = 30 + new_fps = 13 + with self.assertWarns(UserWarning): + clips, idxs = VideoClips.compute_clips_for_video(video_pts, num_frames, num_frames, + orig_fps, new_fps) + self.assertEqual(len(clips), 0) + self.assertEqual(len(idxs), 0) + if __name__ == '__main__': unittest.main() diff --git a/test/test_datasets_video_utils_opt.py b/test/test_datasets_video_utils_opt.py index f94af400838..8075c701ed9 100644 --- a/test/test_datasets_video_utils_opt.py +++ b/test/test_datasets_video_utils_opt.py @@ -2,8 +2,8 @@ from torchvision import set_video_backend import test_datasets_video_utils - -set_video_backend('video_reader') +# Disabling the video backend switching temporarily +# set_video_backend('video_reader') if __name__ == '__main__': diff --git a/test/test_functional_tensor.py b/test/test_functional_tensor.py index ea2f5e55d0b..38a565310d0 100644 --- a/test/test_functional_tensor.py +++ b/test/test_functional_tensor.py @@ -1,126 +1,868 @@ +import os +import unittest +import colorsys +import math + +import numpy as np + import torch -import torchvision.transforms as transforms import torchvision.transforms.functional_tensor as F_t +import torchvision.transforms.functional_pil as F_pil import torchvision.transforms.functional as F -import numpy as np -import unittest -import random +from torchvision.transforms import InterpolationMode + +from common_utils import TransformsTester + + +NEAREST, BILINEAR, BICUBIC = InterpolationMode.NEAREST, InterpolationMode.BILINEAR, InterpolationMode.BICUBIC + + +class Tester(TransformsTester): + def setUp(self): + self.device = "cpu" -class Tester(unittest.TestCase): + def _test_fn_on_batch(self, batch_tensors, fn, **fn_kwargs): + transformed_batch = fn(batch_tensors, **fn_kwargs) + for i in range(len(batch_tensors)): + img_tensor = batch_tensors[i, ...] + transformed_img = fn(img_tensor, **fn_kwargs) + self.assertTrue(transformed_img.equal(transformed_batch[i, ...])) + + scripted_fn = torch.jit.script(fn) + # scriptable function test + s_transformed_batch = scripted_fn(batch_tensors, **fn_kwargs) + self.assertTrue(transformed_batch.allclose(s_transformed_batch)) def test_vflip(self): - img_tensor = torch.randn(3, 16, 16) - vflipped_img = F_t.vflip(img_tensor) - vflipped_img_again = F_t.vflip(vflipped_img) - self.assertEqual(vflipped_img.shape, img_tensor.shape) - self.assertTrue(torch.equal(img_tensor, vflipped_img_again)) + script_vflip = torch.jit.script(F.vflip) + + img_tensor, pil_img = self._create_data(16, 18, device=self.device) + vflipped_img = F.vflip(img_tensor) + vflipped_pil_img = F.vflip(pil_img) + self.compareTensorToPIL(vflipped_img, vflipped_pil_img) + + # scriptable function test + vflipped_img_script = script_vflip(img_tensor) + self.assertTrue(vflipped_img.equal(vflipped_img_script)) + + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + self._test_fn_on_batch(batch_tensors, F.vflip) def test_hflip(self): - img_tensor = torch.randn(3, 16, 16) - hflipped_img = F_t.hflip(img_tensor) - hflipped_img_again = F_t.hflip(hflipped_img) - self.assertEqual(hflipped_img.shape, img_tensor.shape) - self.assertTrue(torch.equal(img_tensor, hflipped_img_again)) + script_hflip = torch.jit.script(F.hflip) + + img_tensor, pil_img = self._create_data(16, 18, device=self.device) + hflipped_img = F.hflip(img_tensor) + hflipped_pil_img = F.hflip(pil_img) + self.compareTensorToPIL(hflipped_img, hflipped_pil_img) + + # scriptable function test + hflipped_img_script = script_hflip(img_tensor) + self.assertTrue(hflipped_img.equal(hflipped_img_script)) + + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + self._test_fn_on_batch(batch_tensors, F.hflip) def test_crop(self): - img_tensor = torch.randint(0, 255, (3, 16, 16), dtype=torch.uint8) - top = random.randint(0, 15) - left = random.randint(0, 15) - height = random.randint(1, 16 - top) - width = random.randint(1, 16 - left) - img_cropped = F_t.crop(img_tensor, top, left, height, width) - img_PIL = transforms.ToPILImage()(img_tensor) - img_PIL_cropped = F.crop(img_PIL, top, left, height, width) - img_cropped_GT = transforms.ToTensor()(img_PIL_cropped) - - self.assertTrue(torch.equal(img_cropped, (img_cropped_GT * 255).to(torch.uint8)), - "functional_tensor crop not working") - - def test_adjustments(self): - fns = ((F.adjust_brightness, F_t.adjust_brightness), - (F.adjust_contrast, F_t.adjust_contrast), - (F.adjust_saturation, F_t.adjust_saturation)) - - for _ in range(20): - channels = 3 - dims = torch.randint(1, 50, (2,)) - shape = (channels, dims[0], dims[1]) - - if torch.randint(0, 2, (1,)) == 0: - img = torch.rand(*shape, dtype=torch.float) - else: - img = torch.randint(0, 256, shape, dtype=torch.uint8) - - factor = 3 * torch.rand(1) - for f, ft in fns: - - ft_img = ft(img, factor) - if not img.dtype.is_floating_point: - ft_img = ft_img.to(torch.float) / 255 - - img_pil = transforms.ToPILImage()(img) - f_img_pil = f(img_pil, factor) - f_img = transforms.ToTensor()(f_img_pil) - - # F uses uint8 and F_t uses float, so there is a small - # difference in values caused by (at most 5) truncations. - max_diff = (ft_img - f_img).abs().max() - self.assertLess(max_diff, 5 / 255 + 1e-5) + script_crop = torch.jit.script(F.crop) + + img_tensor, pil_img = self._create_data(16, 18, device=self.device) + + test_configs = [ + (1, 2, 4, 5), # crop inside top-left corner + (2, 12, 3, 4), # crop inside top-right corner + (8, 3, 5, 6), # crop inside bottom-left corner + (8, 11, 4, 3), # crop inside bottom-right corner + ] + + for top, left, height, width in test_configs: + pil_img_cropped = F.crop(pil_img, top, left, height, width) + + img_tensor_cropped = F.crop(img_tensor, top, left, height, width) + self.compareTensorToPIL(img_tensor_cropped, pil_img_cropped) + + img_tensor_cropped = script_crop(img_tensor, top, left, height, width) + self.compareTensorToPIL(img_tensor_cropped, pil_img_cropped) + + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + self._test_fn_on_batch(batch_tensors, F.crop, top=top, left=left, height=height, width=width) + + def test_hsv2rgb(self): + scripted_fn = torch.jit.script(F_t._hsv2rgb) + shape = (3, 100, 150) + for _ in range(10): + hsv_img = torch.rand(*shape, dtype=torch.float, device=self.device) + rgb_img = F_t._hsv2rgb(hsv_img) + ft_img = rgb_img.permute(1, 2, 0).flatten(0, 1) + + h, s, v, = hsv_img.unbind(0) + h = h.flatten().cpu().numpy() + s = s.flatten().cpu().numpy() + v = v.flatten().cpu().numpy() + + rgb = [] + for h1, s1, v1 in zip(h, s, v): + rgb.append(colorsys.hsv_to_rgb(h1, s1, v1)) + colorsys_img = torch.tensor(rgb, dtype=torch.float32, device=self.device) + max_diff = (ft_img - colorsys_img).abs().max() + self.assertLess(max_diff, 1e-5) + + s_rgb_img = scripted_fn(hsv_img) + self.assertTrue(rgb_img.allclose(s_rgb_img)) + + batch_tensors = self._create_data_batch(120, 100, num_samples=4, device=self.device).float() + self._test_fn_on_batch(batch_tensors, F_t._hsv2rgb) + + def test_rgb2hsv(self): + scripted_fn = torch.jit.script(F_t._rgb2hsv) + shape = (3, 150, 100) + for _ in range(10): + rgb_img = torch.rand(*shape, dtype=torch.float, device=self.device) + hsv_img = F_t._rgb2hsv(rgb_img) + ft_hsv_img = hsv_img.permute(1, 2, 0).flatten(0, 1) + + r, g, b, = rgb_img.unbind(dim=-3) + r = r.flatten().cpu().numpy() + g = g.flatten().cpu().numpy() + b = b.flatten().cpu().numpy() + + hsv = [] + for r1, g1, b1 in zip(r, g, b): + hsv.append(colorsys.rgb_to_hsv(r1, g1, b1)) + + colorsys_img = torch.tensor(hsv, dtype=torch.float32, device=self.device) + + ft_hsv_img_h, ft_hsv_img_sv = torch.split(ft_hsv_img, [1, 2], dim=1) + colorsys_img_h, colorsys_img_sv = torch.split(colorsys_img, [1, 2], dim=1) + + max_diff_h = ((colorsys_img_h * 2 * math.pi).sin() - (ft_hsv_img_h * 2 * math.pi).sin()).abs().max() + max_diff_sv = (colorsys_img_sv - ft_hsv_img_sv).abs().max() + max_diff = max(max_diff_h, max_diff_sv) + self.assertLess(max_diff, 1e-5) + + s_hsv_img = scripted_fn(rgb_img) + self.assertTrue(hsv_img.allclose(s_hsv_img)) + + batch_tensors = self._create_data_batch(120, 100, num_samples=4, device=self.device).float() + self._test_fn_on_batch(batch_tensors, F_t._rgb2hsv) def test_rgb_to_grayscale(self): - img_tensor = torch.randint(0, 255, (3, 16, 16), dtype=torch.uint8) - grayscale_tensor = F_t.rgb_to_grayscale(img_tensor).to(int) - grayscale_pil_img = torch.tensor(np.array(F.to_grayscale(F.to_pil_image(img_tensor)))).to(int) - max_diff = (grayscale_tensor - grayscale_pil_img).abs().max() - self.assertLess(max_diff, 1.0001) + script_rgb_to_grayscale = torch.jit.script(F.rgb_to_grayscale) + + img_tensor, pil_img = self._create_data(32, 34, device=self.device) + + for num_output_channels in (3, 1): + gray_pil_image = F.rgb_to_grayscale(pil_img, num_output_channels=num_output_channels) + gray_tensor = F.rgb_to_grayscale(img_tensor, num_output_channels=num_output_channels) + + self.approxEqualTensorToPIL(gray_tensor.float(), gray_pil_image, tol=1.0 + 1e-10, agg_method="max") + + s_gray_tensor = script_rgb_to_grayscale(img_tensor, num_output_channels=num_output_channels) + self.assertTrue(s_gray_tensor.equal(gray_tensor)) + + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + self._test_fn_on_batch(batch_tensors, F.rgb_to_grayscale, num_output_channels=num_output_channels) def test_center_crop(self): - img_tensor = torch.randint(0, 255, (1, 32, 32), dtype=torch.uint8) - cropped_tensor = F_t.center_crop(img_tensor, [10, 10]) - cropped_pil_image = F.center_crop(transforms.ToPILImage()(img_tensor), [10, 10]) - cropped_pil_tensor = (transforms.ToTensor()(cropped_pil_image) * 255).to(torch.uint8) - self.assertTrue(torch.equal(cropped_tensor, cropped_pil_tensor)) + script_center_crop = torch.jit.script(F.center_crop) + + img_tensor, pil_img = self._create_data(32, 34, device=self.device) + + cropped_pil_image = F.center_crop(pil_img, [10, 11]) + + cropped_tensor = F.center_crop(img_tensor, [10, 11]) + self.compareTensorToPIL(cropped_tensor, cropped_pil_image) + + cropped_tensor = script_center_crop(img_tensor, [10, 11]) + self.compareTensorToPIL(cropped_tensor, cropped_pil_image) + + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + self._test_fn_on_batch(batch_tensors, F.center_crop, output_size=[10, 11]) def test_five_crop(self): - img_tensor = torch.randint(0, 255, (1, 32, 32), dtype=torch.uint8) - cropped_tensor = F_t.five_crop(img_tensor, [10, 10]) - cropped_pil_image = F.five_crop(transforms.ToPILImage()(img_tensor), [10, 10]) - self.assertTrue(torch.equal(cropped_tensor[0], - (transforms.ToTensor()(cropped_pil_image[0]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[1], - (transforms.ToTensor()(cropped_pil_image[2]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[2], - (transforms.ToTensor()(cropped_pil_image[1]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[3], - (transforms.ToTensor()(cropped_pil_image[3]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[4], - (transforms.ToTensor()(cropped_pil_image[4]) * 255).to(torch.uint8))) + script_five_crop = torch.jit.script(F.five_crop) + + img_tensor, pil_img = self._create_data(32, 34, device=self.device) + + cropped_pil_images = F.five_crop(pil_img, [10, 11]) + + cropped_tensors = F.five_crop(img_tensor, [10, 11]) + for i in range(5): + self.compareTensorToPIL(cropped_tensors[i], cropped_pil_images[i]) + + cropped_tensors = script_five_crop(img_tensor, [10, 11]) + for i in range(5): + self.compareTensorToPIL(cropped_tensors[i], cropped_pil_images[i]) + + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + tuple_transformed_batches = F.five_crop(batch_tensors, [10, 11]) + for i in range(len(batch_tensors)): + img_tensor = batch_tensors[i, ...] + tuple_transformed_imgs = F.five_crop(img_tensor, [10, 11]) + self.assertEqual(len(tuple_transformed_imgs), len(tuple_transformed_batches)) + + for j in range(len(tuple_transformed_imgs)): + true_transformed_img = tuple_transformed_imgs[j] + transformed_img = tuple_transformed_batches[j][i, ...] + self.assertTrue(true_transformed_img.equal(transformed_img)) + + # scriptable function test + s_tuple_transformed_batches = script_five_crop(batch_tensors, [10, 11]) + for transformed_batch, s_transformed_batch in zip(tuple_transformed_batches, s_tuple_transformed_batches): + self.assertTrue(transformed_batch.equal(s_transformed_batch)) def test_ten_crop(self): - img_tensor = torch.randint(0, 255, (1, 32, 32), dtype=torch.uint8) - cropped_tensor = F_t.ten_crop(img_tensor, [10, 10]) - cropped_pil_image = F.ten_crop(transforms.ToPILImage()(img_tensor), [10, 10]) - self.assertTrue(torch.equal(cropped_tensor[0], - (transforms.ToTensor()(cropped_pil_image[0]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[1], - (transforms.ToTensor()(cropped_pil_image[2]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[2], - (transforms.ToTensor()(cropped_pil_image[1]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[3], - (transforms.ToTensor()(cropped_pil_image[3]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[4], - (transforms.ToTensor()(cropped_pil_image[4]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[5], - (transforms.ToTensor()(cropped_pil_image[5]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[6], - (transforms.ToTensor()(cropped_pil_image[7]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[7], - (transforms.ToTensor()(cropped_pil_image[6]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[8], - (transforms.ToTensor()(cropped_pil_image[8]) * 255).to(torch.uint8))) - self.assertTrue(torch.equal(cropped_tensor[9], - (transforms.ToTensor()(cropped_pil_image[9]) * 255).to(torch.uint8))) + script_ten_crop = torch.jit.script(F.ten_crop) + + img_tensor, pil_img = self._create_data(32, 34, device=self.device) + + cropped_pil_images = F.ten_crop(pil_img, [10, 11]) + + cropped_tensors = F.ten_crop(img_tensor, [10, 11]) + for i in range(10): + self.compareTensorToPIL(cropped_tensors[i], cropped_pil_images[i]) + + cropped_tensors = script_ten_crop(img_tensor, [10, 11]) + for i in range(10): + self.compareTensorToPIL(cropped_tensors[i], cropped_pil_images[i]) + + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + tuple_transformed_batches = F.ten_crop(batch_tensors, [10, 11]) + for i in range(len(batch_tensors)): + img_tensor = batch_tensors[i, ...] + tuple_transformed_imgs = F.ten_crop(img_tensor, [10, 11]) + self.assertEqual(len(tuple_transformed_imgs), len(tuple_transformed_batches)) + + for j in range(len(tuple_transformed_imgs)): + true_transformed_img = tuple_transformed_imgs[j] + transformed_img = tuple_transformed_batches[j][i, ...] + self.assertTrue(true_transformed_img.equal(transformed_img)) + + # scriptable function test + s_tuple_transformed_batches = script_ten_crop(batch_tensors, [10, 11]) + for transformed_batch, s_transformed_batch in zip(tuple_transformed_batches, s_tuple_transformed_batches): + self.assertTrue(transformed_batch.equal(s_transformed_batch)) + + def test_pad(self): + script_fn = torch.jit.script(F.pad) + tensor, pil_img = self._create_data(7, 8, device=self.device) + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + + for dt in [None, torch.float32, torch.float64, torch.float16]: + + if dt == torch.float16 and torch.device(self.device).type == "cpu": + # skip float16 on CPU case + continue + + if dt is not None: + # This is a trivial cast to float of uint8 data to test all cases + tensor = tensor.to(dt) + batch_tensors = batch_tensors.to(dt) + + for pad in [2, [3, ], [0, 3], (3, 3), [4, 2, 4, 3]]: + configs = [ + {"padding_mode": "constant", "fill": 0}, + {"padding_mode": "constant", "fill": 10}, + {"padding_mode": "constant", "fill": 20}, + {"padding_mode": "edge"}, + {"padding_mode": "reflect"}, + {"padding_mode": "symmetric"}, + ] + for kwargs in configs: + pad_tensor = F_t.pad(tensor, pad, **kwargs) + pad_pil_img = F_pil.pad(pil_img, pad, **kwargs) + + pad_tensor_8b = pad_tensor + # we need to cast to uint8 to compare with PIL image + if pad_tensor_8b.dtype != torch.uint8: + pad_tensor_8b = pad_tensor_8b.to(torch.uint8) + + self.compareTensorToPIL(pad_tensor_8b, pad_pil_img, msg="{}, {}".format(pad, kwargs)) + + if isinstance(pad, int): + script_pad = [pad, ] + else: + script_pad = pad + pad_tensor_script = script_fn(tensor, script_pad, **kwargs) + self.assertTrue(pad_tensor.equal(pad_tensor_script), msg="{}, {}".format(pad, kwargs)) + + self._test_fn_on_batch(batch_tensors, F.pad, padding=script_pad, **kwargs) + + def _test_adjust_fn(self, fn, fn_pil, fn_t, configs, tol=2.0 + 1e-10, agg_method="max"): + script_fn = torch.jit.script(fn) + torch.manual_seed(15) + tensor, pil_img = self._create_data(26, 34, device=self.device) + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + + for dt in [None, torch.float32, torch.float64]: + + if dt is not None: + tensor = F.convert_image_dtype(tensor, dt) + batch_tensors = F.convert_image_dtype(batch_tensors, dt) + + for config in configs: + adjusted_tensor = fn_t(tensor, **config) + adjusted_pil = fn_pil(pil_img, **config) + scripted_result = script_fn(tensor, **config) + msg = "{}, {}".format(dt, config) + self.assertEqual(adjusted_tensor.dtype, scripted_result.dtype, msg=msg) + self.assertEqual(adjusted_tensor.size()[1:], adjusted_pil.size[::-1], msg=msg) + + rbg_tensor = adjusted_tensor + + if adjusted_tensor.dtype != torch.uint8: + rbg_tensor = F.convert_image_dtype(adjusted_tensor, torch.uint8) + + # Check that max difference does not exceed 2 in [0, 255] range + # Exact matching is not possible due to incompatibility convert_image_dtype and PIL results + self.approxEqualTensorToPIL(rbg_tensor.float(), adjusted_pil, tol=tol, msg=msg, agg_method=agg_method) + + atol = 1e-6 + if adjusted_tensor.dtype == torch.uint8 and "cuda" in torch.device(self.device).type: + atol = 1.0 + self.assertTrue(adjusted_tensor.allclose(scripted_result, atol=atol), msg=msg) + + self._test_fn_on_batch(batch_tensors, fn, **config) + + def test_adjust_brightness(self): + self._test_adjust_fn( + F.adjust_brightness, + F_pil.adjust_brightness, + F_t.adjust_brightness, + [{"brightness_factor": f} for f in [0.1, 0.5, 1.0, 1.34, 2.5]] + ) + + def test_adjust_contrast(self): + self._test_adjust_fn( + F.adjust_contrast, + F_pil.adjust_contrast, + F_t.adjust_contrast, + [{"contrast_factor": f} for f in [0.2, 0.5, 1.0, 1.5, 2.0]] + ) + + def test_adjust_saturation(self): + self._test_adjust_fn( + F.adjust_saturation, + F_pil.adjust_saturation, + F_t.adjust_saturation, + [{"saturation_factor": f} for f in [0.5, 0.75, 1.0, 1.5, 2.0]] + ) + + def test_adjust_hue(self): + self._test_adjust_fn( + F.adjust_hue, + F_pil.adjust_hue, + F_t.adjust_hue, + [{"hue_factor": f} for f in [-0.45, -0.25, 0.0, 0.25, 0.45]], + tol=16.1, + agg_method="max" + ) + + def test_adjust_gamma(self): + self._test_adjust_fn( + F.adjust_gamma, + F_pil.adjust_gamma, + F_t.adjust_gamma, + [{"gamma": g1, "gain": g2} for g1, g2 in zip([0.8, 1.0, 1.2], [0.7, 1.0, 1.3])] + ) + + def test_resize(self): + script_fn = torch.jit.script(F.resize) + tensor, pil_img = self._create_data(26, 36, device=self.device) + batch_tensors = self._create_data_batch(16, 18, num_samples=4, device=self.device) + + for dt in [None, torch.float32, torch.float64, torch.float16]: + + if dt == torch.float16 and torch.device(self.device).type == "cpu": + # skip float16 on CPU case + continue + + if dt is not None: + # This is a trivial cast to float of uint8 data to test all cases + tensor = tensor.to(dt) + batch_tensors = batch_tensors.to(dt) + + for size in [32, 26, [32, ], [32, 32], (32, 32), [26, 35]]: + for interpolation in [BILINEAR, BICUBIC, NEAREST]: + resized_tensor = F.resize(tensor, size=size, interpolation=interpolation) + resized_pil_img = F.resize(pil_img, size=size, interpolation=interpolation) + + self.assertEqual( + resized_tensor.size()[1:], resized_pil_img.size[::-1], msg="{}, {}".format(size, interpolation) + ) + + if interpolation not in [NEAREST, ]: + # We can not check values if mode = NEAREST, as results are different + # E.g. resized_tensor = [[a, a, b, c, d, d, e, ...]] + # E.g. resized_pil_img = [[a, b, c, c, d, e, f, ...]] + resized_tensor_f = resized_tensor + # we need to cast to uint8 to compare with PIL image + if resized_tensor_f.dtype == torch.uint8: + resized_tensor_f = resized_tensor_f.to(torch.float) + + # Pay attention to high tolerance for MAE + self.approxEqualTensorToPIL( + resized_tensor_f, resized_pil_img, tol=8.0, msg="{}, {}".format(size, interpolation) + ) + + if isinstance(size, int): + script_size = [size, ] + else: + script_size = size + + resize_result = script_fn(tensor, size=script_size, interpolation=interpolation) + self.assertTrue(resized_tensor.equal(resize_result), msg="{}, {}".format(size, interpolation)) + + self._test_fn_on_batch( + batch_tensors, F.resize, size=script_size, interpolation=interpolation + ) + + # assert changed type warning + with self.assertWarnsRegex(UserWarning, r"Argument interpolation should be of type InterpolationMode"): + res1 = F.resize(tensor, size=32, interpolation=2) + res2 = F.resize(tensor, size=32, interpolation=BILINEAR) + self.assertTrue(res1.equal(res2)) + + def test_resized_crop(self): + # test values of F.resized_crop in several cases: + # 1) resize to the same size, crop to the same size => should be identity + tensor, _ = self._create_data(26, 36, device=self.device) + + for mode in [NEAREST, BILINEAR, BICUBIC]: + out_tensor = F.resized_crop(tensor, top=0, left=0, height=26, width=36, size=[26, 36], interpolation=mode) + self.assertTrue(tensor.equal(out_tensor), msg="{} vs {}".format(out_tensor[0, :5, :5], tensor[0, :5, :5])) + + # 2) resize by half and crop a TL corner + tensor, _ = self._create_data(26, 36, device=self.device) + out_tensor = F.resized_crop(tensor, top=0, left=0, height=20, width=30, size=[10, 15], interpolation=NEAREST) + expected_out_tensor = tensor[:, :20:2, :30:2] + self.assertTrue( + expected_out_tensor.equal(out_tensor), + msg="{} vs {}".format(expected_out_tensor[0, :10, :10], out_tensor[0, :10, :10]) + ) + + batch_tensors = self._create_data_batch(26, 36, num_samples=4, device=self.device) + self._test_fn_on_batch( + batch_tensors, F.resized_crop, top=1, left=2, height=20, width=30, size=[10, 15], interpolation=NEAREST + ) + + def _test_affine_identity_map(self, tensor, scripted_affine): + # 1) identity map + out_tensor = F.affine(tensor, angle=0, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], interpolation=NEAREST) + + self.assertTrue( + tensor.equal(out_tensor), msg="{} vs {}".format(out_tensor[0, :5, :5], tensor[0, :5, :5]) + ) + out_tensor = scripted_affine( + tensor, angle=0, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], interpolation=NEAREST + ) + self.assertTrue( + tensor.equal(out_tensor), msg="{} vs {}".format(out_tensor[0, :5, :5], tensor[0, :5, :5]) + ) + + def _test_affine_square_rotations(self, tensor, pil_img, scripted_affine): + # 2) Test rotation + test_configs = [ + (90, torch.rot90(tensor, k=1, dims=(-1, -2))), + (45, None), + (30, None), + (-30, None), + (-45, None), + (-90, torch.rot90(tensor, k=-1, dims=(-1, -2))), + (180, torch.rot90(tensor, k=2, dims=(-1, -2))), + ] + for a, true_tensor in test_configs: + out_pil_img = F.affine( + pil_img, angle=a, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], interpolation=NEAREST + ) + out_pil_tensor = torch.from_numpy(np.array(out_pil_img).transpose((2, 0, 1))).to(self.device) + + for fn in [F.affine, scripted_affine]: + out_tensor = fn( + tensor, angle=a, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], interpolation=NEAREST + ) + if true_tensor is not None: + self.assertTrue( + true_tensor.equal(out_tensor), + msg="{}\n{} vs \n{}".format(a, out_tensor[0, :5, :5], true_tensor[0, :5, :5]) + ) + + if out_tensor.dtype != torch.uint8: + out_tensor = out_tensor.to(torch.uint8) + + num_diff_pixels = (out_tensor != out_pil_tensor).sum().item() / 3.0 + ratio_diff_pixels = num_diff_pixels / out_tensor.shape[-1] / out_tensor.shape[-2] + # Tolerance : less than 6% of different pixels + self.assertLess( + ratio_diff_pixels, + 0.06, + msg="{}\n{} vs \n{}".format( + ratio_diff_pixels, out_tensor[0, :7, :7], out_pil_tensor[0, :7, :7] + ) + ) + + def _test_affine_rect_rotations(self, tensor, pil_img, scripted_affine): + test_configs = [ + 90, 45, 15, -30, -60, -120 + ] + for a in test_configs: + + out_pil_img = F.affine( + pil_img, angle=a, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], interpolation=NEAREST + ) + out_pil_tensor = torch.from_numpy(np.array(out_pil_img).transpose((2, 0, 1))) + + for fn in [F.affine, scripted_affine]: + out_tensor = fn( + tensor, angle=a, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], interpolation=NEAREST + ).cpu() + + if out_tensor.dtype != torch.uint8: + out_tensor = out_tensor.to(torch.uint8) + + num_diff_pixels = (out_tensor != out_pil_tensor).sum().item() / 3.0 + ratio_diff_pixels = num_diff_pixels / out_tensor.shape[-1] / out_tensor.shape[-2] + # Tolerance : less than 3% of different pixels + self.assertLess( + ratio_diff_pixels, + 0.03, + msg="{}: {}\n{} vs \n{}".format( + a, ratio_diff_pixels, out_tensor[0, :7, :7], out_pil_tensor[0, :7, :7] + ) + ) + + def _test_affine_translations(self, tensor, pil_img, scripted_affine): + # 3) Test translation + test_configs = [ + [10, 12], (-12, -13) + ] + for t in test_configs: + + out_pil_img = F.affine(pil_img, angle=0, translate=t, scale=1.0, shear=[0.0, 0.0], interpolation=NEAREST) + + for fn in [F.affine, scripted_affine]: + out_tensor = fn(tensor, angle=0, translate=t, scale=1.0, shear=[0.0, 0.0], interpolation=NEAREST) + + if out_tensor.dtype != torch.uint8: + out_tensor = out_tensor.to(torch.uint8) + + self.compareTensorToPIL(out_tensor, out_pil_img) + + def _test_affine_all_ops(self, tensor, pil_img, scripted_affine): + # 4) Test rotation + translation + scale + share + test_configs = [ + (45, [5, 6], 1.0, [0.0, 0.0]), + (33, (5, -4), 1.0, [0.0, 0.0]), + (45, [-5, 4], 1.2, [0.0, 0.0]), + (33, (-4, -8), 2.0, [0.0, 0.0]), + (85, (10, -10), 0.7, [0.0, 0.0]), + (0, [0, 0], 1.0, [35.0, ]), + (-25, [0, 0], 1.2, [0.0, 15.0]), + (-45, [-10, 0], 0.7, [2.0, 5.0]), + (-45, [-10, -10], 1.2, [4.0, 5.0]), + (-90, [0, 0], 1.0, [0.0, 0.0]), + ] + for r in [NEAREST, ]: + for a, t, s, sh in test_configs: + out_pil_img = F.affine(pil_img, angle=a, translate=t, scale=s, shear=sh, interpolation=r) + out_pil_tensor = torch.from_numpy(np.array(out_pil_img).transpose((2, 0, 1))) + + for fn in [F.affine, scripted_affine]: + out_tensor = fn(tensor, angle=a, translate=t, scale=s, shear=sh, interpolation=r).cpu() + + if out_tensor.dtype != torch.uint8: + out_tensor = out_tensor.to(torch.uint8) + + num_diff_pixels = (out_tensor != out_pil_tensor).sum().item() / 3.0 + ratio_diff_pixels = num_diff_pixels / out_tensor.shape[-1] / out_tensor.shape[-2] + # Tolerance : less than 5% (cpu), 6% (cuda) of different pixels + tol = 0.06 if self.device == "cuda" else 0.05 + self.assertLess( + ratio_diff_pixels, + tol, + msg="{}: {}\n{} vs \n{}".format( + (r, a, t, s, sh), ratio_diff_pixels, out_tensor[0, :7, :7], out_pil_tensor[0, :7, :7] + ) + ) + + def test_affine(self): + # Tests on square and rectangular images + scripted_affine = torch.jit.script(F.affine) + + data = [self._create_data(26, 26, device=self.device), self._create_data(32, 26, device=self.device)] + for tensor, pil_img in data: + + for dt in [None, torch.float32, torch.float64, torch.float16]: + + if dt == torch.float16 and torch.device(self.device).type == "cpu": + # skip float16 on CPU case + continue + + if dt is not None: + tensor = tensor.to(dtype=dt) + + self._test_affine_identity_map(tensor, scripted_affine) + if pil_img.size[0] == pil_img.size[1]: + self._test_affine_square_rotations(tensor, pil_img, scripted_affine) + else: + self._test_affine_rect_rotations(tensor, pil_img, scripted_affine) + self._test_affine_translations(tensor, pil_img, scripted_affine) + self._test_affine_all_ops(tensor, pil_img, scripted_affine) + + batch_tensors = self._create_data_batch(26, 36, num_samples=4, device=self.device) + if dt is not None: + batch_tensors = batch_tensors.to(dtype=dt) + + self._test_fn_on_batch( + batch_tensors, F.affine, angle=-43, translate=[-3, 4], scale=1.2, shear=[4.0, 5.0] + ) + + tensor, pil_img = data[0] + # assert deprecation warning and non-BC + with self.assertWarnsRegex(UserWarning, r"Argument resample is deprecated and will be removed"): + res1 = F.affine(tensor, 45, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], resample=2) + res2 = F.affine(tensor, 45, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], interpolation=BILINEAR) + self.assertTrue(res1.equal(res2)) + + # assert changed type warning + with self.assertWarnsRegex(UserWarning, r"Argument interpolation should be of type InterpolationMode"): + res1 = F.affine(tensor, 45, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], interpolation=2) + res2 = F.affine(tensor, 45, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], interpolation=BILINEAR) + self.assertTrue(res1.equal(res2)) + + with self.assertWarnsRegex(UserWarning, r"Argument fillcolor is deprecated and will be removed"): + res1 = F.affine(pil_img, 45, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], fillcolor=10) + res2 = F.affine(pil_img, 45, translate=[0, 0], scale=1.0, shear=[0.0, 0.0], fill=10) + self.assertEqual(res1, res2) + + def _test_rotate_all_options(self, tensor, pil_img, scripted_rotate, centers): + img_size = pil_img.size + dt = tensor.dtype + for r in [NEAREST, ]: + for a in range(-180, 180, 17): + for e in [True, False]: + for c in centers: + + out_pil_img = F.rotate(pil_img, angle=a, interpolation=r, expand=e, center=c) + out_pil_tensor = torch.from_numpy(np.array(out_pil_img).transpose((2, 0, 1))) + for fn in [F.rotate, scripted_rotate]: + out_tensor = fn(tensor, angle=a, interpolation=r, expand=e, center=c).cpu() + + if out_tensor.dtype != torch.uint8: + out_tensor = out_tensor.to(torch.uint8) + + self.assertEqual( + out_tensor.shape, + out_pil_tensor.shape, + msg="{}: {} vs {}".format( + (img_size, r, dt, a, e, c), out_tensor.shape, out_pil_tensor.shape + ) + ) + num_diff_pixels = (out_tensor != out_pil_tensor).sum().item() / 3.0 + ratio_diff_pixels = num_diff_pixels / out_tensor.shape[-1] / out_tensor.shape[-2] + # Tolerance : less than 3% of different pixels + self.assertLess( + ratio_diff_pixels, + 0.03, + msg="{}: {}\n{} vs \n{}".format( + (img_size, r, dt, a, e, c), + ratio_diff_pixels, + out_tensor[0, :7, :7], + out_pil_tensor[0, :7, :7] + ) + ) + + def test_rotate(self): + # Tests on square image + scripted_rotate = torch.jit.script(F.rotate) + + data = [self._create_data(26, 26, device=self.device), self._create_data(32, 26, device=self.device)] + for tensor, pil_img in data: + + img_size = pil_img.size + centers = [ + None, + (int(img_size[0] * 0.3), int(img_size[0] * 0.4)), + [int(img_size[0] * 0.5), int(img_size[0] * 0.6)] + ] + + for dt in [None, torch.float32, torch.float64, torch.float16]: + + if dt == torch.float16 and torch.device(self.device).type == "cpu": + # skip float16 on CPU case + continue + + if dt is not None: + tensor = tensor.to(dtype=dt) + + self._test_rotate_all_options(tensor, pil_img, scripted_rotate, centers) + + batch_tensors = self._create_data_batch(26, 36, num_samples=4, device=self.device) + if dt is not None: + batch_tensors = batch_tensors.to(dtype=dt) + + center = (20, 22) + self._test_fn_on_batch( + batch_tensors, F.rotate, angle=32, interpolation=NEAREST, expand=True, center=center + ) + tensor, pil_img = data[0] + # assert deprecation warning and non-BC + with self.assertWarnsRegex(UserWarning, r"Argument resample is deprecated and will be removed"): + res1 = F.rotate(tensor, 45, resample=2) + res2 = F.rotate(tensor, 45, interpolation=BILINEAR) + self.assertTrue(res1.equal(res2)) + + # assert changed type warning + with self.assertWarnsRegex(UserWarning, r"Argument interpolation should be of type InterpolationMode"): + res1 = F.rotate(tensor, 45, interpolation=2) + res2 = F.rotate(tensor, 45, interpolation=BILINEAR) + self.assertTrue(res1.equal(res2)) + + def _test_perspective(self, tensor, pil_img, scripted_transform, test_configs): + dt = tensor.dtype + for r in [NEAREST, ]: + for spoints, epoints in test_configs: + out_pil_img = F.perspective(pil_img, startpoints=spoints, endpoints=epoints, interpolation=r) + out_pil_tensor = torch.from_numpy(np.array(out_pil_img).transpose((2, 0, 1))) + + for fn in [F.perspective, scripted_transform]: + out_tensor = fn(tensor, startpoints=spoints, endpoints=epoints, interpolation=r).cpu() + + if out_tensor.dtype != torch.uint8: + out_tensor = out_tensor.to(torch.uint8) + + num_diff_pixels = (out_tensor != out_pil_tensor).sum().item() / 3.0 + ratio_diff_pixels = num_diff_pixels / out_tensor.shape[-1] / out_tensor.shape[-2] + # Tolerance : less than 5% of different pixels + self.assertLess( + ratio_diff_pixels, + 0.05, + msg="{}: {}\n{} vs \n{}".format( + (r, dt, spoints, epoints), + ratio_diff_pixels, + out_tensor[0, :7, :7], + out_pil_tensor[0, :7, :7] + ) + ) + + def test_perspective(self): + + from torchvision.transforms import RandomPerspective + + data = [self._create_data(26, 34, device=self.device), self._create_data(26, 26, device=self.device)] + scripted_transform = torch.jit.script(F.perspective) + + for tensor, pil_img in data: + + test_configs = [ + [[[0, 0], [33, 0], [33, 25], [0, 25]], [[3, 2], [32, 3], [30, 24], [2, 25]]], + [[[3, 2], [32, 3], [30, 24], [2, 25]], [[0, 0], [33, 0], [33, 25], [0, 25]]], + [[[3, 2], [32, 3], [30, 24], [2, 25]], [[5, 5], [30, 3], [33, 19], [4, 25]]], + ] + n = 10 + test_configs += [ + RandomPerspective.get_params(pil_img.size[0], pil_img.size[1], i / n) for i in range(n) + ] + + for dt in [None, torch.float32, torch.float64, torch.float16]: + + if dt == torch.float16 and torch.device(self.device).type == "cpu": + # skip float16 on CPU case + continue + + if dt is not None: + tensor = tensor.to(dtype=dt) + + self._test_perspective(tensor, pil_img, scripted_transform, test_configs) + + batch_tensors = self._create_data_batch(26, 36, num_samples=4, device=self.device) + if dt is not None: + batch_tensors = batch_tensors.to(dtype=dt) + + for spoints, epoints in test_configs: + self._test_fn_on_batch( + batch_tensors, F.perspective, startpoints=spoints, endpoints=epoints, interpolation=NEAREST + ) + + # assert changed type warning + spoints = [[0, 0], [33, 0], [33, 25], [0, 25]] + epoints = [[3, 2], [32, 3], [30, 24], [2, 25]] + with self.assertWarnsRegex(UserWarning, r"Argument interpolation should be of type InterpolationMode"): + res1 = F.perspective(tensor, startpoints=spoints, endpoints=epoints, interpolation=2) + res2 = F.perspective(tensor, startpoints=spoints, endpoints=epoints, interpolation=BILINEAR) + self.assertTrue(res1.equal(res2)) + + def test_gaussian_blur(self): + small_image_tensor = torch.from_numpy( + np.arange(3 * 10 * 12, dtype="uint8").reshape((10, 12, 3)) + ).permute(2, 0, 1).to(self.device) + + large_image_tensor = torch.from_numpy( + np.arange(26 * 28, dtype="uint8").reshape((1, 26, 28)) + ).to(self.device) + + scripted_transform = torch.jit.script(F.gaussian_blur) + + # true_cv2_results = { + # # np_img = np.arange(3 * 10 * 12, dtype="uint8").reshape((10, 12, 3)) + # # cv2.GaussianBlur(np_img, ksize=(3, 3), sigmaX=0.8) + # "3_3_0.8": ... + # # cv2.GaussianBlur(np_img, ksize=(3, 3), sigmaX=0.5) + # "3_3_0.5": ... + # # cv2.GaussianBlur(np_img, ksize=(3, 5), sigmaX=0.8) + # "3_5_0.8": ... + # # cv2.GaussianBlur(np_img, ksize=(3, 5), sigmaX=0.5) + # "3_5_0.5": ... + # # np_img2 = np.arange(26 * 28, dtype="uint8").reshape((26, 28)) + # # cv2.GaussianBlur(np_img2, ksize=(23, 23), sigmaX=1.7) + # "23_23_1.7": ... + # } + p = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'assets', 'gaussian_blur_opencv_results.pt') + true_cv2_results = torch.load(p) + + for tensor in [small_image_tensor, large_image_tensor]: + + for dt in [None, torch.float32, torch.float64, torch.float16]: + if dt == torch.float16 and torch.device(self.device).type == "cpu": + # skip float16 on CPU case + continue + + if dt is not None: + tensor = tensor.to(dtype=dt) + + for ksize in [(3, 3), [3, 5], (23, 23)]: + for sigma in [[0.5, 0.5], (0.5, 0.5), (0.8, 0.8), (1.7, 1.7)]: + + _ksize = (ksize, ksize) if isinstance(ksize, int) else ksize + _sigma = sigma[0] if sigma is not None else None + shape = tensor.shape + gt_key = "{}_{}_{}__{}_{}_{}".format( + shape[-2], shape[-1], shape[-3], + _ksize[0], _ksize[1], _sigma + ) + if gt_key not in true_cv2_results: + continue + + true_out = torch.tensor( + true_cv2_results[gt_key] + ).reshape(shape[-2], shape[-1], shape[-3]).permute(2, 0, 1).to(tensor) + + for fn in [F.gaussian_blur, scripted_transform]: + out = fn(tensor, kernel_size=ksize, sigma=sigma) + self.assertEqual(true_out.shape, out.shape, msg="{}, {}".format(ksize, sigma)) + self.assertLessEqual( + torch.max(true_out.float() - out.float()), + 1.0, + msg="{}, {}".format(ksize, sigma) + ) + + +@unittest.skipIf(not torch.cuda.is_available(), reason="Skip if no CUDA device") +class CUDATester(Tester): + + def setUp(self): + self.device = "cuda" if __name__ == '__main__': diff --git a/test/test_hub.py b/test/test_hub.py index 4ae9e51021b..29ae90014d1 100644 --- a/test/test_hub.py +++ b/test/test_hub.py @@ -13,7 +13,7 @@ def sum_of_model_parameters(model): return s -SUM_OF_PRETRAINED_RESNET18_PARAMS = -12703.99609375 +SUM_OF_PRETRAINED_RESNET18_PARAMS = -12703.9931640625 @unittest.skipIf('torchvision' in sys.modules, @@ -31,8 +31,9 @@ def test_load_from_github(self): 'resnet18', pretrained=True, progress=False) - self.assertEqual(sum_of_model_parameters(hub_model).item(), - SUM_OF_PRETRAINED_RESNET18_PARAMS) + self.assertAlmostEqual(sum_of_model_parameters(hub_model).item(), + SUM_OF_PRETRAINED_RESNET18_PARAMS, + places=2) def test_set_dir(self): temp_dir = tempfile.gettempdir() @@ -42,8 +43,9 @@ def test_set_dir(self): 'resnet18', pretrained=True, progress=False) - self.assertEqual(sum_of_model_parameters(hub_model).item(), - SUM_OF_PRETRAINED_RESNET18_PARAMS) + self.assertAlmostEqual(sum_of_model_parameters(hub_model).item(), + SUM_OF_PRETRAINED_RESNET18_PARAMS, + places=2) self.assertTrue(os.path.exists(temp_dir + '/pytorch_vision_master')) shutil.rmtree(temp_dir + '/pytorch_vision_master') diff --git a/test/test_image.py b/test/test_image.py new file mode 100644 index 00000000000..ebc9a221f6d --- /dev/null +++ b/test/test_image.py @@ -0,0 +1,282 @@ +import glob +import io +import os +import unittest + +import numpy as np +import torch +from PIL import Image +from common_utils import get_tmp_dir + +from torchvision.io.image import ( + decode_png, decode_jpeg, encode_jpeg, write_jpeg, decode_image, read_file, + encode_png, write_png, write_file, ImageReadMode) + +IMAGE_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets") +FAKEDATA_DIR = os.path.join(IMAGE_ROOT, "fakedata") +IMAGE_DIR = os.path.join(FAKEDATA_DIR, "imagefolder") +DAMAGED_JPEG = os.path.join(IMAGE_ROOT, 'damaged_jpeg') +ENCODE_JPEG = os.path.join(IMAGE_ROOT, "encode_jpeg") + + +def get_images(directory, img_ext): + assert os.path.isdir(directory) + image_paths = glob.glob(directory + f'/**/*{img_ext}', recursive=True) + for path in image_paths: + if path.split(os.sep)[-2] not in ['damaged_jpeg', 'jpeg_write']: + yield path + + +def pil_read_image(img_path): + with Image.open(img_path) as img: + return torch.from_numpy(np.array(img)) + + +def normalize_dimensions(img_pil): + if len(img_pil.shape) == 3: + img_pil = img_pil.permute(2, 0, 1) + else: + img_pil = img_pil.unsqueeze(0) + return img_pil + + +class ImageTester(unittest.TestCase): + def test_decode_jpeg(self): + conversion = [(None, ImageReadMode.UNCHANGED), ("L", ImageReadMode.GRAY), ("RGB", ImageReadMode.RGB)] + for img_path in get_images(IMAGE_ROOT, ".jpg"): + for pil_mode, mode in conversion: + with Image.open(img_path) as img: + is_cmyk = img.mode == "CMYK" + if pil_mode is not None: + if is_cmyk: + # libjpeg does not support the conversion + continue + img = img.convert(pil_mode) + img_pil = torch.from_numpy(np.array(img)) + if is_cmyk: + # flip the colors to match libjpeg + img_pil = 255 - img_pil + + img_pil = normalize_dimensions(img_pil) + data = read_file(img_path) + img_ljpeg = decode_image(data, mode=mode) + + # Permit a small variation on pixel values to account for implementation + # differences between Pillow and LibJPEG. + abs_mean_diff = (img_ljpeg.type(torch.float32) - img_pil).abs().mean().item() + self.assertTrue(abs_mean_diff < 2) + + with self.assertRaisesRegex(RuntimeError, "Expected a non empty 1-dimensional tensor"): + decode_jpeg(torch.empty((100, 1), dtype=torch.uint8)) + + with self.assertRaisesRegex(RuntimeError, "Expected a torch.uint8 tensor"): + decode_jpeg(torch.empty((100,), dtype=torch.float16)) + + with self.assertRaises(RuntimeError): + decode_jpeg(torch.empty((100), dtype=torch.uint8)) + + def test_damaged_images(self): + # Test image with bad Huffman encoding (should not raise) + bad_huff = read_file(os.path.join(DAMAGED_JPEG, 'bad_huffman.jpg')) + try: + _ = decode_jpeg(bad_huff) + except RuntimeError: + self.assertTrue(False) + + # Truncated images should raise an exception + truncated_images = glob.glob( + os.path.join(DAMAGED_JPEG, 'corrupt*.jpg')) + for image_path in truncated_images: + data = read_file(image_path) + with self.assertRaises(RuntimeError): + decode_jpeg(data) + + def test_encode_jpeg(self): + for img_path in get_images(ENCODE_JPEG, ".jpg"): + dirname = os.path.dirname(img_path) + filename, _ = os.path.splitext(os.path.basename(img_path)) + write_folder = os.path.join(dirname, 'jpeg_write') + expected_file = os.path.join( + write_folder, '{0}_pil.jpg'.format(filename)) + img = decode_jpeg(read_file(img_path)) + + with open(expected_file, 'rb') as f: + pil_bytes = f.read() + pil_bytes = torch.as_tensor(list(pil_bytes), dtype=torch.uint8) + for src_img in [img, img.contiguous()]: + # PIL sets jpeg quality to 75 by default + jpeg_bytes = encode_jpeg(src_img, quality=75) + self.assertTrue(jpeg_bytes.equal(pil_bytes)) + + with self.assertRaisesRegex( + RuntimeError, "Input tensor dtype should be uint8"): + encode_jpeg(torch.empty((3, 100, 100), dtype=torch.float32)) + + with self.assertRaisesRegex( + ValueError, "Image quality should be a positive number " + "between 1 and 100"): + encode_jpeg(torch.empty((3, 100, 100), dtype=torch.uint8), quality=-1) + + with self.assertRaisesRegex( + ValueError, "Image quality should be a positive number " + "between 1 and 100"): + encode_jpeg(torch.empty((3, 100, 100), dtype=torch.uint8), quality=101) + + with self.assertRaisesRegex( + RuntimeError, "The number of channels should be 1 or 3, got: 5"): + encode_jpeg(torch.empty((5, 100, 100), dtype=torch.uint8)) + + with self.assertRaisesRegex( + RuntimeError, "Input data should be a 3-dimensional tensor"): + encode_jpeg(torch.empty((1, 3, 100, 100), dtype=torch.uint8)) + + with self.assertRaisesRegex( + RuntimeError, "Input data should be a 3-dimensional tensor"): + encode_jpeg(torch.empty((100, 100), dtype=torch.uint8)) + + def test_write_jpeg(self): + with get_tmp_dir() as d: + for img_path in get_images(ENCODE_JPEG, ".jpg"): + data = read_file(img_path) + img = decode_jpeg(data) + + basedir = os.path.dirname(img_path) + filename, _ = os.path.splitext(os.path.basename(img_path)) + torch_jpeg = os.path.join( + d, '{0}_torch.jpg'.format(filename)) + pil_jpeg = os.path.join( + basedir, 'jpeg_write', '{0}_pil.jpg'.format(filename)) + + write_jpeg(img, torch_jpeg, quality=75) + + with open(torch_jpeg, 'rb') as f: + torch_bytes = f.read() + + with open(pil_jpeg, 'rb') as f: + pil_bytes = f.read() + + self.assertEqual(torch_bytes, pil_bytes) + + def test_decode_png(self): + conversion = [(None, ImageReadMode.UNCHANGED), ("L", ImageReadMode.GRAY), ("LA", ImageReadMode.GRAY_ALPHA), + ("RGB", ImageReadMode.RGB), ("RGBA", ImageReadMode.RGB_ALPHA)] + for img_path in get_images(FAKEDATA_DIR, ".png"): + for pil_mode, mode in conversion: + with Image.open(img_path) as img: + if pil_mode is not None: + img = img.convert(pil_mode) + img_pil = torch.from_numpy(np.array(img)) + + img_pil = normalize_dimensions(img_pil) + data = read_file(img_path) + img_lpng = decode_image(data, mode=mode) + + tol = 0 if conversion is None else 1 + self.assertTrue(img_lpng.allclose(img_pil, atol=tol)) + + with self.assertRaises(RuntimeError): + decode_png(torch.empty((), dtype=torch.uint8)) + with self.assertRaises(RuntimeError): + decode_png(torch.randint(3, 5, (300,), dtype=torch.uint8)) + + def test_encode_png(self): + for img_path in get_images(IMAGE_DIR, '.png'): + pil_image = Image.open(img_path) + img_pil = torch.from_numpy(np.array(pil_image)) + img_pil = img_pil.permute(2, 0, 1) + png_buf = encode_png(img_pil, compression_level=6) + + rec_img = Image.open(io.BytesIO(bytes(png_buf.tolist()))) + rec_img = torch.from_numpy(np.array(rec_img)) + rec_img = rec_img.permute(2, 0, 1) + + self.assertTrue(img_pil.equal(rec_img)) + + with self.assertRaisesRegex( + RuntimeError, "Input tensor dtype should be uint8"): + encode_png(torch.empty((3, 100, 100), dtype=torch.float32)) + + with self.assertRaisesRegex( + RuntimeError, "Compression level should be between 0 and 9"): + encode_png(torch.empty((3, 100, 100), dtype=torch.uint8), + compression_level=-1) + + with self.assertRaisesRegex( + RuntimeError, "Compression level should be between 0 and 9"): + encode_png(torch.empty((3, 100, 100), dtype=torch.uint8), + compression_level=10) + + with self.assertRaisesRegex( + RuntimeError, "The number of channels should be 1 or 3, got: 5"): + encode_png(torch.empty((5, 100, 100), dtype=torch.uint8)) + + def test_write_png(self): + with get_tmp_dir() as d: + for img_path in get_images(IMAGE_DIR, '.png'): + pil_image = Image.open(img_path) + img_pil = torch.from_numpy(np.array(pil_image)) + img_pil = img_pil.permute(2, 0, 1) + + filename, _ = os.path.splitext(os.path.basename(img_path)) + torch_png = os.path.join(d, '{0}_torch.png'.format(filename)) + write_png(img_pil, torch_png, compression_level=6) + saved_image = torch.from_numpy(np.array(Image.open(torch_png))) + saved_image = saved_image.permute(2, 0, 1) + + self.assertTrue(img_pil.equal(saved_image)) + + def test_read_file(self): + with get_tmp_dir() as d: + fname, content = 'test1.bin', b'TorchVision\211\n' + fpath = os.path.join(d, fname) + with open(fpath, 'wb') as f: + f.write(content) + + data = read_file(fpath) + expected = torch.tensor(list(content), dtype=torch.uint8) + self.assertTrue(data.equal(expected)) + os.unlink(fpath) + + with self.assertRaisesRegex( + RuntimeError, "No such file or directory: 'tst'"): + read_file('tst') + + def test_read_file_non_ascii(self): + with get_tmp_dir() as d: + fname, content = '日本語(Japanese).bin', b'TorchVision\211\n' + fpath = os.path.join(d, fname) + with open(fpath, 'wb') as f: + f.write(content) + + data = read_file(fpath) + expected = torch.tensor(list(content), dtype=torch.uint8) + self.assertTrue(data.equal(expected)) + os.unlink(fpath) + + def test_write_file(self): + with get_tmp_dir() as d: + fname, content = 'test1.bin', b'TorchVision\211\n' + fpath = os.path.join(d, fname) + content_tensor = torch.tensor(list(content), dtype=torch.uint8) + write_file(fpath, content_tensor) + + with open(fpath, 'rb') as f: + saved_content = f.read() + self.assertEqual(content, saved_content) + os.unlink(fpath) + + def test_write_file_non_ascii(self): + with get_tmp_dir() as d: + fname, content = '日本語(Japanese).bin', b'TorchVision\211\n' + fpath = os.path.join(d, fname) + content_tensor = torch.tensor(list(content), dtype=torch.uint8) + write_file(fpath, content_tensor) + + with open(fpath, 'rb') as f: + saved_content = f.read() + self.assertEqual(content, saved_content) + os.unlink(fpath) + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_io.py b/test/test_io.py index 4b122461a2c..7d752bdbcf7 100644 --- a/test/test_io.py +++ b/test/test_io.py @@ -1,20 +1,16 @@ import os import contextlib +import sys import tempfile import torch -import torchvision.datasets.utils as utils import torchvision.io as io from torchvision import get_video_backend import unittest -import sys import warnings +from urllib.error import URLError from common_utils import get_tmp_dir -if sys.version_info < (3,): - from urllib2 import URLError -else: - from urllib.error import URLError try: import av @@ -70,7 +66,7 @@ def temp_video(num_frames, height, width, fps, lossless=False, video_codec=None, @unittest.skipIf(get_video_backend() != "pyav" and not io._HAS_VIDEO_OPT, "video_reader backend not available") @unittest.skipIf(av is None, "PyAV unavailable") -class Tester(unittest.TestCase): +class TestIO(unittest.TestCase): # compression adds artifacts, thus we add a tolerance of # 6 in 0-255 range TOLERANCE = 6 @@ -151,20 +147,12 @@ def test_read_partial_video_bframes(self): self.assertTrue((data[5:8].float() - lv.float()).abs().max() < self.TOLERANCE) def test_read_packed_b_frames_divx_file(self): - with get_tmp_dir() as temp_dir: - name = "hmdb51_Turnk_r_Pippi_Michel_cartwheel_f_cm_np2_le_med_6.avi" - f_name = os.path.join(temp_dir, name) - url = "https://download.pytorch.org/vision_tests/io/" + name - try: - utils.download_url(url, temp_dir) - pts, fps = io.read_video_timestamps(f_name) - - self.assertEqual(pts, sorted(pts)) - self.assertEqual(fps, 30) - except URLError: - msg = "could not download test file '{}'".format(url) - warnings.warn(msg, RuntimeWarning) - raise unittest.SkipTest(msg) + name = "hmdb51_Turnk_r_Pippi_Michel_cartwheel_f_cm_np2_le_med_6.avi" + f_name = os.path.join(VIDEO_DIR, name) + pts, fps = io.read_video_timestamps(f_name) + + self.assertEqual(pts, sorted(pts)) + self.assertEqual(fps, 30) def test_read_timestamps_from_packet(self): with temp_video(10, 300, 300, 5, video_codec='mpeg4') as (f_name, data): @@ -244,6 +232,7 @@ def test_read_video_timestamps_corrupted_file(self): self.assertEqual(video_pts, []) self.assertIs(video_fps, None) + @unittest.skip("Temporarily disabled due to new pyav") def test_read_video_partially_corrupted_file(self): with temp_video(5, 4, 4, 5, lossless=True) as (f_name, data): with open(f_name, 'r+b') as f: @@ -266,11 +255,12 @@ def test_read_video_partially_corrupted_file(self): # and the last few frames are wrong self.assertFalse(video.equal(data)) + @unittest.skipIf(sys.platform == 'win32', 'temporarily disabled on Windows') def test_write_video_with_audio(self): f_name = os.path.join(VIDEO_DIR, "R6llTwEh07w.mp4") video_tensor, audio_tensor, info = io.read_video(f_name, pts_unit="sec") - with tempfile.TemporaryDirectory() as tmpdir: + with get_tmp_dir() as tmpdir: out_f_name = os.path.join(tmpdir, "testing.mp4") io.video.write_video( out_f_name, diff --git a/test/test_io_opt.py b/test/test_io_opt.py index 1ad3dea8fa2..87698b34624 100644 --- a/test/test_io_opt.py +++ b/test/test_io_opt.py @@ -3,7 +3,8 @@ import test_io -set_video_backend('video_reader') +# Disabling the video backend switching temporarily +# set_video_backend('video_reader') if __name__ == '__main__': diff --git a/test/test_models.py b/test/test_models.py index 056e8eea588..893ed8ab38e 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -1,19 +1,13 @@ -from common_utils import TestCase, map_nested_tensor_object, freeze_rng_state +from common_utils import TestCase, map_nested_tensor_object, freeze_rng_state, set_rng_seed from collections import OrderedDict from itertools import product +import functools +import operator import torch import torch.nn as nn -import numpy as np from torchvision import models import unittest -import traceback -import random - - -def set_rng_seed(seed): - torch.manual_seed(seed) - random.seed(seed) - np.random.seed(seed) +import warnings def get_available_classification_models(): @@ -36,138 +30,201 @@ def get_available_video_models(): return [k for k, v in models.video.__dict__.items() if callable(v) and k[0].lower() == k[0] and k[0] != "_"] -# models that are in torch hub, as well as r3d_18. we tried testing all models -# but the test was too slow. not included are detection models, because -# they are not yet supported in JIT. # If 'unwrapper' is provided it will be called with the script model outputs # before they are compared to the eager model outputs. This is useful if the # model outputs are different between TorchScript / Eager mode -script_test_models = { - 'deeplabv3_resnet50': {}, - 'deeplabv3_resnet101': {}, - 'mobilenet_v2': {}, - 'resnext50_32x4d': {}, - 'fcn_resnet50': {}, - 'fcn_resnet101': {}, - 'googlenet': { - 'unwrapper': lambda x: x.logits - }, - 'densenet121': {}, - 'resnet18': {}, - 'alexnet': {}, - 'shufflenet_v2_x1_0': {}, - 'squeezenet1_0': {}, - 'vgg11': {}, - 'inception_v3': { - 'unwrapper': lambda x: x.logits - }, - 'r3d_18': {}, - "fasterrcnn_resnet50_fpn": { - 'unwrapper': lambda x: x[1] - }, - "maskrcnn_resnet50_fpn": { - 'unwrapper': lambda x: x[1] - }, - "keypointrcnn_resnet50_fpn": { - 'unwrapper': lambda x: x[1] - }, +script_model_unwrapper = { + 'googlenet': lambda x: x.logits, + 'inception_v3': lambda x: x.logits, + "fasterrcnn_resnet50_fpn": lambda x: x[1], + "maskrcnn_resnet50_fpn": lambda x: x[1], + "keypointrcnn_resnet50_fpn": lambda x: x[1], + "retinanet_resnet50_fpn": lambda x: x[1], } -class ModelTester(TestCase): - def checkModule(self, model, name, args): - if name not in script_test_models: - return - unwrapper = script_test_models[name].get('unwrapper', None) - return super(ModelTester, self).checkModule(model, args, unwrapper=unwrapper, skip=False) +# The following models exhibit flaky numerics under autocast in _test_*_model harnesses. +# This may be caused by the harness environment (e.g. num classes, input initialization +# via torch.rand), and does not prove autocast is unsuitable when training with real data +# (autocast has been used successfully with real data for some of these models). +# TODO: investigate why autocast numerics are flaky in the harnesses. +# +# For the following models, _test_*_model harnesses skip numerical checks on outputs when +# trying autocast. However, they still try an autocasted forward pass, so they still ensure +# autocast coverage suffices to prevent dtype errors in each model. +autocast_flaky_numerics = ( + "inception_v3", + "resnet101", + "resnet152", + "wide_resnet101_2", +) - def _test_classification_model(self, name, input_shape): + +class ModelTester(TestCase): + def _test_classification_model(self, name, input_shape, dev): set_rng_seed(0) # passing num_class equal to a number other than 1000 helps in making the test # more enforcing in nature model = models.__dict__[name](num_classes=50) - model.eval() - x = torch.rand(input_shape) + model.eval().to(device=dev) + # RNG always on CPU, to ensure x in cuda tests is bitwise identical to x in cpu tests + x = torch.rand(input_shape).to(device=dev) out = model(x) - self.assertExpected(out, prec=0.1) + self.assertExpected(out.cpu(), prec=0.1, strip_suffix=f"_{dev}") self.assertEqual(out.shape[-1], 50) - self.checkModule(model, name, (x,)) + self.check_jit_scriptable(model, (x,), unwrapper=script_model_unwrapper.get(name, None)) + + if dev == torch.device("cuda"): + with torch.cuda.amp.autocast(): + out = model(x) + # See autocast_flaky_numerics comment at top of file. + if name not in autocast_flaky_numerics: + self.assertExpected(out.cpu(), prec=0.1, strip_suffix=f"_{dev}") + self.assertEqual(out.shape[-1], 50) - def _test_segmentation_model(self, name): + def _test_segmentation_model(self, name, dev): # passing num_class equal to a number other than 1000 helps in making the test # more enforcing in nature model = models.segmentation.__dict__[name](num_classes=50, pretrained_backbone=False) - model.eval() + model.eval().to(device=dev) input_shape = (1, 3, 300, 300) - x = torch.rand(input_shape) + # RNG always on CPU, to ensure x in cuda tests is bitwise identical to x in cpu tests + x = torch.rand(input_shape).to(device=dev) out = model(x) self.assertEqual(tuple(out["out"].shape), (1, 50, 300, 300)) - self.checkModule(model, name, (x,)) + self.check_jit_scriptable(model, (x,), unwrapper=script_model_unwrapper.get(name, None)) + + if dev == torch.device("cuda"): + with torch.cuda.amp.autocast(): + out = model(x) + self.assertEqual(tuple(out["out"].shape), (1, 50, 300, 300)) - def _test_detection_model(self, name): + def _test_detection_model(self, name, dev): set_rng_seed(0) - model = models.detection.__dict__[name](num_classes=50, pretrained_backbone=False) - model.eval() + kwargs = {} + if "retinanet" in name: + # Reduce the default threshold to ensure the returned boxes are not empty. + kwargs["score_thresh"] = 0.01 + model = models.detection.__dict__[name](num_classes=50, pretrained_backbone=False, **kwargs) + model.eval().to(device=dev) input_shape = (3, 300, 300) - x = torch.rand(input_shape) + # RNG always on CPU, to ensure x in cuda tests is bitwise identical to x in cpu tests + x = torch.rand(input_shape).to(device=dev) model_input = [x] out = model(model_input) self.assertIs(model_input[0], x) - self.assertEqual(len(out), 1) - def subsample_tensor(tensor): - num_elems = tensor.numel() - num_samples = 20 - if num_elems <= num_samples: - return tensor - - flat_tensor = tensor.flatten() - ith_index = num_elems // num_samples - return flat_tensor[ith_index - 1::ith_index] - - def compute_mean_std(tensor): - # can't compute mean of integral tensor - tensor = tensor.to(torch.double) - mean = torch.mean(tensor) - std = torch.std(tensor) - return {"mean": mean, "std": std} - - # maskrcnn_resnet_50_fpn numerically unstable across platforms, so for now - # compare results with mean and std - if name == "maskrcnn_resnet50_fpn": - test_value = map_nested_tensor_object(out, tensor_map_fn=compute_mean_std) - # mean values are small, use large prec - self.assertExpected(test_value, prec=.01) - else: - self.assertExpected(map_nested_tensor_object(out, tensor_map_fn=subsample_tensor), prec=0.01) - - scripted_model = torch.jit.script(model) - scripted_model.eval() - scripted_out = scripted_model(model_input)[1] - self.assertEqual(scripted_out[0]["boxes"], out[0]["boxes"]) - self.assertEqual(scripted_out[0]["scores"], out[0]["scores"]) - # labels currently float in script: need to investigate (though same result) - self.assertEqual(scripted_out[0]["labels"].to(dtype=torch.long), out[0]["labels"]) - self.assertTrue("boxes" in out[0]) - self.assertTrue("scores" in out[0]) - self.assertTrue("labels" in out[0]) - # don't check script because we are compiling it here: - # TODO: refactor tests - # self.check_script(model, name) - self.checkModule(model, name, ([x],)) + def check_out(out): + self.assertEqual(len(out), 1) + + def compact(tensor): + size = tensor.size() + elements_per_sample = functools.reduce(operator.mul, size[1:], 1) + if elements_per_sample > 30: + return compute_mean_std(tensor) + else: + return subsample_tensor(tensor) + + def subsample_tensor(tensor): + num_elems = tensor.size(0) + num_samples = 20 + if num_elems <= num_samples: + return tensor + + ith_index = num_elems // num_samples + return tensor[ith_index - 1::ith_index] + + def compute_mean_std(tensor): + # can't compute mean of integral tensor + tensor = tensor.to(torch.double) + mean = torch.mean(tensor) + std = torch.std(tensor) + return {"mean": mean, "std": std} + + output = map_nested_tensor_object(out, tensor_map_fn=compact) + prec = 0.01 + strip_suffix = f"_{dev}" + try: + # We first try to assert the entire output if possible. This is not + # only the best way to assert results but also handles the cases + # where we need to create a new expected result. + self.assertExpected(output, prec=prec, strip_suffix=strip_suffix) + except AssertionError: + # Unfortunately detection models are flaky due to the unstable sort + # in NMS. If matching across all outputs fails, use the same approach + # as in NMSTester.test_nms_cuda to see if this is caused by duplicate + # scores. + expected_file = self._get_expected_file(strip_suffix=strip_suffix) + expected = torch.load(expected_file) + self.assertEqual(output[0]["scores"], expected[0]["scores"], prec=prec) + + # Note: Fmassa proposed turning off NMS by adapting the threshold + # and then using the Hungarian algorithm as in DETR to find the + # best match between output and expected boxes and eliminate some + # of the flakiness. Worth exploring. + return False # Partial validation performed + + return True # Full validation performed + + full_validation = check_out(out) + self.check_jit_scriptable(model, ([x],), unwrapper=script_model_unwrapper.get(name, None)) + + if dev == torch.device("cuda"): + with torch.cuda.amp.autocast(): + out = model(model_input) + # See autocast_flaky_numerics comment at top of file. + if name not in autocast_flaky_numerics: + full_validation &= check_out(out) + + if not full_validation: + msg = "The output of {} could only be partially validated. " \ + "This is likely due to unit-test flakiness, but you may " \ + "want to do additional manual checks if you made " \ + "significant changes to the codebase.".format(self._testMethodName) + warnings.warn(msg, RuntimeWarning) + raise unittest.SkipTest(msg) + + def _test_detection_model_validation(self, name): + set_rng_seed(0) + model = models.detection.__dict__[name](num_classes=50, pretrained_backbone=False) + input_shape = (3, 300, 300) + x = [torch.rand(input_shape)] + + # validate that targets are present in training + self.assertRaises(ValueError, model, x) + + # validate type + targets = [{'boxes': 0.}] + self.assertRaises(ValueError, model, x, targets=targets) - def _test_video_model(self, name): + # validate boxes shape + for boxes in (torch.rand((4,)), torch.rand((1, 5))): + targets = [{'boxes': boxes}] + self.assertRaises(ValueError, model, x, targets=targets) + + # validate that no degenerate boxes are present + boxes = torch.tensor([[1, 3, 1, 4], [2, 4, 3, 4]]) + targets = [{'boxes': boxes}] + self.assertRaises(ValueError, model, x, targets=targets) + + def _test_video_model(self, name, dev): # the default input shape is # bs * num_channels * clip_len * h *w input_shape = (1, 3, 4, 112, 112) # test both basicblock and Bottleneck model = models.video.__dict__[name](num_classes=50) - model.eval() - x = torch.rand(input_shape) + model.eval().to(device=dev) + # RNG always on CPU, to ensure x in cuda tests is bitwise identical to x in cpu tests + x = torch.rand(input_shape).to(device=dev) out = model(x) - self.checkModule(model, name, (x,)) + self.check_jit_scriptable(model, (x,), unwrapper=script_model_unwrapper.get(name, None)) self.assertEqual(out.shape[-1], 50) + if dev == torch.device("cuda"): + with torch.cuda.amp.autocast(): + out = model(x) + self.assertEqual(out.shape[-1], 50) + def _make_sliced_model(self, model, stop_layer): layers = OrderedDict() for name, layer in model.named_children(): @@ -229,6 +286,20 @@ def get_gn(num_channels): self.assertFalse(any(isinstance(x, nn.BatchNorm2d) for x in model.modules())) self.assertTrue(any(isinstance(x, nn.GroupNorm) for x in model.modules())) + def test_inceptionv3_eval(self): + # replacement for models.inception_v3(pretrained=True) that does not download weights + kwargs = {} + kwargs['transform_input'] = True + kwargs['aux_logits'] = True + kwargs['init_weights'] = False + name = "inception_v3" + model = models.Inception3(**kwargs) + model.aux_logits = False + model.AuxLogits = None + model = model.eval() + x = torch.rand(1, 3, 299, 299) + self.check_jit_scriptable(model, (x,), unwrapper=script_model_unwrapper.get(name, None)) + def test_fasterrcnn_double(self): model = models.detection.fasterrcnn_resnet50_fpn(num_classes=50, pretrained_backbone=False) model.double() @@ -243,8 +314,29 @@ def test_fasterrcnn_double(self): self.assertTrue("scores" in out[0]) self.assertTrue("labels" in out[0]) + def test_googlenet_eval(self): + # replacement for models.googlenet(pretrained=True) that does not download weights + kwargs = {} + kwargs['transform_input'] = True + kwargs['aux_logits'] = True + kwargs['init_weights'] = False + name = "googlenet" + model = models.GoogLeNet(**kwargs) + model.aux_logits = False + model.aux1 = None + model.aux2 = None + model = model.eval() + x = torch.rand(1, 3, 224, 224) + self.check_jit_scriptable(model, (x,), unwrapper=script_model_unwrapper.get(name, None)) + @unittest.skipIf(not torch.cuda.is_available(), 'needs GPU') def test_fasterrcnn_switch_devices(self): + def checkOut(out): + self.assertEqual(len(out), 1) + self.assertTrue("boxes" in out[0]) + self.assertTrue("scores" in out[0]) + self.assertTrue("labels" in out[0]) + model = models.detection.fasterrcnn_resnet50_fpn(num_classes=50, pretrained_backbone=False) model.cuda() model.eval() @@ -253,17 +345,20 @@ def test_fasterrcnn_switch_devices(self): model_input = [x] out = model(model_input) self.assertIs(model_input[0], x) - self.assertEqual(len(out), 1) - self.assertTrue("boxes" in out[0]) - self.assertTrue("scores" in out[0]) - self.assertTrue("labels" in out[0]) + + checkOut(out) + + with torch.cuda.amp.autocast(): + out = model(model_input) + + checkOut(out) + # now switch to cpu and make sure it works model.cpu() x = x.cpu() out_cpu = model([x]) - self.assertTrue("boxes" in out_cpu[0]) - self.assertTrue("scores" in out_cpu[0]) - self.assertTrue("labels" in out_cpu[0]) + + checkOut(out_cpu) def test_generalizedrcnn_transform_repr(self): @@ -285,42 +380,53 @@ def test_generalizedrcnn_transform_repr(self): self.assertEqual(t.__repr__(), expected_string) +_devs = [torch.device("cpu"), torch.device("cuda")] if torch.cuda.is_available() else [torch.device("cpu")] + + for model_name in get_available_classification_models(): - # for-loop bodies don't define scopes, so we have to save the variables - # we want to close over in some way - def do_test(self, model_name=model_name): - input_shape = (1, 3, 224, 224) - if model_name in ['inception_v3']: - input_shape = (1, 3, 299, 299) - self._test_classification_model(model_name, input_shape) + for dev in _devs: + # for-loop bodies don't define scopes, so we have to save the variables + # we want to close over in some way + def do_test(self, model_name=model_name, dev=dev): + input_shape = (1, 3, 224, 224) + if model_name in ['inception_v3']: + input_shape = (1, 3, 299, 299) + self._test_classification_model(model_name, input_shape, dev) - setattr(ModelTester, "test_" + model_name, do_test) + setattr(ModelTester, f"test_{model_name}_{dev}", do_test) for model_name in get_available_segmentation_models(): - # for-loop bodies don't define scopes, so we have to save the variables - # we want to close over in some way - def do_test(self, model_name=model_name): - self._test_segmentation_model(model_name) + for dev in _devs: + # for-loop bodies don't define scopes, so we have to save the variables + # we want to close over in some way + def do_test(self, model_name=model_name, dev=dev): + self._test_segmentation_model(model_name, dev) - setattr(ModelTester, "test_" + model_name, do_test) + setattr(ModelTester, f"test_{model_name}_{dev}", do_test) for model_name in get_available_detection_models(): - # for-loop bodies don't define scopes, so we have to save the variables - # we want to close over in some way - def do_test(self, model_name=model_name): - self._test_detection_model(model_name) + for dev in _devs: + # for-loop bodies don't define scopes, so we have to save the variables + # we want to close over in some way + def do_test(self, model_name=model_name, dev=dev): + self._test_detection_model(model_name, dev) - setattr(ModelTester, "test_" + model_name, do_test) + setattr(ModelTester, f"test_{model_name}_{dev}", do_test) + def do_validation_test(self, model_name=model_name): + self._test_detection_model_validation(model_name) -for model_name in get_available_video_models(): + setattr(ModelTester, "test_" + model_name + "_validation", do_validation_test) - def do_test(self, model_name=model_name): - self._test_video_model(model_name) - setattr(ModelTester, "test_" + model_name, do_test) +for model_name in get_available_video_models(): + for dev in _devs: + def do_test(self, model_name=model_name, dev=dev): + self._test_video_model(model_name, dev) + + setattr(ModelTester, f"test_{model_name}_{dev}", do_test) if __name__ == '__main__': unittest.main() diff --git a/test/test_models_detection_anchor_utils.py b/test/test_models_detection_anchor_utils.py new file mode 100644 index 00000000000..872a57c1365 --- /dev/null +++ b/test/test_models_detection_anchor_utils.py @@ -0,0 +1,61 @@ +from collections import OrderedDict +import torch +from common_utils import TestCase +from torchvision.models.detection.anchor_utils import AnchorGenerator +from torchvision.models.detection.image_list import ImageList + + +class Tester(TestCase): + def test_incorrect_anchors(self): + incorrect_sizes = ((2, 4, 8), (32, 8), ) + incorrect_aspects = (0.5, 1.0) + anc = AnchorGenerator(incorrect_sizes, incorrect_aspects) + image1 = torch.randn(3, 800, 800) + image_list = ImageList(image1, [(800, 800)]) + feature_maps = [torch.randn(1, 50)] + self.assertRaises(ValueError, anc, image_list, feature_maps) + + def _init_test_anchor_generator(self): + anchor_sizes = ((10,),) + aspect_ratios = ((1,),) + anchor_generator = AnchorGenerator(anchor_sizes, aspect_ratios) + + return anchor_generator + + def get_features(self, images): + s0, s1 = images.shape[-2:] + features = [torch.rand(2, 8, s0 // 5, s1 // 5)] + return features + + def test_anchor_generator(self): + images = torch.randn(2, 3, 15, 15) + features = self.get_features(images) + image_shapes = [i.shape[-2:] for i in images] + images = ImageList(images, image_shapes) + + model = self._init_test_anchor_generator() + model.eval() + anchors = model(images, features) + + # Estimate the number of target anchors + grid_sizes = [f.shape[-2:] for f in features] + num_anchors_estimated = 0 + for sizes, num_anchors_per_loc in zip(grid_sizes, model.num_anchors_per_location()): + num_anchors_estimated += sizes[0] * sizes[1] * num_anchors_per_loc + + anchors_output = torch.tensor([[-5., -5., 5., 5.], + [0., -5., 10., 5.], + [5., -5., 15., 5.], + [-5., 0., 5., 10.], + [0., 0., 10., 10.], + [5., 0., 15., 10.], + [-5., 5., 5., 15.], + [0., 5., 10., 15.], + [5., 5., 15., 15.]]) + + self.assertEqual(num_anchors_estimated, 9) + self.assertEqual(len(anchors), 2) + self.assertEqual(tuple(anchors[0].shape), (9, 4)) + self.assertEqual(tuple(anchors[1].shape), (9, 4)) + self.assertEqual(anchors[0], anchors_output) + self.assertEqual(anchors[1], anchors_output) diff --git a/test/test_models_detection_negative_samples.py b/test/test_models_detection_negative_samples.py index ed0cc515940..6d767971f72 100644 --- a/test/test_models_detection_negative_samples.py +++ b/test/test_models_detection_negative_samples.py @@ -128,6 +128,15 @@ def test_forward_negative_sample_krcnn(self): self.assertEqual(loss_dict["loss_rpn_box_reg"], torch.tensor(0.)) self.assertEqual(loss_dict["loss_keypoint"], torch.tensor(0.)) + def test_forward_negative_sample_retinanet(self): + model = torchvision.models.detection.retinanet_resnet50_fpn( + num_classes=2, min_size=100, max_size=100) + + images, targets = self._make_empty_sample() + loss_dict = model(images, targets) + + self.assertEqual(loss_dict["bbox_regression"], torch.tensor(0.)) + if __name__ == '__main__': unittest.main() diff --git a/test/test_models_detection_utils.py b/test/test_models_detection_utils.py index fb0b20678d8..bfb26f24eae 100644 --- a/test/test_models_detection_utils.py +++ b/test/test_models_detection_utils.py @@ -1,6 +1,9 @@ +import copy import torch from torchvision.models.detection import _utils +from torchvision.models.detection.transform import GeneralizedRCNNTransform import unittest +from torchvision.models.detection import backbone_utils class Tester(unittest.TestCase): @@ -17,6 +20,44 @@ def test_balanced_positive_negative_sampler(self): self.assertEqual(neg[0].sum(), 3) self.assertEqual(neg[0][0:6].sum(), 3) + def test_resnet_fpn_backbone_frozen_layers(self): + # we know how many initial layers and parameters of the network should + # be frozen for each trainable_backbone_layers parameter value + # i.e all 53 params are frozen if trainable_backbone_layers=0 + # ad first 24 params are frozen if trainable_backbone_layers=2 + expected_frozen_params = {0: 53, 1: 43, 2: 24, 3: 11, 4: 1, 5: 0} + for train_layers, exp_froz_params in expected_frozen_params.items(): + model = backbone_utils.resnet_fpn_backbone( + 'resnet50', pretrained=False, trainable_layers=train_layers) + # boolean list that is true if the param at that index is frozen + is_frozen = [not parameter.requires_grad for _, parameter in model.named_parameters()] + # check that expected initial number of layers are frozen + self.assertTrue(all(is_frozen[:exp_froz_params])) + + def test_validate_resnet_inputs_detection(self): + # default number of backbone layers to train + ret = backbone_utils._validate_resnet_trainable_layers( + pretrained=True, trainable_backbone_layers=None) + self.assertEqual(ret, 3) + # can't go beyond 5 + with self.assertRaises(AssertionError): + ret = backbone_utils._validate_resnet_trainable_layers( + pretrained=True, trainable_backbone_layers=6) + # if not pretrained, should use all trainable layers and warn + with self.assertWarns(UserWarning): + ret = backbone_utils._validate_resnet_trainable_layers( + pretrained=False, trainable_backbone_layers=0) + self.assertEqual(ret, 5) + + def test_transform_copy_targets(self): + transform = GeneralizedRCNNTransform(300, 500, torch.zeros(3), torch.ones(3)) + image = [torch.rand(3, 200, 300), torch.rand(3, 200, 200)] + targets = [{'boxes': torch.rand(3, 4)}, {'boxes': torch.rand(2, 4)}] + targets_copy = copy.deepcopy(targets) + out = transform(image, targets) # noqa: F841 + self.assertTrue(torch.equal(targets[0]['boxes'], targets_copy[0]['boxes'])) + self.assertTrue(torch.equal(targets[1]['boxes'], targets_copy[1]['boxes'])) + if __name__ == '__main__': unittest.main() diff --git a/test/test_onnx.py b/test/test_onnx.py index c34d48a682b..28e11c0e56f 100644 --- a/test/test_onnx.py +++ b/test/test_onnx.py @@ -66,6 +66,7 @@ def to_numpy(tensor): # compute onnxruntime output prediction ort_inputs = dict((ort_session.get_inputs()[i].name, inpt) for i, inpt in enumerate(inputs)) ort_outs = ort_session.run(None, ort_inputs) + for i in range(0, len(outputs)): try: torch.testing.assert_allclose(outputs[i], ort_outs[i], rtol=1e-03, atol=1e-05) @@ -121,6 +122,34 @@ def test_roi_align(self): model = ops.RoIAlign((5, 5), 1, 2) self.run_model(model, [(x, single_roi)]) + def test_roi_align_aligned(self): + x = torch.rand(1, 1, 10, 10, dtype=torch.float32) + single_roi = torch.tensor([[0, 1.5, 1.5, 3, 3]], dtype=torch.float32) + model = ops.RoIAlign((5, 5), 1, 2, aligned=True) + self.run_model(model, [(x, single_roi)]) + + x = torch.rand(1, 1, 10, 10, dtype=torch.float32) + single_roi = torch.tensor([[0, 0.2, 0.3, 4.5, 3.5]], dtype=torch.float32) + model = ops.RoIAlign((5, 5), 0.5, 3, aligned=True) + self.run_model(model, [(x, single_roi)]) + + x = torch.rand(1, 1, 10, 10, dtype=torch.float32) + single_roi = torch.tensor([[0, 0.2, 0.3, 4.5, 3.5]], dtype=torch.float32) + model = ops.RoIAlign((5, 5), 1.8, 2, aligned=True) + self.run_model(model, [(x, single_roi)]) + + x = torch.rand(1, 1, 10, 10, dtype=torch.float32) + single_roi = torch.tensor([[0, 0.2, 0.3, 4.5, 3.5]], dtype=torch.float32) + model = ops.RoIAlign((2, 2), 2.5, 0, aligned=True) + self.run_model(model, [(x, single_roi)]) + + @unittest.skip # Issue in exporting ROIAlign with aligned = True for malformed boxes + def test_roi_align_malformed_boxes(self): + x = torch.randn(1, 1, 10, 10, dtype=torch.float32) + single_roi = torch.tensor([[0, 2, 0.3, 1.5, 1.5]], dtype=torch.float32) + model = ops.RoIAlign((5, 5), 1, 1, aligned=True) + self.run_model(model, [(x, single_roi)]) + def test_roi_pool(self): x = torch.rand(1, 1, 10, 10, dtype=torch.float32) rois = torch.tensor([[0, 0, 0, 4, 4]], dtype=torch.float32) @@ -397,25 +426,25 @@ def test_paste_mask_in_image(self): def test_mask_rcnn(self): images, test_images = self.get_test_images() - dummy_image = [torch.ones(3, 100, 320) * 0.3] + dummy_image = [torch.ones(3, 100, 100) * 0.3] model = models.detection.mask_rcnn.maskrcnn_resnet50_fpn(pretrained=True, min_size=200, max_size=300) model.eval() model(images) # Test exported model on images of different size, or dummy input self.run_model(model, [(images,), (test_images,), (dummy_image,)], input_names=["images_tensors"], - output_names=["boxes", "labels", "scores"], + output_names=["boxes", "labels", "scores", "masks"], dynamic_axes={"images_tensors": [0, 1, 2, 3], "boxes": [0, 1], "labels": [0], "scores": [0], "masks": [0, 1, 2, 3]}, tolerate_small_mismatch=True) # TODO: enable this test once dynamic model export is fixed # Test exported model for an image with no detections on other images - # self.run_model(model, [(images,),(test_images,)], - # input_names=["images_tensors"], - # output_names=["boxes", "labels", "scores"], - # dynamic_axes={"images_tensors": [0, 1, 2, 3], "boxes": [0, 1], "labels": [0], - # "scores": [0], "masks": [0, 1, 2, 3]}, - # tolerate_small_mismatch=True) + self.run_model(model, [(dummy_image,), (images,)], + input_names=["images_tensors"], + output_names=["boxes", "labels", "scores", "masks"], + dynamic_axes={"images_tensors": [0, 1, 2, 3], "boxes": [0, 1], "labels": [0], + "scores": [0], "masks": [0, 1, 2, 3]}, + tolerate_small_mismatch=True) # Verify that heatmaps_to_keypoints behaves the same in tracing. # This test also compares both heatmaps_to_keypoints and _onnx_heatmaps_to_keypoints @@ -446,38 +475,22 @@ def test_heatmaps_to_keypoints(self): assert torch.all(out2[1].eq(out_trace2[1])) def test_keypoint_rcnn(self): - class KeyPointRCNN(torch.nn.Module): - def __init__(self): - super(KeyPointRCNN, self).__init__() - self.model = models.detection.keypoint_rcnn.keypointrcnn_resnet50_fpn(pretrained=True, min_size=200, max_size=300) - - def forward(self, images): - output = self.model(images) - # TODO: The keypoints_scores require the use of Argmax that is updated in ONNX. - # For now we are testing all the output of KeypointRCNN except keypoints_scores. - # Enable When Argmax is updated in ONNX Runtime. - return output[0]['boxes'], output[0]['labels'], output[0]['scores'], output[0]['keypoints'] - images, test_images = self.get_test_images() - # TODO: - # Enable test for dummy_image (no detection) once issue is - # _onnx_heatmaps_to_keypoints_loop for empty heatmaps is fixed - # dummy_images = [torch.ones(3, 100, 100) * 0.3] - model = KeyPointRCNN() + dummy_images = [torch.ones(3, 100, 100) * 0.3] + model = models.detection.keypoint_rcnn.keypointrcnn_resnet50_fpn(pretrained=True, min_size=200, max_size=300) model.eval() model(images) - self.run_model(model, [(images,), (test_images,)], + self.run_model(model, [(images,), (test_images,), (dummy_images,)], + input_names=["images_tensors"], + output_names=["outputs1", "outputs2", "outputs3", "outputs4"], + dynamic_axes={"images_tensors": [0, 1, 2, 3]}, + tolerate_small_mismatch=True) + + self.run_model(model, [(dummy_images,), (test_images,)], input_names=["images_tensors"], output_names=["outputs1", "outputs2", "outputs3", "outputs4"], dynamic_axes={"images_tensors": [0, 1, 2, 3]}, tolerate_small_mismatch=True) - # TODO: enable this test once dynamic model export is fixed - # Test exported model for an image with no detections on other images - # self.run_model(model, [(dummy_images,), (test_images,)], - # input_names=["images_tensors"], - # output_names=["outputs1", "outputs2", "outputs3", "outputs4"], - # dynamic_axes={"images_tensors": [0, 1, 2, 3]}, - # tolerate_small_mismatch=True) if __name__ == '__main__': diff --git a/test/test_ops.py b/test/test_ops.py index 120ecc4de2d..68e6a5d2825 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -1,3 +1,4 @@ +from common_utils import set_rng_seed import math import unittest @@ -52,25 +53,30 @@ def _test_backward(self, device, contiguous): class RoIOpTester(OpTester): - def _test_forward(self, device, contiguous): + def _test_forward(self, device, contiguous, x_dtype=None, rois_dtype=None): + x_dtype = self.dtype if x_dtype is None else x_dtype + rois_dtype = self.dtype if rois_dtype is None else rois_dtype pool_size = 5 # n_channels % (pool_size ** 2) == 0 required for PS opeartions. n_channels = 2 * (pool_size ** 2) - x = torch.rand(2, n_channels, 10, 10, dtype=self.dtype, device=device) + x = torch.rand(2, n_channels, 10, 10, dtype=x_dtype, device=device) if not contiguous: x = x.permute(0, 1, 3, 2) rois = torch.tensor([[0, 0, 0, 9, 9], # format is (xyxy) [0, 0, 5, 4, 9], [0, 5, 5, 9, 9], [1, 0, 0, 9, 9]], - dtype=self.dtype, device=device) + dtype=rois_dtype, device=device) pool_h, pool_w = pool_size, pool_size y = self.fn(x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1) + # the following should be true whether we're running an autocast test or not. + self.assertTrue(y.dtype == x.dtype) gt_y = self.expected_fn(x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, device=device, dtype=self.dtype) - self.assertTrue(torch.allclose(gt_y, y)) + tol = 1e-3 if (x_dtype is torch.half or rois_dtype is torch.half) else 1e-5 + self.assertTrue(torch.allclose(gt_y.to(y.dtype), y, rtol=tol, atol=tol)) def _test_backward(self, device, contiguous): pool_size = 2 @@ -115,6 +121,13 @@ def get_script_fn(*args, **kwargs): def expected_fn(*args, **kwargs): pass + @unittest.skipIf(not torch.cuda.is_available(), "CUDA unavailable") + def test_autocast(self): + for x_dtype in (torch.float, torch.half): + for rois_dtype in (torch.float, torch.half): + with torch.cuda.amp.autocast(): + self._test_forward(torch.device("cuda"), contiguous=False, x_dtype=x_dtype, rois_dtype=rois_dtype) + class RoIPoolTester(RoIOpTester, unittest.TestCase): def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwargs): @@ -345,6 +358,20 @@ def _test_boxes_shape(self): self._helper_boxes_shape(ops.ps_roi_align) +class MultiScaleRoIAlignTester(unittest.TestCase): + def test_msroialign_repr(self): + fmap_names = ['0'] + output_size = (7, 7) + sampling_ratio = 2 + # Pass mock feature map names + t = ops.poolers.MultiScaleRoIAlign(fmap_names, output_size, sampling_ratio) + + # Check integrity of object __repr__ attribute + expected_string = (f"MultiScaleRoIAlign(featmap_names={fmap_names}, output_size={output_size}, " + f"sampling_ratio={sampling_ratio})") + self.assertEqual(t.__repr__(), expected_string) + + class NMSTester(unittest.TestCase): def reference_nms(self, boxes, scores, iou_threshold): """ @@ -374,10 +401,14 @@ def _create_tensors_with_iou(self, N, iou_thresh): # let b0 be [x0, y0, x1, y1], and b1 be [x0, y0, x1 + d, y1], # then, in order to satisfy ops.iou(b0, b1) == iou_thresh, # we need to have d = (x1 - x0) * (1 - iou_thresh) / iou_thresh + # Adjust the threshold upward a bit with the intent of creating + # at least one box that exceeds (barely) the threshold and so + # should be suppressed. boxes = torch.rand(N, 4) * 100 boxes[:, 2:] += boxes[:, :2] boxes[-1, :] = boxes[0, :] x0, y0, x1, y1 = boxes[-1].tolist() + iou_thresh += 1e-5 boxes[-1, 2] += (x1 - x0) * (1 - iou_thresh) / iou_thresh scores = torch.rand(N) return boxes, scores @@ -389,9 +420,14 @@ def test_nms(self): keep_ref = self.reference_nms(boxes, scores, iou) keep = ops.nms(boxes, scores, iou) self.assertTrue(torch.allclose(keep, keep_ref), err_msg.format(iou)) + self.assertRaises(RuntimeError, ops.nms, torch.rand(4), torch.rand(3), 0.5) + self.assertRaises(RuntimeError, ops.nms, torch.rand(3, 5), torch.rand(3), 0.5) + self.assertRaises(RuntimeError, ops.nms, torch.rand(3, 4), torch.rand(3, 2), 0.5) + self.assertRaises(RuntimeError, ops.nms, torch.rand(3, 4), torch.rand(4), 0.5) @unittest.skipIf(not torch.cuda.is_available(), "CUDA unavailable") - def test_nms_cuda(self): + def test_nms_cuda(self, dtype=torch.float64): + tol = 1e-3 if dtype is torch.half else 1e-5 err_msg = 'NMS incompatible between CPU and CUDA for IoU={}' for iou in [0.2, 0.5, 0.8]: @@ -399,7 +435,18 @@ def test_nms_cuda(self): r_cpu = ops.nms(boxes, scores, iou) r_cuda = ops.nms(boxes.cuda(), scores.cuda(), iou) - self.assertTrue(torch.allclose(r_cpu, r_cuda.cpu()), err_msg.format(iou)) + is_eq = torch.allclose(r_cpu, r_cuda.cpu()) + if not is_eq: + # if the indices are not the same, ensure that it's because the scores + # are duplicate + is_eq = torch.allclose(scores[r_cpu], scores[r_cuda.cpu()], rtol=tol, atol=tol) + self.assertTrue(is_eq, err_msg.format(iou)) + + @unittest.skipIf(not torch.cuda.is_available(), "CUDA unavailable") + def test_autocast(self): + for dtype in (torch.float, torch.half): + with torch.cuda.amp.autocast(): + self.test_nms_cuda(dtype=dtype) class NewEmptyTensorTester(unittest.TestCase): @@ -412,7 +459,7 @@ def test_new_empty_tensor(self): class DeformConvTester(OpTester, unittest.TestCase): - def expected_fn(self, x, weight, offset, bias, stride=1, padding=0, dilation=1): + def expected_fn(self, x, weight, offset, mask, bias, stride=1, padding=0, dilation=1): stride_h, stride_w = _pair(stride) pad_h, pad_w = _pair(padding) dil_h, dil_w = _pair(dilation) @@ -443,18 +490,22 @@ def expected_fn(self, x, weight, offset, bias, stride=1, padding=0, dilation=1): c_in = weight_grp * in_c_per_weight_grp + c offset_grp = c_in // in_c_per_offset_grp - offset_idx = 2 * (offset_grp * (weight_h * weight_w) + di * weight_w + dj) + mask_idx = offset_grp * (weight_h * weight_w) + di * weight_w + dj + offset_idx = 2 * mask_idx pi = stride_h * i - pad_h + dil_h * di + offset[b, offset_idx, i, j] pj = stride_w * j - pad_w + dil_w * dj + offset[b, offset_idx + 1, i, j] - out[b, c_out, i, j] += (weight[c_out, c, di, dj] * + mask_value = 1.0 + if mask is not None: + mask_value = mask[b, mask_idx, i, j] + + out[b, c_out, i, j] += (mask_value * weight[c_out, c, di, dj] * bilinear_interpolate(x[b, c_in, :, :], pi, pj)) out += bias.view(1, n_out_channels, 1, 1) return out - def get_fn_args(self, device, contiguous): - batch_sz = 33 + def get_fn_args(self, device, contiguous, batch_sz, dtype): n_in_channels = 6 n_out_channels = 2 n_weight_grps = 2 @@ -473,71 +524,360 @@ def get_fn_args(self, device, contiguous): out_h = (in_h + 2 * pad_h - (dil_h * (weight_h - 1) + 1)) // stride_h + 1 out_w = (in_w + 2 * pad_w - (dil_w * (weight_w - 1) + 1)) // stride_w + 1 - x = torch.rand(batch_sz, n_in_channels, in_h, in_w, device=device, dtype=self.dtype, requires_grad=True) + x = torch.rand(batch_sz, n_in_channels, in_h, in_w, device=device, dtype=dtype, requires_grad=True) offset = torch.randn(batch_sz, n_offset_grps * 2 * weight_h * weight_w, out_h, out_w, - device=device, dtype=self.dtype, requires_grad=True) + device=device, dtype=dtype, requires_grad=True) + + mask = torch.randn(batch_sz, n_offset_grps * weight_h * weight_w, out_h, out_w, + device=device, dtype=dtype, requires_grad=True) weight = torch.randn(n_out_channels, n_in_channels // n_weight_grps, weight_h, weight_w, - device=device, dtype=self.dtype, requires_grad=True) + device=device, dtype=dtype, requires_grad=True) - bias = torch.randn(n_out_channels, device=device, dtype=self.dtype, requires_grad=True) + bias = torch.randn(n_out_channels, device=device, dtype=dtype, requires_grad=True) if not contiguous: x = x.permute(0, 1, 3, 2).contiguous().permute(0, 1, 3, 2) offset = offset.permute(1, 3, 0, 2).contiguous().permute(2, 0, 3, 1) + mask = mask.permute(1, 3, 0, 2).contiguous().permute(2, 0, 3, 1) weight = weight.permute(3, 2, 0, 1).contiguous().permute(2, 3, 1, 0) - return x, weight, offset, bias, stride, pad, dilation + return x, weight, offset, mask, bias, stride, pad, dilation - def _test_forward(self, device, contiguous): - x, _, offset, _, stride, padding, dilation = self.get_fn_args(device, contiguous) + def _test_forward(self, device, contiguous, dtype=None): + dtype = self.dtype if dtype is None else dtype + for batch_sz in [0, 33]: + self._test_forward_with_batchsize(device, contiguous, batch_sz, dtype) + + def _test_forward_with_batchsize(self, device, contiguous, batch_sz, dtype): + x, _, offset, mask, _, stride, padding, dilation = self.get_fn_args(device, contiguous, batch_sz, dtype) in_channels = 6 out_channels = 2 kernel_size = (3, 2) groups = 2 + tol = 1e-3 if dtype is torch.half else 1e-5 layer = ops.DeformConv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, - dilation=dilation, groups=groups).to(device=x.device, dtype=x.dtype) - res = layer(x, offset) + dilation=dilation, groups=groups).to(device=x.device, dtype=dtype) + res = layer(x, offset, mask) weight = layer.weight.data bias = layer.bias.data - expected = self.expected_fn(x, weight, offset, bias, stride=stride, padding=padding, dilation=dilation) + expected = self.expected_fn(x, weight, offset, mask, bias, stride=stride, padding=padding, dilation=dilation) + + self.assertTrue(torch.allclose(res.to(expected.dtype), expected, rtol=tol, atol=tol), + '\nres:\n{}\nexpected:\n{}'.format(res, expected)) + + # no modulation test + res = layer(x, offset) + expected = self.expected_fn(x, weight, offset, None, bias, stride=stride, padding=padding, dilation=dilation) - self.assertTrue(torch.allclose(res, expected), '\nres:\n{}\nexpected:\n{}'.format(res, expected)) + self.assertTrue(torch.allclose(res.to(expected.dtype), expected, rtol=tol, atol=tol), + '\nres:\n{}\nexpected:\n{}'.format(res, expected)) # test for wrong sizes with self.assertRaises(RuntimeError): wrong_offset = torch.rand_like(offset[:, :2]) res = layer(x, wrong_offset) + with self.assertRaises(RuntimeError): + wrong_mask = torch.rand_like(mask[:, :2]) + res = layer(x, offset, wrong_mask) + def _test_backward(self, device, contiguous): - x, weight, offset, bias, stride, padding, dilation = self.get_fn_args(device, contiguous) + for batch_sz in [0, 33]: + self._test_backward_with_batchsize(device, contiguous, batch_sz) + + def _test_backward_with_batchsize(self, device, contiguous, batch_sz): + x, weight, offset, mask, bias, stride, padding, dilation = self.get_fn_args(device, contiguous, + batch_sz, self.dtype) + + def func(x_, offset_, mask_, weight_, bias_): + return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride, + padding=padding, dilation=dilation, mask=mask_) + + gradcheck(func, (x, offset, mask, weight, bias), nondet_tol=1e-5) - def func(x_, offset_, weight_, bias_): - return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride, padding=padding, dilation=dilation) + def func_no_mask(x_, offset_, weight_, bias_): + return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride, + padding=padding, dilation=dilation, mask=None) - gradcheck(func, (x, offset, weight, bias), nondet_tol=1e-5) + gradcheck(func_no_mask, (x, offset, weight, bias), nondet_tol=1e-5) @torch.jit.script - def script_func(x_, offset_, weight_, bias_, stride_, pad_, dilation_): - # type: (Tensor, Tensor, Tensor, Tensor, Tuple[int, int], Tuple[int, int], Tuple[int, int]) -> Tensor - return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride_, padding=pad_, dilation=dilation_) + def script_func(x_, offset_, mask_, weight_, bias_, stride_, pad_, dilation_): + # type:(Tensor, Tensor, Tensor, Tensor, Tensor, Tuple[int, int], Tuple[int, int], Tuple[int, int])->Tensor + return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride_, + padding=pad_, dilation=dilation_, mask=mask_) - gradcheck(lambda z, off, wei, bi: script_func(z, off, wei, bi, stride, padding, dilation), + gradcheck(lambda z, off, msk, wei, bi: script_func(z, off, msk, wei, bi, stride, padding, dilation), + (x, offset, mask, weight, bias), nondet_tol=1e-5) + + @torch.jit.script + def script_func_no_mask(x_, offset_, weight_, bias_, stride_, pad_, dilation_): + # type:(Tensor, Tensor, Tensor, Tensor, Tuple[int, int], Tuple[int, int], Tuple[int, int])->Tensor + return ops.deform_conv2d(x_, offset_, weight_, bias_, stride=stride_, + padding=pad_, dilation=dilation_, mask=None) + + gradcheck(lambda z, off, wei, bi: script_func_no_mask(z, off, wei, bi, stride, padding, dilation), (x, offset, weight, bias), nondet_tol=1e-5) + # Test from https://github.com/pytorch/vision/issues/2598 + # Run on CUDA only + if "cuda" in device.type: + # compare grads computed on CUDA with grads computed on CPU + true_cpu_grads = None + + init_weight = torch.randn(9, 9, 3, 3, requires_grad=True) + img = torch.randn(8, 9, 1000, 110) + offset = torch.rand(8, 2 * 3 * 3, 1000, 110) + mask = torch.rand(8, 3 * 3, 1000, 110) + + if not contiguous: + img = img.permute(0, 1, 3, 2).contiguous().permute(0, 1, 3, 2) + offset = offset.permute(1, 3, 0, 2).contiguous().permute(2, 0, 3, 1) + mask = mask.permute(1, 3, 0, 2).contiguous().permute(2, 0, 3, 1) + weight = init_weight.permute(3, 2, 0, 1).contiguous().permute(2, 3, 1, 0) + else: + weight = init_weight + + for d in ["cpu", "cuda"]: + + out = ops.deform_conv2d(img.to(d), offset.to(d), weight.to(d), padding=1, mask=mask.to(d)) + out.mean().backward() + if true_cpu_grads is None: + true_cpu_grads = init_weight.grad + self.assertTrue(true_cpu_grads is not None) + else: + self.assertTrue(init_weight.grad is not None) + res_grads = init_weight.grad.to("cpu") + self.assertTrue(true_cpu_grads.allclose(res_grads)) + + @unittest.skipIf(not torch.cuda.is_available(), "CUDA unavailable") + def test_autocast(self): + set_rng_seed(0) + for dtype in (torch.float, torch.half): + with torch.cuda.amp.autocast(): + self._test_forward(torch.device("cuda"), False, dtype=dtype) + class FrozenBNTester(unittest.TestCase): def test_frozenbatchnorm2d_repr(self): num_features = 32 - t = ops.misc.FrozenBatchNorm2d(num_features) + eps = 1e-5 + t = ops.misc.FrozenBatchNorm2d(num_features, eps=eps) # Check integrity of object __repr__ attribute - expected_string = f"FrozenBatchNorm2d({num_features})" + expected_string = f"FrozenBatchNorm2d({num_features}, eps={eps})" self.assertEqual(t.__repr__(), expected_string) + def test_frozenbatchnorm2d_eps(self): + sample_size = (4, 32, 28, 28) + x = torch.rand(sample_size) + state_dict = dict(weight=torch.rand(sample_size[1]), + bias=torch.rand(sample_size[1]), + running_mean=torch.rand(sample_size[1]), + running_var=torch.rand(sample_size[1]), + num_batches_tracked=torch.tensor(100)) + + # Check that default eps is equal to the one of BN + fbn = ops.misc.FrozenBatchNorm2d(sample_size[1]) + fbn.load_state_dict(state_dict, strict=False) + bn = torch.nn.BatchNorm2d(sample_size[1]).eval() + bn.load_state_dict(state_dict) + # Difference is expected to fall in an acceptable range + self.assertTrue(torch.allclose(fbn(x), bn(x), atol=1e-6)) + + # Check computation for eps > 0 + fbn = ops.misc.FrozenBatchNorm2d(sample_size[1], eps=1e-5) + fbn.load_state_dict(state_dict, strict=False) + bn = torch.nn.BatchNorm2d(sample_size[1], eps=1e-5).eval() + bn.load_state_dict(state_dict) + self.assertTrue(torch.allclose(fbn(x), bn(x), atol=1e-6)) + + def test_frozenbatchnorm2d_n_arg(self): + """Ensure a warning is thrown when passing `n` kwarg + (remove this when support of `n` is dropped)""" + self.assertWarns(DeprecationWarning, ops.misc.FrozenBatchNorm2d, 32, eps=1e-5, n=32) + + +class BoxConversionTester(unittest.TestCase): + @staticmethod + def _get_box_sequences(): + # Define here the argument type of `boxes` supported by region pooling operations + box_tensor = torch.tensor([[0, 0, 0, 100, 100], [1, 0, 0, 100, 100]], dtype=torch.float) + box_list = [torch.tensor([[0, 0, 100, 100]], dtype=torch.float), + torch.tensor([[0, 0, 100, 100]], dtype=torch.float)] + box_tuple = tuple(box_list) + return box_tensor, box_list, box_tuple + + def test_check_roi_boxes_shape(self): + # Ensure common sequences of tensors are supported + for box_sequence in self._get_box_sequences(): + self.assertIsNone(ops._utils.check_roi_boxes_shape(box_sequence)) + + def test_convert_boxes_to_roi_format(self): + # Ensure common sequences of tensors yield the same result + ref_tensor = None + for box_sequence in self._get_box_sequences(): + if ref_tensor is None: + ref_tensor = box_sequence + else: + self.assertTrue(torch.equal(ref_tensor, ops._utils.convert_boxes_to_roi_format(box_sequence))) + + +class BoxTester(unittest.TestCase): + def test_bbox_same(self): + box_tensor = torch.tensor([[0, 0, 100, 100], [0, 0, 0, 0], + [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) + + exp_xyxy = torch.tensor([[0, 0, 100, 100], [0, 0, 0, 0], + [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) + + box_same = ops.box_convert(box_tensor, in_fmt="xyxy", out_fmt="xyxy") + self.assertEqual(exp_xyxy.size(), torch.Size([4, 4])) + self.assertEqual(exp_xyxy.dtype, box_tensor.dtype) + assert torch.all(torch.eq(box_same, exp_xyxy)).item() + + box_same = ops.box_convert(box_tensor, in_fmt="xywh", out_fmt="xywh") + self.assertEqual(exp_xyxy.size(), torch.Size([4, 4])) + self.assertEqual(exp_xyxy.dtype, box_tensor.dtype) + assert torch.all(torch.eq(box_same, exp_xyxy)).item() + + box_same = ops.box_convert(box_tensor, in_fmt="cxcywh", out_fmt="cxcywh") + self.assertEqual(exp_xyxy.size(), torch.Size([4, 4])) + self.assertEqual(exp_xyxy.dtype, box_tensor.dtype) + assert torch.all(torch.eq(box_same, exp_xyxy)).item() + + def test_bbox_xyxy_xywh(self): + # Simple test convert boxes to xywh and back. Make sure they are same. + # box_tensor is in x1 y1 x2 y2 format. + box_tensor = torch.tensor([[0, 0, 100, 100], [0, 0, 0, 0], + [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) + exp_xywh = torch.tensor([[0, 0, 100, 100], [0, 0, 0, 0], + [10, 15, 20, 20], [23, 35, 70, 60]], dtype=torch.float) + + box_xywh = ops.box_convert(box_tensor, in_fmt="xyxy", out_fmt="xywh") + self.assertEqual(exp_xywh.size(), torch.Size([4, 4])) + self.assertEqual(exp_xywh.dtype, box_tensor.dtype) + assert torch.all(torch.eq(box_xywh, exp_xywh)).item() + + # Reverse conversion + box_xyxy = ops.box_convert(box_xywh, in_fmt="xywh", out_fmt="xyxy") + self.assertEqual(box_xyxy.size(), torch.Size([4, 4])) + self.assertEqual(box_xyxy.dtype, box_tensor.dtype) + assert torch.all(torch.eq(box_xyxy, box_tensor)).item() + + def test_bbox_xyxy_cxcywh(self): + # Simple test convert boxes to xywh and back. Make sure they are same. + # box_tensor is in x1 y1 x2 y2 format. + box_tensor = torch.tensor([[0, 0, 100, 100], [0, 0, 0, 0], + [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) + exp_cxcywh = torch.tensor([[50, 50, 100, 100], [0, 0, 0, 0], + [20, 25, 20, 20], [58, 65, 70, 60]], dtype=torch.float) + + box_cxcywh = ops.box_convert(box_tensor, in_fmt="xyxy", out_fmt="cxcywh") + self.assertEqual(exp_cxcywh.size(), torch.Size([4, 4])) + self.assertEqual(exp_cxcywh.dtype, box_tensor.dtype) + assert torch.all(torch.eq(box_cxcywh, exp_cxcywh)).item() + + # Reverse conversion + box_xyxy = ops.box_convert(box_cxcywh, in_fmt="cxcywh", out_fmt="xyxy") + self.assertEqual(box_xyxy.size(), torch.Size([4, 4])) + self.assertEqual(box_xyxy.dtype, box_tensor.dtype) + assert torch.all(torch.eq(box_xyxy, box_tensor)).item() + + def test_bbox_xywh_cxcywh(self): + box_tensor = torch.tensor([[0, 0, 100, 100], [0, 0, 0, 0], + [10, 15, 20, 20], [23, 35, 70, 60]], dtype=torch.float) + + # This is wrong + exp_cxcywh = torch.tensor([[50, 50, 100, 100], [0, 0, 0, 0], + [20, 25, 20, 20], [58, 65, 70, 60]], dtype=torch.float) + + box_cxcywh = ops.box_convert(box_tensor, in_fmt="xywh", out_fmt="cxcywh") + self.assertEqual(exp_cxcywh.size(), torch.Size([4, 4])) + self.assertEqual(exp_cxcywh.dtype, box_tensor.dtype) + assert torch.all(torch.eq(box_cxcywh, exp_cxcywh)).item() + + # Reverse conversion + box_xywh = ops.box_convert(box_cxcywh, in_fmt="cxcywh", out_fmt="xywh") + self.assertEqual(box_xywh.size(), torch.Size([4, 4])) + self.assertEqual(box_xywh.dtype, box_tensor.dtype) + assert torch.all(torch.eq(box_xywh, box_tensor)).item() + + def test_bbox_invalid(self): + box_tensor = torch.tensor([[0, 0, 100, 100], [0, 0, 0, 0], + [10, 15, 20, 20], [23, 35, 70, 60]], dtype=torch.float) + + invalid_infmts = ["xwyh", "cxwyh"] + invalid_outfmts = ["xwcx", "xhwcy"] + for inv_infmt in invalid_infmts: + for inv_outfmt in invalid_outfmts: + self.assertRaises(ValueError, ops.box_convert, box_tensor, inv_infmt, inv_outfmt) + + def test_bbox_convert_jit(self): + box_tensor = torch.tensor([[0, 0, 100, 100], [0, 0, 0, 0], + [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) + + scripted_fn = torch.jit.script(ops.box_convert) + TOLERANCE = 1e-3 + + box_xywh = ops.box_convert(box_tensor, in_fmt="xyxy", out_fmt="xywh") + scripted_xywh = scripted_fn(box_tensor, 'xyxy', 'xywh') + self.assertTrue((scripted_xywh - box_xywh).abs().max() < TOLERANCE) + + box_cxcywh = ops.box_convert(box_tensor, in_fmt="xyxy", out_fmt="cxcywh") + scripted_cxcywh = scripted_fn(box_tensor, 'xyxy', 'cxcywh') + self.assertTrue((scripted_cxcywh - box_cxcywh).abs().max() < TOLERANCE) + + +class BoxAreaTester(unittest.TestCase): + def test_box_area(self): + # A bounding box of area 10000 and a degenerate case + box_tensor = torch.tensor([[0, 0, 100, 100], [0, 0, 0, 0]], dtype=torch.float) + expected = torch.tensor([10000, 0]) + calc_area = ops.box_area(box_tensor) + assert calc_area.size() == torch.Size([2]) + assert calc_area.dtype == box_tensor.dtype + assert torch.all(torch.eq(calc_area, expected)).item() is True + + +class BoxIouTester(unittest.TestCase): + def test_iou(self): + # Boxes to test Iou + boxes1 = torch.tensor([[0, 0, 100, 100], [0, 0, 50, 50], [200, 200, 300, 300]], dtype=torch.float) + boxes2 = torch.tensor([[0, 0, 100, 100], [0, 0, 50, 50], [200, 200, 300, 300]], dtype=torch.float) + + # Expected IoU matrix for these boxes + expected = torch.tensor([[1.0, 0.25, 0.0], [0.25, 1.0, 0.0], [0.0, 0.0, 1.0]]) + + out = ops.box_iou(boxes1, boxes2) + + # Check if all elements of tensor are as expected. + assert out.size() == torch.Size([3, 3]) + tolerance = 1e-4 + assert ((out - expected).abs().max() < tolerance).item() is True + + +class GenBoxIouTester(unittest.TestCase): + def test_gen_iou(self): + # Test Generalized IoU + boxes1 = torch.tensor([[0, 0, 100, 100], [0, 0, 50, 50], [200, 200, 300, 300]], dtype=torch.float) + boxes2 = torch.tensor([[0, 0, 100, 100], [0, 0, 50, 50], [200, 200, 300, 300]], dtype=torch.float) + + # Expected gIoU matrix for these boxes + expected = torch.tensor([[1.0, 0.25, -0.7778], [0.25, 1.0, -0.8611], + [-0.7778, -0.8611, 1.0]]) + + out = ops.generalized_box_iou(boxes1, boxes2) + + # Check if all elements of tensor are as expected. + assert out.size() == torch.Size([3, 3]) + tolerance = 1e-4 + assert ((out - expected).abs().max() < tolerance).item() is True + if __name__ == '__main__': unittest.main() diff --git a/test/test_transforms.py b/test/test_transforms.py index 99317dcc41b..8a0762327f9 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -1,9 +1,10 @@ import os -import mock import torch import torchvision.transforms as transforms import torchvision.transforms.functional as F +import torchvision.transforms.functional_tensor as F_t from torch._utils_internal import get_file_path_2 +from numpy.testing import assert_array_almost_equal import unittest import math import random @@ -19,8 +20,11 @@ except ImportError: stats = None +from common_utils import cycle_over, int_dtypes, float_dtypes + + GRACE_HOPPER = get_file_path_2( - os.path.dirname(os.path.abspath(__file__)), 'assets', 'grace_hopper_517x606.jpg') + os.path.dirname(os.path.abspath(__file__)), 'assets', 'encode_jpeg', 'grace_hopper_517x606.jpg') class Tester(unittest.TestCase): @@ -175,49 +179,100 @@ def test_randomperspective(self): self.assertGreater(torch.nn.functional.mse_loss(tr_img, F.to_tensor(img)) + 0.3, torch.nn.functional.mse_loss(tr_img2, F.to_tensor(img))) + def test_randomperspective_fill(self): + height = 100 + width = 100 + img = torch.ones(3, height, width) + to_pil_image = transforms.ToPILImage() + img = to_pil_image(img) + + modes = ("L", "RGB", "F") + nums_bands = [len(mode) for mode in modes] + fill = 127 + + for mode, num_bands in zip(modes, nums_bands): + img_conv = img.convert(mode) + perspective = transforms.RandomPerspective(p=1, fill=fill) + tr_img = perspective(img_conv) + pixel = tr_img.getpixel((0, 0)) + + if not isinstance(pixel, tuple): + pixel = (pixel,) + self.assertTupleEqual(pixel, tuple([fill] * num_bands)) + + for mode, num_bands in zip(modes, nums_bands): + img_conv = img.convert(mode) + startpoints, endpoints = transforms.RandomPerspective.get_params(width, height, 0.5) + tr_img = F.perspective(img_conv, startpoints, endpoints, fill=fill) + pixel = tr_img.getpixel((0, 0)) + + if not isinstance(pixel, tuple): + pixel = (pixel,) + self.assertTupleEqual(pixel, tuple([fill] * num_bands)) + + for wrong_num_bands in set(nums_bands) - {num_bands}: + with self.assertRaises(ValueError): + F.perspective(img_conv, startpoints, endpoints, fill=tuple([fill] * wrong_num_bands)) + def test_resize(self): - height = random.randint(24, 32) * 2 - width = random.randint(24, 32) * 2 - osize = random.randint(5, 12) * 2 - img = torch.ones(3, height, width) - result = transforms.Compose([ - transforms.ToPILImage(), - transforms.Resize(osize), - transforms.ToTensor(), - ])(img) - self.assertIn(osize, result.size()) - if height < width: - self.assertLessEqual(result.size(1), result.size(2)) - elif width < height: - self.assertGreaterEqual(result.size(1), result.size(2)) + input_sizes = [ + # height, width + # square image + (28, 28), + (27, 27), + # rectangular image: h < w + (28, 34), + (29, 35), + # rectangular image: h > w + (34, 28), + (35, 29), + ] + test_output_sizes_1 = [ + # single integer + 22, 27, 28, 36, + # single integer in tuple/list + [22, ], (27, ), + ] + test_output_sizes_2 = [ + # two integers + [22, 22], [22, 28], [22, 36], + [27, 22], [36, 22], [28, 28], + [28, 37], [37, 27], [37, 37] + ] + + for height, width in input_sizes: + img = Image.new("RGB", size=(width, height), color=127) + + for osize in test_output_sizes_1: + + t = transforms.Resize(osize) + result = t(img) + + msg = "{}, {} - {}".format(height, width, osize) + osize = osize[0] if isinstance(osize, (list, tuple)) else osize + # If size is an int, smaller edge of the image will be matched to this number. + # i.e, if height > width, then image will be rescaled to (size * height / width, size). + if height < width: + expected_size = (int(osize * width / height), osize) # (w, h) + self.assertEqual(result.size, expected_size, msg=msg) + elif width < height: + expected_size = (osize, int(osize * height / width)) # (w, h) + self.assertEqual(result.size, expected_size, msg=msg) + else: + expected_size = (osize, osize) # (w, h) + self.assertEqual(result.size, expected_size, msg=msg) - result = transforms.Compose([ - transforms.ToPILImage(), - transforms.Resize([osize, osize]), - transforms.ToTensor(), - ])(img) - self.assertIn(osize, result.size()) - self.assertEqual(result.size(1), osize) - self.assertEqual(result.size(2), osize) + for height, width in input_sizes: + img = Image.new("RGB", size=(width, height), color=127) - oheight = random.randint(5, 12) * 2 - owidth = random.randint(5, 12) * 2 - result = transforms.Compose([ - transforms.ToPILImage(), - transforms.Resize((oheight, owidth)), - transforms.ToTensor(), - ])(img) - self.assertEqual(result.size(1), oheight) - self.assertEqual(result.size(2), owidth) + for osize in test_output_sizes_2: + oheight, owidth = osize - result = transforms.Compose([ - transforms.ToPILImage(), - transforms.Resize([oheight, owidth]), - transforms.ToTensor(), - ])(img) - self.assertEqual(result.size(1), oheight) - self.assertEqual(result.size(2), owidth) + t = transforms.Resize(osize) + result = t(img) + + self.assertEqual((owidth, oheight), result.size) def test_random_crop(self): height = random.randint(10, 32) * 2 @@ -259,18 +314,32 @@ def test_random_crop(self): self.assertEqual(result.size(1), height + 1) self.assertEqual(result.size(2), width + 1) + t = transforms.RandomCrop(48) + img = torch.ones(3, 32, 32) + with self.assertRaisesRegex(ValueError, r"Required crop size .+ is larger then input image size .+"): + t(img) + def test_pad(self): height = random.randint(10, 32) * 2 width = random.randint(10, 32) * 2 img = torch.ones(3, height, width) padding = random.randint(1, 20) + fill = random.randint(1, 50) result = transforms.Compose([ transforms.ToPILImage(), - transforms.Pad(padding), + transforms.Pad(padding, fill=fill), transforms.ToTensor(), ])(img) self.assertEqual(result.size(1), height + 2 * padding) self.assertEqual(result.size(2), width + 2 * padding) + # check that all elements in the padded region correspond + # to the pad value + fill_v = fill / 255 + eps = 1e-5 + self.assertTrue((result[:, :padding, :] - fill_v).abs().max() < eps) + self.assertTrue((result[:, :, :padding] - fill_v).abs().max() < eps) + self.assertRaises(ValueError, transforms.Pad(padding, fill=(1, 2)), + transforms.ToPILImage()(img)) def test_pad_with_tuple_of_pad_values(self): height = random.randint(10, 32) * 2 @@ -320,6 +389,16 @@ def test_pad_with_non_constant_padding_modes(self): self.assertTrue(np.all(symmetric_middle_slice == np.asarray([0, 1, 200, 200, 1, 0]))) self.assertEqual(transforms.ToTensor()(symmetric_padded_img).size(), (3, 32, 34)) + # Check negative padding explicitly for symmetric case, since it is not + # implemented for tensor case to compare to + # Crop 1 to left, pad 2 to top, pad 3 to right, crop 3 to bottom + symmetric_padded_img_neg = F.pad(img, (-1, 2, 3, -3), padding_mode='symmetric') + symmetric_neg_middle_left = np.asarray(symmetric_padded_img_neg).transpose(2, 0, 1)[0][17][:3] + symmetric_neg_middle_right = np.asarray(symmetric_padded_img_neg).transpose(2, 0, 1)[0][17][-4:] + self.assertTrue(np.all(symmetric_neg_middle_left == np.asarray([1, 0, 0]))) + self.assertTrue(np.all(symmetric_neg_middle_right == np.asarray([200, 200, 0, 0]))) + self.assertEqual(transforms.ToTensor()(symmetric_padded_img_neg).size(), (3, 28, 31)) + def test_pad_raises_with_invalid_pad_sequence_len(self): with self.assertRaises(ValueError): transforms.Pad(()) @@ -330,6 +409,14 @@ def test_pad_raises_with_invalid_pad_sequence_len(self): with self.assertRaises(ValueError): transforms.Pad((1, 2, 3, 4, 5)) + def test_pad_with_mode_F_images(self): + pad = 2 + transform = transforms.Pad(pad) + + img = Image.new("F", (10, 10)) + padded_img = transform(img) + self.assertSequenceEqual(padded_img.size, [edge_size + 2 * pad for edge_size in img.size]) + def test_lambda(self): trans = transforms.Lambda(lambda x: x.add(10)) x = torch.randn(10) @@ -466,6 +553,134 @@ def test_to_tensor(self): output = trans(img) self.assertTrue(np.allclose(input_data.numpy(), output.numpy())) + def test_max_value(self): + for dtype in int_dtypes(): + self.assertEqual(F_t._max_value(dtype), torch.iinfo(dtype).max) + + # remove float testing as it can lead to errors such as + # runtime error: 5.7896e+76 is outside the range of representable values of type 'float' + # for dtype in float_dtypes(): + # self.assertGreater(F_t._max_value(dtype), torch.finfo(dtype).max) + + def test_convert_image_dtype_float_to_float(self): + for input_dtype, output_dtypes in cycle_over(float_dtypes()): + input_image = torch.tensor((0.0, 1.0), dtype=input_dtype) + for output_dtype in output_dtypes: + with self.subTest(input_dtype=input_dtype, output_dtype=output_dtype): + transform = transforms.ConvertImageDtype(output_dtype) + transform_script = torch.jit.script(F.convert_image_dtype) + + output_image = transform(input_image) + output_image_script = transform_script(input_image, output_dtype) + + script_diff = output_image_script - output_image + self.assertLess(script_diff.abs().max(), 1e-6) + + actual_min, actual_max = output_image.tolist() + desired_min, desired_max = 0.0, 1.0 + + self.assertAlmostEqual(actual_min, desired_min) + self.assertAlmostEqual(actual_max, desired_max) + + def test_convert_image_dtype_float_to_int(self): + for input_dtype in float_dtypes(): + input_image = torch.tensor((0.0, 1.0), dtype=input_dtype) + for output_dtype in int_dtypes(): + with self.subTest(input_dtype=input_dtype, output_dtype=output_dtype): + transform = transforms.ConvertImageDtype(output_dtype) + transform_script = torch.jit.script(F.convert_image_dtype) + + if (input_dtype == torch.float32 and output_dtype in (torch.int32, torch.int64)) or ( + input_dtype == torch.float64 and output_dtype == torch.int64 + ): + with self.assertRaises(RuntimeError): + transform(input_image) + else: + output_image = transform(input_image) + output_image_script = transform_script(input_image, output_dtype) + + script_diff = output_image_script - output_image + self.assertLess(script_diff.abs().max(), 1e-6) + + actual_min, actual_max = output_image.tolist() + desired_min, desired_max = 0, torch.iinfo(output_dtype).max + + self.assertEqual(actual_min, desired_min) + self.assertEqual(actual_max, desired_max) + + def test_convert_image_dtype_int_to_float(self): + for input_dtype in int_dtypes(): + input_image = torch.tensor((0, torch.iinfo(input_dtype).max), dtype=input_dtype) + for output_dtype in float_dtypes(): + with self.subTest(input_dtype=input_dtype, output_dtype=output_dtype): + transform = transforms.ConvertImageDtype(output_dtype) + transform_script = torch.jit.script(F.convert_image_dtype) + + output_image = transform(input_image) + output_image_script = transform_script(input_image, output_dtype) + + script_diff = output_image_script - output_image + self.assertLess(script_diff.abs().max(), 1e-6) + + actual_min, actual_max = output_image.tolist() + desired_min, desired_max = 0.0, 1.0 + + self.assertAlmostEqual(actual_min, desired_min) + self.assertGreaterEqual(actual_min, desired_min) + self.assertAlmostEqual(actual_max, desired_max) + self.assertLessEqual(actual_max, desired_max) + + def test_convert_image_dtype_int_to_int(self): + for input_dtype, output_dtypes in cycle_over(int_dtypes()): + input_max = torch.iinfo(input_dtype).max + input_image = torch.tensor((0, input_max), dtype=input_dtype) + for output_dtype in output_dtypes: + output_max = torch.iinfo(output_dtype).max + + with self.subTest(input_dtype=input_dtype, output_dtype=output_dtype): + transform = transforms.ConvertImageDtype(output_dtype) + transform_script = torch.jit.script(F.convert_image_dtype) + + output_image = transform(input_image) + output_image_script = transform_script(input_image, output_dtype) + + script_diff = output_image_script.float() - output_image.float() + self.assertLess( + script_diff.abs().max(), 1e-6, msg="{} vs {}".format(output_image_script, output_image) + ) + + actual_min, actual_max = output_image.tolist() + desired_min, desired_max = 0, output_max + + # see https://github.com/pytorch/vision/pull/2078#issuecomment-641036236 for details + if input_max >= output_max: + error_term = 0 + else: + error_term = 1 - (torch.iinfo(output_dtype).max + 1) // (torch.iinfo(input_dtype).max + 1) + + self.assertEqual(actual_min, desired_min) + self.assertEqual(actual_max, desired_max + error_term) + + def test_convert_image_dtype_int_to_int_consistency(self): + for input_dtype, output_dtypes in cycle_over(int_dtypes()): + input_max = torch.iinfo(input_dtype).max + input_image = torch.tensor((0, input_max), dtype=input_dtype) + for output_dtype in output_dtypes: + output_max = torch.iinfo(output_dtype).max + if output_max <= input_max: + continue + + with self.subTest(input_dtype=input_dtype, output_dtype=output_dtype): + transform = transforms.ConvertImageDtype(output_dtype) + inverse_transfrom = transforms.ConvertImageDtype(input_dtype) + output_image = inverse_transfrom(transform(input_image)) + + actual_min, actual_max = output_image.tolist() + desired_min, desired_max = 0, input_max + + self.assertEqual(actual_min, desired_min) + self.assertEqual(actual_max, desired_max) + @unittest.skipIf(accimage is None, 'accimage not available') def test_accimage_to_tensor(self): trans = transforms.ToTensor() @@ -476,6 +691,49 @@ def test_accimage_to_tensor(self): self.assertEqual(expected_output.size(), output.size()) self.assertTrue(np.allclose(output.numpy(), expected_output.numpy())) + def test_pil_to_tensor(self): + test_channels = [1, 3, 4] + height, width = 4, 4 + trans = transforms.PILToTensor() + + with self.assertRaises(TypeError): + trans(np.random.rand(1, height, width).tolist()) + trans(np.random.rand(1, height, width)) + + for channels in test_channels: + input_data = torch.ByteTensor(channels, height, width).random_(0, 255) + img = transforms.ToPILImage()(input_data) + output = trans(img) + self.assertTrue(np.allclose(input_data.numpy(), output.numpy())) + + input_data = np.random.randint(low=0, high=255, size=(height, width, channels)).astype(np.uint8) + img = transforms.ToPILImage()(input_data) + output = trans(img) + expected_output = input_data.transpose((2, 0, 1)) + self.assertTrue(np.allclose(output.numpy(), expected_output)) + + input_data = torch.as_tensor(np.random.rand(channels, height, width).astype(np.float32)) + img = transforms.ToPILImage()(input_data) # CHW -> HWC and (* 255).byte() + output = trans(img) # HWC -> CHW + expected_output = (input_data * 255).byte() + self.assertTrue(np.allclose(output.numpy(), expected_output.numpy())) + + # separate test for mode '1' PIL images + input_data = torch.ByteTensor(1, height, width).bernoulli_() + img = transforms.ToPILImage()(input_data.mul(255)).convert('1') + output = trans(img) + self.assertTrue(np.allclose(input_data.numpy(), output.numpy())) + + @unittest.skipIf(accimage is None, 'accimage not available') + def test_accimage_pil_to_tensor(self): + trans = transforms.PILToTensor() + + expected_output = trans(Image.open(GRACE_HOPPER).convert('RGB')) + output = trans(accimage.Image(GRACE_HOPPER)) + + self.assertEqual(expected_output.size(), output.size()) + self.assertTrue(np.allclose(output.numpy(), expected_output.numpy())) + @unittest.skipIf(accimage is None, 'accimage not available') def test_accimage_resize(self): trans = transforms.Compose([ @@ -731,19 +989,27 @@ def test_2d_ndarray_to_pil_image(self): self.assertTrue(np.allclose(img_data, img)) def test_tensor_bad_types_to_pil_image(self): - with self.assertRaises(ValueError): + with self.assertRaisesRegex(ValueError, r'pic should be 2/3 dimensional. Got \d+ dimensions.'): transforms.ToPILImage()(torch.ones(1, 3, 4, 4)) + with self.assertRaisesRegex(ValueError, r'pic should not have > 4 channels. Got \d+ channels.'): + transforms.ToPILImage()(torch.ones(6, 4, 4)) def test_ndarray_bad_types_to_pil_image(self): trans = transforms.ToPILImage() - with self.assertRaises(TypeError): + reg_msg = r'Input type \w+ is not supported' + with self.assertRaisesRegex(TypeError, reg_msg): trans(np.ones([4, 4, 1], np.int64)) + with self.assertRaisesRegex(TypeError, reg_msg): trans(np.ones([4, 4, 1], np.uint16)) + with self.assertRaisesRegex(TypeError, reg_msg): trans(np.ones([4, 4, 1], np.uint32)) + with self.assertRaisesRegex(TypeError, reg_msg): trans(np.ones([4, 4, 1], np.float64)) - with self.assertRaises(ValueError): + with self.assertRaisesRegex(ValueError, r'pic should be 2/3 dimensional. Got \d+ dimensions.'): transforms.ToPILImage()(np.ones([1, 4, 4, 3])) + with self.assertRaisesRegex(ValueError, r'pic should not have > 4 channels. Got \d+ channels.'): + transforms.ToPILImage()(np.ones([4, 4, 6])) @unittest.skipIf(stats is None, 'scipy.stats not available') def test_random_vertical_flip(self): @@ -842,6 +1108,24 @@ def test_normalize_different_dtype(self): # checks that it doesn't crash transforms.functional.normalize(img, mean, std) + def test_normalize_3d_tensor(self): + torch.manual_seed(28) + n_channels = 3 + img_size = 10 + mean = torch.rand(n_channels) + std = torch.rand(n_channels) + img = torch.rand(n_channels, img_size, img_size) + target = F.normalize(img, mean, std).numpy() + + mean_unsqueezed = mean.view(-1, 1, 1) + std_unsqueezed = std.view(-1, 1, 1) + result1 = F.normalize(img, mean_unsqueezed, std_unsqueezed) + result2 = F.normalize(img, + mean_unsqueezed.repeat(1, img_size, img_size), + std_unsqueezed.repeat(1, img_size, img_size)) + assert_array_almost_equal(target, result1.numpy()) + assert_array_almost_equal(target, result2.numpy()) + def test_adjust_brightness(self): x_shape = [2, 2, 3] x_data = [0, 5, 13, 54, 135, 226, 37, 8, 234, 90, 255, 1] @@ -964,14 +1248,14 @@ def test_adjust_gamma(self): # test 1 y_pil = F.adjust_gamma(x_pil, 0.5) y_np = np.array(y_pil) - y_ans = [0, 35, 57, 117, 185, 240, 97, 45, 244, 151, 255, 15] + y_ans = [0, 35, 57, 117, 186, 241, 97, 45, 245, 152, 255, 16] y_ans = np.array(y_ans, dtype=np.uint8).reshape(x_shape) self.assertTrue(np.allclose(y_np, y_ans)) # test 2 y_pil = F.adjust_gamma(x_pil, 2) y_np = np.array(y_pil) - y_ans = [0, 0, 0, 11, 71, 200, 5, 0, 214, 31, 255, 0] + y_ans = [0, 0, 0, 11, 71, 201, 5, 0, 215, 31, 255, 0] y_ans = np.array(y_ans, dtype=np.uint8).reshape(x_shape) self.assertTrue(np.allclose(y_np, y_ans)) @@ -1043,7 +1327,7 @@ def test_rotate(self): x = np.zeros((100, 100, 3), dtype=np.uint8) x[40, 40] = [255, 255, 255] - with self.assertRaises(TypeError): + with self.assertRaisesRegex(TypeError, r"img should be PIL Image"): F.rotate(x, 10) img = F.to_pil_image(x) @@ -1096,17 +1380,14 @@ def test_rotate_fill(self): def test_affine(self): input_img = np.zeros((40, 40, 3), dtype=np.uint8) - pts = [] cnt = [20, 20] for pt in [(16, 16), (20, 16), (20, 20)]: for i in range(-5, 5): for j in range(-5, 5): input_img[pt[0] + i, pt[1] + j, :] = [255, 155, 55] - pts.append((pt[0] + i, pt[1] + j)) - pts = list(set(pts)) - with self.assertRaises(TypeError): - F.affine(input_img, 10) + with self.assertRaises(TypeError, msg="Argument translate should be a sequence"): + F.affine(input_img, 10, translate=0, scale=1, shear=1) pil_img = F.to_pil_image(input_img) @@ -1158,9 +1439,12 @@ def _test_transformation(a, t, s, sh): inv_true_matrix = np.linalg.inv(true_matrix) for y in range(true_result.shape[0]): for x in range(true_result.shape[1]): - res = np.dot(inv_true_matrix, [x, y, 1]) - _x = int(res[0] + 0.5) - _y = int(res[1] + 0.5) + # Same as for PIL: + # https://github.com/python-pillow/Pillow/blob/71f8ec6a0cfc1008076a023c0756542539d057ab/ + # src/libImaging/Geometry.c#L1060 + input_pt = np.array([x + 0.5, y + 0.5, 1.0]) + res = np.floor(np.dot(inv_true_matrix, input_pt)).astype(np.int) + _x, _y = res[:2] if 0 <= _x < input_img.shape[1] and 0 <= _y < input_img.shape[0]: true_result[y, x, :] = input_img[_y, _x, :] @@ -1193,7 +1477,7 @@ def _test_transformation(a, t, s, sh): # Test rotation, scale, translation, shear for a in range(-90, 90, 25): for t1 in range(-10, 10, 5): - for s in [0.75, 0.98, 1.0, 1.1, 1.2]: + for s in [0.75, 0.98, 1.0, 1.2, 1.4]: for sh in range(-15, 15, 5): _test_transformation(a=a, t=(t1, t1), s=s, sh=(sh, sh)) @@ -1210,11 +1494,21 @@ def test_random_rotation(self): t = transforms.RandomRotation((-10, 10)) angle = t.get_params(t.degrees) - self.assertTrue(angle > -10 and angle < 10) + self.assertTrue(-10 < angle < 10) # Checking if RandomRotation can be printed as string t.__repr__() + # assert deprecation warning and non-BC + with self.assertWarnsRegex(UserWarning, r"Argument resample is deprecated and will be removed"): + t = transforms.RandomRotation((-10, 10), resample=2) + self.assertEqual(t.interpolation, transforms.InterpolationMode.BILINEAR) + + # assert changed type warning + with self.assertWarnsRegex(UserWarning, r"Argument interpolation should be of type InterpolationMode"): + t = transforms.RandomRotation((-10, 10), interpolation=2) + self.assertEqual(t.interpolation, transforms.InterpolationMode.BILINEAR) + def test_random_affine(self): with self.assertRaises(ValueError): @@ -1255,8 +1549,22 @@ def test_random_affine(self): # Checking if RandomAffine can be printed as string t.__repr__() - t = transforms.RandomAffine(10, resample=Image.BILINEAR) - self.assertIn("Image.BILINEAR", t.__repr__()) + t = transforms.RandomAffine(10, interpolation=transforms.InterpolationMode.BILINEAR) + self.assertIn("bilinear", t.__repr__()) + + # assert deprecation warning and non-BC + with self.assertWarnsRegex(UserWarning, r"Argument resample is deprecated and will be removed"): + t = transforms.RandomAffine(10, resample=2) + self.assertEqual(t.interpolation, transforms.InterpolationMode.BILINEAR) + + with self.assertWarnsRegex(UserWarning, r"Argument fillcolor is deprecated and will be removed"): + t = transforms.RandomAffine(10, fillcolor=10) + self.assertEqual(t.fill, 10) + + # assert changed type warning + with self.assertWarnsRegex(UserWarning, r"Argument interpolation should be of type InterpolationMode"): + t = transforms.RandomAffine(10, interpolation=2) + self.assertEqual(t.interpolation, transforms.InterpolationMode.BILINEAR) def test_to_grayscale(self): """Unit tests for grayscale transform""" @@ -1401,40 +1709,47 @@ def test_random_grayscale(self): # Checking if RandomGrayscale can be printed as string trans3.__repr__() - def test_random_erasing(self): - """Unit tests for random erasing transform""" - - img = torch.rand([3, 60, 60]) - - # Test Set 1: Erasing with int value - img_re = transforms.RandomErasing(value=0.2) - i, j, h, w, v = img_re.get_params(img, scale=img_re.scale, ratio=img_re.ratio, value=img_re.value) - img_output = F.erase(img, i, j, h, w, v) - self.assertEqual(img_output.size(0), 3) - - # Test Set 2: Check if the unerased region is preserved - orig_unerased = img.clone() - orig_unerased[:, i:i + h, j:j + w] = 0 - output_unerased = img_output.clone() - output_unerased[:, i:i + h, j:j + w] = 0 - self.assertTrue(torch.equal(orig_unerased, output_unerased)) - - # Test Set 3: Erasing with random value - img_re = transforms.RandomErasing(value='random')(img) - self.assertEqual(img_re.size(0), 3) - - # Test Set 4: Erasing with tuple value - img_re = transforms.RandomErasing(value=(0.2, 0.2, 0.2))(img) - self.assertEqual(img_re.size(0), 3) - - # Test Set 5: Testing the inplace behaviour - img_re = transforms.RandomErasing(value=(0.2), inplace=True)(img) - self.assertTrue(torch.equal(img_re, img)) - - # Test Set 6: Checking when no erased region is selected - img = torch.rand([3, 300, 1]) - img_re = transforms.RandomErasing(ratio=(0.1, 0.2), value='random')(img) - self.assertTrue(torch.equal(img_re, img)) + def test_gaussian_blur_asserts(self): + np_img = np.ones((100, 100, 3), dtype=np.uint8) * 255 + img = F.to_pil_image(np_img, "RGB") + + with self.assertRaisesRegex(ValueError, r"If kernel_size is a sequence its length should be 2"): + F.gaussian_blur(img, [3]) + + with self.assertRaisesRegex(ValueError, r"If kernel_size is a sequence its length should be 2"): + F.gaussian_blur(img, [3, 3, 3]) + with self.assertRaisesRegex(ValueError, r"Kernel size should be a tuple/list of two integers"): + transforms.GaussianBlur([3, 3, 3]) + + with self.assertRaisesRegex(ValueError, r"kernel_size should have odd and positive integers"): + F.gaussian_blur(img, [4, 4]) + with self.assertRaisesRegex(ValueError, r"Kernel size value should be an odd and positive number"): + transforms.GaussianBlur([4, 4]) + + with self.assertRaisesRegex(ValueError, r"kernel_size should have odd and positive integers"): + F.gaussian_blur(img, [-3, -3]) + with self.assertRaisesRegex(ValueError, r"Kernel size value should be an odd and positive number"): + transforms.GaussianBlur([-3, -3]) + + with self.assertRaisesRegex(ValueError, r"If sigma is a sequence, its length should be 2"): + F.gaussian_blur(img, 3, [1, 1, 1]) + with self.assertRaisesRegex(ValueError, r"sigma should be a single number or a list/tuple with length 2"): + transforms.GaussianBlur(3, [1, 1, 1]) + + with self.assertRaisesRegex(ValueError, r"sigma should have positive values"): + F.gaussian_blur(img, 3, -1.0) + with self.assertRaisesRegex(ValueError, r"If sigma is a single number, it must be positive"): + transforms.GaussianBlur(3, -1.0) + + with self.assertRaisesRegex(TypeError, r"kernel_size should be int or a sequence of integers"): + F.gaussian_blur(img, "kernel_size_string") + with self.assertRaisesRegex(ValueError, r"Kernel size should be a tuple/list of two integers"): + transforms.GaussianBlur("kernel_size_string") + + with self.assertRaisesRegex(TypeError, r"sigma should be either float or sequence of floats"): + F.gaussian_blur(img, 3, "sigma_string") + with self.assertRaisesRegex(ValueError, r"sigma should be a single number or a list/tuple with length 2"): + transforms.GaussianBlur(3, "sigma_string") if __name__ == '__main__': diff --git a/test/test_transforms_tensor.py b/test/test_transforms_tensor.py new file mode 100644 index 00000000000..c5c4a7f09e0 --- /dev/null +++ b/test/test_transforms_tensor.py @@ -0,0 +1,605 @@ +import os +import torch +from torchvision import transforms as T +from torchvision.transforms import functional as F +from torchvision.transforms import InterpolationMode + +import numpy as np + +import unittest + +from common_utils import TransformsTester, get_tmp_dir, int_dtypes, float_dtypes + + +NEAREST, BILINEAR, BICUBIC = InterpolationMode.NEAREST, InterpolationMode.BILINEAR, InterpolationMode.BICUBIC + + +class Tester(TransformsTester): + + def setUp(self): + self.device = "cpu" + + def _test_functional_op(self, func, fn_kwargs): + if fn_kwargs is None: + fn_kwargs = {} + + f = getattr(F, func) + tensor, pil_img = self._create_data(height=10, width=10, device=self.device) + transformed_tensor = f(tensor, **fn_kwargs) + transformed_pil_img = f(pil_img, **fn_kwargs) + self.compareTensorToPIL(transformed_tensor, transformed_pil_img) + + def _test_transform_vs_scripted(self, transform, s_transform, tensor, msg=None): + torch.manual_seed(12) + out1 = transform(tensor) + torch.manual_seed(12) + out2 = s_transform(tensor) + self.assertTrue(out1.equal(out2), msg=msg) + + def _test_transform_vs_scripted_on_batch(self, transform, s_transform, batch_tensors, msg=None): + torch.manual_seed(12) + transformed_batch = transform(batch_tensors) + + for i in range(len(batch_tensors)): + img_tensor = batch_tensors[i, ...] + torch.manual_seed(12) + transformed_img = transform(img_tensor) + self.assertTrue(transformed_img.equal(transformed_batch[i, ...]), msg=msg) + + torch.manual_seed(12) + s_transformed_batch = s_transform(batch_tensors) + self.assertTrue(transformed_batch.equal(s_transformed_batch), msg=msg) + + def _test_class_op(self, method, meth_kwargs=None, test_exact_match=True, **match_kwargs): + if meth_kwargs is None: + meth_kwargs = {} + + # test for class interface + f = getattr(T, method)(**meth_kwargs) + scripted_fn = torch.jit.script(f) + + tensor, pil_img = self._create_data(26, 34, device=self.device) + # set seed to reproduce the same transformation for tensor and PIL image + torch.manual_seed(12) + transformed_tensor = f(tensor) + torch.manual_seed(12) + transformed_pil_img = f(pil_img) + if test_exact_match: + self.compareTensorToPIL(transformed_tensor, transformed_pil_img, **match_kwargs) + else: + self.approxEqualTensorToPIL(transformed_tensor.float(), transformed_pil_img, **match_kwargs) + + torch.manual_seed(12) + transformed_tensor_script = scripted_fn(tensor) + self.assertTrue(transformed_tensor.equal(transformed_tensor_script)) + + batch_tensors = self._create_data_batch(height=23, width=34, channels=3, num_samples=4, device=self.device) + self._test_transform_vs_scripted_on_batch(f, scripted_fn, batch_tensors) + + with get_tmp_dir() as tmp_dir: + scripted_fn.save(os.path.join(tmp_dir, "t_{}.pt".format(method))) + + def _test_op(self, func, method, fn_kwargs=None, meth_kwargs=None): + self._test_functional_op(func, fn_kwargs) + self._test_class_op(method, meth_kwargs) + + def test_random_horizontal_flip(self): + self._test_op('hflip', 'RandomHorizontalFlip') + + def test_random_vertical_flip(self): + self._test_op('vflip', 'RandomVerticalFlip') + + def test_color_jitter(self): + + tol = 1.0 + 1e-10 + for f in [0.1, 0.5, 1.0, 1.34, (0.3, 0.7), [0.4, 0.5]]: + meth_kwargs = {"brightness": f} + self._test_class_op( + "ColorJitter", meth_kwargs=meth_kwargs, test_exact_match=False, tol=tol, agg_method="max" + ) + + for f in [0.2, 0.5, 1.0, 1.5, (0.3, 0.7), [0.4, 0.5]]: + meth_kwargs = {"contrast": f} + self._test_class_op( + "ColorJitter", meth_kwargs=meth_kwargs, test_exact_match=False, tol=tol, agg_method="max" + ) + + for f in [0.5, 0.75, 1.0, 1.25, (0.3, 0.7), [0.3, 0.4]]: + meth_kwargs = {"saturation": f} + self._test_class_op( + "ColorJitter", meth_kwargs=meth_kwargs, test_exact_match=False, tol=tol, agg_method="max" + ) + + for f in [0.2, 0.5, (-0.2, 0.3), [-0.4, 0.5]]: + meth_kwargs = {"hue": f} + self._test_class_op( + "ColorJitter", meth_kwargs=meth_kwargs, test_exact_match=False, tol=16.1, agg_method="max" + ) + + # All 4 parameters together + meth_kwargs = {"brightness": 0.2, "contrast": 0.2, "saturation": 0.2, "hue": 0.2} + self._test_class_op( + "ColorJitter", meth_kwargs=meth_kwargs, test_exact_match=False, tol=12.1, agg_method="max" + ) + + def test_pad(self): + for m in ["constant", "edge", "reflect", "symmetric"]: + fill = 127 if m == "constant" else 0 + for mul in [1, -1]: + # Test functional.pad (PIL and Tensor) with padding as single int + self._test_functional_op( + "pad", fn_kwargs={"padding": mul * 2, "fill": fill, "padding_mode": m} + ) + # Test functional.pad and transforms.Pad with padding as [int, ] + fn_kwargs = meth_kwargs = {"padding": [mul * 2, ], "fill": fill, "padding_mode": m} + self._test_op( + "pad", "Pad", fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + # Test functional.pad and transforms.Pad with padding as list + fn_kwargs = meth_kwargs = {"padding": [mul * 4, 4], "fill": fill, "padding_mode": m} + self._test_op( + "pad", "Pad", fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + # Test functional.pad and transforms.Pad with padding as tuple + fn_kwargs = meth_kwargs = {"padding": (mul * 2, 2, 2, mul * 2), "fill": fill, "padding_mode": m} + self._test_op( + "pad", "Pad", fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + + def test_crop(self): + fn_kwargs = {"top": 2, "left": 3, "height": 4, "width": 5} + # Test transforms.RandomCrop with size and padding as tuple + meth_kwargs = {"size": (4, 5), "padding": (4, 4), "pad_if_needed": True, } + self._test_op( + 'crop', 'RandomCrop', fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + + sizes = [5, [5, ], [6, 6]] + padding_configs = [ + {"padding_mode": "constant", "fill": 0}, + {"padding_mode": "constant", "fill": 10}, + {"padding_mode": "constant", "fill": 20}, + {"padding_mode": "edge"}, + {"padding_mode": "reflect"}, + ] + + for size in sizes: + for padding_config in padding_configs: + config = dict(padding_config) + config["size"] = size + self._test_class_op("RandomCrop", config) + + def test_center_crop(self): + fn_kwargs = {"output_size": (4, 5)} + meth_kwargs = {"size": (4, 5), } + self._test_op( + "center_crop", "CenterCrop", fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + fn_kwargs = {"output_size": (5,)} + meth_kwargs = {"size": (5, )} + self._test_op( + "center_crop", "CenterCrop", fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + tensor = torch.randint(0, 255, (3, 10, 10), dtype=torch.uint8, device=self.device) + # Test torchscript of transforms.CenterCrop with size as int + f = T.CenterCrop(size=5) + scripted_fn = torch.jit.script(f) + scripted_fn(tensor) + + # Test torchscript of transforms.CenterCrop with size as [int, ] + f = T.CenterCrop(size=[5, ]) + scripted_fn = torch.jit.script(f) + scripted_fn(tensor) + + # Test torchscript of transforms.CenterCrop with size as tuple + f = T.CenterCrop(size=(6, 6)) + scripted_fn = torch.jit.script(f) + scripted_fn(tensor) + + with get_tmp_dir() as tmp_dir: + scripted_fn.save(os.path.join(tmp_dir, "t_center_crop.pt")) + + def _test_op_list_output(self, func, method, out_length, fn_kwargs=None, meth_kwargs=None): + if fn_kwargs is None: + fn_kwargs = {} + if meth_kwargs is None: + meth_kwargs = {} + + fn = getattr(F, func) + scripted_fn = torch.jit.script(fn) + + tensor, pil_img = self._create_data(height=20, width=20, device=self.device) + transformed_t_list = fn(tensor, **fn_kwargs) + transformed_p_list = fn(pil_img, **fn_kwargs) + self.assertEqual(len(transformed_t_list), len(transformed_p_list)) + self.assertEqual(len(transformed_t_list), out_length) + for transformed_tensor, transformed_pil_img in zip(transformed_t_list, transformed_p_list): + self.compareTensorToPIL(transformed_tensor, transformed_pil_img) + + transformed_t_list_script = scripted_fn(tensor.detach().clone(), **fn_kwargs) + self.assertEqual(len(transformed_t_list), len(transformed_t_list_script)) + self.assertEqual(len(transformed_t_list_script), out_length) + for transformed_tensor, transformed_tensor_script in zip(transformed_t_list, transformed_t_list_script): + self.assertTrue(transformed_tensor.equal(transformed_tensor_script), + msg="{} vs {}".format(transformed_tensor, transformed_tensor_script)) + + # test for class interface + fn = getattr(T, method)(**meth_kwargs) + scripted_fn = torch.jit.script(fn) + output = scripted_fn(tensor) + self.assertEqual(len(output), len(transformed_t_list_script)) + + # test on batch of tensors + batch_tensors = self._create_data_batch(height=23, width=34, channels=3, num_samples=4, device=self.device) + torch.manual_seed(12) + transformed_batch_list = fn(batch_tensors) + + for i in range(len(batch_tensors)): + img_tensor = batch_tensors[i, ...] + torch.manual_seed(12) + transformed_img_list = fn(img_tensor) + for transformed_img, transformed_batch in zip(transformed_img_list, transformed_batch_list): + self.assertTrue(transformed_img.equal(transformed_batch[i, ...]), + msg="{} vs {}".format(transformed_img, transformed_batch[i, ...])) + + with get_tmp_dir() as tmp_dir: + scripted_fn.save(os.path.join(tmp_dir, "t_op_list_{}.pt".format(method))) + + def test_five_crop(self): + fn_kwargs = meth_kwargs = {"size": (5,)} + self._test_op_list_output( + "five_crop", "FiveCrop", out_length=5, fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + fn_kwargs = meth_kwargs = {"size": [5, ]} + self._test_op_list_output( + "five_crop", "FiveCrop", out_length=5, fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + fn_kwargs = meth_kwargs = {"size": (4, 5)} + self._test_op_list_output( + "five_crop", "FiveCrop", out_length=5, fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + fn_kwargs = meth_kwargs = {"size": [4, 5]} + self._test_op_list_output( + "five_crop", "FiveCrop", out_length=5, fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + + def test_ten_crop(self): + fn_kwargs = meth_kwargs = {"size": (5,)} + self._test_op_list_output( + "ten_crop", "TenCrop", out_length=10, fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + fn_kwargs = meth_kwargs = {"size": [5, ]} + self._test_op_list_output( + "ten_crop", "TenCrop", out_length=10, fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + fn_kwargs = meth_kwargs = {"size": (4, 5)} + self._test_op_list_output( + "ten_crop", "TenCrop", out_length=10, fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + fn_kwargs = meth_kwargs = {"size": [4, 5]} + self._test_op_list_output( + "ten_crop", "TenCrop", out_length=10, fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs + ) + + def test_resize(self): + + # TODO: Minimal check for bug-fix, improve this later + x = torch.rand(3, 32, 46) + t = T.Resize(size=38) + y = t(x) + # If size is an int, smaller edge of the image will be matched to this number. + # i.e, if height > width, then image will be rescaled to (size * height / width, size). + self.assertTrue(isinstance(y, torch.Tensor)) + self.assertEqual(y.shape[1], 38) + self.assertEqual(y.shape[2], int(38 * 46 / 32)) + + tensor, _ = self._create_data(height=34, width=36, device=self.device) + batch_tensors = torch.randint(0, 255, size=(4, 3, 44, 56), dtype=torch.uint8, device=self.device) + script_fn = torch.jit.script(F.resize) + + for dt in [None, torch.float32, torch.float64]: + if dt is not None: + # This is a trivial cast to float of uint8 data to test all cases + tensor = tensor.to(dt) + for size in [32, 34, [32, ], [32, 32], (32, 32), [34, 35]]: + for interpolation in [BILINEAR, BICUBIC, NEAREST]: + + resized_tensor = F.resize(tensor, size=size, interpolation=interpolation) + + if isinstance(size, int): + script_size = [size, ] + else: + script_size = size + + s_resized_tensor = script_fn(tensor, size=script_size, interpolation=interpolation) + self.assertTrue(s_resized_tensor.equal(resized_tensor)) + + transform = T.Resize(size=script_size, interpolation=interpolation) + s_transform = torch.jit.script(transform) + self._test_transform_vs_scripted(transform, s_transform, tensor) + self._test_transform_vs_scripted_on_batch(transform, s_transform, batch_tensors) + + with get_tmp_dir() as tmp_dir: + script_fn.save(os.path.join(tmp_dir, "t_resize.pt")) + + def test_resized_crop(self): + tensor = torch.randint(0, 255, size=(3, 44, 56), dtype=torch.uint8, device=self.device) + batch_tensors = torch.randint(0, 255, size=(4, 3, 44, 56), dtype=torch.uint8, device=self.device) + + for scale in [(0.7, 1.2), [0.7, 1.2]]: + for ratio in [(0.75, 1.333), [0.75, 1.333]]: + for size in [(32, ), [44, ], [32, ], [32, 32], (32, 32), [44, 55]]: + for interpolation in [NEAREST, BILINEAR, BICUBIC]: + transform = T.RandomResizedCrop( + size=size, scale=scale, ratio=ratio, interpolation=interpolation + ) + s_transform = torch.jit.script(transform) + self._test_transform_vs_scripted(transform, s_transform, tensor) + self._test_transform_vs_scripted_on_batch(transform, s_transform, batch_tensors) + + with get_tmp_dir() as tmp_dir: + s_transform.save(os.path.join(tmp_dir, "t_resized_crop.pt")) + + def test_random_affine(self): + tensor = torch.randint(0, 255, size=(3, 44, 56), dtype=torch.uint8, device=self.device) + batch_tensors = torch.randint(0, 255, size=(4, 3, 44, 56), dtype=torch.uint8, device=self.device) + + for shear in [15, 10.0, (5.0, 10.0), [-15, 15], [-10.0, 10.0, -11.0, 11.0]]: + for scale in [(0.7, 1.2), [0.7, 1.2]]: + for translate in [(0.1, 0.2), [0.2, 0.1]]: + for degrees in [45, 35.0, (-45, 45), [-90.0, 90.0]]: + for interpolation in [NEAREST, BILINEAR]: + transform = T.RandomAffine( + degrees=degrees, translate=translate, + scale=scale, shear=shear, interpolation=interpolation + ) + s_transform = torch.jit.script(transform) + + self._test_transform_vs_scripted(transform, s_transform, tensor) + self._test_transform_vs_scripted_on_batch(transform, s_transform, batch_tensors) + + with get_tmp_dir() as tmp_dir: + s_transform.save(os.path.join(tmp_dir, "t_random_affine.pt")) + + def test_random_rotate(self): + tensor = torch.randint(0, 255, size=(3, 44, 56), dtype=torch.uint8, device=self.device) + batch_tensors = torch.randint(0, 255, size=(4, 3, 44, 56), dtype=torch.uint8, device=self.device) + + for center in [(0, 0), [10, 10], None, (56, 44)]: + for expand in [True, False]: + for degrees in [45, 35.0, (-45, 45), [-90.0, 90.0]]: + for interpolation in [NEAREST, BILINEAR]: + transform = T.RandomRotation( + degrees=degrees, interpolation=interpolation, expand=expand, center=center + ) + s_transform = torch.jit.script(transform) + + self._test_transform_vs_scripted(transform, s_transform, tensor) + self._test_transform_vs_scripted_on_batch(transform, s_transform, batch_tensors) + + with get_tmp_dir() as tmp_dir: + s_transform.save(os.path.join(tmp_dir, "t_random_rotate.pt")) + + def test_random_perspective(self): + tensor = torch.randint(0, 255, size=(3, 44, 56), dtype=torch.uint8, device=self.device) + batch_tensors = torch.randint(0, 255, size=(4, 3, 44, 56), dtype=torch.uint8, device=self.device) + + for distortion_scale in np.linspace(0.1, 1.0, num=20): + for interpolation in [NEAREST, BILINEAR]: + transform = T.RandomPerspective( + distortion_scale=distortion_scale, + interpolation=interpolation + ) + s_transform = torch.jit.script(transform) + + self._test_transform_vs_scripted(transform, s_transform, tensor) + self._test_transform_vs_scripted_on_batch(transform, s_transform, batch_tensors) + + with get_tmp_dir() as tmp_dir: + s_transform.save(os.path.join(tmp_dir, "t_perspective.pt")) + + def test_to_grayscale(self): + + meth_kwargs = {"num_output_channels": 1} + tol = 1.0 + 1e-10 + self._test_class_op( + "Grayscale", meth_kwargs=meth_kwargs, test_exact_match=False, tol=tol, agg_method="max" + ) + + meth_kwargs = {"num_output_channels": 3} + self._test_class_op( + "Grayscale", meth_kwargs=meth_kwargs, test_exact_match=False, tol=tol, agg_method="max" + ) + + meth_kwargs = {} + self._test_class_op( + "RandomGrayscale", meth_kwargs=meth_kwargs, test_exact_match=False, tol=tol, agg_method="max" + ) + + def test_normalize(self): + tensor, _ = self._create_data(26, 34, device=self.device) + batch_tensors = torch.rand(4, 3, 44, 56, device=self.device) + + tensor = tensor.to(dtype=torch.float32) / 255.0 + # test for class interface + fn = T.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) + scripted_fn = torch.jit.script(fn) + + self._test_transform_vs_scripted(fn, scripted_fn, tensor) + self._test_transform_vs_scripted_on_batch(fn, scripted_fn, batch_tensors) + + with get_tmp_dir() as tmp_dir: + scripted_fn.save(os.path.join(tmp_dir, "t_norm.pt")) + + def test_linear_transformation(self): + c, h, w = 3, 24, 32 + + tensor, _ = self._create_data(h, w, channels=c, device=self.device) + + matrix = torch.rand(c * h * w, c * h * w, device=self.device) + mean_vector = torch.rand(c * h * w, device=self.device) + + fn = T.LinearTransformation(matrix, mean_vector) + scripted_fn = torch.jit.script(fn) + + self._test_transform_vs_scripted(fn, scripted_fn, tensor) + + batch_tensors = torch.rand(4, c, h, w, device=self.device) + # We skip some tests from _test_transform_vs_scripted_on_batch as + # results for scripted and non-scripted transformations are not exactly the same + torch.manual_seed(12) + transformed_batch = fn(batch_tensors) + torch.manual_seed(12) + s_transformed_batch = scripted_fn(batch_tensors) + self.assertTrue(transformed_batch.equal(s_transformed_batch)) + + with get_tmp_dir() as tmp_dir: + scripted_fn.save(os.path.join(tmp_dir, "t_norm.pt")) + + def test_compose(self): + tensor, _ = self._create_data(26, 34, device=self.device) + tensor = tensor.to(dtype=torch.float32) / 255.0 + + transforms = T.Compose([ + T.CenterCrop(10), + T.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)), + ]) + s_transforms = torch.nn.Sequential(*transforms.transforms) + + scripted_fn = torch.jit.script(s_transforms) + torch.manual_seed(12) + transformed_tensor = transforms(tensor) + torch.manual_seed(12) + transformed_tensor_script = scripted_fn(tensor) + self.assertTrue(transformed_tensor.equal(transformed_tensor_script), msg="{}".format(transforms)) + + t = T.Compose([ + lambda x: x, + ]) + with self.assertRaisesRegex(RuntimeError, r"Could not get name of python class object"): + torch.jit.script(t) + + def test_random_apply(self): + tensor, _ = self._create_data(26, 34, device=self.device) + tensor = tensor.to(dtype=torch.float32) / 255.0 + + transforms = T.RandomApply([ + T.RandomHorizontalFlip(), + T.ColorJitter(), + ], p=0.4) + s_transforms = T.RandomApply(torch.nn.ModuleList([ + T.RandomHorizontalFlip(), + T.ColorJitter(), + ]), p=0.4) + + scripted_fn = torch.jit.script(s_transforms) + torch.manual_seed(12) + transformed_tensor = transforms(tensor) + torch.manual_seed(12) + transformed_tensor_script = scripted_fn(tensor) + self.assertTrue(transformed_tensor.equal(transformed_tensor_script), msg="{}".format(transforms)) + + if torch.device(self.device).type == "cpu": + # Can't check this twice, otherwise + # "Can't redefine method: forward on class: __torch__.torchvision.transforms.transforms.RandomApply" + transforms = T.RandomApply([ + T.ColorJitter(), + ], p=0.3) + with self.assertRaisesRegex(RuntimeError, r"Module 'RandomApply' has no attribute 'transforms'"): + torch.jit.script(transforms) + + def test_gaussian_blur(self): + tol = 1.0 + 1e-10 + self._test_class_op( + "GaussianBlur", meth_kwargs={"kernel_size": 3, "sigma": 0.75}, + test_exact_match=False, agg_method="max", tol=tol + ) + + self._test_class_op( + "GaussianBlur", meth_kwargs={"kernel_size": 23, "sigma": [0.1, 2.0]}, + test_exact_match=False, agg_method="max", tol=tol + ) + + self._test_class_op( + "GaussianBlur", meth_kwargs={"kernel_size": 23, "sigma": (0.1, 2.0)}, + test_exact_match=False, agg_method="max", tol=tol + ) + + self._test_class_op( + "GaussianBlur", meth_kwargs={"kernel_size": [3, 3], "sigma": (1.0, 1.0)}, + test_exact_match=False, agg_method="max", tol=tol + ) + + self._test_class_op( + "GaussianBlur", meth_kwargs={"kernel_size": (3, 3), "sigma": (0.1, 2.0)}, + test_exact_match=False, agg_method="max", tol=tol + ) + + self._test_class_op( + "GaussianBlur", meth_kwargs={"kernel_size": [23], "sigma": 0.75}, + test_exact_match=False, agg_method="max", tol=tol + ) + + def test_random_erasing(self): + img = torch.rand(3, 60, 60) + + # Test Set 0: invalid value + random_erasing = T.RandomErasing(value=(0.1, 0.2, 0.3, 0.4), p=1.0) + with self.assertRaises(ValueError, msg="If value is a sequence, it should have either a single value or 3"): + random_erasing(img) + + tensor, _ = self._create_data(24, 32, channels=3, device=self.device) + batch_tensors = torch.rand(4, 3, 44, 56, device=self.device) + + test_configs = [ + {"value": 0.2}, + {"value": "random"}, + {"value": (0.2, 0.2, 0.2)}, + {"value": "random", "ratio": (0.1, 0.2)}, + ] + + for config in test_configs: + fn = T.RandomErasing(**config) + scripted_fn = torch.jit.script(fn) + self._test_transform_vs_scripted(fn, scripted_fn, tensor) + self._test_transform_vs_scripted_on_batch(fn, scripted_fn, batch_tensors) + + with get_tmp_dir() as tmp_dir: + scripted_fn.save(os.path.join(tmp_dir, "t_random_erasing.pt")) + + def test_convert_image_dtype(self): + tensor, _ = self._create_data(26, 34, device=self.device) + batch_tensors = torch.rand(4, 3, 44, 56, device=self.device) + + for in_dtype in int_dtypes() + float_dtypes(): + in_tensor = tensor.to(in_dtype) + in_batch_tensors = batch_tensors.to(in_dtype) + for out_dtype in int_dtypes() + float_dtypes(): + + fn = T.ConvertImageDtype(dtype=out_dtype) + scripted_fn = torch.jit.script(fn) + + if (in_dtype == torch.float32 and out_dtype in (torch.int32, torch.int64)) or \ + (in_dtype == torch.float64 and out_dtype == torch.int64): + with self.assertRaisesRegex(RuntimeError, r"cannot be performed safely"): + self._test_transform_vs_scripted(fn, scripted_fn, in_tensor) + with self.assertRaisesRegex(RuntimeError, r"cannot be performed safely"): + self._test_transform_vs_scripted_on_batch(fn, scripted_fn, in_batch_tensors) + continue + + self._test_transform_vs_scripted(fn, scripted_fn, in_tensor) + self._test_transform_vs_scripted_on_batch(fn, scripted_fn, in_batch_tensors) + + with get_tmp_dir() as tmp_dir: + scripted_fn.save(os.path.join(tmp_dir, "t_convert_dtype.pt")) + + +@unittest.skipIf(not torch.cuda.is_available(), reason="Skip if no CUDA device") +class CUDATester(Tester): + + def setUp(self): + self.device = "cuda" + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_utils.py b/test/test_utils.py index f1982130f75..21e2ab461d7 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -1,3 +1,4 @@ +import numpy as np import os import sys import tempfile @@ -79,6 +80,22 @@ def test_save_image_single_pixel_file_object(self): self.assertTrue(torch.equal(F.to_tensor(img_orig), F.to_tensor(img_bytes)), 'Pixel Image not stored in file object') + def test_draw_boxes(self): + img = torch.full((3, 100, 100), 255, dtype=torch.uint8) + boxes = torch.tensor([[0, 0, 20, 20], [0, 0, 0, 0], + [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) + labels = ["a", "b", "c", "d"] + colors = ["green", "#FF00FF", (0, 255, 0), "red"] + result = utils.draw_bounding_boxes(img, boxes, labels=labels, colors=colors) + + path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "fakedata", "draw_boxes_util.png") + if not os.path.exists(path): + res = Image.fromarray(result.permute(1, 2, 0).contiguous().numpy()) + res.save(path) + + expected = torch.as_tensor(np.array(Image.open(path))).permute(2, 0, 1) + self.assertTrue(torch.equal(result, expected)) + if __name__ == '__main__': unittest.main() diff --git a/test/test_video.py b/test/test_video.py new file mode 100644 index 00000000000..67450de3600 --- /dev/null +++ b/test/test_video.py @@ -0,0 +1,407 @@ +import os +import collections +import contextlib +import tempfile +import unittest +import random + +import itertools + + +import numpy as np + +import torch +import torchvision +from torchvision.io import _HAS_VIDEO_OPT, VideoReader + +try: + import av + + # Do a version test too + torchvision.io.video._check_av_available() +except ImportError: + av = None + + +VIDEO_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "videos") + +CheckerConfig = [ + "duration", + "video_fps", + "audio_sample_rate", + # We find for some videos (e.g. HMDB51 videos), the decoded audio frames and pts are + # slightly different between TorchVision decoder and PyAv decoder. So omit it during check + "check_aframes", + "check_aframe_pts", +] +GroundTruth = collections.namedtuple("GroundTruth", " ".join(CheckerConfig)) + +all_check_config = GroundTruth( + duration=0, + video_fps=0, + audio_sample_rate=0, + check_aframes=True, + check_aframe_pts=True, +) + +test_videos = { + "RATRACE_wave_f_nm_np1_fr_goo_37.avi": GroundTruth( + duration=2.0, + video_fps=30.0, + audio_sample_rate=None, + check_aframes=True, + check_aframe_pts=True, + ), + "SchoolRulesHowTheyHelpUs_wave_f_nm_np1_ba_med_0.avi": GroundTruth( + duration=2.0, + video_fps=30.0, + audio_sample_rate=None, + check_aframes=True, + check_aframe_pts=True, + ), + "TrumanShow_wave_f_nm_np1_fr_med_26.avi": GroundTruth( + duration=2.0, + video_fps=30.0, + audio_sample_rate=None, + check_aframes=True, + check_aframe_pts=True, + ), + "v_SoccerJuggling_g23_c01.avi": GroundTruth( + duration=8.0, + video_fps=29.97, + audio_sample_rate=None, + check_aframes=True, + check_aframe_pts=True, + ), + "v_SoccerJuggling_g24_c01.avi": GroundTruth( + duration=8.0, + video_fps=29.97, + audio_sample_rate=None, + check_aframes=True, + check_aframe_pts=True, + ), + # Last three test segfault on video reader (see issues) + "R6llTwEh07w.mp4": GroundTruth( + duration=10.0, + video_fps=30.0, + audio_sample_rate=44100, + # PyAv miss one audio frame at the beginning (pts=0) + check_aframes=False, + check_aframe_pts=False, + ), + "SOX5yA1l24A.mp4": GroundTruth( + duration=11.0, + video_fps=29.97, + audio_sample_rate=48000, + # PyAv miss one audio frame at the beginning (pts=0) + check_aframes=False, + check_aframe_pts=False, + ), + "WUzgd7C1pWA.mp4": GroundTruth( + duration=11.0, + video_fps=29.97, + audio_sample_rate=48000, + # PyAv miss one audio frame at the beginning (pts=0) + check_aframes=False, + check_aframe_pts=False, + ), +} + +DecoderResult = collections.namedtuple( + "DecoderResult", "vframes vframe_pts vtimebase aframes aframe_pts atimebase" +) + + +def _read_from_stream( + container, start_pts, end_pts, stream, stream_name, buffer_size=4 +): + """ + Args: + container: pyav container + start_pts/end_pts: the starting/ending Presentation TimeStamp where + frames are read + stream: pyav stream + stream_name: a dictionary of streams. For example, {"video": 0} means + video stream at stream index 0 + buffer_size: pts of frames decoded by PyAv is not guaranteed to be in + ascending order. We need to decode more frames even when we meet end + pts + """ + # seeking in the stream is imprecise. Thus, seek to an ealier PTS by a margin + margin = 1 + seek_offset = max(start_pts - margin, 0) + + container.seek(seek_offset, any_frame=False, backward=True, stream=stream) + frames = {} + buffer_count = 0 + for frame in container.decode(**stream_name): + if frame.pts < start_pts: + continue + if frame.pts <= end_pts: + frames[frame.pts] = frame + else: + buffer_count += 1 + if buffer_count >= buffer_size: + break + result = [frames[pts] for pts in sorted(frames)] + + return result + + +def _fraction_to_tensor(fraction): + ret = torch.zeros([2], dtype=torch.int32) + ret[0] = fraction.numerator + ret[1] = fraction.denominator + return ret + + +def _decode_frames_by_av_module( + full_path, + video_start_pts=0, + video_end_pts=None, + audio_start_pts=0, + audio_end_pts=None, +): + """ + Use PyAv to decode video frames. This provides a reference for our decoder + to compare the decoding results. + Input arguments: + full_path: video file path + video_start_pts/video_end_pts: the starting/ending Presentation TimeStamp where + frames are read + """ + if video_end_pts is None: + video_end_pts = float("inf") + if audio_end_pts is None: + audio_end_pts = float("inf") + container = av.open(full_path) + + video_frames = [] + vtimebase = torch.zeros([0], dtype=torch.int32) + if container.streams.video: + video_frames = _read_from_stream( + container, + video_start_pts, + video_end_pts, + container.streams.video[0], + {"video": 0}, + ) + # container.streams.video[0].average_rate is not a reliable estimator of + # frame rate. It can be wrong for certain codec, such as VP80 + # So we do not return video fps here + vtimebase = _fraction_to_tensor(container.streams.video[0].time_base) + + audio_frames = [] + atimebase = torch.zeros([0], dtype=torch.int32) + if container.streams.audio: + audio_frames = _read_from_stream( + container, + audio_start_pts, + audio_end_pts, + container.streams.audio[0], + {"audio": 0}, + ) + atimebase = _fraction_to_tensor(container.streams.audio[0].time_base) + + container.close() + vframes = [frame.to_rgb().to_ndarray() for frame in video_frames] + vframes = torch.as_tensor(np.stack(vframes)) + + vframe_pts = torch.tensor([frame.pts for frame in video_frames], dtype=torch.int64) + + aframes = [frame.to_ndarray() for frame in audio_frames] + if aframes: + aframes = np.transpose(np.concatenate(aframes, axis=1)) + aframes = torch.as_tensor(aframes) + else: + aframes = torch.empty((1, 0), dtype=torch.float32) + + aframe_pts = torch.tensor( + [audio_frame.pts for audio_frame in audio_frames], dtype=torch.int64 + ) + + return DecoderResult( + vframes=vframes.permute(0, 3, 1, 2), + vframe_pts=vframe_pts, + vtimebase=vtimebase, + aframes=aframes, + aframe_pts=aframe_pts, + atimebase=atimebase, + ) + + +def _template_read_video(video_object, s=0, e=None): + + if e is None: + e = float("inf") + if e < s: + raise ValueError( + "end time should be larger than start time, got " + "start time={} and end time={}".format(s, e) + ) + video_object.set_current_stream("video") + video_object.seek(s) + video_frames = torch.empty(0) + frames = [] + video_pts = [] + for frame in itertools.takewhile(lambda x: x['pts'] <= e, video_object): + if frame['pts'] < s: + continue + frames.append(frame['data']) + video_pts.append(frame['pts']) + if len(frames) > 0: + video_frames = torch.stack(frames, 0) + + video_object.set_current_stream("audio") + video_object.seek(s) + audio_frames = torch.empty(0) + frames = [] + audio_pts = [] + for frame in itertools.takewhile(lambda x: x['pts'] <= e, video_object): + if frame['pts'] < s: + continue + frames.append(frame['data']) + audio_pts.append(frame['pts']) + if len(frames) > 0: + audio_frames = torch.stack(frames, 0) + + return DecoderResult( + vframes=video_frames, + vframe_pts=video_pts, + vtimebase=None, + aframes=audio_frames, + aframe_pts=audio_pts, + atimebase=None, + ) + return video_frames, audio_frames, video_object.get_metadata() + + +@unittest.skipIf(_HAS_VIDEO_OPT is False, "Didn't compile with ffmpeg") +class TestVideo(unittest.TestCase): + @unittest.skipIf(av is None, "PyAV unavailable") + def test_read_video_tensor(self): + """ + Check if reading the video using the `next` based API yields the + same sized tensors as the pyav alternative. + """ + torchvision.set_video_backend("pyav") + for test_video, config in test_videos.items(): + full_path = os.path.join(VIDEO_DIR, test_video) + # pass 1: decode all frames using existing TV decoder + tv_result, _, _ = torchvision.io.read_video(full_path, pts_unit="sec") + tv_result = tv_result.permute(0, 3, 1, 2) + # pass 2: decode all frames using new api + reader = VideoReader(full_path, "video") + frames = [] + for frame in reader: + frames.append(frame['data']) + new_api = torch.stack(frames, 0) + self.assertEqual(tv_result.size(), new_api.size()) + + # def test_partial_video_reading_fn(self): + # torchvision.set_video_backend("video_reader") + # for test_video, config in test_videos.items(): + # full_path = os.path.join(VIDEO_DIR, test_video) + + # # select two random points between 0 and duration + # r = [] + # r.append(random.uniform(0, config.duration)) + # r.append(random.uniform(0, config.duration)) + # s = min(r) + # e = max(r) + + # reader = VideoReader(full_path, "video") + # results = _template_read_video(reader, s, e) + # tv_video, tv_audio, info = torchvision.io.read_video( + # full_path, start_pts=s, end_pts=e, pts_unit="sec" + # ) + # self.assertAlmostEqual(tv_video.size(0), results.vframes.size(0), delta=2.0) + + # def test_pts(self): + # """ + # Check if every frame read from + # """ + # torchvision.set_video_backend("video_reader") + # for test_video, config in test_videos.items(): + # full_path = os.path.join(VIDEO_DIR, test_video) + + # tv_timestamps, _ = torchvision.io.read_video_timestamps( + # full_path, pts_unit="sec" + # ) + # # pass 2: decode all frames using new api + # reader = VideoReader(full_path, "video") + # pts = [] + # t, p = next(reader) + # while t.numel() > 0: # THIS NEEDS TO BE FIXED + # pts.append(p) + # t, p = next(reader) + + # tv_timestamps = [float(p) for p in tv_timestamps] + # napi_pts = [float(p) for p in pts] + # for i in range(len(napi_pts)): + # self.assertAlmostEqual(napi_pts[i], tv_timestamps[i], delta=0.001) + # # check if pts of video frames are sorted in ascending order + # for i in range(len(napi_pts) - 1): + # self.assertEqual(napi_pts[i] < napi_pts[i + 1], True) + + @unittest.skipIf(av is None, "PyAV unavailable") + def test_metadata(self): + """ + Test that the metadata returned via pyav corresponds to the one returned + by the new video decoder API + """ + torchvision.set_video_backend("pyav") + for test_video, config in test_videos.items(): + full_path = os.path.join(VIDEO_DIR, test_video) + reader = VideoReader(full_path, "video") + reader_md = reader.get_metadata() + self.assertAlmostEqual( + config.video_fps, reader_md["video"]["fps"][0], delta=0.0001 + ) + self.assertAlmostEqual( + config.duration, reader_md["video"]["duration"][0], delta=0.5 + ) + + @unittest.skipIf(av is None, "PyAV unavailable") + def test_video_reading_fn(self): + """ + Test that the outputs of the pyav and ffmpeg outputs are mostly the same + """ + for test_video, config in test_videos.items(): + full_path = os.path.join(VIDEO_DIR, test_video) + + ref_result = _decode_frames_by_av_module(full_path) + + reader = VideoReader(full_path, "video") + newapi_result = _template_read_video(reader) + + # First we check if the frames are approximately the same + # (note that every codec context has signature artefacts which + # make a direct comparison not feasible) + if newapi_result.vframes.numel() > 0 and ref_result.vframes.numel() > 0: + mean_delta = torch.mean( + torch.abs( + newapi_result.vframes.float() - ref_result.vframes.float() + ) + ) + self.assertAlmostEqual(mean_delta, 0, delta=8.0) + + # Just a sanity check: are the two of the correct size? + self.assertEqual(newapi_result.vframes.size(), ref_result.vframes.size()) + + # Lastly, we compare the resulting audio streams + if ( + config.check_aframes + and newapi_result.aframes.numel() > 0 + and ref_result.aframes.numel() > 0 + ): + """Audio stream is available and audio frame is required to return + from decoder""" + is_same = torch.all( + torch.eq(newapi_result.aframes, ref_result.aframes) + ).item() + self.assertEqual(is_same, True) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/tracing/frcnn/CMakeLists.txt b/test/tracing/frcnn/CMakeLists.txt new file mode 100644 index 00000000000..c79382470bd --- /dev/null +++ b/test/tracing/frcnn/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.1 FATAL_ERROR) +project(test_frcnn_tracing) + +find_package(Torch REQUIRED) +find_package(TorchVision REQUIRED) + +# This due to some headers importing Python.h +find_package(Python3 COMPONENTS Development) + +add_executable(test_frcnn_tracing test_frcnn_tracing.cpp) +target_compile_features(test_frcnn_tracing PUBLIC cxx_range_for) +target_link_libraries(test_frcnn_tracing ${TORCH_LIBRARIES} TorchVision::TorchVision Python3::Python) +set_property(TARGET test_frcnn_tracing PROPERTY CXX_STANDARD 14) diff --git a/test/tracing/frcnn/test_frcnn_tracing.cpp b/test/tracing/frcnn/test_frcnn_tracing.cpp new file mode 100644 index 00000000000..a23b95cf88f --- /dev/null +++ b/test/tracing/frcnn/test_frcnn_tracing.cpp @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +// Windows only +// This is necessary until operators are automatically registered on include +static auto _nms = &nms_cpu; +#endif + +int main() { + torch::DeviceType device_type; + device_type = torch::kCPU; + + torch::jit::script::Module module; + try { + std::cout << "Loading model\n"; + // Deserialize the ScriptModule from a file using torch::jit::load(). + module = torch::jit::load("fasterrcnn_resnet50_fpn.pt"); + std::cout << "Model loaded\n"; + } catch (const torch::Error& e) { + std::cout << "error loading the model\n"; + return -1; + } catch (const std::exception& e) { + std::cout << "Other error: " << e.what() << "\n"; + return -1; + } + + // TorchScript models require a List[IValue] as input + std::vector inputs; + + // Faster RCNN accepts a List[Tensor] as main input + std::vector images; + images.push_back(torch::rand({3, 256, 275})); + images.push_back(torch::rand({3, 256, 275})); + + inputs.push_back(images); + auto output = module.forward(inputs); + + std::cout << "ok\n"; + std::cout << "output" << output << "\n"; + + if (torch::cuda::is_available()) { + // Move traced model to GPU + module.to(torch::kCUDA); + + // Add GPU inputs + images.clear(); + inputs.clear(); + + torch::TensorOptions options = torch::TensorOptions{torch::kCUDA}; + images.push_back(torch::rand({3, 256, 275}, options)); + images.push_back(torch::rand({3, 256, 275}, options)); + + inputs.push_back(images); + auto output = module.forward(inputs); + + std::cout << "ok\n"; + std::cout << "output" << output << "\n"; + } + return 0; +} diff --git a/test/tracing/frcnn/trace_model.py b/test/tracing/frcnn/trace_model.py new file mode 100644 index 00000000000..34961e8684f --- /dev/null +++ b/test/tracing/frcnn/trace_model.py @@ -0,0 +1,14 @@ + +import os.path as osp + +import torch +import torchvision + +HERE = osp.dirname(osp.abspath(__file__)) +ASSETS = osp.dirname(osp.dirname(HERE)) + +model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=False) +model.eval() + +traced_model = torch.jit.script(model) +traced_model.save("fasterrcnn_resnet50_fpn.pt") diff --git a/torchvision/__init__.py b/torchvision/__init__.py index 1f21d34865d..28349cbb78a 100644 --- a/torchvision/__init__.py +++ b/torchvision/__init__.py @@ -1,4 +1,5 @@ import warnings +import os from .extension import _HAS_OPS @@ -16,6 +17,14 @@ except ImportError: pass +# Check if torchvision is being imported within the root folder +if (not _HAS_OPS and os.path.dirname(os.path.realpath(__file__)) == + os.path.join(os.path.realpath(os.getcwd()), 'torchvision')): + message = ('You are importing torchvision within its own root folder ({}). ' + 'This is not expected to work and may give errors. Please exit the ' + 'torchvision project source and relaunch your python interpreter.') + warnings.warn(message.format(os.getcwd())) + _image_backend = 'PIL' _video_backend = "pyav" @@ -62,7 +71,11 @@ def set_video_backend(backend): "Invalid video backend '%s'. Options are 'pyav' and 'video_reader'" % backend ) if backend == "video_reader" and not io._HAS_VIDEO_OPT: - warnings.warn("video_reader video backend is not available") + message = ( + "video_reader video backend is not available." + " Please compile torchvision from source and try again" + ) + warnings.warn(message) else: _video_backend = backend diff --git a/torchvision/csrc/DeformConv.h b/torchvision/csrc/DeformConv.h index 7ce41824cab..f8a8dba60e6 100644 --- a/torchvision/csrc/DeformConv.h +++ b/torchvision/csrc/DeformConv.h @@ -3,103 +3,136 @@ #include "cpu/vision_cpu.h" #ifdef WITH_CUDA +#include "autocast.h" #include "cuda/vision_cuda.h" #endif +#ifdef WITH_HIP +#include "autocast.h" +#include "hip/vision_cuda.h" +#endif + +// TODO: put this stuff in torchvision namespace -at::Tensor DeformConv2d_forward( +at::Tensor deform_conv2d( const at::Tensor& input, const at::Tensor& weight, const at::Tensor& offset, + const at::Tensor& mask, const at::Tensor& bias, - const std::pair& stride, - const std::pair& padding, - const std::pair& dilation, - const int groups, - const int offset_groups) { - if (input.type().is_cuda()) { -#ifdef WITH_CUDA - return DeformConv2d_forward_cuda( - input.contiguous(), - weight.contiguous(), - offset.contiguous(), - bias.contiguous(), - stride, - padding, - dilation, - groups, - offset_groups); -#else - AT_ERROR("Not compiled with GPU support"); -#endif - } - return DeformConv2d_forward_cpu( - input.contiguous(), - weight.contiguous(), - offset.contiguous(), - bias.contiguous(), - stride, - padding, - dilation, + int64_t stride_h, + int64_t stride_w, + int64_t pad_h, + int64_t pad_w, + int64_t dilation_h, + int64_t dilation_w, + int64_t groups, + int64_t offset_groups, + bool use_mask) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::deform_conv2d", "") + .typed(); + return op.call( + input, + weight, + offset, + mask, + bias, + stride_h, + stride_w, + pad_h, + pad_w, + dilation_h, + dilation_w, groups, - offset_groups); + offset_groups, + use_mask); } -std::tuple DeformConv2d_backward( - const at::Tensor& grad, +#if defined(WITH_CUDA) || defined(WITH_HIP) +at::Tensor DeformConv2d_autocast( const at::Tensor& input, const at::Tensor& weight, const at::Tensor& offset, + const at::Tensor& mask, const at::Tensor& bias, - const std::pair& stride, - const std::pair& padding, - const std::pair& dilation, - const int groups, - const int offset_groups) { - if (grad.type().is_cuda()) { -#ifdef WITH_CUDA - return DeformConv2d_backward_cuda( - grad.contiguous(), - input.contiguous(), - weight.contiguous(), - offset.contiguous(), - bias.contiguous(), - stride, - padding, - dilation, - groups, - offset_groups); -#else - AT_ERROR("Not compiled with GPU support"); + int64_t stride_h, + int64_t stride_w, + int64_t pad_h, + int64_t pad_w, + int64_t dilation_h, + int64_t dilation_w, + int64_t groups, + int64_t offset_groups, + bool use_mask) { + c10::impl::ExcludeDispatchKeyGuard no_autocast(c10::DispatchKey::Autocast); + return deform_conv2d( + at::autocast::cached_cast(at::kFloat, input), + at::autocast::cached_cast(at::kFloat, weight), + at::autocast::cached_cast(at::kFloat, offset), + at::autocast::cached_cast(at::kFloat, mask), + at::autocast::cached_cast(at::kFloat, bias), + stride_h, + stride_w, + pad_h, + pad_w, + dilation_h, + dilation_w, + groups, + offset_groups, + use_mask) + .to(input.scalar_type()); +} #endif - } - return DeformConv2d_backward_cpu( - grad.contiguous(), - input.contiguous(), - weight.contiguous(), - offset.contiguous(), - bias.contiguous(), - stride, - padding, - dilation, + +std::tuple +_deform_conv2d_backward( + const at::Tensor& grad, + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& mask, + const at::Tensor& bias, + int64_t stride_h, + int64_t stride_w, + int64_t pad_h, + int64_t pad_w, + int64_t dilation_h, + int64_t dilation_w, + int64_t groups, + int64_t offset_groups, + bool use_mask) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::_deform_conv2d_backward", "") + .typed(); + return op.call( + grad, + input, + weight, + offset, + mask, + bias, + stride_h, + stride_w, + pad_h, + pad_w, + dilation_h, + dilation_w, groups, - offset_groups); + offset_groups, + use_mask); } -using namespace at; -using torch::Tensor; -using torch::autograd::AutogradContext; -using torch::autograd::Variable; -using torch::autograd::variable_list; - class DeformConv2dFunction : public torch::autograd::Function { public: - static variable_list forward( - AutogradContext* ctx, - Variable input, - Variable weight, - Variable offset, - Variable bias, + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& input, + const torch::autograd::Variable& weight, + const torch::autograd::Variable& offset, + const torch::autograd::Variable& mask, + const torch::autograd::Variable& bias, int64_t stride_h, int64_t stride_w, int64_t pad_h, @@ -107,19 +140,26 @@ class DeformConv2dFunction int64_t dilation_h, int64_t dilation_w, int64_t groups, - int64_t offset_groups) { - auto output = DeformConv2d_forward( + int64_t offset_groups, + bool use_mask) { + at::AutoNonVariableTypeMode g; + auto output = deform_conv2d( input, weight, offset, + mask, bias, - {stride_h, stride_w}, - {pad_h, pad_w}, - {dilation_h, dilation_w}, + stride_h, + stride_w, + pad_h, + pad_w, + dilation_h, + dilation_w, groups, - offset_groups); + offset_groups, + use_mask); - ctx->save_for_backward({input, weight, offset, bias}); + ctx->save_for_backward({input, weight, offset, mask, bias}); ctx->saved_data["stride_h"] = stride_h; ctx->saved_data["stride_w"] = stride_w; ctx->saved_data["pad_h"] = pad_h; @@ -128,20 +168,22 @@ class DeformConv2dFunction ctx->saved_data["dilation_w"] = dilation_w; ctx->saved_data["groups"] = groups; ctx->saved_data["offset_groups"] = offset_groups; + ctx->saved_data["use_mask"] = use_mask; return { output, }; } - static variable_list backward( - AutogradContext* ctx, - variable_list grad_output) { + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { auto saved = ctx->get_saved_variables(); auto input = saved[0]; auto weight = saved[1]; auto offset = saved[2]; - auto bias = saved[3]; + auto mask = saved[3]; + auto bias = saved[4]; auto stride_h = ctx->saved_data["stride_h"].toInt(); auto stride_w = ctx->saved_data["stride_w"].toInt(); @@ -151,44 +193,149 @@ class DeformConv2dFunction auto dilation_w = ctx->saved_data["dilation_w"].toInt(); auto groups = ctx->saved_data["groups"].toInt(); auto offset_groups = ctx->saved_data["offset_groups"].toInt(); + auto use_mask = ctx->saved_data["use_mask"].toBool(); - auto grads = DeformConv2d_backward( + auto grads = _deform_conv2d_backward( grad_output[0], input, weight, offset, + mask, bias, - {stride_h, stride_w}, - {pad_h, pad_w}, - {dilation_h, dilation_w}, + stride_h, + stride_w, + pad_h, + pad_w, + dilation_h, + dilation_w, groups, - offset_groups); + offset_groups, + use_mask); auto grad_input = std::get<0>(grads); auto grad_weight = std::get<1>(grads); auto grad_offset = std::get<2>(grads); - auto grad_bias = std::get<3>(grads); + auto grad_mask = std::get<3>(grads); + auto grad_bias = std::get<4>(grads); return { grad_input, grad_weight, grad_offset, + grad_mask, grad_bias, - Variable(), - Variable(), - Variable(), - Variable(), - Variable(), - Variable(), - Variable(), - Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), }; } }; -at::Tensor deform_conv2d( +// TODO: There should be an easier way to do this +class DeformConv2dBackwardFunction + : public torch::autograd::Function { + public: + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& grad, + const torch::autograd::Variable& input, + const torch::autograd::Variable& weight, + const torch::autograd::Variable& offset, + const torch::autograd::Variable& mask, + const torch::autograd::Variable& bias, + int64_t stride_h, + int64_t stride_w, + int64_t pad_h, + int64_t pad_w, + int64_t dilation_h, + int64_t dilation_w, + int64_t groups, + int64_t offset_groups, + bool use_mask) { + at::AutoNonVariableTypeMode g; + auto result = _deform_conv2d_backward( + grad, + input, + weight, + offset, + mask, + bias, + stride_h, + stride_w, + pad_h, + pad_w, + dilation_h, + dilation_w, + groups, + offset_groups, + use_mask); + + auto grad_input = std::get<0>(result); + auto grad_weight = std::get<1>(result); + auto grad_offset = std::get<2>(result); + auto grad_mask = std::get<3>(result); + auto grad_bias = std::get<4>(result); + + return { + grad_input, + grad_weight, + grad_offset, + grad_mask, + grad_bias, + }; + } + + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { + TORCH_CHECK(0, "double backwards on deform_conv2d not supported"); + } +}; + +at::Tensor DeformConv2d_autograd( + const at::Tensor& input, + const at::Tensor& weight, + const at::Tensor& offset, + const at::Tensor& mask, + const at::Tensor& bias, + int64_t stride_h, + int64_t stride_w, + int64_t pad_h, + int64_t pad_w, + int64_t dilation_h, + int64_t dilation_w, + int64_t groups, + int64_t offset_groups, + bool use_mask) { + return DeformConv2dFunction::apply( + input, + weight, + offset, + mask, + bias, + stride_h, + stride_w, + pad_h, + pad_w, + dilation_h, + dilation_w, + groups, + offset_groups, + use_mask)[0]; +} + +std::tuple +DeformConv2d_backward_autograd( + const at::Tensor& grad, const at::Tensor& input, const at::Tensor& weight, const at::Tensor& offset, + const at::Tensor& mask, const at::Tensor& bias, int64_t stride_h, int64_t stride_w, @@ -197,11 +344,14 @@ at::Tensor deform_conv2d( int64_t dilation_h, int64_t dilation_w, int64_t groups, - int64_t offset_groups) { - auto result = DeformConv2dFunction::apply( + int64_t offset_groups, + bool use_mask) { + auto result = DeformConv2dBackwardFunction::apply( + grad, input, weight, offset, + mask, bias, stride_h, stride_w, @@ -210,6 +360,8 @@ at::Tensor deform_conv2d( dilation_h, dilation_w, groups, - offset_groups); - return result[0]; + offset_groups, + use_mask); + + return std::make_tuple(result[0], result[1], result[2], result[3], result[4]); } diff --git a/torchvision/csrc/PSROIAlign.h b/torchvision/csrc/PSROIAlign.h index a5998df2891..1e5dd17aabc 100644 --- a/torchvision/csrc/PSROIAlign.h +++ b/torchvision/csrc/PSROIAlign.h @@ -3,69 +3,75 @@ #include "cpu/vision_cpu.h" #ifdef WITH_CUDA +#include "autocast.h" #include "cuda/vision_cuda.h" #endif +#ifdef WITH_HIP +#include "autocast.h" +#include "hip/vision_cuda.h" +#endif #include -std::tuple PSROIAlign_forward( +// TODO: put this stuff in torchvision namespace + +std::tuple ps_roi_align( const at::Tensor& input, const at::Tensor& rois, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int sampling_ratio) { - if (input.type().is_cuda()) { -#ifdef WITH_CUDA - return PSROIAlign_forward_cuda( - input, - rois, - spatial_scale, - pooled_height, - pooled_width, - sampling_ratio); -#else - AT_ERROR("Not compiled with GPU support"); -#endif - } - return PSROIAlign_forward_cpu( + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::ps_roi_align", "") + .typed(); + return op.call( input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio); } -at::Tensor PSROIAlign_backward( - const at::Tensor& grad, +#if defined(WITH_CUDA) || defined(WITH_HIP) +std::tuple PSROIAlign_autocast( + const at::Tensor& input, const at::Tensor& rois, - const at::Tensor& mapping_channel, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int sampling_ratio, - const int batch_size, - const int channels, - const int height, - const int width) { - if (grad.type().is_cuda()) { -#ifdef WITH_CUDA - return PSROIAlign_backward_cuda( - grad, - rois, - mapping_channel, - spatial_scale, - pooled_height, - pooled_width, - sampling_ratio, - batch_size, - channels, - height, - width); -#else - AT_ERROR("Not compiled with GPU support"); + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio) { + c10::impl::ExcludeDispatchKeyGuard no_autocast(c10::DispatchKey::Autocast); + auto result = ps_roi_align( + at::autocast::cached_cast(at::kFloat, input), + at::autocast::cached_cast(at::kFloat, rois), + spatial_scale, + pooled_height, + pooled_width, + sampling_ratio); + + return std::make_tuple( + std::get<0>(result).to(input.scalar_type()), + std::get<1>(result).to(input.scalar_type())); +} #endif - } - return PSROIAlign_backward_cpu( + +at::Tensor _ps_roi_align_backward( + const at::Tensor& grad, + const at::Tensor& rois, + const at::Tensor& channel_mapping, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::_ps_roi_align_backward", "") + .typed(); + return op.call( grad, rois, - mapping_channel, + channel_mapping, spatial_scale, pooled_height, pooled_width, @@ -76,51 +82,48 @@ at::Tensor PSROIAlign_backward( width); } -using namespace at; -using torch::Tensor; -using torch::autograd::AutogradContext; -using torch::autograd::Variable; -using torch::autograd::variable_list; - class PSROIAlignFunction : public torch::autograd::Function { public: - static variable_list forward( - AutogradContext* ctx, - Variable input, - Variable rois, - const double spatial_scale, - const int64_t pooled_height, - const int64_t pooled_width, - const int64_t sampling_ratio) { + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& input, + const torch::autograd::Variable& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio) { ctx->saved_data["spatial_scale"] = spatial_scale; ctx->saved_data["pooled_height"] = pooled_height; ctx->saved_data["pooled_width"] = pooled_width; ctx->saved_data["sampling_ratio"] = sampling_ratio; ctx->saved_data["input_shape"] = input.sizes(); - auto result = PSROIAlign_forward( + at::AutoNonVariableTypeMode g; + auto result = ps_roi_align( input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio); + auto output = std::get<0>(result); auto channel_mapping = std::get<1>(result); ctx->save_for_backward({rois, channel_mapping}); ctx->mark_non_differentiable({channel_mapping}); + return {output, channel_mapping}; } - static variable_list backward( - AutogradContext* ctx, - variable_list grad_output) { + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { // Use data saved in forward auto saved = ctx->get_saved_variables(); auto rois = saved[0]; auto channel_mapping = saved[1]; auto input_shape = ctx->saved_data["input_shape"].toIntList(); - auto grad_in = PSROIAlign_backward( + auto grad_in = _ps_roi_align_backward( grad_output[0], rois, channel_mapping, @@ -132,19 +135,92 @@ class PSROIAlignFunction input_shape[1], input_shape[2], input_shape[3]); - return { - grad_in, Variable(), Variable(), Variable(), Variable(), Variable()}; + + return {grad_in, + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable()}; } }; -std::tuple ps_roi_align( - const Tensor& input, - const Tensor& rois, - const double spatial_scale, - const int64_t pooled_height, - const int64_t pooled_width, - const int64_t sampling_ratio) { +// TODO: There should be an easier way to do this +class PSROIAlignBackwardFunction + : public torch::autograd::Function { + public: + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& grad, + const torch::autograd::Variable& rois, + const torch::autograd::Variable& channel_mapping, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { + at::AutoNonVariableTypeMode g; + auto grad_in = _ps_roi_align_backward( + grad, + rois, + channel_mapping, + spatial_scale, + pooled_height, + pooled_width, + sampling_ratio, + batch_size, + channels, + height, + width); + + return {grad_in}; + } + + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { + TORCH_CHECK(0, "double backwards on ps_roi_align not supported"); + } +}; + +std::tuple PSROIAlign_autograd( + const at::Tensor& input, + const at::Tensor& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio) { auto result = PSROIAlignFunction::apply( input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio); - return std::tuple(result[0], result[1]); + + return std::make_tuple(result[0], result[1]); +} + +at::Tensor PSROIAlign_backward_autograd( + const at::Tensor& grad, + const at::Tensor& rois, + const at::Tensor& channel_mapping, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { + return PSROIAlignBackwardFunction::apply( + grad, + rois, + channel_mapping, + spatial_scale, + pooled_height, + pooled_width, + sampling_ratio, + batch_size, + channels, + height, + width)[0]; } diff --git a/torchvision/csrc/PSROIPool.h b/torchvision/csrc/PSROIPool.h index c67ce92f54e..c3ced9e7842 100644 --- a/torchvision/csrc/PSROIPool.h +++ b/torchvision/csrc/PSROIPool.h @@ -3,59 +3,68 @@ #include "cpu/vision_cpu.h" #ifdef WITH_CUDA +#include "autocast.h" #include "cuda/vision_cuda.h" #endif +#ifdef WITH_HIP +#include "autocast.h" +#include "hip/vision_cuda.h" +#endif + +// TODO: put this stuff in torchvision namespace -std::tuple PSROIPool_forward( +std::tuple ps_roi_pool( const at::Tensor& input, const at::Tensor& rois, - const float spatial_scale, - const int pooled_height, - const int pooled_width) { - if (input.type().is_cuda()) { -#ifdef WITH_CUDA - return PSROIPool_forward_cuda( - input, rois, spatial_scale, pooled_height, pooled_width); -#else - AT_ERROR("Not compiled with GPU support"); -#endif - } - return PSROIPool_forward_cpu( - input, rois, spatial_scale, pooled_height, pooled_width); + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::ps_roi_pool", "") + .typed(); + return op.call(input, rois, spatial_scale, pooled_height, pooled_width); } -at::Tensor PSROIPool_backward( - const at::Tensor& grad, +#if defined(WITH_CUDA) || defined(WITH_HIP) +std::tuple PSROIPool_autocast( + const at::Tensor& input, const at::Tensor& rois, - const at::Tensor& mapping_channel, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int batch_size, - const int channels, - const int height, - const int width) { - if (grad.type().is_cuda()) { -#ifdef WITH_CUDA - return PSROIPool_backward_cuda( - grad, - rois, - mapping_channel, - spatial_scale, - pooled_height, - pooled_width, - batch_size, - channels, - height, - width); -#else - AT_ERROR("Not compiled with GPU support"); + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { + c10::impl::ExcludeDispatchKeyGuard no_autocast(c10::DispatchKey::Autocast); + auto result = ps_roi_pool( + at::autocast::cached_cast(at::kFloat, input), + at::autocast::cached_cast(at::kFloat, rois), + spatial_scale, + pooled_height, + pooled_width); + + return std::make_tuple( + std::get<0>(result).to(input.scalar_type()), + std::get<1>(result).to(input.scalar_type())); +} #endif - } - return PSROIPool_backward_cpu( + +at::Tensor _ps_roi_pool_backward( + const at::Tensor& grad, + const at::Tensor& rois, + const at::Tensor& channel_mapping, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::_ps_roi_pool_backward", "") + .typed(); + return op.call( grad, rois, - mapping_channel, + channel_mapping, spatial_scale, pooled_height, pooled_width, @@ -65,43 +74,40 @@ at::Tensor PSROIPool_backward( width); } -using namespace at; -using torch::Tensor; -using torch::autograd::AutogradContext; -using torch::autograd::Variable; -using torch::autograd::variable_list; - class PSROIPoolFunction : public torch::autograd::Function { public: - static variable_list forward( - AutogradContext* ctx, - Variable input, - Variable rois, - const double spatial_scale, - const int64_t pooled_height, - const int64_t pooled_width) { + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& input, + const torch::autograd::Variable& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { ctx->saved_data["spatial_scale"] = spatial_scale; ctx->saved_data["pooled_height"] = pooled_height; ctx->saved_data["pooled_width"] = pooled_width; ctx->saved_data["input_shape"] = input.sizes(); - auto result = PSROIPool_forward( - input, rois, spatial_scale, pooled_height, pooled_width); + at::AutoNonVariableTypeMode g; + auto result = + ps_roi_pool(input, rois, spatial_scale, pooled_height, pooled_width); + auto output = std::get<0>(result); auto channel_mapping = std::get<1>(result); ctx->save_for_backward({rois, channel_mapping}); ctx->mark_non_differentiable({channel_mapping}); + return {output, channel_mapping}; } - static variable_list backward( - AutogradContext* ctx, - variable_list grad_output) { + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { // Use data saved in forward auto saved = ctx->get_saved_variables(); auto rois = saved[0]; auto channel_mapping = saved[1]; auto input_shape = ctx->saved_data["input_shape"].toIntList(); - auto grad_in = PSROIPool_backward( + auto grad_in = _ps_roi_pool_backward( grad_output[0], rois, channel_mapping, @@ -112,17 +118,86 @@ class PSROIPoolFunction : public torch::autograd::Function { input_shape[1], input_shape[2], input_shape[3]); - return {grad_in, Variable(), Variable(), Variable(), Variable()}; + + return {grad_in, + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable()}; + } +}; + +// TODO: There should be an easier way to do this +class PSROIPoolBackwardFunction + : public torch::autograd::Function { + public: + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& grad, + const torch::autograd::Variable& rois, + const torch::autograd::Variable& channel_mapping, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { + at::AutoNonVariableTypeMode g; + auto grad_in = _ps_roi_pool_backward( + grad, + rois, + channel_mapping, + spatial_scale, + pooled_height, + pooled_width, + batch_size, + channels, + height, + width); + + return {grad_in}; + } + + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { + TORCH_CHECK(0, "double backwards on ps_roi_pool not supported"); } }; -std::tuple ps_roi_pool( - const Tensor& input, - const Tensor& rois, - const double spatial_scale, - const int64_t pooled_height, - const int64_t pooled_width) { +std::tuple PSROIPool_autograd( + const at::Tensor& input, + const at::Tensor& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { auto result = PSROIPoolFunction::apply( input, rois, spatial_scale, pooled_height, pooled_width); - return std::tuple(result[0], result[1]); + + return std::make_tuple(result[0], result[1]); +} + +at::Tensor PSROIPool_backward_autograd( + const at::Tensor& grad, + const at::Tensor& rois, + const at::Tensor& channel_mapping, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { + return PSROIPoolBackwardFunction::apply( + grad, + rois, + channel_mapping, + spatial_scale, + pooled_height, + pooled_width, + batch_size, + channels, + height, + width)[0]; } diff --git a/torchvision/csrc/ROIAlign.h b/torchvision/csrc/ROIAlign.h index e292da9a033..708981f061e 100644 --- a/torchvision/csrc/ROIAlign.h +++ b/torchvision/csrc/ROIAlign.h @@ -3,70 +3,80 @@ #include "cpu/vision_cpu.h" #ifdef WITH_CUDA +#include "autocast.h" #include "cuda/vision_cuda.h" #endif +#ifdef WITH_HIP +#include "autocast.h" +#include "hip/vision_cuda.h" +#endif + +// TODO: put this stuff in torchvision namespace -// Interface for Python -at::Tensor ROIAlign_forward( +// roi_align dispatch nexus +at::Tensor roi_align( const at::Tensor& input, // Input feature map. const at::Tensor& rois, // List of ROIs to pool over. - const double spatial_scale, // The scale of the image features. ROIs will be + double spatial_scale, // The scale of the image features. ROIs will be // scaled to this. - const int64_t pooled_height, // The height of the pooled feature map. - const int64_t pooled_width, // The width of the pooled feature - const int64_t sampling_ratio, // The number of points to sample in each bin - const bool aligned) // The flag for pixel shift + int64_t pooled_height, // The height of the pooled feature map. + int64_t pooled_width, // The width of the pooled feature + int64_t sampling_ratio, // The number of points to sample in each bin + bool aligned) // The flag for pixel shift // along each axis. { - if (input.type().is_cuda()) { -#ifdef WITH_CUDA - return ROIAlign_forward_cuda( - input, - rois, - spatial_scale, - pooled_height, - pooled_width, - sampling_ratio, - aligned); -#else - AT_ERROR("Not compiled with GPU support"); -#endif - } - return ROIAlign_forward_cpu( - input, rois, spatial_scale, pooled_height, pooled_width, sampling_ratio, aligned); + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::roi_align", "") + .typed(); + return op.call( + input, + rois, + spatial_scale, + pooled_height, + pooled_width, + sampling_ratio, + aligned); } -at::Tensor ROIAlign_backward( - const at::Tensor& grad, +#if defined(WITH_CUDA) || defined(WITH_HIP) +at::Tensor ROIAlign_autocast( + const at::Tensor& input, const at::Tensor& rois, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int batch_size, - const int channels, - const int height, - const int width, - const int sampling_ratio, - const bool aligned) { - if (grad.type().is_cuda()) { -#ifdef WITH_CUDA - return ROIAlign_backward_cuda( - grad, - rois, - spatial_scale, - pooled_height, - pooled_width, - batch_size, - channels, - height, - width, - sampling_ratio, - aligned); -#else - AT_ERROR("Not compiled with GPU support"); + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio, + bool aligned) { + c10::impl::ExcludeDispatchKeyGuard no_autocast(c10::DispatchKey::Autocast); + return roi_align( + at::autocast::cached_cast(at::kFloat, input), + at::autocast::cached_cast(at::kFloat, rois), + spatial_scale, + pooled_height, + pooled_width, + sampling_ratio, + aligned) + .to(input.scalar_type()); +} #endif - } - return ROIAlign_backward_cpu( + +at::Tensor _roi_align_backward( + const at::Tensor& grad, + const at::Tensor& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width, + int64_t sampling_ratio, + bool aligned) { + static auto op = + c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::_roi_align_backward", "") + .typed(); + return op.call( grad, rois, spatial_scale, @@ -80,23 +90,17 @@ at::Tensor ROIAlign_backward( aligned); } -using namespace at; -using torch::Tensor; -using torch::autograd::AutogradContext; -using torch::autograd::Variable; -using torch::autograd::variable_list; - class ROIAlignFunction : public torch::autograd::Function { public: - static variable_list forward( - AutogradContext* ctx, - Variable input, - Variable rois, - const double spatial_scale, - const int64_t pooled_height, - const int64_t pooled_width, - const int64_t sampling_ratio, - const bool aligned) { + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& input, + const torch::autograd::Variable& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio, + bool aligned) { ctx->saved_data["spatial_scale"] = spatial_scale; ctx->saved_data["pooled_height"] = pooled_height; ctx->saved_data["pooled_width"] = pooled_width; @@ -104,7 +108,8 @@ class ROIAlignFunction : public torch::autograd::Function { ctx->saved_data["aligned"] = aligned; ctx->saved_data["input_shape"] = input.sizes(); ctx->save_for_backward({rois}); - auto result = ROIAlign_forward( + at::AutoNonVariableTypeMode g; + auto result = roi_align( input, rois, spatial_scale, @@ -115,14 +120,14 @@ class ROIAlignFunction : public torch::autograd::Function { return {result}; } - static variable_list backward( - AutogradContext* ctx, - variable_list grad_output) { + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { // Use data saved in forward auto saved = ctx->get_saved_variables(); auto rois = saved[0]; auto input_shape = ctx->saved_data["input_shape"].toIntList(); - auto grad_in = ROIAlign_backward( + auto grad_in = _roi_align_backward( grad_output[0], rois, ctx->saved_data["spatial_scale"].toDouble(), @@ -134,19 +139,64 @@ class ROIAlignFunction : public torch::autograd::Function { input_shape[3], ctx->saved_data["sampling_ratio"].toInt(), ctx->saved_data["aligned"].toBool()); - return { - grad_in, Variable(), Variable(), Variable(), Variable(), Variable(), Variable()}; + return {grad_in, + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable()}; + } +}; + +// TODO: There should be an easier way to do this +class ROIAlignBackwardFunction + : public torch::autograd::Function { + public: + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& grad, + const torch::autograd::Variable& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width, + int64_t sampling_ratio, + bool aligned) { + at::AutoNonVariableTypeMode g; + auto result = _roi_align_backward( + grad, + rois, + spatial_scale, + pooled_height, + pooled_width, + batch_size, + channels, + height, + width, + sampling_ratio, + aligned); + return {result}; + } + + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { + TORCH_CHECK(0, "double backwards on roi_align not supported"); } }; -Tensor roi_align( - const Tensor& input, - const Tensor& rois, - const double spatial_scale, - const int64_t pooled_height, - const int64_t pooled_width, - const int64_t sampling_ratio, - const bool aligned) { +at::Tensor ROIAlign_autograd( + const at::Tensor& input, + const at::Tensor& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio, + bool aligned) { return ROIAlignFunction::apply( input, rois, @@ -156,3 +206,29 @@ Tensor roi_align( sampling_ratio, aligned)[0]; } + +at::Tensor ROIAlign_backward_autograd( + const at::Tensor& grad, + const at::Tensor& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width, + int64_t sampling_ratio, + bool aligned) { + return ROIAlignBackwardFunction::apply( + grad, + rois, + spatial_scale, + pooled_height, + pooled_width, + batch_size, + channels, + height, + width, + sampling_ratio, + aligned)[0]; +} diff --git a/torchvision/csrc/ROIPool.h b/torchvision/csrc/ROIPool.h index 79b40293176..7950005f1bd 100644 --- a/torchvision/csrc/ROIPool.h +++ b/torchvision/csrc/ROIPool.h @@ -3,56 +3,64 @@ #include "cpu/vision_cpu.h" #ifdef WITH_CUDA +#include "autocast.h" #include "cuda/vision_cuda.h" #endif +#ifdef WITH_HIP +#include "autocast.h" +#include "hip/vision_cuda.h" +#endif + +// TODO: put this stuff in torchvision namespace -std::tuple ROIPool_forward( +std::tuple roi_pool( const at::Tensor& input, const at::Tensor& rois, - const double spatial_scale, - const int64_t pooled_height, - const int64_t pooled_width) { - if (input.type().is_cuda()) { -#ifdef WITH_CUDA - return ROIPool_forward_cuda( - input, rois, spatial_scale, pooled_height, pooled_width); -#else - AT_ERROR("Not compiled with GPU support"); -#endif - } - return ROIPool_forward_cpu( - input, rois, spatial_scale, pooled_height, pooled_width); + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::roi_pool", "") + .typed(); + return op.call(input, rois, spatial_scale, pooled_height, pooled_width); } -at::Tensor ROIPool_backward( +#if defined(WITH_CUDA) || defined(WITH_HIP) +std::tuple ROIPool_autocast( + const at::Tensor& input, + const at::Tensor& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { + c10::impl::ExcludeDispatchKeyGuard no_autocast(c10::DispatchKey::Autocast); + auto result = roi_pool( + at::autocast::cached_cast(at::kFloat, input), + at::autocast::cached_cast(at::kFloat, rois), + spatial_scale, + pooled_height, + pooled_width); + + return std::make_tuple( + std::get<0>(result).to(input.scalar_type()), + std::get<1>(result).to(input.scalar_type())); +} +#endif + +at::Tensor _roi_pool_backward( const at::Tensor& grad, const at::Tensor& rois, const at::Tensor& argmax, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int batch_size, - const int channels, - const int height, - const int width) { - if (grad.type().is_cuda()) { -#ifdef WITH_CUDA - return ROIPool_backward_cuda( - grad, - rois, - argmax, - spatial_scale, - pooled_height, - pooled_width, - batch_size, - channels, - height, - width); -#else - AT_ERROR("Not compiled with GPU support"); -#endif - } - return ROIPool_backward_cpu( + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { + static auto op = c10::Dispatcher::singleton() + .findSchemaOrThrow("torchvision::_roi_pool_backward", "") + .typed(); + return op.call( grad, rois, argmax, @@ -65,43 +73,40 @@ at::Tensor ROIPool_backward( width); } -using namespace at; -using torch::Tensor; -using torch::autograd::AutogradContext; -using torch::autograd::Variable; -using torch::autograd::variable_list; - class ROIPoolFunction : public torch::autograd::Function { public: - static variable_list forward( - AutogradContext* ctx, - Variable input, - Variable rois, - const double spatial_scale, - const int64_t pooled_height, - const int64_t pooled_width) { + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& input, + const torch::autograd::Variable& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { ctx->saved_data["spatial_scale"] = spatial_scale; ctx->saved_data["pooled_height"] = pooled_height; ctx->saved_data["pooled_width"] = pooled_width; ctx->saved_data["input_shape"] = input.sizes(); - auto result = ROIPool_forward( - input, rois, spatial_scale, pooled_height, pooled_width); + at::AutoNonVariableTypeMode g; + auto result = + roi_pool(input, rois, spatial_scale, pooled_height, pooled_width); + auto output = std::get<0>(result); auto argmax = std::get<1>(result); ctx->save_for_backward({rois, argmax}); ctx->mark_non_differentiable({argmax}); + return {output, argmax}; } - static variable_list backward( - AutogradContext* ctx, - variable_list grad_output) { + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { // Use data saved in forward auto saved = ctx->get_saved_variables(); auto rois = saved[0]; auto argmax = saved[1]; auto input_shape = ctx->saved_data["input_shape"].toIntList(); - auto grad_in = ROIPool_backward( + auto grad_in = _roi_pool_backward( grad_output[0], rois, argmax, @@ -112,17 +117,86 @@ class ROIPoolFunction : public torch::autograd::Function { input_shape[1], input_shape[2], input_shape[3]); - return {grad_in, Variable(), Variable(), Variable(), Variable()}; + + return {grad_in, + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable(), + torch::autograd::Variable()}; } }; -std::tuple roi_pool( - const Tensor& input, - const Tensor& rois, - const double spatial_scale, - const int64_t pooled_height, - const int64_t pooled_width) { +// TODO: There should be an easier way to do this +class ROIPoolBackwardFunction + : public torch::autograd::Function { + public: + static torch::autograd::variable_list forward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::Variable& grad, + const torch::autograd::Variable& rois, + const torch::autograd::Variable& argmax, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { + at::AutoNonVariableTypeMode g; + auto grad_in = _roi_pool_backward( + grad, + rois, + argmax, + spatial_scale, + pooled_height, + pooled_width, + batch_size, + channels, + height, + width); + + return {grad_in}; + } + + static torch::autograd::variable_list backward( + torch::autograd::AutogradContext* ctx, + const torch::autograd::variable_list& grad_output) { + TORCH_CHECK(0, "double backwards on roi_pool not supported"); + } +}; + +std::tuple ROIPool_autograd( + const at::Tensor& input, + const at::Tensor& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { auto result = ROIPoolFunction::apply( input, rois, spatial_scale, pooled_height, pooled_width); - return std::tuple(result[0], result[1]); + + return std::make_tuple(result[0], result[1]); +} + +at::Tensor ROIPool_backward_autograd( + const at::Tensor& grad, + const at::Tensor& rois, + const at::Tensor& argmax, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { + return ROIPoolBackwardFunction::apply( + grad, + rois, + argmax, + spatial_scale, + pooled_height, + pooled_width, + batch_size, + channels, + height, + width)[0]; } diff --git a/torchvision/csrc/autocast.h b/torchvision/csrc/autocast.h new file mode 100644 index 00000000000..1f954464b72 --- /dev/null +++ b/torchvision/csrc/autocast.h @@ -0,0 +1,5 @@ +#pragma once + +#if defined(WITH_CUDA) || defined(WITH_HIP) +#include +#endif diff --git a/torchvision/csrc/cpu/DeformConv_cpu.cpp b/torchvision/csrc/cpu/DeformConv_cpu.cpp index 65e9c0fe450..0212be55aa4 100644 --- a/torchvision/csrc/cpu/DeformConv_cpu.cpp +++ b/torchvision/csrc/cpu/DeformConv_cpu.cpp @@ -74,15 +74,13 @@ #include #include -using namespace at; - const int kMaxParallelImgs = 32; template static scalar_t bilinear_interpolate( const scalar_t* in, - const int height, - const int width, + int height, + int width, scalar_t h, scalar_t w) { if (h <= -1 || height <= h || w <= -1 || width <= w) { @@ -119,24 +117,26 @@ static scalar_t bilinear_interpolate( template static void deformable_im2col_kernel( - const int n, + int n, const scalar_t* input, const scalar_t* offset, - const int height, - const int width, - const int weight_h, - const int weight_w, - const int pad_h, - const int pad_w, - const int stride_h, - const int stride_w, - const int dil_h, - const int dil_w, - const int batch_sz, - const int n_in_channels, - const int n_offset_grps, - const int out_h, - const int out_w, + const scalar_t* mask, + int height, + int width, + int weight_h, + int weight_w, + int pad_h, + int pad_w, + int stride_h, + int stride_w, + int dil_h, + int dil_w, + int batch_sz, + int n_in_channels, + int n_offset_grps, + int out_h, + int out_w, + bool use_mask, scalar_t* columns) { for (int index = 0; index != n; ++index) { const int out_x = index % out_w; @@ -159,16 +159,31 @@ static void deformable_im2col_kernel( (out_b * n_offset_grps + grp_idx) * 2 * weight_h * weight_w * out_h * out_w; + auto mask_ptr = mask; + if (use_mask) { + mask_ptr += (out_b * n_offset_grps + grp_idx) * weight_h * weight_w * + out_h * out_w; + } + for (int i = 0; i < weight_h; ++i) { for (int j = 0; j < weight_w; ++j) { - const int offset_idx = 2 * (i * weight_w + j); + const int mask_idx = i * weight_w + j; + const int offset_idx = 2 * mask_idx; + + scalar_t mask_value = 1; + if (use_mask) { + mask_value = + mask_ptr[mask_idx * (out_h * out_w) + out_y * out_w + out_x]; + } + const scalar_t offset_h = offset_ptr[offset_idx * (out_h * out_w) + out_y * out_w + out_x]; const scalar_t offset_w = offset_ptr [(offset_idx + 1) * (out_h * out_w) + out_y * out_w + out_x]; const scalar_t y = (out_y * stride_h - pad_h) + i * dil_h + offset_h; const scalar_t x = (out_x * stride_w - pad_w) + j * dil_w + offset_w; - *columns_ptr = bilinear_interpolate(input_ptr, height, width, y, x); + *columns_ptr = + mask_value * bilinear_interpolate(input_ptr, height, width, y, x); columns_ptr += batch_sz * out_h * out_w; } } @@ -176,8 +191,9 @@ static void deformable_im2col_kernel( } static void deformable_im2col( - const at::Tensor input, - const at::Tensor data_offset, + const at::Tensor& input, + const at::Tensor& data_offset, + const at::Tensor& data_mask, int n_in_channels, int height, int width, @@ -193,6 +209,7 @@ static void deformable_im2col( int out_w, int parallel_imgs, int deformable_group, + bool use_mask, at::Tensor data_col) { int num_kernels = n_in_channels * out_h * out_w * parallel_imgs; @@ -202,6 +219,7 @@ static void deformable_im2col( num_kernels, input.data_ptr(), data_offset.data_ptr(), + data_mask.data_ptr(), height, width, weight_h, @@ -217,6 +235,7 @@ static void deformable_im2col( deformable_group, out_h, out_w, + use_mask, data_col.data_ptr()); })); } @@ -234,22 +253,27 @@ at::Tensor DeformConv2d_forward_cpu( const at::Tensor& input_param, const at::Tensor& weight_param, const at::Tensor& offset_param, - const at::Tensor& bias, - std::pair stride, - std::pair pad, - std::pair dilation, - int n_weight_grps, - int n_offset_grps) { - at::Tensor input = input_param; - at::Tensor offset = offset_param; - at::Tensor weight = weight_param; + const at::Tensor& mask_param, + const at::Tensor& bias_param, + int64_t stride_h, + int64_t stride_w, + int64_t pad_h, + int64_t pad_w, + int64_t dil_h, + int64_t dil_w, + int64_t n_weight_grps, + int64_t n_offset_grps, + bool use_mask) { + at::Tensor input = input_param.contiguous(); + at::Tensor offset = offset_param.contiguous(); + at::Tensor weight = weight_param.contiguous(); + at::Tensor mask = mask_param.contiguous(); + at::Tensor bias = bias_param.contiguous(); TORCH_CHECK(input.ndimension() == 4); TORCH_CHECK(offset.ndimension() == 4); + TORCH_CHECK(!use_mask || mask.ndimension() == 4); TORCH_CHECK(weight.ndimension() == 4); - TORCH_CHECK(input.is_contiguous()); - TORCH_CHECK(offset.is_contiguous()); - TORCH_CHECK(weight.is_contiguous()); TORCH_CHECK(input.device().is_cpu(), "input must be a CPU tensor"); int batch_sz = input.size(0); @@ -265,15 +289,6 @@ at::Tensor DeformConv2d_forward_cpu( int weight_h = weight.size(2); int weight_w = weight.size(3); - int stride_h = stride.first; - int stride_w = stride.second; - - int pad_h = pad.first; - int pad_w = pad.second; - - int dil_h = dilation.first; - int dil_w = dilation.second; - int ker_h = dil_h * (weight_h - 1) + 1; int ker_w = dil_w * (weight_w - 1) + 1; int out_h = ((in_h + 2 * pad_h - ker_h) / stride_h) + 1; @@ -302,6 +317,12 @@ at::Tensor DeformConv2d_forward_cpu( offset.size(1), " expected: ", n_offset_grps * 2 * weight_h * weight_w); + TORCH_CHECK( + (!use_mask || mask.size(1) == n_offset_grps * weight_h * weight_w), + "mask.shape[1] is not valid: got: ", + mask.size(1), + " expected: ", + n_offset_grps * weight_h * weight_w); TORCH_CHECK(input.size(1) % n_offset_grps == 0); TORCH_CHECK( @@ -318,6 +339,19 @@ at::Tensor DeformConv2d_forward_cpu( ", ", out_w, ")"); + TORCH_CHECK((mask.size(0) == input.size(0)), "invalid batch size of mask"); + TORCH_CHECK( + (!use_mask || (mask.size(2) == out_h && mask.size(3) == out_w)), + "offset output dims: (", + mask.size(2), + ", ", + mask.size(3), + ") - ", + "computed output dims: (", + out_h, + ", ", + out_w, + ")"); TORCH_CHECK( out_h > 0 && out_w > 0, "Calculated output size too small - out_h: ", @@ -326,6 +360,9 @@ at::Tensor DeformConv2d_forward_cpu( out_w); auto out = at::zeros({batch_sz, out_channels, out_h, out_w}, input.options()); + if (batch_sz == 0) { + return out; + } // Separate batches into blocks out = out.view({batch_sz / n_parallel_imgs, @@ -335,11 +372,21 @@ at::Tensor DeformConv2d_forward_cpu( out_w}); input = input.view( {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + offset = offset.view({batch_sz / n_parallel_imgs, n_parallel_imgs, n_offset_grps * 2 * weight_h * weight_w, out_h, out_w}); + + if (use_mask) { + mask = mask.view({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * weight_h * weight_w, + out_h, + out_w}); + } + at::Tensor out_buf = at::zeros( {batch_sz / n_parallel_imgs, out_channels, @@ -367,6 +414,7 @@ at::Tensor DeformConv2d_forward_cpu( deformable_im2col( input[b], offset[b], + mask[b], n_in_channels, in_h, in_w, @@ -382,6 +430,7 @@ at::Tensor DeformConv2d_forward_cpu( out_w, n_parallel_imgs, n_offset_grps, + use_mask, columns); columns = columns.view( @@ -393,7 +442,7 @@ at::Tensor DeformConv2d_forward_cpu( .view_as(out_buf[b][g]); } columns = - columns.view({columns.size(0) * columns.size(1), columns.size(2)}); + columns.view({columns.size(0) * columns.size(1), columns.size(2)}); } out_buf = out_buf.view({batch_sz / n_parallel_imgs, @@ -410,24 +459,26 @@ at::Tensor DeformConv2d_forward_cpu( template static void deformable_col2im_kernel( - const int n, + int n, const scalar_t* col, const scalar_t* offset, - const int channels, - const int height, - const int width, - const int kernel_h, - const int kernel_w, - const int pad_h, - const int pad_w, - const int stride_h, - const int stride_w, - const int dilation_h, - const int dilation_w, - const int batch_sz, - const int n_offset_grps, - const int out_h, - const int out_w, + const scalar_t* mask, + int channels, + int height, + int width, + int kernel_h, + int kernel_w, + int pad_h, + int pad_w, + int stride_h, + int stride_w, + int dilation_h, + int dilation_w, + int batch_sz, + int n_offset_grps, + int out_h, + int out_w, + bool use_mask, scalar_t* grad_im) { for (int index = 0; index != n; ++index) { const int out_x = index % out_w; @@ -443,12 +494,27 @@ static void deformable_col2im_kernel( auto offset_ptr = offset + (b * n_offset_grps + offset_grp) * 2 * kernel_h * kernel_w * out_h * out_w; - const int offset_h_ptr = - ((2 * (i * kernel_w + j)) * out_h + out_y) * out_w + out_x; - const int offset_w_ptr = - ((2 * (i * kernel_w + j) + 1) * out_h + out_y) * out_w + out_x; + + auto mask_ptr = mask; + if (use_mask) { + mask_ptr += (b * n_offset_grps + offset_grp) * kernel_h * kernel_w * + out_h * out_w; + } + + const int mask_idx = i * kernel_w + j; + const int offset_idx = 2 * mask_idx; + + const int offset_h_ptr = ((offset_idx)*out_h + out_y) * out_w + out_x; + const int offset_w_ptr = ((offset_idx + 1) * out_h + out_y) * out_w + out_x; + const scalar_t offset_h = offset_ptr[offset_h_ptr]; const scalar_t offset_w = offset_ptr[offset_w_ptr]; + + scalar_t mask_value = 1; + if (use_mask) { + mask_value = mask_ptr[(mask_idx * out_h + out_y) * out_w + out_x]; + } + const scalar_t y = (out_y * stride_h - pad_h) + i * dilation_h + offset_h; const scalar_t x = (out_x * stride_w - pad_w) + j * dilation_w + offset_w; @@ -460,7 +526,7 @@ static void deformable_col2im_kernel( std::abs(y - yp) < 1 && std::abs(x - xp) < 1) { int grad_pos = ((b * channels + c) * height + yp) * width + xp; scalar_t weight = (1 - std::abs(y - yp)) * (1 - std::abs(x - xp)); - grad_im[grad_pos] += weight * col[index]; + grad_im[grad_pos] += mask_value * weight * col[index]; } } } @@ -468,21 +534,23 @@ static void deformable_col2im_kernel( } static void compute_grad_input( - const at::Tensor columns, - const at::Tensor offset, - const int channels, - const int height, - const int width, - const int weight_h, - const int weight_w, - const int pad_h, - const int pad_w, - const int stride_h, - const int stride_w, - const int dilation_h, - const int dilation_w, - const int parallel_imgs, - const int n_offset_grps, + const at::Tensor& columns, + const at::Tensor& offset, + const at::Tensor& mask, + int channels, + int height, + int width, + int weight_h, + int weight_w, + int pad_h, + int pad_w, + int stride_h, + int stride_w, + int dilation_h, + int dilation_w, + int parallel_imgs, + int n_offset_grps, + bool use_mask, at::Tensor grad_im) { int out_h = (height + 2 * pad_h - (dilation_h * (weight_h - 1) + 1)) / stride_h + 1; @@ -497,6 +565,7 @@ static void compute_grad_input( num_kernels, columns.data_ptr(), offset.data_ptr(), + mask.data_ptr(), channels, height, width, @@ -512,6 +581,7 @@ static void compute_grad_input( n_offset_grps, out_h, out_w, + use_mask, grad_im.data_ptr()); })); } @@ -519,8 +589,8 @@ static void compute_grad_input( template static scalar_t get_coordinate_weight( const scalar_t* im_data, - const int height, - const int width, + int height, + int width, scalar_t y, scalar_t x, bool is_y_direction) { @@ -551,31 +621,38 @@ static scalar_t get_coordinate_weight( template static void deformable_col2im_coord_kernel( - const int n, + int n, const scalar_t* col, const scalar_t* im, const scalar_t* offset, - const int channels, - const int height, - const int width, - const int weight_h, - const int weight_w, - const int pad_h, - const int pad_w, - const int stride_h, - const int stride_w, - const int dilation_h, - const int dilation_w, - const int batch_sz, - const int offset_channels, - const int n_offset_grps, - const int out_h, - const int out_w, - scalar_t* grad_offset) { + const scalar_t* mask, + int channels, + int height, + int width, + int weight_h, + int weight_w, + int pad_h, + int pad_w, + int stride_h, + int stride_w, + int dilation_h, + int dilation_w, + int batch_sz, + int offset_channels, + int n_offset_grps, + int out_h, + int out_w, + bool use_mask, + scalar_t* grad_offset, + scalar_t* grad_mask) { for (int index = 0; index != n; ++index) { - scalar_t val = 0; + scalar_t grad_offset_val = 0; + scalar_t grad_mask_val = 0; + int w = index % out_w; int h = (index / out_w) % out_h; + int w_w = (index / (out_w * out_h * 2)) % weight_w; + int w_h = (index / (out_w * out_h * 2 * weight_w)) % weight_h; int c = (index / (out_w * out_h)) % offset_channels; int b = index / (out_w * out_h * offset_channels); @@ -593,8 +670,14 @@ static void deformable_col2im_coord_kernel( (b * n_offset_grps + offset_grp) * 2 * weight_h * weight_w * out_h * out_w; + auto mask_ptr = mask; + if (use_mask) { + mask_ptr += (b * n_offset_grps + offset_grp) * weight_h * weight_w * + out_h * out_w; + } + const int offset_c = c - offset_grp * 2 * weight_h * weight_w; - const int is_y_direction = offset_c % 2 == 0; + const bool is_y_direction = offset_c % 2 == 0; const int c_bound = c_per_offset_grp * weight_h * weight_w; for (int col_c = (offset_c / 2); col_c < c_bound; col_c += col_step) { @@ -605,44 +688,71 @@ static void deformable_col2im_coord_kernel( int j = (col_pos / (out_w * out_h * batch_sz)) % weight_w; int i = (col_pos / (out_w * out_h * batch_sz * weight_w)) % weight_h; + const int mask_idx = i * weight_w + j; + const int offset_h_idx = - (((2 * (i * weight_w + j)) * out_h + out_y) * out_w + out_x); + (((2 * mask_idx) * out_h + out_y) * out_w + out_x); const int offset_w_idx = - (((2 * (i * weight_w + j) + 1) * out_h + out_y) * out_w + out_x); + (((2 * mask_idx + 1) * out_h + out_y) * out_w + out_x); const scalar_t offset_h = offset_ptr[offset_h_idx]; const scalar_t offset_w = offset_ptr[offset_w_idx]; + scalar_t mask_value = 1; + if (use_mask) { + mask_value = mask_ptr[(mask_idx * out_h + out_y) * out_w + out_x]; + } + scalar_t y = (out_y * stride_h - pad_h) + i * dilation_h + offset_h; scalar_t x = (out_x * stride_w - pad_w) + j * dilation_w + offset_w; const scalar_t weight = get_coordinate_weight(im_ptr, height, width, y, x, is_y_direction); - val += weight * col_ptr[col_pos]; + grad_offset_val += mask_value * weight * col_ptr[col_pos]; + + if (use_mask && is_y_direction) { + grad_mask_val += col_ptr[col_pos] * + bilinear_interpolate(im_ptr, height, width, y, x); + } + im_ptr += height * width; } - grad_offset[index] = val; + grad_offset[index] = grad_offset_val; + + if (use_mask && is_y_direction) { + const int idx = + ((((b * n_offset_grps + offset_grp) * weight_h + w_h) * weight_w + + w_w) * + out_h + + h) * + out_w + + w; + grad_mask[idx] = grad_mask_val; + } } } -static void compute_grad_offset( - const at::Tensor columns, - const at::Tensor input, - const at::Tensor offset, - const int channels, - const int height, - const int width, - const int weight_h, - const int weight_w, - const int pad_h, - const int pad_w, - const int stride_h, - const int stride_w, - const int dilation_h, - const int dilation_w, - const int parallel_imgs, - const int n_offset_grps, - at::Tensor grad_offset) { +static void compute_grad_offset_and_mask( + const at::Tensor& columns, + const at::Tensor& input, + const at::Tensor& offset, + const at::Tensor& mask, + int channels, + int height, + int width, + int weight_h, + int weight_w, + int pad_h, + int pad_w, + int stride_h, + int stride_w, + int dilation_h, + int dilation_w, + int parallel_imgs, + int n_offset_grps, + bool use_mask, + at::Tensor grad_offset, + at::Tensor grad_mask) { int out_h = (height + 2 * pad_h - (dilation_h * (weight_h - 1) + 1)) / stride_h + 1; int out_w = @@ -657,6 +767,7 @@ static void compute_grad_offset( columns.data_ptr(), input.data_ptr(), offset.data_ptr(), + mask.data_ptr(), channels, height, width, @@ -673,21 +784,29 @@ static void compute_grad_offset( n_offset_grps, out_h, out_w, - grad_offset.data_ptr()); + use_mask, + grad_offset.data_ptr(), + grad_mask.data_ptr()); })); } -static std::tuple deform_conv2d_backward_input_cpu( +static std::tuple +deform_conv2d_backward_input_cpu( at::Tensor input, at::Tensor weight, at::Tensor offset, + at::Tensor mask, at::Tensor grad_out, - std::pair stride, - std::pair pad, - std::pair dilation, + int stride_h, + int stride_w, + int pad_h, + int pad_w, + int dil_h, + int dil_w, int n_weight_grps, int n_offset_grps, - int n_parallel_imgs) { + int n_parallel_imgs, + bool use_mask) { int batch_sz = input.size(0); int n_in_channels = input.size(1); int in_h = input.size(2); @@ -699,20 +818,17 @@ static std::tuple deform_conv2d_backward_input_cpu( int weight_h = weight.size(2); int weight_w = weight.size(3); - int stride_h = stride.first; - int stride_w = stride.second; - - int pad_h = pad.first; - int pad_w = pad.second; - - int dil_h = dilation.first; - int dil_w = dilation.second; - long out_h = (in_h + 2 * pad_h - (dil_h * (weight_h - 1) + 1)) / stride_h + 1; long out_w = (in_w + 2 * pad_w - (dil_w * (weight_w - 1) + 1)) / stride_w + 1; auto grad_input = at::zeros_like(input); auto grad_offset = at::zeros_like(offset); + auto grad_mask = at::zeros_like(mask); + + if (batch_sz == 0) { + return std::make_tuple(grad_input, grad_offset, grad_mask); + } + auto columns = at::empty( {n_in_channels * weight_w * weight_h, n_parallel_imgs * out_h * out_w}, input.options()); @@ -722,6 +838,7 @@ static std::tuple deform_conv2d_backward_input_cpu( {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); input = input.reshape( {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + grad_offset = grad_offset.reshape({batch_sz / n_parallel_imgs, n_parallel_imgs, n_offset_grps * 2 * weight_h * weight_w, @@ -733,12 +850,27 @@ static std::tuple deform_conv2d_backward_input_cpu( out_h, out_w}); - grad_out = grad_out.reshape({batch_sz / n_parallel_imgs, - n_parallel_imgs, - n_weight_grps, - n_out_channels / n_weight_grps, - out_h, - out_w}).permute({0, 2, 3, 1, 4, 5}); + if (use_mask) { + grad_mask = grad_mask.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * weight_h * weight_w, + out_h, + out_w}); + mask = mask.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * weight_h * weight_w, + out_h, + out_w}); + } + + grad_out = grad_out + .reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_weight_grps, + n_out_channels / n_weight_grps, + out_h, + out_w}) + .permute({0, 2, 3, 1, 4, 5}); weight = weight.reshape({n_weight_grps, weight.size(0) / n_weight_grps, @@ -757,10 +889,11 @@ static std::tuple deform_conv2d_backward_input_cpu( weight[g].flatten(1).transpose(0, 1), grad_out[elt][g].flatten(1)); } - compute_grad_offset( + compute_grad_offset_and_mask( columns, input[elt], offset[elt], + mask[elt], n_in_channels, in_h, in_w, @@ -774,11 +907,14 @@ static std::tuple deform_conv2d_backward_input_cpu( dil_w, n_parallel_imgs, n_offset_grps, - grad_offset[elt]); + use_mask, + grad_offset[elt], + grad_mask[elt]); compute_grad_input( columns, offset[elt], + mask[elt], n_in_channels, in_h, in_w, @@ -792,6 +928,7 @@ static std::tuple deform_conv2d_backward_input_cpu( dil_w, n_parallel_imgs, n_offset_grps, + use_mask, grad_input[elt]); } @@ -799,20 +936,30 @@ static std::tuple deform_conv2d_backward_input_cpu( grad_offset = grad_offset.view( {batch_sz, n_offset_grps * 2 * weight_h * weight_w, out_h, out_w}); - return std::make_tuple(grad_input, grad_offset); + if (use_mask) { + grad_mask = grad_mask.view( + {batch_sz, n_offset_grps * weight_h * weight_w, out_h, out_w}); + } + + return std::make_tuple(grad_input, grad_offset, grad_mask); } static at::Tensor deform_conv2d_backward_parameters_cpu( at::Tensor input, - at::Tensor weight, + const at::Tensor& weight, at::Tensor offset, - at::Tensor grad_out, - std::pair stride, - std::pair pad, - std::pair dilation, + at::Tensor mask, + const at::Tensor& grad_out, + int stride_h, + int stride_w, + int pad_h, + int pad_w, + int dil_h, + int dil_w, int n_weight_grps, int n_offset_grps, - int n_parallel_imgs) { + int n_parallel_imgs, + bool use_mask) { int batch_sz = input.size(0); int n_in_channels = input.size(1); int in_h = input.size(2); @@ -824,37 +971,41 @@ static at::Tensor deform_conv2d_backward_parameters_cpu( int weight_h = weight.size(2); int weight_w = weight.size(3); - int stride_h = stride.first; - int stride_w = stride.second; - - int pad_h = pad.first; - int pad_w = pad.second; - - int dil_h = dilation.first; - int dil_w = dilation.second; - long out_h = grad_out.size(2); long out_w = grad_out.size(3); auto grad_weight = at::zeros_like(weight); + if (batch_sz == 0) { + return grad_weight; + } - at::Tensor grad_out_buf = grad_out.reshape( - {batch_sz / n_parallel_imgs, - n_parallel_imgs, - n_weight_grps, - n_out_channels / n_weight_grps, - out_h, - out_w} - ).permute({0, 2, 3, 1, 4, 5}).contiguous(); + at::Tensor grad_out_buf = grad_out + .reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_weight_grps, + n_out_channels / n_weight_grps, + out_h, + out_w}) + .permute({0, 2, 3, 1, 4, 5}) + .contiguous(); input = input.reshape( {batch_sz / n_parallel_imgs, n_parallel_imgs, n_in_channels, in_h, in_w}); + offset = offset.reshape({batch_sz / n_parallel_imgs, n_parallel_imgs, n_offset_grps * 2 * weight_h * weight_w, out_h, out_w}); + if (use_mask) { + mask = mask.reshape({batch_sz / n_parallel_imgs, + n_parallel_imgs, + n_offset_grps * weight_h * weight_w, + out_h, + out_w}); + } + grad_weight = grad_weight.view({n_weight_grps, grad_weight.size(0) / n_weight_grps, grad_weight.size(1), @@ -871,6 +1022,7 @@ static at::Tensor deform_conv2d_backward_parameters_cpu( deformable_im2col( input[elt], offset[elt], + mask[elt], n_in_channels, in_h, in_w, @@ -886,6 +1038,7 @@ static at::Tensor deform_conv2d_backward_parameters_cpu( out_w, n_parallel_imgs, n_offset_grps, + use_mask, columns); for (int g = 0; g < n_weight_grps; g++) { @@ -905,50 +1058,74 @@ static at::Tensor deform_conv2d_backward_parameters_cpu( return grad_weight; } -std::tuple +std::tuple DeformConv2d_backward_cpu( - const at::Tensor& grad_out, - const at::Tensor& input, - const at::Tensor& weight, - const at::Tensor& offset, - const at::Tensor& bias, - std::pair stride, - std::pair pad, - std::pair dilation, - int n_weight_grps, - int n_offset_grps) { + const at::Tensor& grad_out_param, + const at::Tensor& input_param, + const at::Tensor& weight_param, + const at::Tensor& offset_param, + const at::Tensor& mask_param, + const at::Tensor& bias_param, + int64_t stride_h, + int64_t stride_w, + int64_t pad_h, + int64_t pad_w, + int64_t dil_h, + int64_t dil_w, + int64_t n_weight_grps, + int64_t n_offset_grps, + bool use_mask) { + at::Tensor grad_out = grad_out_param.contiguous(); + at::Tensor input = input_param.contiguous(); + at::Tensor weight = weight_param.contiguous(); + at::Tensor offset = offset_param.contiguous(); + at::Tensor mask = mask_param.contiguous(); + at::Tensor bias = bias_param.contiguous(); + const int batch_sz = input.size(0); const int n_parallel_imgs = get_greatest_divisor_below_bound(batch_sz, kMaxParallelImgs); - auto grad_input_and_offset = deform_conv2d_backward_input_cpu( + auto grad_input_and_offset_and_mask = deform_conv2d_backward_input_cpu( input, weight, offset, + mask, grad_out, - stride, - pad, - dilation, + stride_h, + stride_w, + pad_h, + pad_w, + dil_h, + dil_w, n_weight_grps, n_offset_grps, - n_parallel_imgs); + n_parallel_imgs, + use_mask); - auto grad_input = std::get<0>(grad_input_and_offset); - auto grad_offset = std::get<1>(grad_input_and_offset); + auto grad_input = std::get<0>(grad_input_and_offset_and_mask); + auto grad_offset = std::get<1>(grad_input_and_offset_and_mask); + auto grad_mask = std::get<2>(grad_input_and_offset_and_mask); auto grad_weight = deform_conv2d_backward_parameters_cpu( input, weight, offset, + mask, grad_out, - stride, - pad, - dilation, + stride_h, + stride_w, + pad_h, + pad_w, + dil_h, + dil_w, n_weight_grps, n_offset_grps, - n_parallel_imgs); + n_parallel_imgs, + use_mask); auto grad_bias = at::ones_like(bias) * grad_out.sum({0, 2, 3}); - return std::make_tuple(grad_input, grad_weight, grad_offset, grad_bias); + return std::make_tuple( + grad_input, grad_weight, grad_offset, grad_mask, grad_bias); } diff --git a/torchvision/csrc/cpu/PSROIAlign_cpu.cpp b/torchvision/csrc/cpu/PSROIAlign_cpu.cpp index d5306ba7cac..899dbb208b6 100644 --- a/torchvision/csrc/cpu/PSROIAlign_cpu.cpp +++ b/torchvision/csrc/cpu/PSROIAlign_cpu.cpp @@ -5,11 +5,11 @@ template T bilinear_interpolate( const T* input, - const int height, - const int width, + int height, + int width, T y, T x, - const int index /* index for debug only*/) { + int index /* index for debug only*/) { // deal with cases that inverse elements are out of feature map boundary if (y < -1.0 || y > height || x < -1.0 || x > width) { // empty @@ -58,17 +58,17 @@ T bilinear_interpolate( template void PSROIAlignForwardCPU( - const int nthreads, + int nthreads, const T* input, const T spatial_scale, - const int channels, - const int height, - const int width, - const int pooled_height, - const int pooled_width, - const int sampling_ratio, + int channels, + int height, + int width, + int pooled_height, + int pooled_width, + int sampling_ratio, const T* rois, - const int channels_out, + int channels_out, T* output, int* channel_mapping) { int num_rois = nthreads / channels_out / pooled_width / pooled_height; @@ -139,8 +139,8 @@ void PSROIAlignForwardCPU( template void bilinear_interpolate_gradient( - const int height, - const int width, + int height, + int width, T y, T x, T& w1, @@ -151,7 +151,7 @@ void bilinear_interpolate_gradient( int& x_high, int& y_low, int& y_high, - const int index /* index for debug only*/) { + int index /* index for debug only*/) { // deal with cases that inverse elements are out of feature map boundary if (y < -1.0 || y > height || x < -1.0 || x > width) { // empty @@ -194,8 +194,6 @@ void bilinear_interpolate_gradient( // T val = (w1 * v1 + w2 * v2 + w3 * v3 + w4 * v4); w1 = hy * hx, w2 = hy * lx, w3 = ly * hx, w4 = ly * lx; - - return; } template @@ -205,18 +203,18 @@ inline void add(T* address, const T& val) { template void PSROIAlignBackwardCPU( - const int nthreads, + int nthreads, const T* grad_output, const int* channel_mapping, - const int num_rois, + int num_rois, const T spatial_scale, - const int channels, - const int height, - const int width, - const int pooled_height, - const int pooled_width, - const int sampling_ratio, - const int channels_out, + int channels, + int height, + int width, + int pooled_height, + int pooled_width, + int sampling_ratio, + int channels_out, T* grad_input, const T* rois) { for (int index = 0; index < nthreads; index++) { @@ -303,13 +301,15 @@ void PSROIAlignBackwardCPU( std::tuple PSROIAlign_forward_cpu( const at::Tensor& input, const at::Tensor& rois, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int sampling_ratio) { + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio) { // Check if input tensors are CPU tensors - AT_ASSERTM(input.device().is_cpu(), "input must be a CPU tensor"); - AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); + TORCH_CHECK(input.device().is_cpu(), "input must be a CPU tensor"); + TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor"); + TORCH_CHECK( + rois.size(1) == 5, "Tensor rois should have shape as Tensor[K, 5]"); at::TensorArg input_t{input, "input", 1}, rois_t{rois, "rois", 2}; @@ -321,7 +321,7 @@ std::tuple PSROIAlign_forward_cpu( int height = input.size(2); int width = input.size(3); - AT_ASSERTM( + TORCH_CHECK( channels % (pooled_height * pooled_width) == 0, "input channels must be a multiple of pooling height * pooling width"); int channels_out = channels / (pooled_height * pooled_width); @@ -336,11 +336,12 @@ std::tuple PSROIAlign_forward_cpu( return std::make_tuple(output, channel_mapping); } + auto input_ = input.contiguous(), rois_ = rois.contiguous(); AT_DISPATCH_FLOATING_TYPES_AND_HALF( input.scalar_type(), "PSROIAlign_forward", [&] { PSROIAlignForwardCPU( output_size, - input.contiguous().data(), + input_.data_ptr(), spatial_scale, channels, height, @@ -348,10 +349,10 @@ std::tuple PSROIAlign_forward_cpu( pooled_height, pooled_width, sampling_ratio, - rois.contiguous().data(), + rois_.data_ptr(), channels_out, - output.data(), - channel_mapping.data()); + output.data_ptr(), + channel_mapping.data_ptr()); }); return std::make_tuple(output, channel_mapping); } @@ -360,18 +361,18 @@ at::Tensor PSROIAlign_backward_cpu( const at::Tensor& grad, const at::Tensor& rois, const at::Tensor& channel_mapping, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int sampling_ratio, - const int batch_size, - const int channels, - const int height, - const int width) { + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { // Check if input tensors are CPU tensors - AT_ASSERTM(grad.device().is_cpu(), "grad must be a CPU tensor"); - AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); - AT_ASSERTM( + TORCH_CHECK(grad.device().is_cpu(), "grad must be a CPU tensor"); + TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor"); + TORCH_CHECK( channel_mapping.device().is_cpu(), "channel_mapping must be a CPU tensor"); @@ -392,12 +393,13 @@ at::Tensor PSROIAlign_backward_cpu( int channels_out = channels / (pooled_height * pooled_width); + auto grad_ = grad.contiguous(), rois_ = rois.contiguous(); AT_DISPATCH_FLOATING_TYPES_AND_HALF( grad.scalar_type(), "PSROIAlign_backward", [&] { PSROIAlignBackwardCPU( grad.numel(), - grad.contiguous().data(), - channel_mapping.data(), + grad_.data_ptr(), + channel_mapping.data_ptr(), num_rois, spatial_scale, channels, @@ -407,8 +409,8 @@ at::Tensor PSROIAlign_backward_cpu( pooled_width, sampling_ratio, channels_out, - grad_input.data(), - rois.contiguous().data()); + grad_input.data_ptr(), + rois_.data_ptr()); }); return grad_input; } diff --git a/torchvision/csrc/cpu/PSROIPool_cpu.cpp b/torchvision/csrc/cpu/PSROIPool_cpu.cpp index d8c738bb1be..c6e0a64cac3 100644 --- a/torchvision/csrc/cpu/PSROIPool_cpu.cpp +++ b/torchvision/csrc/cpu/PSROIPool_cpu.cpp @@ -12,14 +12,14 @@ template void PSROIPoolForward( const T* input, const T spatial_scale, - const int channels, - const int height, - const int width, - const int pooled_height, - const int pooled_width, + int channels, + int height, + int width, + int pooled_height, + int pooled_width, const T* rois, - const int channels_out, - const int num_rois, + int channels_out, + int num_rois, T* output, int* channel_mapping) { for (int n = 0; n < num_rois; ++n) { @@ -82,14 +82,14 @@ template void PSROIPoolBackward( const T* grad_output, const int* channel_mapping, - const int num_rois, + int num_rois, const T spatial_scale, - const int channels, - const int height, - const int width, - const int pooled_height, - const int pooled_width, - const int channels_out, + int channels, + int height, + int width, + int pooled_height, + int pooled_width, + int channels_out, T* grad_input, const T* rois) { for (int n = 0; n < num_rois; ++n) { @@ -146,12 +146,14 @@ void PSROIPoolBackward( std::tuple PSROIPool_forward_cpu( const at::Tensor& input, const at::Tensor& rois, - const float spatial_scale, - const int pooled_height, - const int pooled_width) { + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { // Check if input tensors are CPU tensors - AT_ASSERTM(input.device().is_cpu(), "input must be a CPU tensor"); - AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); + TORCH_CHECK(input.device().is_cpu(), "input must be a CPU tensor"); + TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor"); + TORCH_CHECK( + rois.size(1) == 5, "Tensor rois should have shape as Tensor[K, 5]"); at::TensorArg input_t{input, "input", 1}, rois_t{rois, "rois", 2}; @@ -163,7 +165,7 @@ std::tuple PSROIPool_forward_cpu( int height = input.size(2); int width = input.size(3); - AT_ASSERTM( + TORCH_CHECK( channels % (pooled_height * pooled_width) == 0, "input channels must be a multiple of pooling height * pooling width"); int channels_out = channels / (pooled_height * pooled_width); @@ -178,21 +180,22 @@ std::tuple PSROIPool_forward_cpu( return std::make_tuple(output, channel_mapping); } + auto input_ = input.contiguous(), rois_ = rois.contiguous(); AT_DISPATCH_FLOATING_TYPES_AND_HALF( input.scalar_type(), "PSROIPool_forward", [&] { PSROIPoolForward( - input.contiguous().data(), + input_.data_ptr(), spatial_scale, channels, height, width, pooled_height, pooled_width, - rois.contiguous().data(), + rois_.data_ptr(), channels_out, num_rois, - output.data(), - channel_mapping.data()); + output.data_ptr(), + channel_mapping.data_ptr()); }); return std::make_tuple(output, channel_mapping); } @@ -201,17 +204,17 @@ at::Tensor PSROIPool_backward_cpu( const at::Tensor& grad, const at::Tensor& rois, const at::Tensor& channel_mapping, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int batch_size, - const int channels, - const int height, - const int width) { + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { // Check if input tensors are CPU tensors - AT_ASSERTM(grad.device().is_cpu(), "grad must be a CPU tensor"); - AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); - AT_ASSERTM( + TORCH_CHECK(grad.device().is_cpu(), "grad must be a CPU tensor"); + TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor"); + TORCH_CHECK( channel_mapping.device().is_cpu(), "channel_mapping must be a CPU tensor"); @@ -232,11 +235,12 @@ at::Tensor PSROIPool_backward_cpu( int channels_out = channels / (pooled_height * pooled_width); + auto grad_ = grad.contiguous(), rois_ = rois.contiguous(); AT_DISPATCH_FLOATING_TYPES_AND_HALF( grad.scalar_type(), "PSROIPool_backward", [&] { PSROIPoolBackward( - grad.contiguous().data(), - channel_mapping.data(), + grad_.data_ptr(), + channel_mapping.data_ptr(), num_rois, spatial_scale, channels, @@ -245,8 +249,8 @@ at::Tensor PSROIPool_backward_cpu( pooled_height, pooled_width, channels_out, - grad_input.data(), - rois.contiguous().data()); + grad_input.data_ptr(), + rois_.data_ptr()); }); return grad_input; } diff --git a/torchvision/csrc/cpu/ROIAlign_cpu.cpp b/torchvision/csrc/cpu/ROIAlign_cpu.cpp index 87766bd68cc..10ebd8158cc 100644 --- a/torchvision/csrc/cpu/ROIAlign_cpu.cpp +++ b/torchvision/csrc/cpu/ROIAlign_cpu.cpp @@ -16,12 +16,12 @@ struct PreCalc { template void pre_calc_for_bilinear_interpolate( - const int height, - const int width, - const int pooled_height, - const int pooled_width, - const int iy_upper, - const int ix_upper, + int height, + int width, + int pooled_height, + int pooled_width, + int iy_upper, + int ix_upper, T roi_start_h, T roi_start_w, T bin_size_h, @@ -112,16 +112,16 @@ void pre_calc_for_bilinear_interpolate( template void ROIAlignForward( - const int nthreads, + int nthreads, const T* input, const T& spatial_scale, - const int channels, - const int height, - const int width, - const int pooled_height, - const int pooled_width, - const int sampling_ratio, - const bool aligned, + int channels, + int height, + int width, + int pooled_height, + int pooled_width, + int sampling_ratio, + bool aligned, const T* rois, T* output) { int n_rois = nthreads / channels / pooled_width / pooled_height; @@ -214,8 +214,8 @@ void ROIAlignForward( template void bilinear_interpolate_gradient( - const int height, - const int width, + int height, + int width, T y, T x, T& w1, @@ -226,7 +226,7 @@ void bilinear_interpolate_gradient( int& x_high, int& y_low, int& y_high, - const int index /* index for debug only*/) { + int index /* index for debug only*/) { // deal with cases that inverse elements are out of feature map boundary if (y < -1.0 || y > height || x < -1.0 || x > width) { // empty @@ -269,8 +269,6 @@ void bilinear_interpolate_gradient( // T val = (w1 * v1 + w2 * v2 + w3 * v3 + w4 * v4); w1 = hy * hx, w2 = hy * lx, w3 = ly * hx, w4 = ly * lx; - - return; } template @@ -280,22 +278,22 @@ inline void add(T* address, const T& val) { template void ROIAlignBackward( - const int nthreads, + int nthreads, const T* grad_output, const T& spatial_scale, - const int channels, - const int height, - const int width, - const int pooled_height, - const int pooled_width, - const int sampling_ratio, - const bool aligned, + int channels, + int height, + int width, + int pooled_height, + int pooled_width, + int sampling_ratio, + bool aligned, T* grad_input, const T* rois, - const int n_stride, - const int c_stride, - const int h_stride, - const int w_stride) { + int n_stride, + int c_stride, + int h_stride, + int w_stride) { for (int index = 0; index < nthreads; index++) { // (n, c, ph, pw) is an element in the pooled output int pw = index % pooled_width; @@ -389,13 +387,14 @@ void ROIAlignBackward( at::Tensor ROIAlign_forward_cpu( const at::Tensor& input, const at::Tensor& rois, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int sampling_ratio, - const bool aligned) { - AT_ASSERTM(input.device().is_cpu(), "input must be a CPU tensor"); - AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio, + bool aligned) { + TORCH_CHECK(input.device().is_cpu(), "input must be a CPU tensor"); + TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor"); + TORCH_CHECK(rois.size(1) == 5, "rois must have shape as Tensor[K, 5]"); at::TensorArg input_t{input, "input", 1}, rois_t{rois, "rois", 2}; @@ -415,38 +414,40 @@ at::Tensor ROIAlign_forward_cpu( if (output.numel() == 0) return output; - AT_DISPATCH_FLOATING_TYPES_AND_HALF(input.type(), "ROIAlign_forward", [&] { - ROIAlignForward( - output_size, - input.contiguous().data_ptr(), - spatial_scale, - channels, - height, - width, - pooled_height, - pooled_width, - sampling_ratio, - aligned, - rois.contiguous().data_ptr(), - output.data_ptr()); - }); + auto input_ = input.contiguous(), rois_ = rois.contiguous(); + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + input.scalar_type(), "ROIAlign_forward", [&] { + ROIAlignForward( + output_size, + input_.data_ptr(), + spatial_scale, + channels, + height, + width, + pooled_height, + pooled_width, + sampling_ratio, + aligned, + rois_.data_ptr(), + output.data_ptr()); + }); return output; } at::Tensor ROIAlign_backward_cpu( const at::Tensor& grad, const at::Tensor& rois, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int batch_size, - const int channels, - const int height, - const int width, - const int sampling_ratio, - const bool aligned) { - AT_ASSERTM(grad.device().is_cpu(), "grad must be a CPU tensor"); - AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width, + int64_t sampling_ratio, + bool aligned) { + TORCH_CHECK(grad.device().is_cpu(), "grad must be a CPU tensor"); + TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor"); at::TensorArg grad_t{grad, "grad", 1}, rois_t{rois, "rois", 2}; @@ -467,24 +468,26 @@ at::Tensor ROIAlign_backward_cpu( int h_stride = grad.stride(2); int w_stride = grad.stride(3); - AT_DISPATCH_FLOATING_TYPES_AND_HALF(grad.type(), "ROIAlign_forward", [&] { - ROIAlignBackward( - grad.numel(), - grad.data_ptr(), - spatial_scale, - channels, - height, - width, - pooled_height, - pooled_width, - sampling_ratio, - aligned, - grad_input.data_ptr(), - rois.contiguous().data_ptr(), - n_stride, - c_stride, - h_stride, - w_stride); - }); + auto rois_ = rois.contiguous(); + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + grad.scalar_type(), "ROIAlign_forward", [&] { + ROIAlignBackward( + grad.numel(), + grad.data_ptr(), + spatial_scale, + channels, + height, + width, + pooled_height, + pooled_width, + sampling_ratio, + aligned, + grad_input.data_ptr(), + rois_.data_ptr(), + n_stride, + c_stride, + h_stride, + w_stride); + }); return grad_input; } diff --git a/torchvision/csrc/cpu/ROIPool_cpu.cpp b/torchvision/csrc/cpu/ROIPool_cpu.cpp index eeb78250654..34da4f1d1cc 100644 --- a/torchvision/csrc/cpu/ROIPool_cpu.cpp +++ b/torchvision/csrc/cpu/ROIPool_cpu.cpp @@ -12,13 +12,13 @@ template void RoIPoolForward( const T* input, const T spatial_scale, - const int channels, - const int height, - const int width, - const int pooled_height, - const int pooled_width, + int channels, + int height, + int width, + int pooled_height, + int pooled_width, const T* rois, - const int num_rois, + int num_rois, T* output, int* argmax_data) { for (int n = 0; n < num_rois; ++n) { @@ -81,18 +81,18 @@ template void RoIPoolBackward( const T* grad_output, const int* argmax_data, - const int num_rois, - const int channels, - const int height, - const int width, - const int pooled_height, - const int pooled_width, + int num_rois, + int channels, + int height, + int width, + int pooled_height, + int pooled_width, T* grad_input, const T* rois, - const int n_stride, - const int c_stride, - const int h_stride, - const int w_stride) { + int n_stride, + int c_stride, + int h_stride, + int w_stride) { for (int n = 0; n < num_rois; ++n) { const T* offset_rois = rois + n * 5; int roi_batch_ind = offset_rois[0]; @@ -123,11 +123,11 @@ void RoIPoolBackward( std::tuple ROIPool_forward_cpu( const at::Tensor& input, const at::Tensor& rois, - const float spatial_scale, - const int pooled_height, - const int pooled_width) { - AT_ASSERTM(input.device().is_cpu(), "input must be a CPU tensor"); - AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width) { + TORCH_CHECK(input.device().is_cpu(), "input must be a CPU tensor"); + TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor"); at::TensorArg input_t{input, "input", 1}, rois_t{rois, "rois", 2}; @@ -149,20 +149,22 @@ std::tuple ROIPool_forward_cpu( return std::make_tuple(output, argmax); } - AT_DISPATCH_FLOATING_TYPES_AND_HALF(input.type(), "ROIPool_forward", [&] { - RoIPoolForward( - input.contiguous().data_ptr(), - spatial_scale, - channels, - height, - width, - pooled_height, - pooled_width, - rois.contiguous().data_ptr(), - num_rois, - output.data_ptr(), - argmax.data_ptr()); - }); + auto input_ = input.contiguous(), rois_ = rois.contiguous(); + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + input.scalar_type(), "ROIPool_forward", [&] { + RoIPoolForward( + input_.data_ptr(), + spatial_scale, + channels, + height, + width, + pooled_height, + pooled_width, + rois_.data_ptr(), + num_rois, + output.data_ptr(), + argmax.data_ptr()); + }); return std::make_tuple(output, argmax); } @@ -170,17 +172,19 @@ at::Tensor ROIPool_backward_cpu( const at::Tensor& grad, const at::Tensor& rois, const at::Tensor& argmax, - const float spatial_scale, - const int pooled_height, - const int pooled_width, - const int batch_size, - const int channels, - const int height, - const int width) { + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t batch_size, + int64_t channels, + int64_t height, + int64_t width) { // Check if input tensors are CPU tensors - AT_ASSERTM(grad.device().is_cpu(), "grad must be a CPU tensor"); - AT_ASSERTM(rois.device().is_cpu(), "rois must be a CPU tensor"); - AT_ASSERTM(argmax.device().is_cpu(), "argmax must be a CPU tensor"); + TORCH_CHECK(grad.device().is_cpu(), "grad must be a CPU tensor"); + TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor"); + TORCH_CHECK(argmax.device().is_cpu(), "argmax must be a CPU tensor"); + TORCH_CHECK( + rois.size(1) == 5, "Tensor rois should have shape as Tensor[K, 5]"); at::TensorArg grad_t{grad, "grad", 1}, rois_t{rois, "rois", 2}; @@ -203,22 +207,24 @@ at::Tensor ROIPool_backward_cpu( int h_stride = grad.stride(2); int w_stride = grad.stride(3); - AT_DISPATCH_FLOATING_TYPES_AND_HALF(grad.type(), "ROIPool_backward", [&] { - RoIPoolBackward( - grad.data_ptr(), - argmax.data_ptr(), - num_rois, - channels, - height, - width, - pooled_height, - pooled_width, - grad_input.data_ptr(), - rois.contiguous().data_ptr(), - n_stride, - c_stride, - h_stride, - w_stride); - }); + auto rois_ = rois.contiguous(); + AT_DISPATCH_FLOATING_TYPES_AND_HALF( + grad.scalar_type(), "ROIPool_backward", [&] { + RoIPoolBackward( + grad.data_ptr(), + argmax.data_ptr(), + num_rois, + channels, + height, + width, + pooled_height, + pooled_width, + grad_input.data_ptr(), + rois_.data_ptr(), + n_stride, + c_stride, + h_stride, + w_stride); + }); return grad_input; } diff --git a/torchvision/csrc/cpu/decoder/decoder.cpp b/torchvision/csrc/cpu/decoder/decoder.cpp index ca272541072..6281cea3292 100644 --- a/torchvision/csrc/cpu/decoder/decoder.cpp +++ b/torchvision/csrc/cpu/decoder/decoder.cpp @@ -149,8 +149,7 @@ bool Decoder::enableLogLevel(int level) const { } void Decoder::logCallback(int level, const std::string& message) { - LOG(INFO) << - "Msg, uuid=" << params_.loggingUuid << " level=" << level << " msg=" << message; + LOG(INFO) << "Msg, level: " << level << ", msg: " << message; } /* static */ @@ -222,8 +221,8 @@ bool Decoder::init( cleanUp(); if ((params.uri.empty() || in) && (!params.uri.empty() || !in)) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " either external URI gets provided or explicit input callback"; + LOG(ERROR) << "Either external URI gets provided" + << " or explicit input callback"; return false; } @@ -231,8 +230,7 @@ bool Decoder::init( params_ = params; if (!(inputCtx_ = avformat_alloc_context())) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " cannot allocate format context"; + LOG(ERROR) << "Cannot allocate format context"; return false; } @@ -245,8 +243,7 @@ bool Decoder::init( params_.timeoutMs, params_.maxSeekableBytes, params_.isImage ? &type : nullptr)) < 0) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " can't initiate seekable buffer"; + LOG(ERROR) << "can't initiate seekable buffer"; cleanUp(); return false; } @@ -274,8 +271,8 @@ bool Decoder::init( uint8_t* avioCtxBuffer = (uint8_t*)av_malloc(avioCtxBufferSize + kIoPaddingSize); if (!avioCtxBuffer) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " av_malloc cannot allocate " << avioCtxBufferSize << " bytes"; + LOG(ERROR) << "av_malloc cannot allocate " << avioCtxBufferSize + << " bytes"; cleanUp(); return false; } @@ -288,8 +285,7 @@ bool Decoder::init( &Decoder::readFunction, nullptr, result == 1 ? &Decoder::seekFunction : nullptr))) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " avio_alloc_context failed"; + LOG(ERROR) << "avio_alloc_context failed"; av_free(avioCtxBuffer); cleanUp(); return false; @@ -327,8 +323,8 @@ bool Decoder::init( guard = std::make_unique([&f, this]() { auto timeout = std::chrono::milliseconds(params_.timeoutMs); if (std::future_status::timeout == f.wait_for(timeout)) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " cannot open stream within " << params_.timeoutMs << " ms"; + LOG(ERROR) << "Cannot open stream within " << params_.timeoutMs + << " ms"; interrupted_ = true; } }); @@ -350,8 +346,8 @@ bool Decoder::init( } if (result < 0 || interrupted_) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " avformat_open_input failed, error=" << Util::generateErrorDesc(result); + LOG(ERROR) << "avformat_open_input failed, error: " + << Util::generateErrorDesc(result); cleanUp(); return false; } @@ -359,15 +355,14 @@ bool Decoder::init( result = avformat_find_stream_info(inputCtx_, nullptr); if (result < 0) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " avformat_find_stream_info failed, error=" << Util::generateErrorDesc(result); + LOG(ERROR) << "avformat_find_stream_info failed, error: " + << Util::generateErrorDesc(result); cleanUp(); return false; } if (!openStreams(metadata)) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " cannot activate streams"; + LOG(ERROR) << "Cannot activate streams"; cleanUp(); return false; } @@ -423,8 +418,7 @@ bool Decoder::openStreams(std::vector* metadata) { params_.loggingUuid); CHECK(stream); if (stream->openCodec(metadata) < 0) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " open codec failed, stream_idx=" << i; + LOG(ERROR) << "Cannot open codec " << i; return false; } streams_.emplace(i, std::move(stream)); @@ -524,15 +518,13 @@ int Decoder::getFrame(size_t workingTimeInMs) { bool hasMsg = false; // packet either got consumed completely or not at all if ((result = processPacket(stream, &avPacket, &gotFrame, &hasMsg)) < 0) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " processPacket failed with code=" << result; + LOG(ERROR) << "processPacket failed with code: " << result; break; } if (!gotFrame && params_.maxProcessNoBytes != 0 && ++numConsecutiveNoBytes > params_.maxProcessNoBytes) { - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " exceeding max amount of consecutive no bytes"; + LOG(ERROR) << "Exceeding max amount of consecutive no bytes"; break; } if (result > 0) { @@ -546,8 +538,7 @@ int Decoder::getFrame(size_t workingTimeInMs) { if (result < 0) { if (params_.maxPackageErrors != 0 && // check errors ++decodingErrors >= params_.maxPackageErrors) { // reached the limit - LOG(ERROR) << - "uuid=" << params_.loggingUuid << " exceeding max amount of consecutive package errors"; + LOG(ERROR) << "Exceeding max amount of consecutive package errors"; break; } } else { diff --git a/torchvision/csrc/cpu/decoder/decoder.h b/torchvision/csrc/cpu/decoder/decoder.h index 69b69721226..c2d8f163bc3 100644 --- a/torchvision/csrc/cpu/decoder/decoder.h +++ b/torchvision/csrc/cpu/decoder/decoder.h @@ -5,6 +5,11 @@ #include "seekable_buffer.h" #include "stream.h" +#if defined(_MSC_VER) +#include +using ssize_t = SSIZE_T; +#endif + namespace ffmpeg { /** diff --git a/torchvision/csrc/cpu/decoder/defs.h b/torchvision/csrc/cpu/decoder/defs.h index 5db17b3e92c..7523969fd58 100644 --- a/torchvision/csrc/cpu/decoder/defs.h +++ b/torchvision/csrc/cpu/decoder/defs.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -51,7 +52,7 @@ struct VideoFormat { } /* When width = 0, height = 0, minDimension = 0, and maxDimension = 0, - keep the orignal frame resolution + keep the original frame resolution When width = 0, height = 0, minDimension != 0, and maxDimension = 0, keep the aspect ratio and resize the frame so that shorter edge size is minDimension diff --git a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp index 0d7ec7236a2..41e3e689c7b 100644 --- a/torchvision/csrc/cpu/decoder/seekable_buffer.cpp +++ b/torchvision/csrc/cpu/decoder/seekable_buffer.cpp @@ -55,7 +55,7 @@ bool SeekableBuffer::readBytes( size_t maxBytes, uint64_t timeoutMs) { // Resize to th minimum 4K page or less - buffer_.resize(std::min(maxBytes, 4 * 1024UL)); + buffer_.resize(std::min(maxBytes, size_t(4 * 1024UL))); end_ = 0; eof_ = false; @@ -72,7 +72,7 @@ bool SeekableBuffer::readBytes( if (res > 0) { end_ += res; if (end_ == buffer_.size()) { - buffer_.resize(std::min(end_ * 4UL, maxBytes)); + buffer_.resize(std::min(size_t(end_ * 4UL), maxBytes)); } } else if (res == 0) { eof_ = true; diff --git a/torchvision/csrc/cpu/decoder/stream.cpp b/torchvision/csrc/cpu/decoder/stream.cpp index 67d2f57a6ee..4da48647382 100644 --- a/torchvision/csrc/cpu/decoder/stream.cpp +++ b/torchvision/csrc/cpu/decoder/stream.cpp @@ -3,6 +3,7 @@ #include "util.h" namespace ffmpeg { +const AVRational timeBaseQ = AVRational{1, AV_TIME_BASE}; Stream::Stream( AVFormatContext* inputCtx, @@ -32,30 +33,30 @@ int Stream::openCodec(std::vector* metadata) { AVCodec* codec = findCodec(steam->codecpar); if (!codec) { - LOG(ERROR) << "uuid=" << loggingUuid_ - << " avcodec_find_decoder failed for codec_id=" + LOG(ERROR) << "LoggingUuid #" << loggingUuid_ + << ", avcodec_find_decoder failed for codec_id: " << int(steam->codecpar->codec_id); return AVERROR(EINVAL); } if (!(codecCtx_ = avcodec_alloc_context3(codec))) { - LOG(ERROR) << "uuid=" << loggingUuid_ - << " avcodec_alloc_context3 failed"; + LOG(ERROR) << "LoggingUuid #" << loggingUuid_ + << ", avcodec_alloc_context3 failed"; return AVERROR(ENOMEM); } int ret; // Copy codec parameters from input stream to output codec context if ((ret = avcodec_parameters_to_context(codecCtx_, steam->codecpar)) < 0) { - LOG(ERROR) << "uuid=" << loggingUuid_ - << " avcodec_parameters_to_context failed"; + LOG(ERROR) << "LoggingUuid #" << loggingUuid_ + << ", avcodec_parameters_to_context failed"; return ret; } // after avcodec_open2, value of codecCtx_->time_base is NOT meaningful if ((ret = avcodec_open2(codecCtx_, codec, nullptr)) < 0) { - LOG(ERROR) << "uuid=" << loggingUuid_ - << " avcodec_open2 failed: " << Util::generateErrorDesc(ret); + LOG(ERROR) << "LoggingUuid #" << loggingUuid_ + << ", avcodec_open2 failed: " << Util::generateErrorDesc(ret); avcodec_free_context(&codecCtx_); codecCtx_ = nullptr; return ret; @@ -75,8 +76,7 @@ int Stream::openCodec(std::vector* metadata) { } if ((ret = initFormat())) { - LOG(ERROR) << "uuid=" << loggingUuid_ - << " initFormat failed, type=" << format_.type; + LOG(ERROR) << "initFormat failed, type: " << format_.type; } if (metadata) { @@ -86,7 +86,7 @@ int Stream::openCodec(std::vector* metadata) { header.num = steam->time_base.num; header.den = steam->time_base.den; header.duration = - av_rescale_q(steam->duration, steam->time_base, AV_TIME_BASE_Q); + av_rescale_q(steam->duration, steam->time_base, timeBaseQ); metadata->push_back(header); } @@ -105,8 +105,7 @@ int Stream::analyzePacket(const AVPacket* packet, bool* gotFrame) { return result; } } else if (result < 0) { - LOG(ERROR) << "uuid=" << loggingUuid_ - << " avcodec_send_packet failed, err=" + LOG(ERROR) << "avcodec_send_packet failed, err: " << Util::generateErrorDesc(result); return result; // error } else { @@ -128,8 +127,7 @@ int Stream::analyzePacket(const AVPacket* packet, bool* gotFrame) { // precaution, if no more frames are available assume we consume all bytes consumed = 0; } else { // error - LOG(ERROR) << "uuid=" << loggingUuid_ - << " avcodec_receive_frame failed, err=" + LOG(ERROR) << "avcodec_receive_frame failed, err: " << Util::generateErrorDesc(result); return result; } @@ -241,7 +239,7 @@ void Stream::setFramePts(DecoderHeader* header, bool flush) { header->pts = av_rescale_q( header->pts, inputCtx_->streams[format_.stream]->time_base, - AV_TIME_BASE_Q); + timeBaseQ); } switch (format_.type) { diff --git a/torchvision/csrc/cpu/decoder/subtitle_stream.cpp b/torchvision/csrc/cpu/decoder/subtitle_stream.cpp index 87906e78fe4..0d3fc9f12c1 100644 --- a/torchvision/csrc/cpu/decoder/subtitle_stream.cpp +++ b/torchvision/csrc/cpu/decoder/subtitle_stream.cpp @@ -4,6 +4,7 @@ #include "util.h" namespace ffmpeg { +const AVRational timeBaseQ = AVRational{1, AV_TIME_BASE}; SubtitleStream::SubtitleStream( AVFormatContext* inputCtx, @@ -65,7 +66,7 @@ int SubtitleStream::analyzePacket(const AVPacket* packet, bool* gotFrame) { // set proper pts in us if (gotFramePtr) { sub_.pts = av_rescale_q( - pkt.pts, inputCtx_->streams[format_.stream]->time_base, AV_TIME_BASE_Q); + pkt.pts, inputCtx_->streams[format_.stream]->time_base, timeBaseQ); } return result; diff --git a/torchvision/csrc/cpu/decoder/util.cpp b/torchvision/csrc/cpu/decoder/util.cpp index 0dbcf885cf5..774612d3927 100644 --- a/torchvision/csrc/cpu/decoder/util.cpp +++ b/torchvision/csrc/cpu/decoder/util.cpp @@ -395,8 +395,8 @@ void setFormatDimensions( } } // prevent zeros - destW = std::max(destW, 1UL); - destH = std::max(destH, 1UL); + destW = std::max(destW, size_t(1UL)); + destH = std::max(destH, size_t(1UL)); } } // namespace Util } // namespace ffmpeg diff --git a/torchvision/csrc/cpu/image/image.cpp b/torchvision/csrc/cpu/image/image.cpp new file mode 100644 index 00000000000..d9234aceb6e --- /dev/null +++ b/torchvision/csrc/cpu/image/image.cpp @@ -0,0 +1,22 @@ + +#include "image.h" +#include +#include + +// If we are in a Windows environment, we need to define +// initialization functions for the _custom_ops extension +#ifdef _WIN32 +PyMODINIT_FUNC PyInit_image(void) { + // No need to do anything. + return NULL; +} +#endif + +static auto registry = torch::RegisterOperators() + .op("image::decode_png", &decodePNG) + .op("image::encode_png", &encodePNG) + .op("image::decode_jpeg", &decodeJPEG) + .op("image::encode_jpeg", &encodeJPEG) + .op("image::read_file", &read_file) + .op("image::write_file", &write_file) + .op("image::decode_image", &decode_image); diff --git a/torchvision/csrc/cpu/image/image.h b/torchvision/csrc/cpu/image/image.h new file mode 100644 index 00000000000..3a652bef244 --- /dev/null +++ b/torchvision/csrc/cpu/image/image.h @@ -0,0 +1,11 @@ +#pragma once + +// Comment +#include +#include +#include "read_image_cpu.h" +#include "read_write_file_cpu.h" +#include "readjpeg_cpu.h" +#include "readpng_cpu.h" +#include "writejpeg_cpu.h" +#include "writepng_cpu.h" diff --git a/torchvision/csrc/cpu/image/image_read_mode.h b/torchvision/csrc/cpu/image/image_read_mode.h new file mode 100644 index 00000000000..00ff4f6b581 --- /dev/null +++ b/torchvision/csrc/cpu/image/image_read_mode.h @@ -0,0 +1,9 @@ +#pragma once + +/* Should be kept in-sync with Python ImageReadMode enum */ +using ImageReadMode = int64_t; +#define IMAGE_READ_MODE_UNCHANGED 0 +#define IMAGE_READ_MODE_GRAY 1 +#define IMAGE_READ_MODE_GRAY_ALPHA 2 +#define IMAGE_READ_MODE_RGB 3 +#define IMAGE_READ_MODE_RGB_ALPHA 4 \ No newline at end of file diff --git a/torchvision/csrc/cpu/image/jpegcommon.cpp b/torchvision/csrc/cpu/image/jpegcommon.cpp new file mode 100644 index 00000000000..9ef7c2903d7 --- /dev/null +++ b/torchvision/csrc/cpu/image/jpegcommon.cpp @@ -0,0 +1,19 @@ +#include "jpegcommon.h" +#include + +#if JPEG_FOUND +void torch_jpeg_error_exit(j_common_ptr cinfo) { + /* cinfo->err really points to a torch_jpeg_error_mgr struct, so coerce + * pointer */ + torch_jpeg_error_ptr myerr = (torch_jpeg_error_ptr)cinfo->err; + + /* Always display the message. */ + /* We could postpone this until after returning, if we chose. */ + // (*cinfo->err->output_message)(cinfo); + /* Create the message */ + (*(cinfo->err->format_message))(cinfo, myerr->jpegLastErrorMsg); + + /* Return control to the setjmp point */ + longjmp(myerr->setjmp_buffer, 1); +} +#endif diff --git a/torchvision/csrc/cpu/image/jpegcommon.h b/torchvision/csrc/cpu/image/jpegcommon.h new file mode 100644 index 00000000000..c0f8eee0457 --- /dev/null +++ b/torchvision/csrc/cpu/image/jpegcommon.h @@ -0,0 +1,23 @@ +#pragma once + +// clang-format off +#include +#include +// clang-format on + +#if JPEG_FOUND +#include +#include +#include + +static const JOCTET EOI_BUFFER[1] = {JPEG_EOI}; +struct torch_jpeg_error_mgr { + struct jpeg_error_mgr pub; /* "public" fields */ + char jpegLastErrorMsg[JMSG_LENGTH_MAX]; /* error messages */ + jmp_buf setjmp_buffer; /* for return to caller */ +}; + +using torch_jpeg_error_ptr = struct torch_jpeg_error_mgr*; +void torch_jpeg_error_exit(j_common_ptr cinfo); + +#endif diff --git a/torchvision/csrc/cpu/image/read_image_cpu.cpp b/torchvision/csrc/cpu/image/read_image_cpu.cpp new file mode 100644 index 00000000000..6039b870f31 --- /dev/null +++ b/torchvision/csrc/cpu/image/read_image_cpu.cpp @@ -0,0 +1,28 @@ +#include "read_image_cpu.h" +#include "readjpeg_cpu.h" +#include "readpng_cpu.h" + +torch::Tensor decode_image(const torch::Tensor& data, ImageReadMode mode) { + // Check that the input tensor dtype is uint8 + TORCH_CHECK(data.dtype() == torch::kU8, "Expected a torch.uint8 tensor"); + // Check that the input tensor is 1-dimensional + TORCH_CHECK( + data.dim() == 1 && data.numel() > 0, + "Expected a non empty 1-dimensional tensor"); + + auto datap = data.data_ptr(); + + const uint8_t jpeg_signature[3] = {255, 216, 255}; // == "\xFF\xD8\xFF" + const uint8_t png_signature[4] = {137, 80, 78, 71}; // == "\211PNG" + + if (memcmp(jpeg_signature, datap, 3) == 0) { + return decodeJPEG(data, mode); + } else if (memcmp(png_signature, datap, 4) == 0) { + return decodePNG(data, mode); + } else { + TORCH_CHECK( + false, + "Unsupported image file. Only jpeg and png ", + "are currently supported."); + } +} diff --git a/torchvision/csrc/cpu/image/read_image_cpu.h b/torchvision/csrc/cpu/image/read_image_cpu.h new file mode 100644 index 00000000000..6186d0d0d98 --- /dev/null +++ b/torchvision/csrc/cpu/image/read_image_cpu.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include "image_read_mode.h" + +C10_EXPORT torch::Tensor decode_image( + const torch::Tensor& data, + ImageReadMode mode = IMAGE_READ_MODE_UNCHANGED); diff --git a/torchvision/csrc/cpu/image/read_write_file_cpu.cpp b/torchvision/csrc/cpu/image/read_write_file_cpu.cpp new file mode 100644 index 00000000000..8ecae99078c --- /dev/null +++ b/torchvision/csrc/cpu/image/read_write_file_cpu.cpp @@ -0,0 +1,92 @@ +#include "read_write_file_cpu.h" + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +std::wstring utf8_decode(const std::string& str) { + if (str.empty()) { + return std::wstring(); + } + int size_needed = MultiByteToWideChar( + CP_UTF8, 0, str.c_str(), static_cast(str.size()), NULL, 0); + TORCH_CHECK(size_needed > 0, "Error converting the content to Unicode"); + std::wstring wstrTo(size_needed, 0); + MultiByteToWideChar( + CP_UTF8, + 0, + str.c_str(), + static_cast(str.size()), + &wstrTo[0], + size_needed); + return wstrTo; +} +#endif + +torch::Tensor read_file(const std::string& filename) { +#ifdef _WIN32 + // According to + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/stat-functions?view=vs-2019, + // we should use struct __stat64 and _wstat64 for 64-bit file size on Windows. + struct __stat64 stat_buf; + auto fileW = utf8_decode(filename); + int rc = _wstat64(fileW.c_str(), &stat_buf); +#else + struct stat stat_buf; + int rc = stat(filename.c_str(), &stat_buf); +#endif + // errno is a variable defined in errno.h + TORCH_CHECK( + rc == 0, "[Errno ", errno, "] ", strerror(errno), ": '", filename, "'"); + + int64_t size = stat_buf.st_size; + + TORCH_CHECK(size > 0, "Expected a non empty file"); + +#ifdef _WIN32 + // TODO: Once torch::from_file handles UTF-8 paths correctly, we should move + // back to use the following implementation since it uses file mapping. + // auto data = + // torch::from_file(filename, /*shared=*/false, /*size=*/size, + // torch::kU8).clone() + FILE* infile = _wfopen(fileW.c_str(), L"rb"); + + TORCH_CHECK(infile != nullptr, "Error opening input file"); + + auto data = torch::empty({size}, torch::kU8); + auto dataBytes = data.data_ptr(); + + fread(dataBytes, sizeof(uint8_t), size, infile); + fclose(infile); +#else + auto data = + torch::from_file(filename, /*shared=*/false, /*size=*/size, torch::kU8); +#endif + + return data; +} + +void write_file(const std::string& filename, torch::Tensor& data) { + // Check that the input tensor is on CPU + TORCH_CHECK(data.device() == torch::kCPU, "Input tensor should be on CPU"); + + // Check that the input tensor dtype is uint8 + TORCH_CHECK(data.dtype() == torch::kU8, "Input tensor dtype should be uint8"); + + // Check that the input tensor is 3-dimensional + TORCH_CHECK(data.dim() == 1, "Input data should be a 1-dimensional tensor"); + + auto fileBytes = data.data_ptr(); + auto fileCStr = filename.c_str(); +#ifdef _WIN32 + auto fileW = utf8_decode(filename); + FILE* outfile = _wfopen(fileW.c_str(), L"wb"); +#else + FILE* outfile = fopen(fileCStr, "wb"); +#endif + + TORCH_CHECK(outfile != nullptr, "Error opening output file"); + + fwrite(fileBytes, sizeof(uint8_t), data.numel(), outfile); + fclose(outfile); +} diff --git a/torchvision/csrc/cpu/image/read_write_file_cpu.h b/torchvision/csrc/cpu/image/read_write_file_cpu.h new file mode 100644 index 00000000000..084f5c105f8 --- /dev/null +++ b/torchvision/csrc/cpu/image/read_write_file_cpu.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include +#include + +C10_EXPORT torch::Tensor read_file(const std::string& filename); + +C10_EXPORT void write_file(const std::string& filename, torch::Tensor& data); diff --git a/torchvision/csrc/cpu/image/readjpeg_cpu.cpp b/torchvision/csrc/cpu/image/readjpeg_cpu.cpp new file mode 100644 index 00000000000..58584612697 --- /dev/null +++ b/torchvision/csrc/cpu/image/readjpeg_cpu.cpp @@ -0,0 +1,153 @@ +#include "readjpeg_cpu.h" + +#include + +#if !JPEG_FOUND +torch::Tensor decodeJPEG(const torch::Tensor& data, ImageReadMode mode) { + TORCH_CHECK( + false, "decodeJPEG: torchvision not compiled with libjpeg support"); +} +#else +#include +#include +#include "jpegcommon.h" + +struct torch_jpeg_mgr { + struct jpeg_source_mgr pub; + const JOCTET* data; + size_t len; +}; + +static void torch_jpeg_init_source(j_decompress_ptr cinfo) {} + +static boolean torch_jpeg_fill_input_buffer(j_decompress_ptr cinfo) { + torch_jpeg_mgr* src = (torch_jpeg_mgr*)cinfo->src; + // No more data. Probably an incomplete image; Raise exception. + torch_jpeg_error_ptr myerr = (torch_jpeg_error_ptr)cinfo->err; + strcpy(myerr->jpegLastErrorMsg, "Image is incomplete or truncated"); + longjmp(myerr->setjmp_buffer, 1); + src->pub.next_input_byte = EOI_BUFFER; + src->pub.bytes_in_buffer = 1; + return TRUE; +} + +static void torch_jpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { + torch_jpeg_mgr* src = (torch_jpeg_mgr*)cinfo->src; + if (src->pub.bytes_in_buffer < num_bytes) { + // Skipping over all of remaining data; output EOI. + src->pub.next_input_byte = EOI_BUFFER; + src->pub.bytes_in_buffer = 1; + } else { + // Skipping over only some of the remaining data. + src->pub.next_input_byte += num_bytes; + src->pub.bytes_in_buffer -= num_bytes; + } +} + +static void torch_jpeg_term_source(j_decompress_ptr cinfo) {} + +static void torch_jpeg_set_source_mgr( + j_decompress_ptr cinfo, + const unsigned char* data, + size_t len) { + torch_jpeg_mgr* src; + if (cinfo->src == 0) { // if this is first time; allocate memory + cinfo->src = (struct jpeg_source_mgr*)(*cinfo->mem->alloc_small)( + (j_common_ptr)cinfo, JPOOL_PERMANENT, sizeof(torch_jpeg_mgr)); + } + src = (torch_jpeg_mgr*)cinfo->src; + src->pub.init_source = torch_jpeg_init_source; + src->pub.fill_input_buffer = torch_jpeg_fill_input_buffer; + src->pub.skip_input_data = torch_jpeg_skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; // default + src->pub.term_source = torch_jpeg_term_source; + // fill the buffers + src->data = (const JOCTET*)data; + src->len = len; + src->pub.bytes_in_buffer = len; + src->pub.next_input_byte = src->data; +} + +torch::Tensor decodeJPEG(const torch::Tensor& data, ImageReadMode mode) { + // Check that the input tensor dtype is uint8 + TORCH_CHECK(data.dtype() == torch::kU8, "Expected a torch.uint8 tensor"); + // Check that the input tensor is 1-dimensional + TORCH_CHECK( + data.dim() == 1 && data.numel() > 0, + "Expected a non empty 1-dimensional tensor"); + + struct jpeg_decompress_struct cinfo; + struct torch_jpeg_error_mgr jerr; + + auto datap = data.data_ptr(); + // Setup decompression structure + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = torch_jpeg_error_exit; + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object. + */ + jpeg_destroy_decompress(&cinfo); + TORCH_CHECK(false, jerr.jpegLastErrorMsg); + } + + jpeg_create_decompress(&cinfo); + torch_jpeg_set_source_mgr(&cinfo, datap, data.numel()); + + // read info from header. + jpeg_read_header(&cinfo, TRUE); + + int channels = cinfo.num_components; + + if (mode != IMAGE_READ_MODE_UNCHANGED) { + switch (mode) { + case IMAGE_READ_MODE_GRAY: + if (cinfo.jpeg_color_space != JCS_GRAYSCALE) { + cinfo.out_color_space = JCS_GRAYSCALE; + channels = 1; + } + break; + case IMAGE_READ_MODE_RGB: + if (cinfo.jpeg_color_space != JCS_RGB) { + cinfo.out_color_space = JCS_RGB; + channels = 3; + } + break; + /* + * Libjpeg does not support converting from CMYK to grayscale etc. There + * is a way to do this but it involves converting it manually to RGB: + * https://github.com/tensorflow/tensorflow/blob/86871065265b04e0db8ca360c046421efb2bdeb4/tensorflow/core/lib/jpeg/jpeg_mem.cc#L284-L313 + */ + default: + jpeg_destroy_decompress(&cinfo); + TORCH_CHECK(false, "Provided mode not supported"); + } + + jpeg_calc_output_dimensions(&cinfo); + } + + jpeg_start_decompress(&cinfo); + + int height = cinfo.output_height; + int width = cinfo.output_width; + + int stride = width * channels; + auto tensor = + torch::empty({int64_t(height), int64_t(width), channels}, torch::kU8); + auto ptr = tensor.data_ptr(); + while (cinfo.output_scanline < cinfo.output_height) { + /* jpeg_read_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could ask for + * more than one scanline at a time if that's more convenient. + */ + jpeg_read_scanlines(&cinfo, &ptr, 1); + ptr += stride; + } + + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + return tensor.permute({2, 0, 1}); +} + +#endif // JPEG_FOUND diff --git a/torchvision/csrc/cpu/image/readjpeg_cpu.h b/torchvision/csrc/cpu/image/readjpeg_cpu.h new file mode 100644 index 00000000000..f05d05a9064 --- /dev/null +++ b/torchvision/csrc/cpu/image/readjpeg_cpu.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include "image_read_mode.h" + +C10_EXPORT torch::Tensor decodeJPEG( + const torch::Tensor& data, + ImageReadMode mode = IMAGE_READ_MODE_UNCHANGED); diff --git a/torchvision/csrc/cpu/image/readpng_cpu.cpp b/torchvision/csrc/cpu/image/readpng_cpu.cpp new file mode 100644 index 00000000000..7adc125b2e8 --- /dev/null +++ b/torchvision/csrc/cpu/image/readpng_cpu.cpp @@ -0,0 +1,165 @@ +#include "readpng_cpu.h" + +#include + +#if !PNG_FOUND +torch::Tensor decodePNG(const torch::Tensor& data, ImageReadMode mode) { + TORCH_CHECK(false, "decodePNG: torchvision not compiled with libPNG support"); +} +#else +#include +#include + +torch::Tensor decodePNG(const torch::Tensor& data, ImageReadMode mode) { + // Check that the input tensor dtype is uint8 + TORCH_CHECK(data.dtype() == torch::kU8, "Expected a torch.uint8 tensor"); + // Check that the input tensor is 1-dimensional + TORCH_CHECK( + data.dim() == 1 && data.numel() > 0, + "Expected a non empty 1-dimensional tensor"); + + auto png_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + TORCH_CHECK(png_ptr, "libpng read structure allocation failed!") + auto info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + png_destroy_read_struct(&png_ptr, nullptr, nullptr); + // Seems redundant with the if statement. done here to avoid leaking memory. + TORCH_CHECK(info_ptr, "libpng info structure allocation failed!") + } + + auto datap = data.accessor().data(); + + if (setjmp(png_jmpbuf(png_ptr)) != 0) { + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); + TORCH_CHECK(false, "Internal error."); + } + auto is_png = !png_sig_cmp(datap, 0, 8); + TORCH_CHECK(is_png, "Content is not png!") + + struct Reader { + png_const_bytep ptr; + } reader; + reader.ptr = png_const_bytep(datap) + 8; + + auto read_callback = + [](png_structp png_ptr, png_bytep output, png_size_t bytes) { + auto reader = static_cast(png_get_io_ptr(png_ptr)); + std::copy(reader->ptr, reader->ptr + bytes, output); + reader->ptr += bytes; + }; + png_set_sig_bytes(png_ptr, 8); + png_set_read_fn(png_ptr, &reader, read_callback); + png_read_info(png_ptr, info_ptr); + + png_uint_32 width, height; + int bit_depth, color_type; + auto retval = png_get_IHDR( + png_ptr, + info_ptr, + &width, + &height, + &bit_depth, + &color_type, + nullptr, + nullptr, + nullptr); + + if (retval != 1) { + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); + TORCH_CHECK(retval == 1, "Could read image metadata from content.") + } + + int channels = png_get_channels(png_ptr, info_ptr); + + if (mode != IMAGE_READ_MODE_UNCHANGED) { + // TODO: consider supporting PNG_INFO_tRNS + bool is_palette = (color_type & PNG_COLOR_MASK_PALETTE) != 0; + bool has_color = (color_type & PNG_COLOR_MASK_COLOR) != 0; + bool has_alpha = (color_type & PNG_COLOR_MASK_ALPHA) != 0; + + switch (mode) { + case IMAGE_READ_MODE_GRAY: + if (color_type != PNG_COLOR_TYPE_GRAY) { + if (is_palette) { + png_set_palette_to_rgb(png_ptr); + has_alpha = true; + } + + if (has_alpha) { + png_set_strip_alpha(png_ptr); + } + + if (has_color) { + png_set_rgb_to_gray(png_ptr, 1, 0.2989, 0.587); + } + channels = 1; + } + break; + case IMAGE_READ_MODE_GRAY_ALPHA: + if (color_type != PNG_COLOR_TYPE_GRAY_ALPHA) { + if (is_palette) { + png_set_palette_to_rgb(png_ptr); + has_alpha = true; + } + + if (!has_alpha) { + png_set_add_alpha(png_ptr, (1 << bit_depth) - 1, PNG_FILLER_AFTER); + } + + if (has_color) { + png_set_rgb_to_gray(png_ptr, 1, 0.2989, 0.587); + } + channels = 2; + } + break; + case IMAGE_READ_MODE_RGB: + if (color_type != PNG_COLOR_TYPE_RGB) { + if (is_palette) { + png_set_palette_to_rgb(png_ptr); + has_alpha = true; + } else if (!has_color) { + png_set_gray_to_rgb(png_ptr); + } + + if (has_alpha) { + png_set_strip_alpha(png_ptr); + } + channels = 3; + } + break; + case IMAGE_READ_MODE_RGB_ALPHA: + if (color_type != PNG_COLOR_TYPE_RGB_ALPHA) { + if (is_palette) { + png_set_palette_to_rgb(png_ptr); + has_alpha = true; + } else if (!has_color) { + png_set_gray_to_rgb(png_ptr); + } + + if (!has_alpha) { + png_set_add_alpha(png_ptr, (1 << bit_depth) - 1, PNG_FILLER_AFTER); + } + channels = 4; + } + break; + default: + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); + TORCH_CHECK(false, "Provided mode not supported"); + } + + png_read_update_info(png_ptr, info_ptr); + } + + auto tensor = + torch::empty({int64_t(height), int64_t(width), channels}, torch::kU8); + auto ptr = tensor.accessor().data(); + auto bytes = png_get_rowbytes(png_ptr, info_ptr); + for (png_uint_32 i = 0; i < height; ++i) { + png_read_row(png_ptr, ptr, nullptr); + ptr += bytes; + } + png_destroy_read_struct(&png_ptr, &info_ptr, nullptr); + return tensor.permute({2, 0, 1}); +} +#endif // PNG_FOUND diff --git a/torchvision/csrc/cpu/image/readpng_cpu.h b/torchvision/csrc/cpu/image/readpng_cpu.h new file mode 100644 index 00000000000..9c74cb2c678 --- /dev/null +++ b/torchvision/csrc/cpu/image/readpng_cpu.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include "image_read_mode.h" + +C10_EXPORT torch::Tensor decodePNG( + const torch::Tensor& data, + ImageReadMode mode = IMAGE_READ_MODE_UNCHANGED); diff --git a/torchvision/csrc/cpu/image/writejpeg_cpu.cpp b/torchvision/csrc/cpu/image/writejpeg_cpu.cpp new file mode 100644 index 00000000000..658ffaba55c --- /dev/null +++ b/torchvision/csrc/cpu/image/writejpeg_cpu.cpp @@ -0,0 +1,105 @@ +#include "writejpeg_cpu.h" + +#include +#include + +#if !JPEG_FOUND + +torch::Tensor encodeJPEG(const torch::Tensor& data, int64_t quality) { + TORCH_CHECK( + false, "encodeJPEG: torchvision not compiled with libjpeg support"); +} + +#else + +#include +#include "jpegcommon.h" + +torch::Tensor encodeJPEG(const torch::Tensor& data, int64_t quality) { + // Define compression structures and error handling + struct jpeg_compress_struct cinfo; + struct torch_jpeg_error_mgr jerr; + + // Define buffer to write JPEG information to and its size + unsigned long jpegSize = 0; + uint8_t* jpegBuf = NULL; + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = torch_jpeg_error_exit; + + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object and the buffer. + */ + jpeg_destroy_compress(&cinfo); + if (jpegBuf != NULL) { + free(jpegBuf); + } + + TORCH_CHECK(false, (const char*)jerr.jpegLastErrorMsg); + } + + // Check that the input tensor is on CPU + TORCH_CHECK(data.device() == torch::kCPU, "Input tensor should be on CPU"); + + // Check that the input tensor dtype is uint8 + TORCH_CHECK(data.dtype() == torch::kU8, "Input tensor dtype should be uint8"); + + // Check that the input tensor is 3-dimensional + TORCH_CHECK(data.dim() == 3, "Input data should be a 3-dimensional tensor"); + + // Get image info + int channels = data.size(0); + int height = data.size(1); + int width = data.size(2); + auto input = data.permute({1, 2, 0}).contiguous(); + + TORCH_CHECK( + channels == 1 || channels == 3, + "The number of channels should be 1 or 3, got: ", + channels); + + // Initialize JPEG structure + jpeg_create_compress(&cinfo); + + // Set output image information + cinfo.image_width = width; + cinfo.image_height = height; + cinfo.input_components = channels; + cinfo.in_color_space = channels == 1 ? JCS_GRAYSCALE : JCS_RGB; + + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, TRUE); + + // Save JPEG output to a buffer + jpeg_mem_dest(&cinfo, &jpegBuf, &jpegSize); + + // Start JPEG compression + jpeg_start_compress(&cinfo, TRUE); + + auto stride = width * channels; + auto ptr = input.data_ptr(); + + // Encode JPEG file + while (cinfo.next_scanline < cinfo.image_height) { + jpeg_write_scanlines(&cinfo, &ptr, 1); + ptr += stride; + } + + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + torch::TensorOptions options = torch::TensorOptions{torch::kU8}; + auto outTensor = torch::empty({(long)jpegSize}, options); + + // Copy memory from jpeg buffer, since torch cannot get ownership of it via + // `from_blob` + auto outPtr = outTensor.data_ptr(); + std::memcpy(outPtr, jpegBuf, sizeof(uint8_t) * outTensor.numel()); + + free(jpegBuf); + + return outTensor; +} +#endif diff --git a/torchvision/csrc/cpu/image/writejpeg_cpu.h b/torchvision/csrc/cpu/image/writejpeg_cpu.h new file mode 100644 index 00000000000..7f984af9407 --- /dev/null +++ b/torchvision/csrc/cpu/image/writejpeg_cpu.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +C10_EXPORT torch::Tensor encodeJPEG(const torch::Tensor& data, int64_t quality); diff --git a/torchvision/csrc/cpu/image/writepng_cpu.cpp b/torchvision/csrc/cpu/image/writepng_cpu.cpp new file mode 100644 index 00000000000..f599a9824e0 --- /dev/null +++ b/torchvision/csrc/cpu/image/writepng_cpu.cpp @@ -0,0 +1,176 @@ +#include "writejpeg_cpu.h" + +#include +#include + +#if !PNG_FOUND + +torch::Tensor encodePNG(const torch::Tensor& data, int64_t compression_level) { + TORCH_CHECK(false, "encodePNG: torchvision not compiled with libpng support"); +} + +#else + +#include + +struct torch_mem_encode { + char* buffer; + size_t size; +}; + +struct torch_png_error_mgr { + const char* pngLastErrorMsg; /* error messages */ + jmp_buf setjmp_buffer; /* for return to caller */ +}; + +using torch_png_error_mgr_ptr = torch_png_error_mgr*; + +void torch_png_warn(png_structp png_ptr, png_const_charp warn_msg) { + /* Display warning to user */ + TORCH_WARN_ONCE(warn_msg); +} + +void torch_png_error(png_structp png_ptr, png_const_charp error_msg) { + /* png_ptr->err really points to a torch_png_error_mgr struct, so coerce + * pointer */ + auto error_ptr = (torch_png_error_mgr_ptr)png_get_error_ptr(png_ptr); + /* Replace the error message on the error structure */ + error_ptr->pngLastErrorMsg = error_msg; + /* Return control to the setjmp point */ + longjmp(error_ptr->setjmp_buffer, 1); +} + +void torch_png_write_data( + png_structp png_ptr, + png_bytep data, + png_size_t length) { + struct torch_mem_encode* p = + (struct torch_mem_encode*)png_get_io_ptr(png_ptr); + size_t nsize = p->size + length; + + /* allocate or grow buffer */ + if (p->buffer) + p->buffer = (char*)realloc(p->buffer, nsize); + else + p->buffer = (char*)malloc(nsize); + + if (!p->buffer) + png_error(png_ptr, "Write Error"); + + /* copy new bytes to end of buffer */ + memcpy(p->buffer + p->size, data, length); + p->size += length; +} + +torch::Tensor encodePNG(const torch::Tensor& data, int64_t compression_level) { + // Define compression structures and error handling + png_structp png_write; + png_infop info_ptr; + struct torch_png_error_mgr err_ptr; + + // Define output buffer + struct torch_mem_encode buf_info; + buf_info.buffer = NULL; + buf_info.size = 0; + + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp(err_ptr.setjmp_buffer)) { + /* If we get here, the PNG code has signaled an error. + * We need to clean up the PNG object and the buffer. + */ + if (info_ptr != NULL) { + png_destroy_info_struct(png_write, &info_ptr); + } + + if (png_write != NULL) { + png_destroy_write_struct(&png_write, NULL); + } + + if (buf_info.buffer != NULL) { + free(buf_info.buffer); + } + + TORCH_CHECK(false, err_ptr.pngLastErrorMsg); + } + + // Check that the compression level is between 0 and 9 + TORCH_CHECK( + compression_level >= 0 && compression_level <= 9, + "Compression level should be between 0 and 9"); + + // Check that the input tensor is on CPU + TORCH_CHECK(data.device() == torch::kCPU, "Input tensor should be on CPU"); + + // Check that the input tensor dtype is uint8 + TORCH_CHECK(data.dtype() == torch::kU8, "Input tensor dtype should be uint8"); + + // Check that the input tensor is 3-dimensional + TORCH_CHECK(data.dim() == 3, "Input data should be a 3-dimensional tensor"); + + // Get image info + int channels = data.size(0); + int height = data.size(1); + int width = data.size(2); + auto input = data.permute({1, 2, 0}).contiguous(); + + TORCH_CHECK( + channels == 1 || channels == 3, + "The number of channels should be 1 or 3, got: ", + channels); + + // Initialize PNG structures + png_write = png_create_write_struct( + PNG_LIBPNG_VER_STRING, &err_ptr, torch_png_error, NULL); + + info_ptr = png_create_info_struct(png_write); + + // Define custom buffer output + png_set_write_fn(png_write, &buf_info, torch_png_write_data, NULL); + + // Set output image information + auto color_type = PNG_COLOR_TYPE_GRAY ? channels == 1 : PNG_COLOR_TYPE_RGB; + png_set_IHDR( + png_write, + info_ptr, + width, + height, + 8, + color_type, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + // Set image compression level + png_set_compression_level(png_write, compression_level); + + // Write file header + png_write_info(png_write, info_ptr); + + auto stride = width * channels; + auto ptr = input.data_ptr(); + + // Encode PNG file + for (size_t y = 0; y < height; ++y) { + png_write_row(png_write, ptr); + ptr += stride; + } + + // Write EOF + png_write_end(png_write, info_ptr); + + // Destroy structures + png_destroy_write_struct(&png_write, &info_ptr); + + torch::TensorOptions options = torch::TensorOptions{torch::kU8}; + auto outTensor = torch::empty({(long)buf_info.size}, options); + + // Copy memory from png buffer, since torch cannot get ownership of it via + // `from_blob` + auto outPtr = outTensor.data_ptr(); + std::memcpy(outPtr, buf_info.buffer, sizeof(uint8_t) * outTensor.numel()); + free(buf_info.buffer); + + return outTensor; +} + +#endif diff --git a/torchvision/csrc/cpu/image/writepng_cpu.h b/torchvision/csrc/cpu/image/writepng_cpu.h new file mode 100644 index 00000000000..8f477191cbe --- /dev/null +++ b/torchvision/csrc/cpu/image/writepng_cpu.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +C10_EXPORT torch::Tensor encodePNG( + const torch::Tensor& data, + int64_t compression_level); diff --git a/torchvision/csrc/cpu/nms_cpu.cpp b/torchvision/csrc/cpu/nms_cpu.cpp index 55afb03a4e9..00a4c61db7a 100644 --- a/torchvision/csrc/cpu/nms_cpu.cpp +++ b/torchvision/csrc/cpu/nms_cpu.cpp @@ -4,11 +4,12 @@ template at::Tensor nms_cpu_kernel( const at::Tensor& dets, const at::Tensor& scores, - const float iou_threshold) { - AT_ASSERTM(!dets.type().is_cuda(), "dets must be a CPU tensor"); - AT_ASSERTM(!scores.type().is_cuda(), "scores must be a CPU tensor"); - AT_ASSERTM( - dets.type() == scores.type(), "dets should have the same type as scores"); + double iou_threshold) { + TORCH_CHECK(!dets.is_cuda(), "dets must be a CPU tensor"); + TORCH_CHECK(!scores.is_cuda(), "scores must be a CPU tensor"); + TORCH_CHECK( + dets.scalar_type() == scores.scalar_type(), + "dets should have the same type as scores"); if (dets.numel() == 0) return at::empty({0}, dets.options().dtype(at::kLong)); @@ -71,10 +72,29 @@ at::Tensor nms_cpu_kernel( at::Tensor nms_cpu( const at::Tensor& dets, const at::Tensor& scores, - const float iou_threshold) { + double iou_threshold) { + TORCH_CHECK( + dets.dim() == 2, "boxes should be a 2d tensor, got ", dets.dim(), "D"); + TORCH_CHECK( + dets.size(1) == 4, + "boxes should have 4 elements in dimension 1, got ", + dets.size(1)); + TORCH_CHECK( + scores.dim() == 1, + "scores should be a 1d tensor, got ", + scores.dim(), + "D"); + TORCH_CHECK( + dets.size(0) == scores.size(0), + "boxes and scores should have same number of elements in ", + "dimension 0, got ", + dets.size(0), + " and ", + scores.size(0)); + auto result = at::empty({0}, dets.options()); - AT_DISPATCH_FLOATING_TYPES(dets.type(), "nms", [&] { + AT_DISPATCH_FLOATING_TYPES(dets.scalar_type(), "nms", [&] { result = nms_cpu_kernel(dets, scores, iou_threshold); }); return result; diff --git a/torchvision/csrc/cpu/video/Video.cpp b/torchvision/csrc/cpu/video/Video.cpp new file mode 100644 index 00000000000..9a995c23e6c --- /dev/null +++ b/torchvision/csrc/cpu/video/Video.cpp @@ -0,0 +1,321 @@ +#include "Video.h" +#include +#include +#include "defs.h" +#include "memory_buffer.h" +#include "sync_decoder.h" + +using namespace std; +using namespace ffmpeg; + +const size_t decoderTimeoutMs = 600000; +const AVPixelFormat defaultVideoPixelFormat = AV_PIX_FMT_RGB24; +const AVSampleFormat defaultAudioSampleFormat = AV_SAMPLE_FMT_FLT; + +// returns number of written bytes +template +size_t fillTensorList(DecoderOutputMessage& msgs, torch::Tensor& frame) { + const auto& msg = msgs; + T* frameData = frame.numel() > 0 ? frame.data_ptr() : nullptr; + if (frameData) { + auto sizeInBytes = msg.payload->length(); + memcpy(frameData, msg.payload->data(), sizeInBytes); + } + return sizeof(T); +} + +size_t fillVideoTensor(DecoderOutputMessage& msgs, torch::Tensor& videoFrame) { + return fillTensorList(msgs, videoFrame); +} + +size_t fillAudioTensor(DecoderOutputMessage& msgs, torch::Tensor& audioFrame) { + return fillTensorList(msgs, audioFrame); +} + +std::array, 4>::const_iterator +_parse_type(const std::string& stream_string) { + static const std::array, 4> types = {{ + {"video", TYPE_VIDEO}, + {"audio", TYPE_AUDIO}, + {"subtitle", TYPE_SUBTITLE}, + {"cc", TYPE_CC}, + }}; + auto device = std::find_if( + types.begin(), + types.end(), + [stream_string](const std::pair& p) { + return p.first == stream_string; + }); + if (device != types.end()) { + return device; + } + TORCH_CHECK( + false, "Expected one of [audio, video, subtitle, cc] ", stream_string); +} + +std::string parse_type_to_string(const std::string& stream_string) { + auto device = _parse_type(stream_string); + return device->first; +} + +MediaType parse_type_to_mt(const std::string& stream_string) { + auto device = _parse_type(stream_string); + return device->second; +} + +std::tuple _parseStream(const std::string& streamString) { + TORCH_CHECK(!streamString.empty(), "Stream string must not be empty"); + static const std::regex regex("([a-zA-Z_]+)(?::([1-9]\\d*|0))?"); + std::smatch match; + + TORCH_CHECK( + std::regex_match(streamString, match, regex), + "Invalid stream string: '", + streamString, + "'"); + + std::string type_ = "video"; + type_ = parse_type_to_string(match[1].str()); + long index_ = -1; + if (match[2].matched) { + try { + index_ = c10::stoi(match[2].str()); + } catch (const std::exception&) { + TORCH_CHECK( + false, + "Could not parse device index '", + match[2].str(), + "' in device string '", + streamString, + "'"); + } + } + return std::make_tuple(type_, index_); +} + +void Video::_getDecoderParams( + double videoStartS, + int64_t getPtsOnly, + std::string stream, + long stream_id = -1, + bool all_streams = false, + double seekFrameMarginUs = 10) { + int64_t videoStartUs = int64_t(videoStartS * 1e6); + + params.timeoutMs = decoderTimeoutMs; + params.startOffset = videoStartUs; + params.seekAccuracy = seekFrameMarginUs; + params.headerOnly = false; + + params.preventStaleness = false; // not sure what this is about + + if (all_streams == true) { + MediaFormat format; + format.stream = -2; + format.type = TYPE_AUDIO; + params.formats.insert(format); + + format.type = TYPE_VIDEO; + format.stream = -2; + format.format.video.width = 0; + format.format.video.height = 0; + format.format.video.cropImage = 0; + format.format.video.format = defaultVideoPixelFormat; + params.formats.insert(format); + + format.type = TYPE_SUBTITLE; + format.stream = -2; + params.formats.insert(format); + + format.type = TYPE_CC; + format.stream = -2; + params.formats.insert(format); + } else { + // parse stream type + MediaType stream_type = parse_type_to_mt(stream); + + // TODO: reset params.formats + std::set formats; + params.formats = formats; + // Define new format + MediaFormat format; + format.type = stream_type; + format.stream = stream_id; + if (stream_type == TYPE_VIDEO) { + format.format.video.width = 0; + format.format.video.height = 0; + format.format.video.cropImage = 0; + format.format.video.format = defaultVideoPixelFormat; + } + params.formats.insert(format); + } + +} // _get decoder params + +Video::Video(std::string videoPath, std::string stream) { + // parse stream information + current_stream = _parseStream(stream); + // note that in the initial call we want to get all streams + Video::_getDecoderParams( + 0, // video start + 0, // headerOnly + get<0>(current_stream), // stream info - remove that + long(-1), // stream_id parsed from info above change to -2 + true // read all streams + ); + + std::string logMessage, logType; + + // TODO: add read from memory option + params.uri = videoPath; + logType = "file"; + logMessage = videoPath; + + // locals + std::vector audioFPS, videoFPS, ccFPS, subsFPS; + std::vector audioDuration, videoDuration, ccDuration, subsDuration; + std::vector audioTB, videoTB, ccTB, subsTB; + c10::Dict> audioMetadata; + c10::Dict> videoMetadata; + + // calback and metadata defined in struct + succeeded = decoder.init(params, std::move(callback), &metadata); + if (succeeded) { + for (const auto& header : metadata) { + double fps = double(header.fps); + double duration = double(header.duration) * 1e-6; // * timeBase; + + if (header.format.type == TYPE_VIDEO) { + videoFPS.push_back(fps); + videoDuration.push_back(duration); + } else if (header.format.type == TYPE_AUDIO) { + audioFPS.push_back(fps); + audioDuration.push_back(duration); + } else if (header.format.type == TYPE_CC) { + ccFPS.push_back(fps); + ccDuration.push_back(duration); + } else if (header.format.type == TYPE_SUBTITLE) { + subsFPS.push_back(fps); + subsDuration.push_back(duration); + }; + } + } + audioMetadata.insert("duration", audioDuration); + audioMetadata.insert("framerate", audioFPS); + videoMetadata.insert("duration", videoDuration); + videoMetadata.insert("fps", videoFPS); + streamsMetadata.insert("video", videoMetadata); + streamsMetadata.insert("audio", audioMetadata); + + succeeded = Video::setCurrentStream(stream); + LOG(INFO) << "\nDecoder inited with: " << succeeded << "\n"; + if (get<1>(current_stream) != -1) { + LOG(INFO) + << "Stream index set to " << get<1>(current_stream) + << ". If you encounter trouble, consider switching it to automatic stream discovery. \n"; + } +} // video + +bool Video::setCurrentStream(std::string stream = "video") { + if ((!stream.empty()) && (_parseStream(stream) != current_stream)) { + current_stream = _parseStream(stream); + } + + double ts = 0; + if (seekTS > 0) { + ts = seekTS; + } + + _getDecoderParams( + ts, // video start + 0, // headerOnly + get<0>(current_stream), // stream + long(get<1>( + current_stream)), // stream_id parsed from info above change to -2 + false // read all streams + ); + + // calback and metadata defined in Video.h + return (decoder.init(params, std::move(callback), &metadata)); +} + +std::tuple Video::getCurrentStream() const { + return current_stream; +} + +c10::Dict>> Video:: + getStreamMetadata() const { + return streamsMetadata; +} + +void Video::Seek(double ts) { + // initialize the class variables used for seeking and retrurn + _getDecoderParams( + ts, // video start + 0, // headerOnly + get<0>(current_stream), // stream + long(get<1>( + current_stream)), // stream_id parsed from info above change to -2 + false // read all streams + ); + + // calback and metadata defined in Video.h + succeeded = decoder.init(params, std::move(callback), &metadata); + LOG(INFO) << "Decoder init at seek " << succeeded << "\n"; +} + +std::tuple Video::Next() { + // if failing to decode simply return a null tensor (note, should we + // raise an exeption?) + double frame_pts_s; + torch::Tensor outFrame = torch::zeros({0}, torch::kByte); + + // decode single frame + DecoderOutputMessage out; + int64_t res = decoder.decode(&out, decoderTimeoutMs); + // if successfull + if (res == 0) { + frame_pts_s = double(double(out.header.pts) * 1e-6); + + auto header = out.header; + const auto& format = header.format; + + // initialize the output variables based on type + + if (format.type == TYPE_VIDEO) { + // note: this can potentially be optimized + // by having the global tensor that we fill at decode time + // (would avoid allocations) + int outHeight = format.format.video.height; + int outWidth = format.format.video.width; + int numChannels = 3; + outFrame = torch::zeros({outHeight, outWidth, numChannels}, torch::kByte); + auto numberWrittenBytes = fillVideoTensor(out, outFrame); + outFrame = outFrame.permute({2, 0, 1}); + + } else if (format.type == TYPE_AUDIO) { + int outAudioChannels = format.format.audio.channels; + int bytesPerSample = av_get_bytes_per_sample( + static_cast(format.format.audio.format)); + int frameSizeTotal = out.payload->length(); + + CHECK_EQ(frameSizeTotal % (outAudioChannels * bytesPerSample), 0); + int numAudioSamples = + frameSizeTotal / (outAudioChannels * bytesPerSample); + + outFrame = + torch::zeros({numAudioSamples, outAudioChannels}, torch::kFloat); + + auto numberWrittenBytes = fillAudioTensor(out, outFrame); + } + // currently not supporting other formats (will do soon) + + out.payload.reset(); + } else if (res == 61) { + LOG(INFO) << "Decoder ran out of frames (error 61)\n"; + } else { + LOG(ERROR) << "Decoder failed with ERROR_CODE " << res; + } + + return std::make_tuple(outFrame, frame_pts_s); +} diff --git a/torchvision/csrc/cpu/video/Video.h b/torchvision/csrc/cpu/video/Video.h new file mode 100644 index 00000000000..f7d47c0454c --- /dev/null +++ b/torchvision/csrc/cpu/video/Video.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include "defs.h" +#include "memory_buffer.h" +#include "sync_decoder.h" + +using namespace ffmpeg; + +struct Video : torch::CustomClassHolder { + std::tuple current_stream; // stream type, id + // global video metadata + c10::Dict>> + streamsMetadata; + + public: + Video(std::string videoPath, std::string stream); + std::tuple getCurrentStream() const; + c10::Dict>> + getStreamMetadata() const; + void Seek(double ts); + bool setCurrentStream(std::string stream); + std::tuple Next(); + + private: + bool video_any_frame = false; // add this to input parameters? + bool succeeded = false; // decoder init flag + // seekTS and doSeek act as a flag - if it's not set, next function simply + // retruns the next frame. If it's set, we look at the global seek + // time in comination with any_frame settings + double seekTS = -1; + bool doSeek = false; + + void _getDecoderParams( + double videoStartS, + int64_t getPtsOnly, + std::string stream, + long stream_id, + bool all_streams, + double seekFrameMarginUs); // this needs to be improved + + std::map> streamTimeBase; // not used + + DecoderInCallback callback = nullptr; + std::vector metadata; + + protected: + SyncDecoder decoder; + DecoderParameters params; + +}; // struct Video diff --git a/torchvision/csrc/cpu/video/register.cpp b/torchvision/csrc/cpu/video/register.cpp new file mode 100644 index 00000000000..a88615987bf --- /dev/null +++ b/torchvision/csrc/cpu/video/register.cpp @@ -0,0 +1,18 @@ +#ifndef REGISTER_H +#define REGISTER_H + +#include "Video.h" + +namespace { + +static auto registerVideo = + torch::class_


|*C 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 Y-TOH`Mp_V&f&8xt(Lemh|Ld{;2P9lj*Z=?k literal 0 HcmV?d00001 diff --git a/test/expect/ModelTester.test_fcn_resnet101_expect.pkl b/test/expect/ModelTester.test_fcn_resnet101_expect.pkl new file mode 100644 index 0000000000000000000000000000000000000000..ae6f21bb95c48695d391c27ed6d7f2f242675fa2 GIT binary patch literal 41785 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

$ogfmb6G@^fF7+dP|0%)+PmCl% z={HHugd8&JUIlTtcuR8b{vDa>2=%hpq;rha=)^<`YU|iZlS0tGZud2!*%n=ZLEI@$A6Rc5B^X1 z6z~5_e`ufokNZ#j+t1CP*O&j_eoHogJ2rnMHviVX{N?}3e-fMj zAAcpA{~!OKy#K`im7iaKe*WD0&t~h-_y4K?A3wMLlv96x{{JigzNJ3E<=e9p@P(as z+Zi4NpFB^(ht+4G!~Pt+9UBg9@=-96L_@9dB{*{FGK^4&ha&F;aQm7F@*8eI+KXGT z@9uSQ{&5*BZ6ZPS#A)bx><3lyM_}8XonQnjLH4+FKe%rG_`m)Cwe=rwbsD%Fs5=7# z*?pW&Z;Alz>9Nx(h!nuftmP%TV$o9IWb2LL4~(vN4{}DY_Mwwyge*YhS$Cbq%;2>q!Db;oI<+DJH0)RK|2>eVq(2r3!vVn`gLLSU+C;<5zPoQdl8ARGu z!E%LK7}n4LZP%M2Y;7xylWKuyH=AJ7{5K%p^BQ8K8UWe6f)~wo(D|y0{ci9Hs2|RO zTTk!76zv;Oy)_oxnDZbk69kV_PxK>p-3#Dy#;6u{5q6%rV=I`|cYvZ>Cw%$!4a$Rl z!Hb{)IB}v7URo%K2QL=DKF@!^yUre%BmWiBOuImR?kCXGe+!Qj**&FA%Ro0h9|}+g z?0k5O?dKWC?%fv#n#yNDqYwUAQ}=T}A{@TJ`Ka$uutyM2ixI{T3&pT)mjuq%l*ZU@ zFb>Ebj4uVt;QLDk;gV63xV2jx3*?Go<&(mA%+djP-iGh&e%T+O13?a~lG};$YL>=-+Jai$$A7Fqb)|V%RlP0&isZPuyKL7$04#fP>qVal|fl950}a zH#unImiZcZ)iPCFzd;Ev-X)JK4-Llie5LV|(~=lhh~mWA0@(1}XAlTzg6D^;Ai=!| z4sK*%&a&I^p!!-reC!8fF6C$lb{nmPB~;b$Wl=4RKI`J@I(@veXcU&dHwHVDj=_d% z26)iQ;kZ3vD1Q7&3tzWX$3b4ocx!%hDFh|` zOpvm=3le=uve9<92Ik^CQww`V48;j;!*QvFA^z@dg!P`A;psys;9c7$VZ+6f@V0sj zoVwZ!_qL72$jtzIcj@DTeY#jyKof6QQ^uc)WbrnSf%wDN0k|%!3u=co!%Lq^c=7fT zI7epn10C1JTvAWz;n>6x_*AYTK3r>rw{)9fSJ?^JVdNw{0Rs+xhp^)aD=f2WJbrw^ z1P8ttjb|v0#8Pwha8aNZuJBXAqwVFem$)RZ%oD=S65l}dcpKanssUHeVo0{m`-j`? z*nNWz=JHN%b~VCl9~t0O zv*B1IS{Kig)WnzERj^ON5d2GY5Z-Mgife!UgvWb6LdM6}khq~7B3|c%yf(W&lSP4r zKTevVjk)Lq>fnJgdiZmYK7JuP66b^%;6%AG_{=FI>>+Q8m+P8f$QX^a7LLRMpY?EU zfHuw?p^hW6mGA-AA$Y<-X)yHM0M&NY2Q8@aC0d~k3h3_5L$0O(H;P8U4AI8`!N(}HR)l~g+sB)94%}#T@4%ADq*%mB_3@l zgGZZ5V#6`)9%VEh!KF64sqp!;BvbEhA(yVWt5ED;SH zqpN|vcp7+xiw3sYtAU4xYG9#c4cz!d1FL;j!wKrjc!I4w&fhAF7o3;EOhc#kciT zaqun`yg5%9+bb#K5$lw&=siU&94L>6Hp^l_gYdHR1M#6xA~?!n0Ny+82c-6PLAO{3 zSZ#R&o@F(VXITak7Yo5rEE`U5PKV0UThQyB)Q`*zRm{auKoyG}Q^pMgmGFZ=1$=IZ zJl=jz4$ssWj7P-C;Pw%NaQLl(*xphUf6W?zXP*5DiSgYap8f&W6t=Q!gB##gb2V(V zFNMy;LO3Xs1ESj>Ku}oD zZ$`@C27PI)byE^=m>`amvxMzJIriof^bw1(QQ=_ce)f3t&8Dy z3%f7HNdlQx>5$Wu3=i+$ggg#|#gs6Y0jY}k%@9TWaGL^-e+1zhk%0lN%P#2sde`0!dq ztaMf$-^`Z9(>_Sy2K9k>|1=RS?=Fa)r}Tn<)MuzO=>W$8Z`t0Q&0un|5iYvD0y$I* zM`d0>XKe)}+Lrgjh20yQ%a3_OFwaFEA6cn@^EN1A@$E|3VXra{^i;u5kE`NS5-PYv zTmj3AvF~@0LHLZ&K>S=#1S<*%;_KhPvC9v-U_{_&nEv4-?40uf&ZTq!QEZ2%J#Rtk zMJs4ZwSqRwpXiw?i@EHN9gMel4#CS@6!1I?B|KGL1zUbl#bb)pu}-`umhsTQUuLM_ zS`GI2+GX+e3@IEMAdWqj2;()Q1+d<*@9?^IPhYOMw?R?^1X@^!J_M;)wsN&{at zQ^6C;+5ZD}%i@J9Qn)!?474^#``DN({$dW8rsA0~>UT1D{@ z2eIFH^~C~DDa>W3jWm9gKNxGwRKRYf$~b4CI##aL!kbnO#iT_ai>}tklPY!aP6rKq zEt7qp8p~tl%QDzeSrU8uiQ;5Q)^$!4_Y4!q8p#7OLXvn@u@pY;ER7SIWw6zC*?xRj zErGdwIw^&}ypzSfwhH)XvKkR;C9C?IFMZK#;Xusg zR=Ok}bVwF&uu;Gd#Z<9gktX&G9*S$`jlh;FqcM^jjX&~6;MmPW@q%zoJn)eUPX8j0 zH|fb@%{h|T-&O*r2@b-I4`i^+9yx4js({yYDB+N+s`$Yw4Lm1H^EY$ZIGcs*=8tc( ze(64c9_t_4=YPriC-nJ0_xYVzzc|OQ@o)TVS${Cc&-e2EeE#-x^Z(;N)R+Gs|EGWB z=jR{Lm;dYkP5yuC@VB3z|DXE*@&Bp6MPL4Z{PX|H|NqAC=pZI;>nOWdAX-3xkE4T- zuz-NLID74{i;RGc!1C=Y*R6M7J=T5o_8sfDZn4E|pUVHYi>UGw#%7ysuY^;O2vK~&VR??#$JqyM?NP~YfJ%QJV_ck_FWpJ zBx%qnl|m?uO4IMqt!tgG-~GJL`@VlX??1P-K5N@q_}Vt-cpT?``ulc}mXMH>llcFA zs7RyL`?ks$d zy_21zvxAGPv!k=Ki@nR-4x>8=U!62(!CdJ<66O(eWrq4nnEOil%KIAn8b-{OH5a}* zNJ3ipOfq6_$GAz8!e`E$JSk#&`0V-eL*|7}o;NwP@AOF#@^j@ZhRy91F;{-rTm@Ty z-;Q!wfk{QDgkRmt|Gyl9o65xMo#8!L ziKj7J;b6k<-ZW#kbgbEp$#$$b+lgKN=E^R3b1Xl(4?Fv~A9IoN`K^~wTLr9sLB(w} zucK<=A8GQbUsP_n4C`;Cz+x|{u%fA&OjbdUg&Z+pk9>_-Kz(;sveuY+TbeRfY{p!t zTd)&yR;>A~EmK(P#0=csn8SC%y!n1CaJes=O@^|S5~G;>voTCT&{|s^Qh7ne+1;w8 zqG2DY&+T8-;*bnGK0|>yTdA_VdQH~nh#oV}HDsY3da$fvCaik5a5;Zx!9qQ(S=M@6 zR$XbwbTXY;zXu{VN2M=I>+j2omJeg^PmN*vjT4xU@ig|7h5c69RwdG&Q*k9rYUvc` zkMw8LFY0?whH2$0uWen2OI5mXp5hx07vkq}g*SZd&(Rnxy@a z26mKSGo@r%)DH!g@f6nnETI$!}7UhH@;AC~Dolv$4q zW~V2IF^>g{+2q1#W;rmPHQidza>s08TX$}6XH;<&6$iZwHz2IqlY9 zW0vZ$6~hhLf*4aKQnFz(TO8R9eK)pwzXuy<*Pj`m8^jv>1TfW3<5`OGY^I^Hj9pV) z!`7`&WPWO!nd0U&c0((R**w_KtOd4hb?)J>R9xx&pVU)In(ewK$G)W~vC(7ISZ)t3 zrqZCxW(n85f}5sH0k&+^5oeaE!?DJ=zRb1Rm#vySoR!`VWbx&bS@y&THgoYxCRq^2 zHh0{>EQV}l{FZb!v~n-gjXu~;oRbU_H%z4?ds!sUmaI@_ioMiW#+xq8XYA}fvwO0Gg}vBfO%LWh!-r{5fA&Ik3_CG-B9lm)$!_K@WjCk9uwL`mv0W=t zm~6s!HhWtJyO*_}$y*&}odkdCsEtZY9REt0#U-i=_lp{=+apa@yRs`gX|BhX-_&OV z787@Yck8>+RVDHE9<#Jm)Ujc#vBjpGv_{rtXG8* z%RFJm7MIyGzqjtJyRtWHw)SV&eFIs>j8L{9el~k+yOgatx{7V~TFbH?Y+yOzTUmij zIxE|e#VYL&vzL*_*ek)G`q^KfiQBkQpOt7EFxhki=F!8DEjeJwPTCl;h8!bi>e`*X z`EJI%B^}u=8L-ct2C%`(0c@Yzc=k(k1{7E%Z zYUe%{^5qD-W0Kv@mE)#N+|TKzEWFZ$RSCE6{zb;D(A}6hWcOfujC(MR?cG^#A9L2l z!HG5Ldax21KeqqvC>H%-5*v3hoVgzTi@m8@#j+&UvOvQPOvPghyD~nFMXtzX_PY+S z8hVTsmY!&5vvN-+Zn}ppQ_Heu=Q~=lkT44-FWjHzIGD1)Eyhf$r8`@*(VSI>I5STN zPnID$gh|{Q%YrkevHb7_EXiOcJJc_hIa(&NeC3VI`@=SNvm%|1&d*}cGY+w^)!FR$ zqLVCJ%#EWCOq_m(J-ZOolZ8wduH%EP*nS5K=A&iC>c1JY#H#MhJ5uQXrZcNH@?yCW z{%m#8I2NE2#*AkzW-U*nS@^9u_CY?0E$q9IwJh7lmYvzjel=yX7|R1pHuNYflE`Mo zg4TLf5T0n?j()ryTNY)@9xbwFZsC?}`xJB5JkFGj8ezn=y1J^Shn? zw?V=>+plLkdSh+bN1^wUO_nU{ggIMQYAQU|F=p0sJ(#qK5qqU<#_n8pVg-?&?5LwZ z+wpoFi`^Z@B1SJ^*|DowWnC;QERSdV^VYF-S&71I*R$aZlbP%IjZDvHGg~j((#|kz zTPChsUmKP^--`9yW5FJlo3YtarmTa5G21$^JF`wUWZgEKvgxy&SZ+U0CZX@o{63Fk zTT8=O^}Z!+D_g~mrp2N|fVh5Bx*>E|3_ER#L9sCx? zhJRYZRy40-kwaqHZmC#SbZQN2n6`$g>aAfeH&?T<(W_aM@c2Wm^J=CpW>dWt6Q`?b z#VmyDolAik>)XYY4Vz)iCa~^owuTXloNmD4cAK!2eBpk-q7U2qehAA}3TEfbXR=FP zOWBm3G0acMPDx$ODjZ^%-t}k}GHE3n+`NK4G+V|(M=xcEnijX?eBF|X>-tN0Y$06c zj|>0zB|`6g(|a&w+3xJYEJK!cSD#Tc6J{3b$Tnp3VP75(VH3Lsvuh(}GRKsqZ1B_= zrYrQlQpm13zLISZT+SwsSiskX5nHcg$j+?OXZK$lvv<85ncV6=tb6$o=4KGghRvMG!p<#aeOAS=RY_~u zlI5#d`0OZlEq^IHl@`G=BWJUuplNKWD1^X|%f2NS{`ET-1x8<+@NB-QlzvG|z+uQp8lmCC){~V$JVxj*t|EB*x*{!qq z-_1{In}3Bc|0bdTPHpr5)BlYBrvHD=KfJAf|8*bp#d+M=)!T63Vs6->X71Y7-k2G< z2y2p3Q4xL)=0oqp1U^$hw=57F1-4o20MwIiP0y8ci8|Lpubol4IaXE(%MevW6&AJ9Rj8768i@HY4X;dvUlk|s$;_2@uq4@#5X7Sd$EZb@>| z;V15N|B8=lAEDXdEnGg-VbqIiOdb3Dw`oFc<-ho*n>gF=ow!xYuX2lincx_kig#=i z6f;i2H0mBaCp67QXAEY%$wPXEQ^sNacLdN z##~vFULr#dRtrD#y#rwy9mu5&sdm(}&WglsFrLhng?{4>>w035=PGnvv={k@ix5;* zhZXX&WZFh$QoB}}OpjJ3bxV}Vw7Ei^CVW0YsH2q0k>kqb#MI8@jDZTtuTUX{>s3in ze>HOBml`QQqfYLsYqaBU?!bv#YMQ|%nP{P^S1`2qrl61QY0NnD04W|n@FY})^mwXG zbUSMkb)rQS!Zk^UU0p~^sRnufQ=PoFRVOv?)yb=Yn&efcHhI;eLtYK*MqV8FuT`A5!{={sx!dfZ99m1eEs1> zK7Vy-XU^+moVdq>zi|&02Ey2N9Rg>Zz=pI6Tq*s5bf4=+v^seZ#ohgg>?|MB zQP5gjrQChMiHn`90jU*}0PpQ+DJj6&;k9sY>`1m}>yj_?dy-Lwy~wE@PDFiyJ()My zmfSM4B6gDIBiibIHD-;qSCYRuoX zh4t78QV_Sx-3n&!BQZK)KX&viLzVnjsC`f&xf4vt$kN_KP1%#w8h|i+H?rBwg@lc8 zAbqCV60IecZHd6GvaIQPE2LJ$eBiv0e9WV!+aMqJVkFaxWRG_w9_M?Kn;O<+T(~)DC^jZb zjg5%UY-2KNzb%rQ+P4aogQ zT@tt3fQ)swB(`^*h-5e+cjX3>1DOG2sc1YId~Z5&?GgUBUc!1KKNI3SC&j>VW(ImJ z$cOs!`;dMMJo-!g^KIs!97d>)hVOQdEMw1lX z(IMk+nvmvVJF@DE-X5Du+^lD{(_grK7q`Y>1EdBY!1Blfv>dvR zg%6tWb(J*fwL^t0$k8JYwi=NTUjy>`ryiM?qeEIIYm?}%nndA-I@uJZN;=AEl1Y<{ z2&2|SPsf!kS>Q$Pl?^5i)`27`b~53d!`iugA{pX}AML=cp4qs+>Jq9d?xWVK5nq@D z`CcbaBs98^exk0VBt(l0i|<12A6F;A_f$#s_s%4&hcbCTK#_R6tCFeBdL-_oIXM*W zL`tkYNJEV;QO+7g>?TYieK4JP2>w*hvAZBnaoc`msGfz>x~nLXet@yd>+q)eD=xUo zkhKexNKTasaar1#oL5&SII2hry%mUeRVQ+7i5wZC-jT%2RwOglX_KJ`j7hJ{c0~WV zh)DnPA+L2ukTTba#H;^Q(pS)0TNOwjg*g9!lbG{?At|K<$Lt^AM%ha=gujPk=U>pQ zkRkf3RrQKAZw=U(Ieyiafv?(1`x zOOdbdB?*}-Nmf6SAlHUS5W~1%I6UVkT*mys`p(kCZenLrE?hR|OPi7|BkjqV{US2@ zYk$%*a5yRXFq&K!wANO^tM^0Pp}HgJlXC|5mlh)2>jvZ$?_<}U=WyBCh#Ql?pf>df z)`)(fd*yc&toV*`M&Hp=_zhb^zrjiN8*0u-k`w;&^<8VFlZOVnV!qS(+$V5b=r9h@wkjm+GQww`w&ZuUczBl6Q;U;hStW;!f5p(=L!G6ML*r>MPL{AA)GO`1CwM>>s?(IbMN)(C9ht6cEjykD4szIKL(SMQz zak`^7L3{8nX!JdV&TglmXjg!arq>~*cMm^RpJD3!8n}7XL0PFD&mT14)V?=}o8N>W zkN2=s`iLhJKVcF+qgJOG;mytXbX$0Sko^^si7kko{teeE{-wCB%I#ePaa+w2kZZja zx9l_V*5xP^MQ35z=OVnlOA+e(0M#m0DB1EH*?KRrEwcuZ=C2WQtN}hwZ()1>9TIbz zFsWMu+~R7W`r$ch$5nz}eSpo5cQG@)3>Cvmf4e8tR<9mJwxiy>3PTmvV}n5|N*(t? z$tN3rL3vm^=L)XH+`{Bz_Yu_i2qUbY!Y}MO`W|`-QC%&Z%^P4d^)0v#4G8`I4C_8s zAm_~uJgm70$!F(a@$fkOZ|_C*&5U;Prq6^poy0|WQ?~|#lu~faZYPuj4q*18len2m z(UTUV+V>XTdfmkr_Xm)2dICl3XV5f$2_wBaSZOq(es~Q+A64LS$W;WqK8upM2hsQI zcH~E`#WaMsAejd*rUdEo( z8*qJl3)j8wA$Z$EylbdLOrICf+ERmquj}FUy&Bcm$`P}@04CFp;fhNdrpl~^(t&Uc z>gS6__1<_RXsr!`|0>_QEnm4Uze&h{F63tk`MrevYyT$yu#n$R$bTv1uWrk~EaXoS z@)d>r!9xC@>_7QgLjU5#``7<3`u~$Z?jQXh67u`D_5bhk{r-{P`ZxTu|IKalZ|%P| z|G(?Mscrt6!uJ{7Rw7N6$&T3#*Lsu9Y8lZf*F=ApZ z;F4#H+Bc3Ul+#C?>O)Sm#~f~Pf}QB$V=aEho1?sAb4P05>`Gl<51~F~esuKd0d!iL zH(eaKesWiC?d48))!`IZ=H-3*>chY4!}HTRC{XoHhV;`g1A1RopPnnz zqp9n4>9WB(bi7hm+NVT|=2&Ub6N1*-YUz4Ih!b@-MuD;wyp$bKq|_S&l{|1mu|I|? z4#sVT5vXqVMpRi3=pB^6+zxqM!1U={+}3j<^Zq1%WVndmd~+3_ksZe$N>1c+=cVv$ z_*VX!QyPD#%Wl5%^Ikr5>H&VTU`ks(vfl>catrKn@qKUHGWJB($bonpHw@p;2STwi z1iA)cXz3Gz10#Gea=I;~muVo>=o44qbAjtNCy{$^>&SiR@k*4Vc1koyGDg(5%0#sI zuUPje(+}rI$4cZk9Sq6e{vRj{qCRx&q;vzkY6`JNBPyAMOluCdr8JsGysXXEOP zMX=u<1(k$lD0?^)>n(yXWU((g7rCLVizU{FcE#Y6a!7vmnfu!N1veq(CRg-2kF)VQ zz-`{KiTnN`io3QgkaKwF&DjZhw$;w}`$OEG9)oc8{3yH`8Ul^Fndlw02-ylN;W=sz z?q;roT37^6xB9_Bji4~W9>Y2sOP2**BlLEz|1S>C+SdaXNPcaXozsBB#xRjl*)h{Skw!&(|WOXaklU*#do)RBU*k z3aPt0F#k*%s<-dN$jEdQ1@D4ep9~xeO@ndqMx@%TgGx#?lpE)x=?( zv(PxjL&^CfZ{fUKn$C??A= z9O62;F2pp)Xp{_$hh4}9Y+AAvUpAy8=)hiFU`OB-cnW70F}Q6m2FB6KjyV>>F|)_T=(3(iZJ!g!`ygP=2i0)~8_hYN+#2s=Dr(EcaG!iY>Ftk8}P||1QpS1JiPk_WoJ5&4!5O={E}Z#7M>5N8q}l9`zmN( zz6ZT+CD0EmL`DGr+wQjN^i>w(x)rJ5ZHO@nfA+$rR9{SS84uU;d64O~3U8zn5f--{ z%Pt&1Qp*`+I2Ivi<~>~6`x195KjMRe6gj`916jd-VC~$G*wmvQ>35&uQ0#r=_Pz;L ze;JqhUT8;!J?6x%ob`_DIavw2)Vo8u&;`rq2#;CxCm`rX1YYqmIDR)7^2c^#@|qJU z2)+QFUbnEI^D~syG(mHM1exn5MLx)Uhs@Rw&@``y#kuEj8~6}@k8UA&W-)467m}t<3sng*qWLOceTT)iqAugWC_fd zJVr@V1Hz~MfY}=fGS#mIEA!tY)w&)zX)jQs_!uuE@8D-c2^36<+sV(4;Ka#UCv!o! zDVMXffs;~I!qMs;7=6|ak_kg`Wc)PrniCD<*o{z2&%&?VQ)sw;1rMKBpy+EYa#dQ8 z=k*JZQoi8Fvv<(5uLl=Zjd3@hV7Yz;(r1;yw#$unX4LQD#BG{$mV3GM8JFfMgUdx- z@y5><+U1_`7&QvhABQ1e*(!V&o+Ive+KVA7r}3r!3Nni-FmO*TJ}&iGrz zZ@t5l@xt~0O*J|%tHgeV`yi>eux?`M-_{E2+1)kTaZJ<&A7Y7quDx+n$p@ofjKuS^ zlQA)j(L+mVk06H5?f_86lZ>(TS%Hyjg=Q9K#@730>v$CI=5 z2(GEd(=L?=?puMXd1Ww^zX1b5Yi(sVWMn(K&jTSV7m6mES-3xZAqtnQz`Y?cxc)p2 z1q%`Zt*z)+v=_dMaxv8GB1TsTm#f$+Oz!m-Gi!ce*lh`-xS$0Kygr~(wE_LBs&V|- z6KF5HhbZ5hIF)m~ohB{;;-YmEvHxBYZX|EOd%qND%58$^;$}=-z7=bFZ---b2Bs}P zhMn5^xSdmsj)N*75_+7s@;z=VNsv$LC5c zuVJ7Vzks6<*L?X1{0<(*?u0}59DWdf!w(?CWj{W5-3Q+vSuj6w2OfKpejso5Cp^(>#LsKhFchwzea!A)(%tKrf261#nU!xLu1co?n+Lyy zZ*(OjPgme{T^VL}y9T477jZ8pA8Ni7xA$Ddrtjql81V#}$7*n2_C2-<=R9qKI*_NA zJCLgne&V*-XFOieh*uY@(WLqqE#q%P`q(ve8gT`3VovzV5pjo~%aENalEiS?7sx(% zg9fLUDBJJ|ryFizr_WW$XnWL2~@`SSi3 zURMeErHv@fuSUV4N66V$j;uAsNdIx^x1DX(Cs~Dv>wiOu^zSD}`tedEZbl2%1ir

)_5e|qrHKAng1FOnv3_e9FA(}~&G%}X|DXQFdvDEmk+o_kX`&aP9f5^YQ*g8J5X|&1V)>Fs zxOe9Rw6tZ(?Fn*Z*Ch#Z&;LDUYrlX@)orBhzXa#-Qz&uShr>&E;Evm7d}~QUkGwbx z{3{wS7cPcVa~M`F8jr)h#{71qt^Ozf|Ly$Ei+Vtu%9!4G5gCfHWwGcRvJ*BRbD+8A zDt>BJqW0him=9?N>nNPdFL;Qzi%YP^oquQ z4TEIEMC3?~#-y%;k#9Vp9fbj1AWqZA1lHdD;MI3BY<5SZcSZ{O?#jgA^c;-YSqQ5c zmry8u7GrlE#{1s85Pv5HM&WBPPdx$|K4bAd#t&1k_QxXyFZd4uE~oT{+dU^7>uQG{ z!pfColSA8#tqg5LlCzu6wl@?!7k%ilx#>w&(+DeA{mSP z?~76QX%e*G4u(%{Z!COfjC~I~W6XLPB>$4ZwQyNTRmsB5zat_FI^u|(9I7+qAn`yB zl7c@qYkLzX&daZbE4VL<3F}nwi_<}RQx9N|4Jt?U!ZNu&2=U;M^1})j&g-CQQ75?1 zXyUe4-{6{q4|BsF#BtxJEaeu@isNSQ-^fjUmd;JkJ;aS1af%zVzJT*7zRvZXa_cv* zwmM_yZBE=^%W|$u-<#ayaV6Z|MaA5V^Z&BwJMWPE%Acdtly2*U9;^^9%Az zjXUxhDz<#!w*Wrl)nEL_Y03Q7$}Ik6W;$OGwv0cX%<OL#u1)z=a}>WuZU=vC^)+7Iy_P>? z{*kvDLt#Xh}{8-T5+MghB7x~ZP6}^l2hwl{VF%Ksiy*`Lqg-6q+8`jZd zhvRA0l~~&4`D*I(V-=0mj;6;Qqv(~Lk@QaRY#MiH1QmT2(f56f>E1*Inw#^I?=~=( zk9`)+FA5Cc7YbTyD~YHOkvP-m=krPfdhtj09p>Lhthvb7iudx~~|jQKcKbZrp`R_g12!K{B+qu!SE} z|C%pWf5c0g-{z&-w63N18@01?!W_P!?h2oNOP&VXI#9iJW9XatQFL(kP4sBletIwQ z5G@{)M)ORP=-3x4sK;NEsEK-iDu39LHhC&j178Wc{h|a_6G_sgiuMRbCxFWnxXPqSoR@LfXU`E8kF`ToN<@LqRwcrxlP@AjaX-(jOfx6jt6TaWjo zn*OfsT#Eb1i#xkSiH1}=QpF*G^ifb0wM*GZR~PN055J$IJsoaPhjqpDMaScGbIc~1 zAQeHIzJU(^)QN^YImln}_?15>FFAkjyq zidzm;*SemcI%6X5s+;D%rF5gHp=EJ?L8v!Bso#En%IJFj)G00M!g|xQSI5%DH)gie zwbqo1OUrYmdqaX~g>)1hdq0^zJ-mlbT5*cj3@f5xrVr>1t#YblmP7qqQmD?lP`d4) zF?HNf%!j0^^Qfp0DGlqvxfX45|I6ch{>hoKe81wGe50Bob?#$FSA+-9tTj{GsSdEE z;%+_R=;60PG)6L#9*<9?JJfd4xE)7mgmFF%IeMM$cf3UVp4m&EyTww8WkV?!qaj@O zj`OLT@8o-L>%?V*cyX)D*NEoSM&w7var~_MbUsb(DgQF9GhLS5lMXmf{x(opXJ2q` zr=x@y&5j&LgT5}J9o*yTm?c~2(KCB!htJt`v=gN(hn%L7{kPMm<%?;}Y|y8{()8%g zO?=qrmHCZ*%{YholQ>s{8j-(bn43xX{d^1EAb!HHy}Z@CCw$~PdHS|d`)_ZAb)+rV zj;Om2J>4moI=q`tM>WLIE>-Jk`R!DiT(p-C&da7_!w%4s6$w-)E`;8kU`0F3ujR{q zBKR*seBP#aeYqDGR&rnDjk&?b@gfiBioCbCYomw#Vst~&E1QN=E8!#Ijg*m-0hwzq74Jh+=I^h=O5YgGJjDIHGZ*RXr>MJUaB)0=nwdL~3I1LW_>b(>wl@ zx7#q7uWgacKcAw+buHh?$-lV3*?-UB#&pTzR@iRl_Vr)GrCylL)qe2jTudFgam4s< zLBd*XTQC)8DjHAyV`tK%|AJo?Wc_Dw1kgsz5U;TRt{kP`J3H?`z_5aWOzq4EahJVc8{NK#K zwg1-ndyCEgtk8dJerx}K@>}Qsr~m&|{-6IrYfbqz3*tf&mP6|HdX$gPKxRWW<}bMb zFWGWvY!d$+0WNHj)Zb-y^oYY02&UhF|i&IxQ;$*{x! z1~LpDpmDFzYXx@qyNlWn<*>;tgLKSw%-ntvw~yt){nAP7d2kqt zZ}%WVIt`DzZo+!w4S!1#*4tu3+9`;hjabnt9PPCp_Z)WMhs}N%Tb#r|V}^MK*KzJa z84QM(VNJNgyK(I-*PaH|sgWoTjDucu3Z@)P!-=weXlc$yUxPf@+%3S#u7&6w zd=Ukim*8D<8KqW52$*vfk8+FA-RCkaEc4)?cmi&3_6g^Q(=ae61;aMQA-5qC`K9xa zC#EcL48)0!O@!u%dHAwyB|>k-qs%x3Se%MO*E6AMa2Oe7*}^%ElX&y?G`9RY2d*=Z zYW)JNwY>-jT!Fo1A>!Yk#`E)s(R)<}l7(}YuhrLL)!Aim7%&xURfDij@Tbna6aaDG zyvCxd*EG0#E)Z@zR>D0a7S{}t5V&g-UhD5bmy!%T-nSQfRvtoF&~Z5Q%0-LnITSYV zh%YKcA4P`O=W~!eeII&jr{dX_M8q#xi4dO|II(vq#su_hN6ywC;_@B@K;J$X(Q#Ap z>ggQ#_F9TjMJv&1{u<=zuS1;hI)pj1wqmq;Iy{8eikgo<3>BFid=bu3RQWUbzsZBo zs$=lb-VN8I8)4_U2L8w9!sGr(*hz_CzSS0Hg4Wt9YpZWNi^B(_yFmc1myW@L<>O&! zI~m1KW?)|89O!Zj@x3q#(oXSE+M5hb%~a^eX2SH#A@rPn61^VgVSL$H9PmAaw^w!u zGfc$KrOS{scLMaMdEr>FDLy~YYG-TZ0EmlY12J=@ABK1hhLemxw2Ow~d)#nT4jh4t zilgvq`$P8dxSR@~u3!fhW zkR0lY^I5vsI#}s%+k|zMly5t)iwEG_sQyrX)fe3(JmD!dd13UYqPdhIbN1OkD{LmFZY9bO`EFoDpzG z7xJH!p&;laXkD9|`L*M7#|P_dJy9Cx4wV;9@aJrivegWC-x)&NPY0#njPO;$6(+KS zh1ZFOV!6sv+?9_*n9@c_s-#2x$xdWOq@br_EdJ`h2-_DmO!;gg5#*~_)zMw1Cos`E2zh-WW{R8fq?-Cba@R{3nK^+_CTO-b-A0jKp zVNU!)oZK0UvV?f3sIA0q+qp36JpsGDhQMeruzR!(x=+#*UOS=Qj`XG>5I6HfKe*>O zpwnCf-0!J~Ay3|Mje*y>b@#KlVMijlVck}9Qnu%~(`e*!_p3lL+Y(dG_5~{lhF0-n z1QjpG`U`VVa4rNNP6WW@kT*tWx*|T+5_u_lxRcc7x4UiC@2o$>UH{P+*Wzq&Rb3P7 zxF1~n@KP>j`YulD*95M`vI95wr#v@h$zsm7C5JnBrjAQ-Q^An!R#5!njcX%AptEEK zegu!l^S%MNVmSbZRDi_K4w(1Y3?mBl(BE0Boz0JjLY$RcUyK=Vj@Z+Rn5O%jD=a?5 zxiwAUo@{RtnWyTwOB;*alWcy728Ye%>I`x?o3-_v>ryoY_UwtsYF|{CkHoC+gCJGb z58L)|uwCSgO9O2%M&AT)-|6A}Bkgtu-0cr>rZ0u#|I+$MHL$*!vl};F zZ?h=jx_Z79rb;7)pM(|%}jkHY`sM%=>$NfF9 zBHIwx&UJ&x#MQ?| z!3X8@{(5>l@3mVe(Nza3>RheMojEp|%gJBM$#y@;1;!R}@_in0T0^S29^)E0yRgrk zXvr@w%S#%EuE`;Ls1h7EcZQRowYG{4@7B)nzUsL3=m+=1_AX}`eS{l%cNHf))P>7` zQ!F~)nC33((lxJa&q#Ntt*WBP)w4vE=dwf+C(1>_{#Pz*h!*$yo*UO#H-lTeJdyhn zyO&#<%yTWNce%){M(*c5DFh40{>AMR$wA!BnqS<#OO;&ZZk~I&JdL}5W+7KQ*NJNw zRV`B6MnqrC>)lj*-k$fEos;LWS|fkL?IHP>HmuGs>$NApscGnUOM%1PEmoWs z#SF0EW)EM)9XXcCWt=SLww!I^;=4(q9ragSyqK@v54gui8AmntaT$LlaMG72bHynR zoX&-xqRgOeB5i|0_l8f;^Qcs2zC@M`zuVi5_o$oAzq_2wdukowPmy$f^KySa>f6=) z2_a2xw>#E|@?yqw#f5u0hl`K6X%|2LHnpu@Ihx0bGufBJJ>QbS?TSs}&NeOP?8^hV zLnrMx+Dh6dxgCF*1g>_)O77>!S)A?b(OmFT zFD~JZEtg;1m8+-H+?3F1qIp9S@)M?c^Tz`A@LdFPl4;jO-$aC(i)dg02g zZE)abf3oI=|1{-#cQoQ=blf7Et$jLQB`J#UxaBtgbFe!7S}vj=M^2%O8e?gdlbv+_R{)QDtWq;b=ON`ITyRttiAaN-Qjjk&7xCS1lKGj2ka zIcGTEl6xv+&F$J|!;QD<$;rOoC#wH`E&sFIdOr7bJ>RRVG3_#H7+o?jicXupm6jda zOoO{Eq}^V6(8osX!x`gZgWNvw@I+Ejd*tJ`oGJU5%OOP`OQLp zj#&QE|03T>$e$vX|0lb(w)%JZPyf+>mC%2>SpTj0t^NPI{G0#i-=(d85262ILjSFO z|CzzR%QyHp^KZ@15b}fD=3n=Jkl)(>WTF2*`G5NUQ)m7)6yj2DPZb^?tc6x;1|U3+ z4;^>|>oQ*;r{ybVS;&!8szR#rHHmqi9+`cvJ2@@vf&6jGmU!hlk+nH)B+aKcS+dZM zjLb44j^+A9MM9G_*eH?WvC_m(y%`pL-n1j0-Maoy{{QU!-8u$9oN>!^e0#eVFP~@N z=H1gcbF~B+dC#%#*cY7l??|%GbtdL1T}b8(U83t{L^kT05yg+zWOa!H`H|&HUUlz9 zMBcV!({vNkkf29Av(-uJZF$o4S(2=GdXHD5>e{)lKL+Bw`_G1&Ujm{ccH?c@X#`)s zj*`YIxM_Yyz%Ch5d0dI)iPXuKVr?>iq_EffMGs;%$AWbHVN0sxoyg(}2Xg791yT8E zNCKs_$pMwl4DDG1rzBMXjow+8tHeHt}95y5a8%#*NjTI@LZAau1Y{@`jPw?91dZc8L zI#HY}PX^79BsxV+*m15Bk8|#}qc(UF#I1X_5RhJvvs*J^XLT9}ggsx~hdsfLmraNl zNs-=Zoye19WfB#uPP#ACCRgTlBh#mKCyK#lzg<`H}cy@AO(;XOW5 zI+9r;MH2B!g)H6Bg{*YbA#v6EBq^x}+2m?YtUsBM(U;9Nj714 z#uFUCb(AX=wliqiEQl-nYX!pclkw*K9?Uy;3ZKptVe#n)_?BCb+|ufmh}PbSwSHMhi8_VU+$-2qTY)3O{<>WM78EY;KsE^bZ-cWGh}D_S z9CDHf$US4;80hAlX~@V^8X14zqfElC*nOpiCi~UB}3{o$ep9wWb`~e z^2EiE)Y*3<%Ofb zuox_-+p$3PIA(`l!W7~CH-hEg;;^k0nK-u-89GRbcv`3u2bnI!_?b4*;Pr^~c0=+> z*pttXHzGk}w8*z%N@Ry$2eKgHJx;Eu6!uSFgWZ(VC>t-lZduGiLuZJqPVqzGqQ5Z2 zb~E^lBd}7xgw)lKAot}x+?{2}Y6T_o{HF@RdkvEMQkyj2*CPQXh9sLA6J=q~dvc-) z5e?BLuT)e?a=9#7Z2lED4p*bQ@Lm#&bMnw5;slHZf9ll`BZxcp(G3f=XTvak1ElQ^ zq4vT>ln#G_oR^<*-Cd3x+^a(7W@`|)JZ;k9iXORMW=J+YGA83*nG@4@)+98~g6Q@$ zAh(3~B#9d>Pa-e2r)8B}pQO zs1l6`U1D_EfY@pp6Zfg+#OJIv3Fu@`CI&i_S%-U*s=hAdoT(K_mNO(XUTYA~l1{`W z=m%aI)L`3-GR(Prxt+YBn>lf|11q@roi_NkIUFuU+c4+iIUHmUQI+=%%0bGcPn1GfxToVfKGP!HXAg zGQ5e|^wMv$+N$BkZk)J>IUBfhp7M~k_QQVpSorp|&}`$X8RITarI!YG>*ftkxzHT;X)|Euz6G558Tfa(j}WP^IFKbn6c%(ObNY26 zce*GL*H?-p?X)tHj8!3_qtr+k>r6D59O0=XDT(|9gUA}p{p$fPExiuSr99}8(_n%> zRbTgOzPLF`&)n>EVmZyxGSKMJA99O?qKut=9b*!bp(Kft z%#~0fG@=rfP=usJ8VpHt_FJJj36WU{nL;v8&wW0>e4jh(`+c5gt!J&@U%#x^y7u9m zUiWpKoOAAd?|pUg1vTpVkS+$4Q^3xBQ_bTlLL}DeU>k9A`@?_r-c@ zBRfFTE0XD;>0x?%`T((B(G(mRLAM%jCEb;QRDEeZrFU9Osn0i()g3>&o*hV*iCd^N zG=wIu+D3)8;iOU;(SW=g3}WVLbV1klXSkAXnQVlLHj}AeV=3GFlDFnEN+{h$n-(0R z$5-|e8xcuS@muLb%Rq{$T}#vRmr}DBJKDQ%7AciDlIypnbVqMBjh(rHDlYg_3*ma! zsP|jxo@Dz!+^vsdw|p%3YYYA+g5N~&X9@n~djDa;zeVsr5&7!`|31M#qu#$q@GIB* zZwvl0|H1#~IR2eq=db+b{a{s@}f4|5t&%cQ%f3bhGDF6TDw-@r4`;|rY7w7-) z{POyX^Ox7(MX0|#e{uc)oqtBpWe{_@ov>)_i#qJi9OHF$mu1;&RGGqO8QUJ!i4L5$ zCJjGNs{ZLsl@ebn`sPm=nVTriBZxwcw~|-wHVU@iP8YpG>3c*78K(r%vi!{y|0s~| zfA^<$ntn8}hi?PKZu$6s{Qtf6Pun*SVtRfb1+@$%ynVEdw?}tbxzi-JQ&!0w4hLt{==O!|Ew1p<^522;Aw^2}sa5{2hhp^6m7gbG(rtHipvcDWj-yen1?oV53aPuI# zrV~i6#=g`(Vy)0G#-joA!zMt?wcI|ibtvb(UHbBpl0=Djm!s@)kG9n0>~w0E7(_ZR z_t2q)eWdFUOUJYhk^Zd&I=SNr4ViL`vYMrm{_2Zj@Z`?}`K|3g4_&L;%@h82B zo>VtyAWHyEzzZDgWHY=i*;bX;%dH)QR@6ICGR8EJRXH!`21=`yURIGE7zI8cFeYN(GZ6|q+{Ak61Wpt&_ z4Eo*Mj1=_#H>ImPL(H6vTF!UR;3^;8BsxKd*_Aczsb$)1p(osS%4>0w$m0@)>gUtF zXNA=FKnbm#d4&pET_eqca$4Y1K`J-Ps8ONNyX)L>`j8q+uMdXN(?}mW*UEuXK8~b> zYQuksuaEwVlprQ+;sx%lbVK$j!hp3auVOZDhf(~hjr8S59K}lWXtLxsHTodzM?3m} zmdtxZ+U=|8+T~}oDc}W}n7k&B;3qW9{R(}Xb&h1C5@|!99puw}11Z&7(UzP6WPY^c zznCbD-7@ZQF`AFUg*D-~Gp$yIvrXI8snW@oy6g+5qNW+N#{CY>QLLfWXWmiRvJZ5$ z+b6no^9$V%`A%O({vwri3eqZ}_mErX2f})ZTna2tq1GpM(y-3!$fDewoI-^?6N?r9 z;cb1qvp1QGsd_z{dr!SCG1Mt$jZPcVqC4xTdgCG5r%^~#6KZIPQzPj|VQ<#y_DWLW zx4}q_iU^;8EK#{!fOrfud+bG@fG`V)UN9~q1lCu2fQiHB)((Xd<$#&OT zNt^almwxlt5PBcBkv<&UPWte=n)KfC@AS>+F17!bMMJXp(BT%V>2Z`X4L7f5t8ON; z)dGKF=knoPjDcqp+2Z`o?5=ieQnIz9UFMP0SLlT$3#_CgQyWWNPO3=^J#H_}-q}$)<+-{vxk5pz9`=xm-8cnK-7D;Occ=Hg^eMOWIvW&gtV#98HZlu4Nr4lEedfyFsIXU4>DR5QQoXw7 zQk&T=rCTnvmS*;8Bdr$ZqS}9HFa3I|wX{>vZyKF+pOzG#qaClKX;o)8x-_Rh^&WYZ zdHRJik9y?e<*LOpF}9z7nY5q2liAHyqXBA`v~g|_EzC?JOZ5^OzT^${6884zq&Jq@ zmnloXzfzS(HC2-i?$KK4FwjQoYO5)Y_h}`4;P{hPUb;)Fx>*#vIf|BETTW3s`_h&Z zr7V3_$UmGGqMX*NmdnJ1e)EykbckUwUz^i~XA`LIg+FbojH8YfIh1_4l74rnqqb+i zQ)F@@>3;7f(j${pr6;x2q_WqorTMb9(#exsO7}~?)1e2q>8MX8C3oLVjzLRl>1927 z(Y=J#ItQ^20`e#)EGg)mm~lfdNOB*%ek4{refk ztGuHf>R)M;S|e#@coV6iW;5yGJuRi$I&Gw%I;u$>G`~{$mkKhyn?YH8C(RnUn5ao_ zGLI}|2D3IZLxDe0X-B?^m|tfbv6%RyOlycLy^dy-^>YPXGTcGQjw!SwGM|<`yG_P6 zRrI^Ch6+r+Qo+qe(iEZZLxfoisfVw+H1=6@Y4>-ZNU6}f``+Uk*0?Krw<>_j_EeCeWH7}c#m zK)nv6l2taRO^-?_|8YKbx|B-G6L!)DwKdeE%#;cu+S1*mOKiftk*rVg8Ht|2pXjwb zm5T|UwUf`AZ_20kz9jQ$+-gKX`^yrKyXGuv=WgcC3t53eBl>RGl?FISXuAPr3sPU%onkJ(V(m^xu;K1PZz83uCdccMkF_7y zaxtHc9`MA9bZ)aQgtw)!{AIHzvTWy1=enj%kvPUHvkZwFbF|H5i*|isLlmBRPBTj;Qor{-NumD_mbf~V#cmkIvd4Fj#D;6j;sg!~$j6Sy zIz!CB&23OdjdAbwQ{Krgm(MJY=aC}MJ7Tzil*zpUF*CYhKcc~|bly85NFg6L1| ztc@0Jbz(Hn&7MX&*i*lujM}Sdk#gQgc5lTg=4|4~^mNZjzRb{)UA}frRw5veax$JW zh*?-S6ea5YVQA15J14cpx5X;pEx+=B36Ho%Kp|H z$YjTx|6ty~b?B$Kleslt_G}S5Bah;(fqeWj}QA=b#B4W z`;w5DwQOLQi|m4=jD1dyXER5*v+Pctnf0g55}O{;=NfM*mqpDV#pi!m_AeZT@gTMW zVunY#V7$d*OjmM(W0pN!-DbgCcLsv*Szvd>1h~>*w60Xgg2wmxVbfi_yp0aeySDY* zXndAfBnPl*op%arZtPjbISqFIN2o;O;qI*LFR`+`;ac3_^Fsdq<)#LR-SY7t{|v$J z@RvVISf9bFMNtAzwdVhi7 z*B9kqE7U>G|1E!)`uYb6_5VBn#QORdi2PIQ>o3p$fl&X}qWs1FKhJ~it~C&2{dyg2 zC;1>a&JS5%0`S6OGdd;&!R&hoyryo${>CB5QujlO)E&=e&x5v?1!hJ{u>E*n6qE@2 zExpvR<&+9yYZ}9C`Y(R4u#R7ozT%1*kNBYex48Mj>kSaQ<>UYH|M%8^>MdW0F{|^% z(Efht>Es8E7(X;B_ru%f{c?+X zS#z(7NxVzZXr3(_#+}pjdDFO_JTa7VG7>$_4WT!-i}1S86vG{=cAtBKp^77{(JE|RK|10=Bvm_*TQoaBe+ILR*odCcn_3o&1+qhYr+6gh8v zU|zWh>QATO&Wj<4tLcIzACxfi^=Ttu{%`%0GY?E}uYDsxJOQzm_ zJ!`AAj%jvV!`kb5vd;Zhv(APqS(m{pSho?bEKcIWVg(M?GiG!W#27t2h_?O0@zKo( z$Cl5<@~;f~fm(Rn?Gtw#eu~@1x^v%>);#R7iL83rM2TivTUP7m!4~#QW;5E|XTHH7 z*z4f8%qHX&yAbl6_22r0?b`Z~DTLl-OG7Kz!O$E3B2E~ew@Zf@mq$lY@-h zcPkXA^+!NgMXYr`&a2uF=kH?2$=a&Sl8k%Zg^e!uV~(*I%y0EeX4$J1J!;j5FxHr! zUo;f1Nem##g+AmwN|(a2yHl1_hpNz-*8b{9YXts8i6QdOhS+D zosjBzg&SI1@vdbi=bl|@#kN?k7kU_;X4QJHS!@hCR|DpbE`u2BglvpkdJx6~{V=v>9J;Sv6_|-0bWST)! z*vA_=Y-8)MY;&&;RC2+HH0Dhqo1aT)%4C1~&^esWKiMT*n~9`j3nJ*CuCTx6c_?i^ z5<-ECgJ@mf&Gf0+Ci*NOk8%bE-GG=zBl8fKl8CXLgM`mvR%rdEJ>tVo^CYb|vQer( zB$w{*V1^SfvVEDgtVtVnI#;MiD}6>%@1ZvI@Qo{lP4T8-cI)ZMq7Afl^+xJE%7@(Y zeJF3TFLf&SrE%^38lYHq2Vzq06r<6*6j(P2!}P&U_&!$;X6$95EiMbu=hHo$WerOk4317QAln!$9)Ijd2rT-l{d$oJiq;>ThIv(+`*^zu7Dq z-K1KAmOa_MPBWNy8$TA(aSw|Y)}#Ahxxyy&`M@@hYEFx5v}n>^ebP4@Nv%IlrP_n@ z$;oRO%@_C+z2aX&Oj^=CbUu@fEf?eQ@yZrl%$$XotKIOj{5l_|X2w4?50kC5)RvWv zugYq%zR2W9lZ6tQbGpRK{G+5(`_9b#{4Dm=VlV57LgqB!3!7%qhH3-*QUo7GgFf1j zVz?722sEn4{MB2CnKkY))_l!FRLU`AI)ovu-xAd9Fv6@aUwK8rRzBxb4=&Sg!?ngM z^3M+*%Q6jeWS%|;WNvZmWOZYP$(H=sZ=(1@nR(T&VV~A#uoH^!SjNS+)MnE_ax=4_ z14r%tVZRXNXbt)ZF-|FM(6ux_&Bf~4yaw^nLgosFyF~feU0V@ zL-z9&_c-1s?J!S#mBf4LrSa^F5dN;N5wGdL-=x1!A7;Pr083c=l6^YXiK07=q*qs` z{ln|}xU1?p#DuQ8iw%(%;F5k6_T^#NU+szwdIbALEwI7zG&ec4iGLKHhqRgqzOZdH z?>6E9zcV+1M+P3_7ROF-qutwhK!g&%V;*ZFN$AhE#m2D>H8pJL{w`#YJBE%4`>@1( z8gn0FPFP$;52v%(z2+dAZ4bhCv-x* z8pK@J%SWNnah#`UoSxtZo1@kkdtMI?Ngui7W;FLJbKuXiSM!8h0sL0kHr}i-ic50h zxXamO9(y8#chHRF$(L1m=B9X)*>4B2cZZL#K{r3MEWaMYwFu#y{F%M57ECxtu8*0D z!uyYiIzoWuGK9-P72J83&5tt&zUx3&?$mT7ALKfhD^zUY3w5@0i|hOO;LWLA z%LIJIj2OP;usZjtOfm_wmoVSsC)k51MOr_rKXvY8O-sHlX~6BSM<8Z)_reM{(bth`arrC(lXaE*Hn~n5t&{v9><%Gixe$+p&t@eHOxh`S0W1yQT55$mUPl z9N<64wB>HUl1-xgrR?OXbXIari7?TCj$fKZeH*zpAh;|JVwP=)hT)w}c)4^D+w>+-0MAW7kQXZQXa;2nkw+PzP)%)3v;2bi7Ve_9?Y%p#qbU;Y5ex@9KLU5EH8*? z$DP$uO}c81ViN~vunTXS(8EiH^dovU1uL!ihY%sk5xeE%KmKaLzoOpXMDT0=W?)}4G^_vJfZ&c{)7LI_s?-GD>zPKQjLz#pk})% zqcV_Ixh$r2oyU`ZK~D-!}7Ntv>TYE=#ZJrGqnq#=>HJYt-B<5l|f-UYlggLbw#O!Mauvs_zuo=Rh8jJni*rYI>29)PVl9*qgL+I%7 zRb;hdDk%)or(?Cv=(zJ0*0fq^=5tMn@yRZd7&9A*$C%NQ8Ps2*H(XPqWUL@5m{V@z zGyRCk_min6qr9J+T-? ze-{fH7v7ib(}muEskw|^u486zZb_;?G?z__xGSr;`&?$r$<9hG$ya*U`p?ou#qiKO1g&3m!*`L^U4U}_5RZ~u01<~OV01)wmqWxn$0mh z>eT_BG35}iiWS}q9&Y1vyZG?oXB>ID(KxPuyf;76zZoAl?Y8WE={Z@pfIP|>8#}6s^SHCjsmh)?sqB>eII}}$AhG9$7H4_CQI)*u=O_G0@^gOP@fF|O;Vt(l zt>x1KK5_jK--I4N@A=N)``kpokXK$6dcLiWGHJt(9;giAL7``PAz~F~nutMmIX1n(XzovShPw?VAFikj*64+E9bKC7;Vt!As zVVRxXC6l}$8}@rG@99v?XC7>U&Jjka^s|MEt}DXUtw5)%D-o~j0ex>TWLy=_5qhsj zk@rSyw)2EXo)Z=tPJ_)JDa@1xV32KTE(%-o2)x0qyq;XJURWcqZ|^U2@K0 zu`bWw8_gdmR`MUlZLoRK5VVb%h3&hSm9Q=A_BlZ$aa@Jb?PhvNpx6DuRx?lB$t-CKVA zWvjFNi|JdgbY24?cLu&2G;LPr>nZD%GCv%gAe5}@NFEA7&P-|1(=>$D>H zw;q{Xq2B|p)KL-kX&MN>)fJZ-8Q@c2hCag2fZh68*mig!a;~gKk&-8p$1TOyO>^Or zKOL4TW*9g@f;Pd1s4MCTr&rooARv!&BK5YN6GLv=GU2n1OzquInd0HT{O5FQ{zJi+ zf2-KVzoaJf5RW3BssE0z{Ll# zs>91>_T^bxbNSTd{oJ(ZGM7~U;2j!kLL*`TT6P-;mE(3Od9nbrWb^PWayC{jw?-pV z;s1s9Bxrp$#gQwcP-7y+TY*3E)~t?POm10AK4Sd`*-M*3S&Z=kSxna@vL6-gWXHAr z&t(_x9IB9gt5~U7zxOuoDn_ea4|YdNAqW2T5wynG+Fsn6`5Ym9+Mvj!X+*N zKO}DHMyzQ-3s%{xxk=lxpJeSmZs4t*a(L0vQrdT1uR+RVan ze_Oo#Fk3jM6ne^)+hfhvx$qMB6D>W%xR|v~Jh*{TS6+}4DYMiZYT~&0g5+zvp{)C= zP0Vc031-~)AiHw9AB#PE#AN>FM*Nq?RzA_Of|uB+!(Cx0CJ&kfyBbR@5qfa0b+$!N z_qm9AFdvC~79qoWIe5A&AVQfZa4`vP+jvo$l<)X)Nv0QlG;2j+nq;WvV0OPp5Q~wW zVS29;*%x~w_Cs>UBx8FMzPWKYA0&Oq-MA)9?=pn$oq_ScY@z7j0Df^HJat`!`Mp(m z^J*=oC;C8fq+bI@%}?cG%s1}knJ!EDy$3q{_r4>tVYSWAxgQLa?3&k-t#~(!$y5ik zviUzv!W~}8ls57O^{hfPCTF#n(;v)-M?C z?L(padD}nqs*m2PXSkTRp-1?&T_M~>I)@LL+Jpbfy(VjWoyl77?rmamWsAh|#Z{9g zEvjYFJ$?B=(*j;~sws|-?Fa807BF*mN8WLN#6Q^tKh0n`ObCV4I}F-sJMiO?FrU|U z56n~dVuFA?%E?SS&&BMBInB*I4sr#{Q0_9_o!?P5=cZZR_@cYDG8!Exo4;LwkG$v4 zOWpE$s$Ua)oYWhV_7f2BXbGNLZGx#|7@qFjfq=qY=>9Vr7Yz4do>MFoq7Gqy@nN_u zIPwp!^|8*XfQuP+>;liRI>XHslKHiySU%foCx7xgh~JvAp1(Ni%)h6E@{Ol2bH4}5 z82eZk%Fj$u@WL6n9{xD&wF7x=_6hI1u?X}&gsS6*G4|>Sz<0f)cqp=xi6dBbOayM_Aa;2Z;lwHzPLTg44NCA z(bwJ&1>WIUxHlH2xkusrEg72(j^nV?Dda_G;92QeC@XR34$nr$^_&JQiM!3k_!ivb zscoO|yYpUf)s(k<$k&hDaoi7HVAco^U6f$T+TzzKLuB-w4A+B;(YA#@+{TBa#P0xl zBSok~1`?CcV#{M07InymnZ-ru1>`|Bs}L{Wmf%isX#)pvuLd59qP`}y-OW%#a{#YxNS-Qc`ClGsYMIgg47NuKKP+ggYae5c=%svlW zb{3*fNePM+%dl+tb*Q=BMC#$&_%-To11{}-#>IHrzvJ)TH$p;sbIkH=2elD8$oZiM z&+~)O*H40<6D)*&n~U)Fy|CZ^Rwyd52eT3qQ5KSp3GO*i_ANxy%o3=+y@F=C*U@~= zO{hiQMyuj`XsuX@uzimjAa={gfBRe3`&Wznuj~B_>-{!@|El0O6Z}o;{VMhT7J|Qp z;BWbte|!CL{3n0>U-^5~`+wBuUnAuIxBu__o7d<6xBrh@UW>o|YyPUgJpT(q{r~oh z>;ETzx&Kf8f9l^%lz%Hx{ln|?@9egfi?JM&%4IL!^EL&Ygub8>Y;>{5ovuDu-7Flf z>JFk;dK@y$cfjSZo#QN}G=U+3*3${Qed%g6uY|L?7Tq+J*n^Xtt?e!cY#iTKE8_WZ=1 zf(AUL=ri{fv3YP57c+Z|jQbcU3M-&>(R-pfzT3E9p-~W~j@XM4qf+q9 z?Kq|v#v{91GzP2<#hz=vXkon!&y}rk;S9suJHmXen?Bw&>5t`m`{1=UO52jOQ*x)qZe|e+fk(y2gM@cx?J>GsINQ@ z*`!1`>+XlT!cNF;hrs!iAG&v1i6Ym9xUkR>S##$geWnePr%Xq}cnj>8PC(Sqv4}i1 z3OfYkQO>gGiCm0EO({=X-x5{OI(%w-YTA!r4(sIsFLRBOk+XBvnCfO>$ikD*J(7fd1&9Adj4&QLF`tX^8&k(ybm|RjjTx{E^npjC-PpT6 z1=(MP_x06xP(A-S@-Du_;T|;z@P7}dCv_Mz<_o$X`i@48f1_#tA28DXfVr(-B1G{K z&eT<)>RBmT-_C`kScYk1GaK-F*%dBkh|PEIyt@xh_*vm+h7S%U?}AxeGT!XIfXL8W zuvK`9k?)?PPvuLrDtm*^=ilLB+6Uww_=J@0Uy-8B`Uv{Vnz&Re3O?HZJ)hr#q=JkF?|MQ`KFkO|kP zJrCT(K>eF|CA)!yi8nC!PB}U(F30uH*Af2o8mtCgMTd=7aJTp}4shF2ER4gc&&8_*4g=J9#M#9BBm!- zb1?&7Dq)m{E-Xik$2`YH7@8XZ>8za?|0V%bd^6xb@EjihJcZFk$%x&RfJXE8W1hio zod3QZIt5!WQ&_vSARz*)59~!?bUY$=q#!;t1E)5h#|7U46#Xhep@2LV%h7z##SEX( z6c3*Y^J$)=(O-2QuI*V5$u6M}{oEKl?tKhTh1cK?DRD6G5Cw1lP^8xQ;le35=myV5 z$UIZH3!eubaG}S0nlEN4grVis{kU{68Eb2^U@)c-K}*XJEbu3e@%_rhjD#xIpY4IH zbcQc!Gcov>uqO0+Aa0dKz_auKCQLhk$#&tG=IoEO$|cCEv%m!vBV5*Mk2Hr*eAr_J z)EMd^VdE6om3knk<#s$h9fy%~GK6!6BADO0jtK&P;{A^b5M!p-0$QQn@$UUFT(X{m zsB;UjtgAO-M+c$V>PQ@O42OSnADmt^2hLd|pxL4Wg3rC=)%FQ|o6<;Ld%&Lm8ZZ2g zhuF?&5;GYpQ5(^uC<@92C!ms71eI|W|DY;FIUV~oX~2|-mdKjd4ZRGE5%$v*--~Bq z;htrNzM-GKN-UGgO&g;F`tu{CGDfncu40lG^aClF@ekIef10 z)WtpVQ^Nte54Pd*pcJgyT#SMfcN$R6T0%^xahgb+t_x$wA;@tvg~di|+zoZc!Wa*% zwerWf0c$Y3hXq!2>;W~McYJvBJv_grDffBOS`swRlG%>cW!6K}Wfd%i*JNnoZK*Z9 zRtjrJHy*>9kYcO}zxxksg(yc&U#kI0BYU7~!9d~nUPxhed@{D(n2o$|i=oif3o+gO zab?dMWOtp0lZX2vp?_oOFF3<{KDOj1pHGzSzIQ|76z?Y)T57&rrLcWX1K&qSko$jQo0#lyq$q7{Tz_Ka5?rI61;DP>+vdU z(OcUZAB_g#(u9`ialV{qzud~t3iIpPzG)+FZ)_=Z%=Y7j$3O5W%RwkESOTBeaO}C4 zf>RxekUiuUas=d2j!(;B4Ja7OU>iIhukTI8dILMO^m9gRxf=%cUWdmrKRjN&7F#>p zVo1(#JaX=c4jpUxa;FnKaIOQN_xij{J3@sYiB93&RyT)BmyyWI73Mk;$0)$*NusL4^@S(uO8ld6vnXJ(^hZUCBB?ZL!FClLHPA4&Sx|KVtT z?Dx>SM@j=rBKQH!$%8E`<*KUSS z>1~iccqrU5Y@t7N13ujigH=o%P6_KgHM-+=9^07RBdHw%W{&N4#`ue{T>i?hof7kzyU+k9qEhjcraY%QpQHWJgkYhQq zv66yeE2c| literal 0 HcmV?d00001 diff --git a/test/test_models.py b/test/test_models.py index 28236598177..14880425aed 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -59,6 +59,10 @@ def get_available_video_models(): "resnet101", "resnet152", "wide_resnet101_2", + "deeplabv3_resnet50", + "deeplabv3_resnet101", + "fcn_resnet50", + "fcn_resnet101", ) @@ -85,21 +89,53 @@ def _test_classification_model(self, name, input_shape, dev): self.assertEqual(out.shape[-1], 50) def _test_segmentation_model(self, name, dev): - # passing num_class equal to a number other than 1000 helps in making the test - # more enforcing in nature - model = models.segmentation.__dict__[name](num_classes=50, pretrained_backbone=False) + set_rng_seed(0) + # passing num_classes equal to a number other than 21 helps in making the test's + # expected file size smaller + model = models.segmentation.__dict__[name](num_classes=10, pretrained_backbone=False) model.eval().to(device=dev) - input_shape = (1, 3, 300, 300) + input_shape = (1, 3, 32, 32) # RNG always on CPU, to ensure x in cuda tests is bitwise identical to x in cpu tests x = torch.rand(input_shape).to(device=dev) - out = model(x) - self.assertEqual(tuple(out["out"].shape), (1, 50, 300, 300)) + out = model(x)["out"] + + def check_out(out): + prec = 0.01 + strip_suffix = f"_{dev}" + try: + # We first try to assert the entire output if possible. This is not + # only the best way to assert results but also handles the cases + # where we need to create a new expected result. + self.assertExpected(out.cpu(), prec=prec, strip_suffix=strip_suffix) + except AssertionError: + # Unfortunately some segmentation models are flaky with autocast + # so instead of validating the probability scores, check that the class + # predictions match. + expected_file = self._get_expected_file(strip_suffix=strip_suffix) + expected = torch.load(expected_file) + self.assertEqual(out.argmax(dim=1), expected.argmax(dim=1), prec=prec) + return False # Partial validation performed + + return True # Full validation performed + + full_validation = check_out(out) + self.check_jit_scriptable(model, (x,), unwrapper=script_model_unwrapper.get(name, None)) if dev == torch.device("cuda"): with torch.cuda.amp.autocast(): - out = model(x) - self.assertEqual(tuple(out["out"].shape), (1, 50, 300, 300)) + out = model(x)["out"] + # See autocast_flaky_numerics comment at top of file. + if name not in autocast_flaky_numerics: + full_validation &= check_out(out) + + if not full_validation: + msg = "The output of {} could only be partially validated. " \ + "This is likely due to unit-test flakiness, but you may " \ + "want to do additional manual checks if you made " \ + "significant changes to the codebase.".format(self._testMethodName) + warnings.warn(msg, RuntimeWarning) + raise unittest.SkipTest(msg) def _test_detection_model(self, name, dev): set_rng_seed(0) From 2174ba481bbb9bd54e7ba45fc920e2bf4afcbc2d Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 12:16:52 -0800 Subject: [PATCH 169/357] Load variables when --resume /path/to/checkpoint --test-only (#3285) Summary: Co-authored-by: Francisco Massa Reviewed By: datumbox Differential Revision: D26156373 fbshipit-source-id: 83f22c90477ca2da8db176d2455a70ca302d17d1 --- references/segmentation/train.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/references/segmentation/train.py b/references/segmentation/train.py index e82e5bda651..5e5e5615e19 100644 --- a/references/segmentation/train.py +++ b/references/segmentation/train.py @@ -133,11 +133,6 @@ def main(args): model = torch.nn.parallel.DistributedDataParallel(model, device_ids=[args.gpu]) model_without_ddp = model.module - if args.test_only: - confmat = evaluate(model, data_loader_test, device=device, num_classes=num_classes) - print(confmat) - return - params_to_optimize = [ {"params": [p for p in model_without_ddp.backbone.parameters() if p.requires_grad]}, {"params": [p for p in model_without_ddp.classifier.parameters() if p.requires_grad]}, @@ -155,10 +150,16 @@ def main(args): if args.resume: checkpoint = torch.load(args.resume, map_location='cpu') - model_without_ddp.load_state_dict(checkpoint['model']) - optimizer.load_state_dict(checkpoint['optimizer']) - lr_scheduler.load_state_dict(checkpoint['lr_scheduler']) - args.start_epoch = checkpoint['epoch'] + 1 + model_without_ddp.load_state_dict(checkpoint['model'], strict=not args.test_only) + if not args.test_only: + optimizer.load_state_dict(checkpoint['optimizer']) + lr_scheduler.load_state_dict(checkpoint['lr_scheduler']) + args.start_epoch = checkpoint['epoch'] + 1 + + if args.test_only: + confmat = evaluate(model, data_loader_test, device=device, num_classes=num_classes) + print(confmat) + return start_time = time.time() for epoch in range(args.start_epoch, args.epochs): From 6bd0b85213a48b0a8055b9725a053a9aed16fc0f Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 12:16:52 -0800 Subject: [PATCH 170/357] Limitations declared better for pad (#3295) Reviewed By: datumbox Differential Revision: D26156385 fbshipit-source-id: a514702a775c37ff9fa1af7fe6e6e1f3003cfb33 --- torchvision/transforms/functional.py | 7 +++++-- torchvision/transforms/transforms.py | 10 +++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 587bc12b108..63b28ed8889 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -384,7 +384,9 @@ def scale(*args, **kwargs): def pad(img: Tensor, padding: List[int], fill: int = 0, padding_mode: str = "constant") -> Tensor: r"""Pad the given image on all sides with the given "pad" value. If the image is torch Tensor, it is expected - to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions + to have [..., H, W] shape, where ... means at most 2 leading dimensions for mode reflect and symmetric, + at most 3 leading dimensions for mode edge, + and an arbitrary number of leading dimensions for mode constant Args: img (PIL Image or Tensor): Image to be padded. @@ -402,7 +404,8 @@ def pad(img: Tensor, padding: List[int], fill: int = 0, padding_mode: str = "con - constant: pads with a constant value, this value is specified with fill - - edge: pads with the last value on the edge of the image + - edge: pads with the last value on the edge of the image, + if input a 5D torch Tensor, the last 3 dimensions will be padded instead of the last 2 - reflect: pads with reflection of image (without repeating the last value on the edge) diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 1a308f4a7ef..27b8a388a3a 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -319,7 +319,9 @@ def __repr__(self): class Pad(torch.nn.Module): """Pad the given image on all sides with the given "pad" value. If the image is torch Tensor, it is expected - to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions + to have [..., H, W] shape, where ... means at most 2 leading dimensions for mode reflect and symmetric, + at most 3 leading dimensions for mode edge, + and an arbitrary number of leading dimensions for mode constant Args: padding (int or sequence): Padding on each border. If a single int is provided this @@ -337,7 +339,8 @@ class Pad(torch.nn.Module): - constant: pads with a constant value, this value is specified with fill - - edge: pads with the last value at the edge of the image + - edge: pads with the last value at the edge of the image, + if input a 5D torch Tensor, the last 3 dimensions will be padded instead of the last 2 - reflect: pads with reflection of image without repeating the last value on the edge @@ -491,7 +494,8 @@ def __call__(self, img): class RandomCrop(torch.nn.Module): """Crop the given image at a random location. If the image is torch Tensor, it is expected - to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions + to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions, + but if non-constant padding is used, the input is expected to have at most 2 leading dimensions Args: size (sequence or int): Desired output size of the crop. If size is an From a4e5cc01f6adc56805b40482c170c7aaf9a30c2e Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 12:16:52 -0800 Subject: [PATCH 171/357] Fix sphinx warnings and turn warnings into errors (#3290) Summary: Co-authored-by: Vasilis Vryniotis Reviewed By: datumbox Differential Revision: D26156360 fbshipit-source-id: 001ecf0ae755140d8dca59f30e5940caf78484a4 --- docs/Makefile | 2 +- docs/source/conf.py | 17 +++++++++++++++++ docs/source/datasets.rst | 2 +- docs/source/io.rst | 2 +- torchvision/datasets/celeba.py | 13 ++++++++----- torchvision/datasets/hmdb51.py | 10 ++++++---- torchvision/datasets/kinetics.py | 10 ++++++---- torchvision/datasets/mnist.py | 3 +-- torchvision/datasets/omniglot.py | 1 + torchvision/datasets/stl10.py | 3 +-- torchvision/datasets/ucf101.py | 10 ++++++---- torchvision/io/__init__.py | 15 ++++++++++----- torchvision/io/image.py | 4 ++-- torchvision/io/video.py | 6 ++---- torchvision/models/detection/faster_rcnn.py | 2 ++ torchvision/models/detection/keypoint_rcnn.py | 4 ++++ torchvision/models/detection/mask_rcnn.py | 2 ++ torchvision/models/detection/retinanet.py | 2 ++ torchvision/transforms/functional.py | 4 ++-- torchvision/transforms/transforms.py | 6 +++--- 20 files changed, 78 insertions(+), 40 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index 2ca4b0d71a2..1cacf08002f 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -2,7 +2,7 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W # turn warnings into errors SPHINXBUILD = sphinx-build SPHINXPROJ = torchvision SOURCEDIR = source diff --git a/docs/source/conf.py b/docs/source/conf.py index 47f37c4fe25..8b4d098f66b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -23,8 +23,23 @@ import torch import torchvision import pytorch_sphinx_theme +from sphinxcontrib import googleanalytics +# Wrap sphinxcontrib-googleanalytics setup() function to avoid a Sphinx warning: +# "WARNING: extension ‘sphinxcontrib.googleanalytics’ returned an unsupported +# object from its setup() function; it should return None or a metadata +# dictionary" +_googleanalytics_setup_original = googleanalytics.setup + + +def _googleanalytics_setup_wrapper(app): + _googleanalytics_setup_original(app) + return {"version": "0.1"} + + +googleanalytics.setup = _googleanalytics_setup_wrapper + # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -48,6 +63,8 @@ ] napoleon_use_ivar = True +napoleon_numpy_docstring = False +napoleon_google_docstring = True googleanalytics_id = 'UA-90545585-1' googleanalytics_enabled = True diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index 2947f0cf80f..6341e00fca0 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -155,7 +155,7 @@ MNIST .. autoclass:: MNIST Omniglot -~~~~~~ +~~~~~~~~ .. autoclass:: Omniglot diff --git a/docs/source/io.rst b/docs/source/io.rst index 1d776369e84..e85951e719a 100644 --- a/docs/source/io.rst +++ b/docs/source/io.rst @@ -18,7 +18,7 @@ Video Fine-grained video API -------------------- +---------------------- In addition to the :mod:`read_video` function, we provide a high-performance lower-level API for more fine-grained control compared to the :mod:`read_video` function. diff --git a/torchvision/datasets/celeba.py b/torchvision/datasets/celeba.py index 7a20c5c2d60..12beded2a19 100644 --- a/torchvision/datasets/celeba.py +++ b/torchvision/datasets/celeba.py @@ -17,12 +17,15 @@ class CelebA(VisionDataset): target_type (string or list, optional): Type of target to use, ``attr``, ``identity``, ``bbox``, or ``landmarks``. Can also be a list to output a tuple with all specified target types. The targets represent: - ``attr`` (np.array shape=(40,) dtype=int): binary (0, 1) labels for attributes - ``identity`` (int): label for each person (data points with the same identity are the same person) - ``bbox`` (np.array shape=(4,) dtype=int): bounding box (x, y, width, height) - ``landmarks`` (np.array shape=(10,) dtype=int): landmark points (lefteye_x, lefteye_y, righteye_x, - righteye_y, nose_x, nose_y, leftmouth_x, leftmouth_y, rightmouth_x, rightmouth_y) + + - ``attr`` (np.array shape=(40,) dtype=int): binary (0, 1) labels for attributes + - ``identity`` (int): label for each person (data points with the same identity are the same person) + - ``bbox`` (np.array shape=(4,) dtype=int): bounding box (x, y, width, height) + - ``landmarks`` (np.array shape=(10,) dtype=int): landmark points (lefteye_x, lefteye_y, righteye_x, + righteye_y, nose_x, nose_y, leftmouth_x, leftmouth_y, rightmouth_x, rightmouth_y) + Defaults to ``attr``. If empty, ``None`` will be returned as target. + transform (callable, optional): A function/transform that takes in an PIL image and returns a transformed version. E.g, ``transforms.ToTensor`` target_transform (callable, optional): A function/transform that takes in the diff --git a/torchvision/datasets/hmdb51.py b/torchvision/datasets/hmdb51.py index 1e180f8ca11..621630cf264 100644 --- a/torchvision/datasets/hmdb51.py +++ b/torchvision/datasets/hmdb51.py @@ -37,10 +37,12 @@ class HMDB51(VisionDataset): and returns a transformed version. Returns: - video (Tensor[T, H, W, C]): the `T` video frames - audio(Tensor[K, L]): the audio frames, where `K` is the number of channels - and `L` is the number of points - label (int): class of the video clip + tuple: A 3-tuple with the following entries: + + - video (Tensor[T, H, W, C]): The `T` video frames + - audio(Tensor[K, L]): the audio frames, where `K` is the number of channels + and `L` is the number of points + - label (int): class of the video clip """ data_url = "http://serre-lab.clps.brown.edu/wp-content/uploads/2013/10/hmdb51_org.rar" diff --git a/torchvision/datasets/kinetics.py b/torchvision/datasets/kinetics.py index 07db91cc195..8be0ca8b5cd 100644 --- a/torchvision/datasets/kinetics.py +++ b/torchvision/datasets/kinetics.py @@ -30,10 +30,12 @@ class Kinetics400(VisionDataset): and returns a transformed version. Returns: - video (Tensor[T, H, W, C]): the `T` video frames - audio(Tensor[K, L]): the audio frames, where `K` is the number of channels - and `L` is the number of points - label (int): class of the video clip + tuple: A 3-tuple with the following entries: + + - video (Tensor[T, H, W, C]): the `T` video frames + - audio(Tensor[K, L]): the audio frames, where `K` is the number of channels + and `L` is the number of points + - label (int): class of the video clip """ def __init__(self, root, frames_per_clip, step_between_clips=1, frame_rate=None, diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index 9a0ffa86160..e798894089b 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -318,7 +318,7 @@ class QMNIST(MNIST): """`QMNIST `_ Dataset. Args: - root (string): Root directory of dataset whose ``processed'' + root (string): Root directory of dataset whose ``processed`` subdir contains torch binary files with the datasets. what (string,optional): Can be 'train', 'test', 'test10k', 'test50k', or 'nist' for respectively the mnist compatible @@ -342,7 +342,6 @@ class QMNIST(MNIST): train (bool,optional,compatibility): When argument 'what' is not specified, this boolean decides whether to load the training set ot the testing set. Default: True. - """ subsets = { diff --git a/torchvision/datasets/omniglot.py b/torchvision/datasets/omniglot.py index 20eee3b38ae..2f20bff72c6 100644 --- a/torchvision/datasets/omniglot.py +++ b/torchvision/datasets/omniglot.py @@ -7,6 +7,7 @@ class Omniglot(VisionDataset): """`Omniglot `_ Dataset. + Args: root (string): Root directory of dataset where directory ``omniglot-py`` exists. diff --git a/torchvision/datasets/stl10.py b/torchvision/datasets/stl10.py index 1d619183330..1ef861fe563 100644 --- a/torchvision/datasets/stl10.py +++ b/torchvision/datasets/stl10.py @@ -18,7 +18,7 @@ class STL10(VisionDataset): Accordingly dataset is selected. folds (int, optional): One of {0-9} or None. For training, loads one of the 10 pre-defined folds of 1k samples for the - standard evaluation procedure. If no value is passed, loads the 5k samples. + standard evaluation procedure. If no value is passed, loads the 5k samples. transform (callable, optional): A function/transform that takes in an PIL image and returns a transformed version. E.g, ``transforms.RandomCrop`` target_transform (callable, optional): A function/transform that takes in the @@ -26,7 +26,6 @@ class STL10(VisionDataset): download (bool, optional): If true, downloads the dataset from the internet and puts it in root directory. If dataset is already downloaded, it is not downloaded again. - """ base_folder = 'stl10_binary' url = "http://ai.stanford.edu/~acoates/stl10/stl10_binary.tar.gz" diff --git a/torchvision/datasets/ucf101.py b/torchvision/datasets/ucf101.py index 2c10d739427..e5cf11d7fa2 100644 --- a/torchvision/datasets/ucf101.py +++ b/torchvision/datasets/ucf101.py @@ -35,10 +35,12 @@ class UCF101(VisionDataset): and returns a transformed version. Returns: - video (Tensor[T, H, W, C]): the `T` video frames - audio(Tensor[K, L]): the audio frames, where `K` is the number of channels - and `L` is the number of points - label (int): class of the video clip + tuple: A 3-tuple with the following entries: + + - video (Tensor[T, H, W, C]): the `T` video frames + - audio(Tensor[K, L]): the audio frames, where `K` is the number of channels + and `L` is the number of points + - label (int): class of the video clip """ def __init__(self, root, annotation_path, frames_per_clip, step_between_clips=1, diff --git a/torchvision/io/__init__.py b/torchvision/io/__init__.py index 5f26fbb7db8..fe4cc81ccd7 100644 --- a/torchvision/io/__init__.py +++ b/torchvision/io/__init__.py @@ -51,28 +51,33 @@ class VideoReader: Example: The following examples creates a :mod:`VideoReader` object, seeks into 2s point, and returns a single frame:: - import torchvision - video_path = "path_to_a_test_video" - reader = torchvision.io.VideoReader(video_path, "video") - reader.seek(2.0) - frame = next(reader) + import torchvision + video_path = "path_to_a_test_video" + reader = torchvision.io.VideoReader(video_path, "video") + reader.seek(2.0) + frame = next(reader) :mod:`VideoReader` implements the iterable API, which makes it suitable to using it in conjunction with :mod:`itertools` for more advanced reading. As such, we can use a :mod:`VideoReader` instance inside for loops:: + reader.seek(2) for frame in reader: frames.append(frame['data']) # additionally, `seek` implements a fluent API, so we can do for frame in reader.seek(2): frames.append(frame['data']) + With :mod:`itertools`, we can read all frames between 2 and 5 seconds with the following code:: + for frame in itertools.takewhile(lambda x: x['pts'] <= 5, reader.seek(2)): frames.append(frame['data']) + and similarly, reading 10 frames after the 2s timestamp can be achieved as follows:: + for frame in itertools.islice(reader.seek(2), 10): frames.append(frame['data']) diff --git a/torchvision/io/image.py b/torchvision/io/image.py index 43c6cedb26a..e193555e447 100644 --- a/torchvision/io/image.py +++ b/torchvision/io/image.py @@ -126,8 +126,8 @@ def encode_png(input: torch.Tensor, compression_level: int = 6) -> torch.Tensor: between 0 and 9. Default: 6 Returns: - output (Tensor[1]): A one dimensional int8 tensor that contains the raw bytes of the - PNG file. + Tensor[1]: A one dimensional int8 tensor that contains the raw bytes of the + PNG file. """ output = torch.ops.image.encode_png(input, compression_level) return output diff --git a/torchvision/io/video.py b/torchvision/io/video.py index 58a05246835..34a11826049 100644 --- a/torchvision/io/video.py +++ b/torchvision/io/video.py @@ -253,10 +253,8 @@ def read_video( Returns: vframes (Tensor[T, H, W, C]): the `T` video frames - aframes (Tensor[K, L]): the audio frames, where `K` is the number of channels and `L` is the - number of points - info (Dict): metadata for the video and audio. Can contain the fields video_fps (float) - and audio_fps (int) + aframes (Tensor[K, L]): the audio frames, where `K` is the number of channels and `L` is the number of points + info (Dict): metadata for the video and audio. Can contain the fields video_fps (float) and audio_fps (int) """ from torchvision import get_video_backend diff --git a/torchvision/models/detection/faster_rcnn.py b/torchvision/models/detection/faster_rcnn.py index c37a5632ebd..0599d1da484 100644 --- a/torchvision/models/detection/faster_rcnn.py +++ b/torchvision/models/detection/faster_rcnn.py @@ -308,6 +308,7 @@ def fasterrcnn_resnet50_fpn(pretrained=False, progress=True, During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` - labels (``Int64Tensor[N]``): the class label for each ground-truth box @@ -318,6 +319,7 @@ def fasterrcnn_resnet50_fpn(pretrained=False, progress=True, During inference, the model requires only the input tensors, and returns the post-processed predictions as a ``List[Dict[Tensor]]``, one for each input image. The fields of the ``Dict`` are as follows: + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` - labels (``Int64Tensor[N]``): the predicted labels for each image diff --git a/torchvision/models/detection/keypoint_rcnn.py b/torchvision/models/detection/keypoint_rcnn.py index ea4a078da9d..f784273f5c2 100644 --- a/torchvision/models/detection/keypoint_rcnn.py +++ b/torchvision/models/detection/keypoint_rcnn.py @@ -26,6 +26,7 @@ class KeypointRCNN(FasterRCNN): During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: + - boxes (FloatTensor[N, 4]): the ground-truth boxes in [x1, y1, x2, y2] format, with values of x between 0 and W and values of y between 0 and H - labels (Int64Tensor[N]): the class label for each ground-truth box @@ -38,6 +39,7 @@ class KeypointRCNN(FasterRCNN): During inference, the model requires only the input tensors, and returns the post-processed predictions as a List[Dict[Tensor]], one for each input image. The fields of the Dict are as follows: + - boxes (FloatTensor[N, 4]): the predicted boxes in [x1, y1, x2, y2] format, with values of x between 0 and W and values of y between 0 and H - labels (Int64Tensor[N]): the predicted labels for each image @@ -283,6 +285,7 @@ def keypointrcnn_resnet50_fpn(pretrained=False, progress=True, During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` - labels (``Int64Tensor[N]``): the class label for each ground-truth box @@ -295,6 +298,7 @@ def keypointrcnn_resnet50_fpn(pretrained=False, progress=True, During inference, the model requires only the input tensors, and returns the post-processed predictions as a ``List[Dict[Tensor]]``, one for each input image. The fields of the ``Dict`` are as follows: + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` - labels (``Int64Tensor[N]``): the predicted labels for each image diff --git a/torchvision/models/detection/mask_rcnn.py b/torchvision/models/detection/mask_rcnn.py index 7dac4d0a105..09be4fa684c 100644 --- a/torchvision/models/detection/mask_rcnn.py +++ b/torchvision/models/detection/mask_rcnn.py @@ -278,6 +278,7 @@ def maskrcnn_resnet50_fpn(pretrained=False, progress=True, During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` - labels (``Int64Tensor[N]``): the class label for each ground-truth box @@ -289,6 +290,7 @@ def maskrcnn_resnet50_fpn(pretrained=False, progress=True, During inference, the model requires only the input tensors, and returns the post-processed predictions as a ``List[Dict[Tensor]]``, one for each input image. The fields of the ``Dict`` are as follows: + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` - labels (``Int64Tensor[N]``): the predicted labels for each image diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index 60238485f60..b0168bbb593 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -575,6 +575,7 @@ def retinanet_resnet50_fpn(pretrained=False, progress=True, During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with values between ``0`` and ``H`` and ``0`` and ``W`` - labels (``Int64Tensor[N]``): the class label for each ground-truth box @@ -585,6 +586,7 @@ def retinanet_resnet50_fpn(pretrained=False, progress=True, During inference, the model requires only the input tensors, and returns the post-processed predictions as a ``List[Dict[Tensor]]``, one for each input image. The fields of the ``Dict`` are as follows: + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with values between ``0`` and ``H`` and ``0`` and ``W`` - labels (``Int64Tensor[N]``): the predicted labels for each image diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 63b28ed8889..993a17db1eb 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -982,9 +982,9 @@ def affine( of length 1: ``[value, ]``. If input is PIL Image, the options is only available for ``Pillow>=5.0.0``. fillcolor (sequence, int, float): deprecated argument and will be removed since v0.10.0. - Please use `arg`:fill: instead. + Please use the ``fill`` parameter instead. resample (int, optional): deprecated argument and will be removed since v0.10.0. - Please use `arg`:interpolation: instead. + Please use the ``interpolation`` parameter instead. Returns: PIL Image or Tensor: Transformed image. diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 27b8a388a3a..bf847c8fc75 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -1179,7 +1179,7 @@ class RandomRotation(torch.nn.Module): image. If given a number, the value is used for all bands respectively. If input is PIL Image, the options is only available for ``Pillow>=5.2.0``. resample (int, optional): deprecated argument and will be removed since v0.10.0. - Please use `arg`:interpolation: instead. + Please use the ``interpolation`` parameter instead. .. _filters: https://pillow.readthedocs.io/en/latest/handbook/concepts.html#filters @@ -1284,9 +1284,9 @@ class RandomAffine(torch.nn.Module): image. If given a number, the value is used for all bands respectively. If input is PIL Image, the options is only available for ``Pillow>=5.0.0``. fillcolor (sequence or number, optional): deprecated argument and will be removed since v0.10.0. - Please use `arg`:fill: instead. + Please use the ``fill`` parameter instead. resample (int, optional): deprecated argument and will be removed since v0.10.0. - Please use `arg`:interpolation: instead. + Please use the ``interpolation`` parameter instead. .. _filters: https://pillow.readthedocs.io/en/latest/handbook/concepts.html#filters From 05e0435b8b99652c55f5d5f9a387e5556a41b81c Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 12:16:52 -0800 Subject: [PATCH 172/357] Sort input file list (#3302) Reviewed By: datumbox Differential Revision: D26156387 fbshipit-source-id: 443b0a34d6186b3a372d900c3ac78b3473abef64 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index e8a3ecd9ac7..0317d6e6483 100644 --- a/setup.py +++ b/setup.py @@ -227,7 +227,7 @@ def get_extensions(): ext_modules = [ extension( 'torchvision._C', - sources, + sorted(sources), include_dirs=include_dirs, define_macros=define_macros, extra_compile_args=extra_compile_args, From dfab2df5e18318032244815fb76e36a08223eec1 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 12:16:52 -0800 Subject: [PATCH 173/357] Replace functional.sigmoid with torch.sigmoid (#3307) Summary: Removes deprecation warning Reviewed By: datumbox Differential Revision: D26156378 fbshipit-source-id: 796fce9c05fa3818c26e9ba2ba0cbab7085c9d1a --- torchvision/models/detection/rpn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/detection/rpn.py b/torchvision/models/detection/rpn.py index 9ea05c94136..736c82a9009 100644 --- a/torchvision/models/detection/rpn.py +++ b/torchvision/models/detection/rpn.py @@ -252,7 +252,7 @@ def filter_proposals(self, proposals, objectness, image_shapes, num_anchors_per_ levels = levels[batch_idx, top_n_idx] proposals = proposals[batch_idx, top_n_idx] - objectness_prob = F.sigmoid(objectness) + objectness_prob = torch.sigmoid(objectness) final_boxes = [] final_scores = [] From 23a877a0b4c32902b801897722496c8bd97e20b1 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 12:16:52 -0800 Subject: [PATCH 174/357] Add MobileNetV3 architecture for Segmentation (#3276) Summary: * Making _segm_resnet() generic and reusable. * Adding fcn and deeplabv3 directly on mobilenetv3 backbone. * Adding tests for segmentation models. * Rename is_strided with _is_cn. * Add dilation support on MobileNetV3 for Segmentation. * Add Lite R-ASPP with MobileNetV3 backbone. * Add pretrained model weights. * Removing model fcn_mobilenet_v3_large. * Adding docs and imports. * Fixing typo and readme. Reviewed By: datumbox Differential Revision: D26156380 fbshipit-source-id: e62528b52728804a40da79c1311562a7f1c2afbd --- docs/source/models.rst | 12 +- hubconf.py | 2 +- references/segmentation/README.md | 10 ++ ...st_deeplabv3_mobilenet_v3_large_expect.pkl | Bin 0 -> 41785 bytes ....test_lraspp_mobilenet_v3_large_expect.pkl | Bin 0 -> 41785 bytes test/test_models.py | 2 + .../models/detection/backbone_utils.py | 4 +- torchvision/models/mobilenetv2.py | 8 +- torchvision/models/mobilenetv3.py | 86 ++++++------ torchvision/models/segmentation/__init__.py | 1 + torchvision/models/segmentation/_utils.py | 1 - torchvision/models/segmentation/lraspp.py | 69 ++++++++++ .../models/segmentation/segmentation.py | 127 +++++++++++++++--- 13 files changed, 250 insertions(+), 72 deletions(-) create mode 100644 test/expect/ModelTester.test_deeplabv3_mobilenet_v3_large_expect.pkl create mode 100644 test/expect/ModelTester.test_lraspp_mobilenet_v3_large_expect.pkl create mode 100644 torchvision/models/segmentation/lraspp.py diff --git a/docs/source/models.rst b/docs/source/models.rst index 7fbae2a55d1..f4188a5ad1f 100644 --- a/docs/source/models.rst +++ b/docs/source/models.rst @@ -271,7 +271,8 @@ The models subpackage contains definitions for the following model architectures for semantic segmentation: - `FCN ResNet50, ResNet101 `_ -- `DeepLabV3 ResNet50, ResNet101 `_ +- `DeepLabV3 ResNet50, ResNet101, MobileNetV3-Large `_ +- `LR-ASPP MobileNetV3-Large `_ As with image classification models, all pre-trained models expect input images normalized in the same way. The images have to be loaded in to a range of ``[0, 1]`` and then normalized using @@ -298,6 +299,8 @@ FCN ResNet50 60.5 91.4 FCN ResNet101 63.7 91.9 DeepLabV3 ResNet50 66.4 92.4 DeepLabV3 ResNet101 67.4 92.4 +DeepLabV3 MobileNetV3-Large 60.3 91.2 +LR-ASPP MobileNetV3-Large 57.9 91.2 ================================ ============= ==================== @@ -313,6 +316,13 @@ DeepLabV3 .. autofunction:: torchvision.models.segmentation.deeplabv3_resnet50 .. autofunction:: torchvision.models.segmentation.deeplabv3_resnet101 +.. autofunction:: torchvision.models.segmentation.deeplabv3_mobilenet_v3_large + + +LR-ASPP +------- + +.. autofunction:: torchvision.models.segmentation.lraspp_mobilenet_v3_large Object Detection, Instance Segmentation and Person Keypoint Detection diff --git a/hubconf.py b/hubconf.py index dec4a7fb196..097759bdd89 100644 --- a/hubconf.py +++ b/hubconf.py @@ -18,4 +18,4 @@ # segmentation from torchvision.models.segmentation import fcn_resnet50, fcn_resnet101, \ - deeplabv3_resnet50, deeplabv3_resnet101 + deeplabv3_resnet50, deeplabv3_resnet101, deeplabv3_mobilenet_v3_large, lraspp_mobilenet_v3_large diff --git a/references/segmentation/README.md b/references/segmentation/README.md index 34db88c7a3a..6e24f836624 100644 --- a/references/segmentation/README.md +++ b/references/segmentation/README.md @@ -31,3 +31,13 @@ python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py --lr 0. ``` python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py --lr 0.02 --dataset coco -b 4 --model deeplabv3_resnet101 --aux-loss ``` + +## deeplabv3_mobilenet_v3_large +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py --dataset coco -b 4 --model deeplabv3_mobilenet_v3_large --aux-loss --wd 0.000001 +``` + +## lraspp_mobilenet_v3_large +``` +python -m torch.distributed.launch --nproc_per_node=8 --use_env train.py --dataset coco -b 4 --model lraspp_mobilenet_v3_large --wd 0.000001 +``` diff --git a/test/expect/ModelTester.test_deeplabv3_mobilenet_v3_large_expect.pkl b/test/expect/ModelTester.test_deeplabv3_mobilenet_v3_large_expect.pkl new file mode 100644 index 0000000000000000000000000000000000000000..58d6da6c7210da8850ae5f6e4278653b38e35159 GIT binary patch literal 41785 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 TZf9&4a_&5Gi|s$)A7TFsY4Ws_ literal 0 HcmV?d00001 diff --git a/test/expect/ModelTester.test_lraspp_mobilenet_v3_large_expect.pkl b/test/expect/ModelTester.test_lraspp_mobilenet_v3_large_expect.pkl new file mode 100644 index 0000000000000000000000000000000000000000..b2aa2ca89a948424ef80b032ce84af68cb109cfd GIT binary patch literal 41785 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 None: - padding = (kernel_size - 1) // 2 + padding = (kernel_size - 1) // 2 * dilation if norm_layer is None: norm_layer = nn.BatchNorm2d if activation_layer is None: activation_layer = nn.ReLU6 super(ConvBNReLU, self).__init__( - nn.Conv2d(in_planes, out_planes, kernel_size, stride, padding, groups=groups, bias=False), + nn.Conv2d(in_planes, out_planes, kernel_size, stride, padding, dilation=dilation, groups=groups, + bias=False), norm_layer(out_planes), activation_layer(inplace=True) ) @@ -88,7 +90,7 @@ def __init__( ]) self.conv = nn.Sequential(*layers) self.out_channels = oup - self.is_strided = stride > 1 + self._is_cn = stride > 1 def forward(self, x: Tensor) -> Tensor: if self.use_res_connect: diff --git a/torchvision/models/mobilenetv3.py b/torchvision/models/mobilenetv3.py index eba4823277b..a7d45264dc5 100644 --- a/torchvision/models/mobilenetv3.py +++ b/torchvision/models/mobilenetv3.py @@ -38,7 +38,7 @@ def forward(self, input: Tensor) -> Tensor: class InvertedResidualConfig: def __init__(self, input_channels: int, kernel: int, expanded_channels: int, out_channels: int, use_se: bool, - activation: str, stride: int, width_mult: float): + activation: str, stride: int, dilation: int, width_mult: float): self.input_channels = self.adjust_channels(input_channels, width_mult) self.kernel = kernel self.expanded_channels = self.adjust_channels(expanded_channels, width_mult) @@ -46,6 +46,7 @@ def __init__(self, input_channels: int, kernel: int, expanded_channels: int, out self.use_se = use_se self.use_hs = activation == "HS" self.stride = stride + self.dilation = dilation @staticmethod def adjust_channels(channels: int, width_mult: float): @@ -70,9 +71,10 @@ def __init__(self, cnf: InvertedResidualConfig, norm_layer: Callable[..., nn.Mod norm_layer=norm_layer, activation_layer=activation_layer)) # depthwise + stride = 1 if cnf.dilation > 1 else cnf.stride layers.append(ConvBNActivation(cnf.expanded_channels, cnf.expanded_channels, kernel_size=cnf.kernel, - stride=cnf.stride, groups=cnf.expanded_channels, norm_layer=norm_layer, - activation_layer=activation_layer)) + stride=stride, dilation=cnf.dilation, groups=cnf.expanded_channels, + norm_layer=norm_layer, activation_layer=activation_layer)) if cnf.use_se: layers.append(SqueezeExcitation(cnf.expanded_channels)) @@ -82,7 +84,7 @@ def __init__(self, cnf: InvertedResidualConfig, norm_layer: Callable[..., nn.Mod self.block = nn.Sequential(*layers) self.out_channels = cnf.out_channels - self.is_strided = cnf.stride > 1 + self._is_cn = cnf.stride > 1 def forward(self, input: Tensor) -> Tensor: result = self.block(input) @@ -194,8 +196,7 @@ def _mobilenet_v3( return model -def mobilenet_v3_large(pretrained: bool = False, progress: bool = True, reduced_tail: bool = False, - **kwargs: Any) -> MobileNetV3: +def mobilenet_v3_large(pretrained: bool = False, progress: bool = True, **kwargs: Any) -> MobileNetV3: """ Constructs a large MobileNetV3 architecture from `"Searching for MobileNetV3" `_. @@ -203,40 +204,38 @@ def mobilenet_v3_large(pretrained: bool = False, progress: bool = True, reduced_ Args: pretrained (bool): If True, returns a model pre-trained on ImageNet progress (bool): If True, displays a progress bar of the download to stderr - reduced_tail (bool): If True, reduces the channel counts of all feature layers - between C4 and C5 by 2. It is used to reduce the channel redundancy in the - backbone for Detection and Segmentation. """ + # non-public config parameters + reduce_divider = 2 if kwargs.pop('_reduced_tail', False) else 1 + dilation = 2 if kwargs.pop('_dilated', False) else 1 width_mult = 1.0 + bneck_conf = partial(InvertedResidualConfig, width_mult=width_mult) adjust_channels = partial(InvertedResidualConfig.adjust_channels, width_mult=width_mult) - reduce_divider = 2 if reduced_tail else 1 - inverted_residual_setting = [ - bneck_conf(16, 3, 16, 16, False, "RE", 1), - bneck_conf(16, 3, 64, 24, False, "RE", 2), # C1 - bneck_conf(24, 3, 72, 24, False, "RE", 1), - bneck_conf(24, 5, 72, 40, True, "RE", 2), # C2 - bneck_conf(40, 5, 120, 40, True, "RE", 1), - bneck_conf(40, 5, 120, 40, True, "RE", 1), - bneck_conf(40, 3, 240, 80, False, "HS", 2), # C3 - bneck_conf(80, 3, 200, 80, False, "HS", 1), - bneck_conf(80, 3, 184, 80, False, "HS", 1), - bneck_conf(80, 3, 184, 80, False, "HS", 1), - bneck_conf(80, 3, 480, 112, True, "HS", 1), - bneck_conf(112, 3, 672, 112, True, "HS", 1), - bneck_conf(112, 5, 672, 160 // reduce_divider, True, "HS", 2), # C4 - bneck_conf(160 // reduce_divider, 5, 960 // reduce_divider, 160 // reduce_divider, True, "HS", 1), - bneck_conf(160 // reduce_divider, 5, 960 // reduce_divider, 160 // reduce_divider, True, "HS", 1), + bneck_conf(16, 3, 16, 16, False, "RE", 1, 1), + bneck_conf(16, 3, 64, 24, False, "RE", 2, 1), # C1 + bneck_conf(24, 3, 72, 24, False, "RE", 1, 1), + bneck_conf(24, 5, 72, 40, True, "RE", 2, 1), # C2 + bneck_conf(40, 5, 120, 40, True, "RE", 1, 1), + bneck_conf(40, 5, 120, 40, True, "RE", 1, 1), + bneck_conf(40, 3, 240, 80, False, "HS", 2, 1), # C3 + bneck_conf(80, 3, 200, 80, False, "HS", 1, 1), + bneck_conf(80, 3, 184, 80, False, "HS", 1, 1), + bneck_conf(80, 3, 184, 80, False, "HS", 1, 1), + bneck_conf(80, 3, 480, 112, True, "HS", 1, 1), + bneck_conf(112, 3, 672, 112, True, "HS", 1, 1), + bneck_conf(112, 5, 672, 160 // reduce_divider, True, "HS", 2, dilation), # C4 + bneck_conf(160 // reduce_divider, 5, 960 // reduce_divider, 160 // reduce_divider, True, "HS", 1, dilation), + bneck_conf(160 // reduce_divider, 5, 960 // reduce_divider, 160 // reduce_divider, True, "HS", 1, dilation), ] last_channel = adjust_channels(1280 // reduce_divider) # C5 return _mobilenet_v3("mobilenet_v3_large", inverted_residual_setting, last_channel, pretrained, progress, **kwargs) -def mobilenet_v3_small(pretrained: bool = False, progress: bool = True, reduced_tail: bool = False, - **kwargs: Any) -> MobileNetV3: +def mobilenet_v3_small(pretrained: bool = False, progress: bool = True, **kwargs: Any) -> MobileNetV3: """ Constructs a small MobileNetV3 architecture from `"Searching for MobileNetV3" `_. @@ -244,28 +243,27 @@ def mobilenet_v3_small(pretrained: bool = False, progress: bool = True, reduced_ Args: pretrained (bool): If True, returns a model pre-trained on ImageNet progress (bool): If True, displays a progress bar of the download to stderr - reduced_tail (bool): If True, reduces the channel counts of all feature layers - between C4 and C5 by 2. It is used to reduce the channel redundancy in the - backbone for Detection and Segmentation. """ + # non-public config parameters + reduce_divider = 2 if kwargs.pop('_reduced_tail', False) else 1 + dilation = 2 if kwargs.pop('_dilated', False) else 1 width_mult = 1.0 + bneck_conf = partial(InvertedResidualConfig, width_mult=width_mult) adjust_channels = partial(InvertedResidualConfig.adjust_channels, width_mult=width_mult) - reduce_divider = 2 if reduced_tail else 1 - inverted_residual_setting = [ - bneck_conf(16, 3, 16, 16, True, "RE", 2), # C1 - bneck_conf(16, 3, 72, 24, False, "RE", 2), # C2 - bneck_conf(24, 3, 88, 24, False, "RE", 1), - bneck_conf(24, 5, 96, 40, True, "HS", 2), # C3 - bneck_conf(40, 5, 240, 40, True, "HS", 1), - bneck_conf(40, 5, 240, 40, True, "HS", 1), - bneck_conf(40, 5, 120, 48, True, "HS", 1), - bneck_conf(48, 5, 144, 48, True, "HS", 1), - bneck_conf(48, 5, 288, 96 // reduce_divider, True, "HS", 2), # C4 - bneck_conf(96 // reduce_divider, 5, 576 // reduce_divider, 96 // reduce_divider, True, "HS", 1), - bneck_conf(96 // reduce_divider, 5, 576 // reduce_divider, 96 // reduce_divider, True, "HS", 1), + bneck_conf(16, 3, 16, 16, True, "RE", 2, 1), # C1 + bneck_conf(16, 3, 72, 24, False, "RE", 2, 1), # C2 + bneck_conf(24, 3, 88, 24, False, "RE", 1, 1), + bneck_conf(24, 5, 96, 40, True, "HS", 2, 1), # C3 + bneck_conf(40, 5, 240, 40, True, "HS", 1, 1), + bneck_conf(40, 5, 240, 40, True, "HS", 1, 1), + bneck_conf(40, 5, 120, 48, True, "HS", 1, 1), + bneck_conf(48, 5, 144, 48, True, "HS", 1, 1), + bneck_conf(48, 5, 288, 96 // reduce_divider, True, "HS", 2, dilation), # C4 + bneck_conf(96 // reduce_divider, 5, 576 // reduce_divider, 96 // reduce_divider, True, "HS", 1, dilation), + bneck_conf(96 // reduce_divider, 5, 576 // reduce_divider, 96 // reduce_divider, True, "HS", 1, dilation), ] last_channel = adjust_channels(1024 // reduce_divider) # C5 diff --git a/torchvision/models/segmentation/__init__.py b/torchvision/models/segmentation/__init__.py index 43c80c355ad..fb6633d7fb5 100644 --- a/torchvision/models/segmentation/__init__.py +++ b/torchvision/models/segmentation/__init__.py @@ -1,3 +1,4 @@ from .segmentation import * from .fcn import * from .deeplabv3 import * +from .lraspp import * diff --git a/torchvision/models/segmentation/_utils.py b/torchvision/models/segmentation/_utils.py index c5a7ae99e43..176b7490038 100644 --- a/torchvision/models/segmentation/_utils.py +++ b/torchvision/models/segmentation/_utils.py @@ -1,6 +1,5 @@ from collections import OrderedDict -import torch from torch import nn from torch.nn import functional as F diff --git a/torchvision/models/segmentation/lraspp.py b/torchvision/models/segmentation/lraspp.py new file mode 100644 index 00000000000..44cd9b1e773 --- /dev/null +++ b/torchvision/models/segmentation/lraspp.py @@ -0,0 +1,69 @@ +from collections import OrderedDict + +from torch import nn, Tensor +from torch.nn import functional as F +from typing import Dict + + +__all__ = ["LRASPP"] + + +class LRASPP(nn.Module): + """ + Implements a Lite R-ASPP Network for semantic segmentation from + `"Searching for MobileNetV3" + `_. + + Args: + backbone (nn.Module): the network used to compute the features for the model. + The backbone should return an OrderedDict[Tensor], with the key being + "high" for the high level feature map and "low" for the low level feature map. + low_channels (int): the number of channels of the low level features. + high_channels (int): the number of channels of the high level features. + num_classes (int): number of output classes of the model (including the background). + inter_channels (int, optional): the number of channels for intermediate computations. + """ + + def __init__(self, backbone, low_channels, high_channels, num_classes, inter_channels=128): + super().__init__() + self.backbone = backbone + self.classifier = LRASPPHead(low_channels, high_channels, num_classes, inter_channels) + + def forward(self, input): + features = self.backbone(input) + out = self.classifier(features) + out = F.interpolate(out, size=input.shape[-2:], mode='bilinear', align_corners=False) + + result = OrderedDict() + result["out"] = out + + return result + + +class LRASPPHead(nn.Module): + + def __init__(self, low_channels, high_channels, num_classes, inter_channels): + super().__init__() + self.cbr = nn.Sequential( + nn.Conv2d(high_channels, inter_channels, 1, bias=False), + nn.BatchNorm2d(inter_channels), + nn.ReLU(inplace=True) + ) + self.scale = nn.Sequential( + nn.AdaptiveAvgPool2d(1), + nn.Conv2d(high_channels, inter_channels, 1, bias=False), + nn.Sigmoid(), + ) + self.low_classifier = nn.Conv2d(low_channels, num_classes, 1) + self.high_classifier = nn.Conv2d(inter_channels, num_classes, 1) + + def forward(self, input: Dict[str, Tensor]) -> Tensor: + low = input["low"] + high = input["high"] + + x = self.cbr(high) + s = self.scale(high) + x = x * s + x = F.interpolate(x, size=low.shape[-2:], mode='bilinear', align_corners=False) + + return self.low_classifier(low) + self.high_classifier(x) diff --git a/torchvision/models/segmentation/segmentation.py b/torchvision/models/segmentation/segmentation.py index 158ba5e3d0e..371be9b97da 100644 --- a/torchvision/models/segmentation/segmentation.py +++ b/torchvision/models/segmentation/segmentation.py @@ -1,11 +1,14 @@ from .._utils import IntermediateLayerGetter from ..utils import load_state_dict_from_url +from .. import mobilenetv3 from .. import resnet from .deeplabv3 import DeepLabHead, DeepLabV3 from .fcn import FCN, FCNHead +from .lraspp import LRASPP -__all__ = ['fcn_resnet50', 'fcn_resnet101', 'deeplabv3_resnet50', 'deeplabv3_resnet101'] +__all__ = ['fcn_resnet50', 'fcn_resnet101', 'deeplabv3_resnet50', 'deeplabv3_resnet101', + 'deeplabv3_mobilenet_v3_large', 'lraspp_mobilenet_v3_large'] model_urls = { @@ -13,30 +16,50 @@ 'fcn_resnet101_coco': 'https://download.pytorch.org/models/fcn_resnet101_coco-7ecb50ca.pth', 'deeplabv3_resnet50_coco': 'https://download.pytorch.org/models/deeplabv3_resnet50_coco-cd0a2569.pth', 'deeplabv3_resnet101_coco': 'https://download.pytorch.org/models/deeplabv3_resnet101_coco-586e9e4e.pth', + 'deeplabv3_mobilenet_v3_large_coco': + 'https://download.pytorch.org/models/deeplabv3_mobilenet_v3_large-fc3c493d.pth', + 'lraspp_mobilenet_v3_large_coco': 'https://download.pytorch.org/models/lraspp_mobilenet_v3_large-d234d4ea.pth', } -def _segm_resnet(name, backbone_name, num_classes, aux, pretrained_backbone=True): - backbone = resnet.__dict__[backbone_name]( - pretrained=pretrained_backbone, - replace_stride_with_dilation=[False, True, True]) - - return_layers = {'layer4': 'out'} +def _segm_model(name, backbone_name, num_classes, aux, pretrained_backbone=True): + if 'resnet' in backbone_name: + backbone = resnet.__dict__[backbone_name]( + pretrained=pretrained_backbone, + replace_stride_with_dilation=[False, True, True]) + out_layer = 'layer4' + out_inplanes = 2048 + aux_layer = 'layer3' + aux_inplanes = 1024 + elif 'mobilenet_v3' in backbone_name: + backbone = mobilenetv3.__dict__[backbone_name](pretrained=pretrained_backbone, _dilated=True).features + + # Gather the indices of blocks which are strided. These are the locations of C1, ..., Cn-1 blocks. + # The first and last blocks are always included because they are the C0 (conv1) and Cn. + stage_indices = [0] + [i for i, b in enumerate(backbone) if getattr(b, "_is_cn", False)] + [len(backbone) - 1] + out_pos = stage_indices[-1] # use C5 which has output_stride = 16 + out_layer = str(out_pos) + out_inplanes = backbone[out_pos].out_channels + aux_pos = stage_indices[-4] # use C2 here which has output_stride = 8 + aux_layer = str(aux_pos) + aux_inplanes = backbone[aux_pos].out_channels + else: + raise NotImplementedError('backbone {} is not supported as of now'.format(backbone_name)) + + return_layers = {out_layer: 'out'} if aux: - return_layers['layer3'] = 'aux' + return_layers[aux_layer] = 'aux' backbone = IntermediateLayerGetter(backbone, return_layers=return_layers) aux_classifier = None if aux: - inplanes = 1024 - aux_classifier = FCNHead(inplanes, num_classes) + aux_classifier = FCNHead(aux_inplanes, num_classes) model_map = { 'deeplabv3': (DeepLabHead, DeepLabV3), 'fcn': (FCNHead, FCN), } - inplanes = 2048 - classifier = model_map[name][0](inplanes, num_classes) + classifier = model_map[name][0](out_inplanes, num_classes) base_model = model_map[name][1] model = base_model(backbone, classifier, aux_classifier) @@ -46,15 +69,36 @@ def _segm_resnet(name, backbone_name, num_classes, aux, pretrained_backbone=True def _load_model(arch_type, backbone, pretrained, progress, num_classes, aux_loss, **kwargs): if pretrained: aux_loss = True - model = _segm_resnet(arch_type, backbone, num_classes, aux_loss, **kwargs) + model = _segm_model(arch_type, backbone, num_classes, aux_loss, **kwargs) if pretrained: - arch = arch_type + '_' + backbone + '_coco' - model_url = model_urls[arch] - if model_url is None: - raise NotImplementedError('pretrained {} is not supported as of now'.format(arch)) - else: - state_dict = load_state_dict_from_url(model_url, progress=progress) - model.load_state_dict(state_dict) + _load_weights(model, arch_type, backbone, progress) + return model + + +def _load_weights(model, arch_type, backbone, progress): + arch = arch_type + '_' + backbone + '_coco' + model_url = model_urls.get(arch, None) + if model_url is None: + raise NotImplementedError('pretrained {} is not supported as of now'.format(arch)) + else: + state_dict = load_state_dict_from_url(model_url, progress=progress) + model.load_state_dict(state_dict) + + +def _segm_lraspp_mobilenetv3(backbone_name, num_classes, pretrained_backbone=True): + backbone = mobilenetv3.__dict__[backbone_name](pretrained=pretrained_backbone, _dilated=True).features + + # Gather the indices of blocks which are strided. These are the locations of C1, ..., Cn-1 blocks. + # The first and last blocks are always included because they are the C0 (conv1) and Cn. + stage_indices = [0] + [i for i, b in enumerate(backbone) if getattr(b, "_is_cn", False)] + [len(backbone) - 1] + low_pos = stage_indices[-4] # use C2 here which has output_stride = 8 + high_pos = stage_indices[-1] # use C5 which has output_stride = 16 + low_channels = backbone[low_pos].out_channels + high_channels = backbone[high_pos].out_channels + + backbone = IntermediateLayerGetter(backbone, return_layers={str(low_pos): 'low', str(high_pos): 'high'}) + + model = LRASPP(backbone, low_channels, high_channels, num_classes) return model @@ -66,6 +110,8 @@ def fcn_resnet50(pretrained=False, progress=True, pretrained (bool): If True, returns a model pre-trained on COCO train2017 which contains the same classes as Pascal VOC progress (bool): If True, displays a progress bar of the download to stderr + num_classes (int): number of output classes of the model (including the background) + aux_loss (bool): If True, it uses an auxiliary loss """ return _load_model('fcn', 'resnet50', pretrained, progress, num_classes, aux_loss, **kwargs) @@ -78,6 +124,8 @@ def fcn_resnet101(pretrained=False, progress=True, pretrained (bool): If True, returns a model pre-trained on COCO train2017 which contains the same classes as Pascal VOC progress (bool): If True, displays a progress bar of the download to stderr + num_classes (int): number of output classes of the model (including the background) + aux_loss (bool): If True, it uses an auxiliary loss """ return _load_model('fcn', 'resnet101', pretrained, progress, num_classes, aux_loss, **kwargs) @@ -90,6 +138,8 @@ def deeplabv3_resnet50(pretrained=False, progress=True, pretrained (bool): If True, returns a model pre-trained on COCO train2017 which contains the same classes as Pascal VOC progress (bool): If True, displays a progress bar of the download to stderr + num_classes (int): number of output classes of the model (including the background) + aux_loss (bool): If True, it uses an auxiliary loss """ return _load_model('deeplabv3', 'resnet50', pretrained, progress, num_classes, aux_loss, **kwargs) @@ -102,5 +152,42 @@ def deeplabv3_resnet101(pretrained=False, progress=True, pretrained (bool): If True, returns a model pre-trained on COCO train2017 which contains the same classes as Pascal VOC progress (bool): If True, displays a progress bar of the download to stderr + num_classes (int): number of output classes of the model (including the background) + aux_loss (bool): If True, it uses an auxiliary loss """ return _load_model('deeplabv3', 'resnet101', pretrained, progress, num_classes, aux_loss, **kwargs) + + +def deeplabv3_mobilenet_v3_large(pretrained=False, progress=True, + num_classes=21, aux_loss=None, **kwargs): + """Constructs a DeepLabV3 model with a MobileNetV3-Large backbone. + + Args: + pretrained (bool): If True, returns a model pre-trained on COCO train2017 which + contains the same classes as Pascal VOC + progress (bool): If True, displays a progress bar of the download to stderr + num_classes (int): number of output classes of the model (including the background) + aux_loss (bool): If True, it uses an auxiliary loss + """ + return _load_model('deeplabv3', 'mobilenet_v3_large', pretrained, progress, num_classes, aux_loss, **kwargs) + + +def lraspp_mobilenet_v3_large(pretrained=False, progress=True, num_classes=21, **kwargs): + """Constructs a Lite R-ASPP Network model with a MobileNetV3-Large backbone. + + Args: + pretrained (bool): If True, returns a model pre-trained on COCO train2017 which + contains the same classes as Pascal VOC + progress (bool): If True, displays a progress bar of the download to stderr + num_classes (int): number of output classes of the model (including the background) + """ + if kwargs.pop("aux_loss", False): + raise NotImplementedError('This model does not use auxiliary loss') + + backbone_name = 'mobilenet_v3_large' + model = _segm_lraspp_mobilenetv3(backbone_name, num_classes, **kwargs) + + if pretrained: + _load_weights(model, 'lraspp', backbone_name, progress) + + return model From a209c5bda95a3832af03e1ce46f684f73c9b1e44 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 12:16:52 -0800 Subject: [PATCH 175/357] adding the note to docstring (#3298) Summary: * Adding the note to the backend function * addressing the new master change Reviewed By: datumbox Differential Revision: D26156375 fbshipit-source-id: 915b121621dc68ea241405252d58b1c5eb2ebc37 Co-authored-by: Francisco Massa --- torchvision/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/torchvision/__init__.py b/torchvision/__init__.py index 28349cbb78a..1dcc07bde6c 100644 --- a/torchvision/__init__.py +++ b/torchvision/__init__.py @@ -64,6 +64,10 @@ def set_video_backend(backend): The :mod:`video_reader` package includes a native C++ implementation on top of FFMPEG libraries, and a python API of TorchScript custom operator. It is generally decoding faster than :mod:`pyav`, but perhaps is less robust. + + .. note:: + Building with FFMPEG is disabled by default in the latest master. If you want to use the 'video_reader' + backend, please compile torchvision from source. """ global _video_backend if backend not in ["pyav", "video_reader"]: From 9220f39182a7d64da7d513db4623fbf18dbcc2fd Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 12:16:52 -0800 Subject: [PATCH 176/357] Renamed files (#3308) Summary: Co-authored-by: Vasilis Vryniotis Reviewed By: datumbox Differential Revision: D26156383 fbshipit-source-id: e444e164cc9f25f3dd9d9761e461f79c9bab878f --- .../cpu/{read_image_cpu.cpp => read_image_impl.cpp} | 6 +++--- .../cpu/{read_image_cpu.h => read_image_impl.h} | 0 ...d_write_file_cpu.cpp => read_write_file_impl.cpp} | 2 +- ...{read_write_file_cpu.h => read_write_file_impl.h} | 0 .../cpu/{readjpeg_cpu.cpp => readjpeg_impl.cpp} | 2 +- .../io/image/cpu/{readjpeg_cpu.h => readjpeg_impl.h} | 0 .../image/cpu/{readpng_cpu.cpp => readpng_impl.cpp} | 2 +- .../io/image/cpu/{readpng_cpu.h => readpng_impl.h} | 0 .../cpu/{writejpeg_cpu.cpp => writejpeg_impl.cpp} | 2 +- .../image/cpu/{writejpeg_cpu.h => writejpeg_impl.h} | 0 .../cpu/{writepng_cpu.cpp => writepng_impl.cpp} | 2 +- .../io/image/cpu/{writepng_cpu.h => writepng_impl.h} | 0 torchvision/csrc/io/image/image.h | 12 ++++++------ 13 files changed, 14 insertions(+), 14 deletions(-) rename torchvision/csrc/io/image/cpu/{read_image_cpu.cpp => read_image_impl.cpp} (91%) rename torchvision/csrc/io/image/cpu/{read_image_cpu.h => read_image_impl.h} (100%) rename torchvision/csrc/io/image/cpu/{read_write_file_cpu.cpp => read_write_file_impl.cpp} (98%) rename torchvision/csrc/io/image/cpu/{read_write_file_cpu.h => read_write_file_impl.h} (100%) rename torchvision/csrc/io/image/cpu/{readjpeg_cpu.cpp => readjpeg_impl.cpp} (99%) rename torchvision/csrc/io/image/cpu/{readjpeg_cpu.h => readjpeg_impl.h} (100%) rename torchvision/csrc/io/image/cpu/{readpng_cpu.cpp => readpng_impl.cpp} (99%) rename torchvision/csrc/io/image/cpu/{readpng_cpu.h => readpng_impl.h} (100%) rename torchvision/csrc/io/image/cpu/{writejpeg_cpu.cpp => writejpeg_impl.cpp} (99%) rename torchvision/csrc/io/image/cpu/{writejpeg_cpu.h => writejpeg_impl.h} (100%) rename torchvision/csrc/io/image/cpu/{writepng_cpu.cpp => writepng_impl.cpp} (99%) rename torchvision/csrc/io/image/cpu/{writepng_cpu.h => writepng_impl.h} (100%) diff --git a/torchvision/csrc/io/image/cpu/read_image_cpu.cpp b/torchvision/csrc/io/image/cpu/read_image_impl.cpp similarity index 91% rename from torchvision/csrc/io/image/cpu/read_image_cpu.cpp rename to torchvision/csrc/io/image/cpu/read_image_impl.cpp index d4c2bf0fdea..0301371485c 100644 --- a/torchvision/csrc/io/image/cpu/read_image_cpu.cpp +++ b/torchvision/csrc/io/image/cpu/read_image_impl.cpp @@ -1,7 +1,7 @@ -#include "read_image_cpu.h" +#include "read_image_impl.h" -#include "readjpeg_cpu.h" -#include "readpng_cpu.h" +#include "readjpeg_impl.h" +#include "readpng_impl.h" torch::Tensor decode_image(const torch::Tensor& data, ImageReadMode mode) { // Check that the input tensor dtype is uint8 diff --git a/torchvision/csrc/io/image/cpu/read_image_cpu.h b/torchvision/csrc/io/image/cpu/read_image_impl.h similarity index 100% rename from torchvision/csrc/io/image/cpu/read_image_cpu.h rename to torchvision/csrc/io/image/cpu/read_image_impl.h diff --git a/torchvision/csrc/io/image/cpu/read_write_file_cpu.cpp b/torchvision/csrc/io/image/cpu/read_write_file_impl.cpp similarity index 98% rename from torchvision/csrc/io/image/cpu/read_write_file_cpu.cpp rename to torchvision/csrc/io/image/cpu/read_write_file_impl.cpp index 8ecae99078c..ac29308d853 100644 --- a/torchvision/csrc/io/image/cpu/read_write_file_cpu.cpp +++ b/torchvision/csrc/io/image/cpu/read_write_file_impl.cpp @@ -1,4 +1,4 @@ -#include "read_write_file_cpu.h" +#include "read_write_file_impl.h" #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN diff --git a/torchvision/csrc/io/image/cpu/read_write_file_cpu.h b/torchvision/csrc/io/image/cpu/read_write_file_impl.h similarity index 100% rename from torchvision/csrc/io/image/cpu/read_write_file_cpu.h rename to torchvision/csrc/io/image/cpu/read_write_file_impl.h diff --git a/torchvision/csrc/io/image/cpu/readjpeg_cpu.cpp b/torchvision/csrc/io/image/cpu/readjpeg_impl.cpp similarity index 99% rename from torchvision/csrc/io/image/cpu/readjpeg_cpu.cpp rename to torchvision/csrc/io/image/cpu/readjpeg_impl.cpp index 94121b4e78f..3c2a8808e3d 100644 --- a/torchvision/csrc/io/image/cpu/readjpeg_cpu.cpp +++ b/torchvision/csrc/io/image/cpu/readjpeg_impl.cpp @@ -1,4 +1,4 @@ -#include "readjpeg_cpu.h" +#include "readjpeg_impl.h" #if !JPEG_FOUND torch::Tensor decodeJPEG(const torch::Tensor& data, ImageReadMode mode) { diff --git a/torchvision/csrc/io/image/cpu/readjpeg_cpu.h b/torchvision/csrc/io/image/cpu/readjpeg_impl.h similarity index 100% rename from torchvision/csrc/io/image/cpu/readjpeg_cpu.h rename to torchvision/csrc/io/image/cpu/readjpeg_impl.h diff --git a/torchvision/csrc/io/image/cpu/readpng_cpu.cpp b/torchvision/csrc/io/image/cpu/readpng_impl.cpp similarity index 99% rename from torchvision/csrc/io/image/cpu/readpng_cpu.cpp rename to torchvision/csrc/io/image/cpu/readpng_impl.cpp index bb2d70b47cd..118651f2558 100644 --- a/torchvision/csrc/io/image/cpu/readpng_cpu.cpp +++ b/torchvision/csrc/io/image/cpu/readpng_impl.cpp @@ -1,4 +1,4 @@ -#include "readpng_cpu.h" +#include "readpng_impl.h" #if !PNG_FOUND torch::Tensor decodePNG(const torch::Tensor& data, ImageReadMode mode) { diff --git a/torchvision/csrc/io/image/cpu/readpng_cpu.h b/torchvision/csrc/io/image/cpu/readpng_impl.h similarity index 100% rename from torchvision/csrc/io/image/cpu/readpng_cpu.h rename to torchvision/csrc/io/image/cpu/readpng_impl.h diff --git a/torchvision/csrc/io/image/cpu/writejpeg_cpu.cpp b/torchvision/csrc/io/image/cpu/writejpeg_impl.cpp similarity index 99% rename from torchvision/csrc/io/image/cpu/writejpeg_cpu.cpp rename to torchvision/csrc/io/image/cpu/writejpeg_impl.cpp index 2787b19c447..46e0dde3b7c 100644 --- a/torchvision/csrc/io/image/cpu/writejpeg_cpu.cpp +++ b/torchvision/csrc/io/image/cpu/writejpeg_impl.cpp @@ -1,4 +1,4 @@ -#include "writejpeg_cpu.h" +#include "writejpeg_impl.h" #if !JPEG_FOUND diff --git a/torchvision/csrc/io/image/cpu/writejpeg_cpu.h b/torchvision/csrc/io/image/cpu/writejpeg_impl.h similarity index 100% rename from torchvision/csrc/io/image/cpu/writejpeg_cpu.h rename to torchvision/csrc/io/image/cpu/writejpeg_impl.h diff --git a/torchvision/csrc/io/image/cpu/writepng_cpu.cpp b/torchvision/csrc/io/image/cpu/writepng_impl.cpp similarity index 99% rename from torchvision/csrc/io/image/cpu/writepng_cpu.cpp rename to torchvision/csrc/io/image/cpu/writepng_impl.cpp index 515d0b85dc2..ec8fea24a61 100644 --- a/torchvision/csrc/io/image/cpu/writepng_cpu.cpp +++ b/torchvision/csrc/io/image/cpu/writepng_impl.cpp @@ -1,4 +1,4 @@ -#include "writejpeg_cpu.h" +#include "writejpeg_impl.h" #if !PNG_FOUND diff --git a/torchvision/csrc/io/image/cpu/writepng_cpu.h b/torchvision/csrc/io/image/cpu/writepng_impl.h similarity index 100% rename from torchvision/csrc/io/image/cpu/writepng_cpu.h rename to torchvision/csrc/io/image/cpu/writepng_impl.h diff --git a/torchvision/csrc/io/image/image.h b/torchvision/csrc/io/image/image.h index 12b93ae27f9..837c121b3ff 100644 --- a/torchvision/csrc/io/image/image.h +++ b/torchvision/csrc/io/image/image.h @@ -1,8 +1,8 @@ #pragma once -#include "cpu/read_image_cpu.h" -#include "cpu/read_write_file_cpu.h" -#include "cpu/readjpeg_cpu.h" -#include "cpu/readpng_cpu.h" -#include "cpu/writejpeg_cpu.h" -#include "cpu/writepng_cpu.h" +#include "cpu/read_image_impl.h" +#include "cpu/read_write_file_impl.h" +#include "cpu/readjpeg_impl.h" +#include "cpu/readpng_impl.h" +#include "cpu/writejpeg_impl.h" +#include "cpu/writepng_impl.h" From 9e6b0e7730d3bfb403629c24e75fee57d3d6c742 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Mon, 1 Feb 2021 12:16:52 -0800 Subject: [PATCH 177/357] Temporarily disable broken RCNN Onnx tests. (#3310) Reviewed By: datumbox Differential Revision: D26156367 fbshipit-source-id: e5b871da8d42f648d6730a3eb736687eface4037 --- test/test_onnx.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_onnx.py b/test/test_onnx.py index b2a7624fc61..a57fca1e3d2 100644 --- a/test/test_onnx.py +++ b/test/test_onnx.py @@ -368,6 +368,7 @@ def get_test_images(self): test_images = [image2] return images, test_images + @unittest.skip # Skip until pytorch/vision#3251 is fixed and pytorch/pytorch#50910 is merged. def test_faster_rcnn(self): images, test_images = self.get_test_images() dummy_image = [torch.ones(3, 100, 100) * 0.3] @@ -419,6 +420,7 @@ def test_paste_mask_in_image(self): assert torch.all(out2.eq(out_trace2)) + @unittest.skip # Skip until pytorch/vision#3251 is fixed and pytorch/pytorch#50910 is merged. def test_mask_rcnn(self): images, test_images = self.get_test_images() dummy_image = [torch.ones(3, 100, 100) * 0.3] @@ -469,6 +471,7 @@ def test_heatmaps_to_keypoints(self): assert torch.all(out2[0].eq(out_trace2[0])) assert torch.all(out2[1].eq(out_trace2[1])) + @unittest.skip # Skip until pytorch/vision#3251 is fixed and pytorch/pytorch#50910 is merged. def test_keypoint_rcnn(self): images, test_images = self.get_test_images() dummy_images = [torch.ones(3, 100, 100) * 0.3] From 899eb7484e9daee6287a1b1d911c9d46b27076ea Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Tue, 2 Feb 2021 10:04:26 -0800 Subject: [PATCH 178/357] Renaming Video.* to video_.* Summary: Implements the workaround discussed at D26110952 for ambiguous-path-case error caused by renaming Video.* to video.* DO NOT sync with Github master Reviewed By: fmassa Differential Revision: D26197400 fbshipit-source-id: 0612845bc3230dea2082125c60b9cafe833fadf6 --- torchvision/csrc/io/video/{Video.cpp => video_.cpp} | 2 +- torchvision/csrc/io/video/{Video.h => video_.h} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename torchvision/csrc/io/video/{Video.cpp => video_.cpp} (99%) rename torchvision/csrc/io/video/{Video.h => video_.h} (100%) diff --git a/torchvision/csrc/io/video/Video.cpp b/torchvision/csrc/io/video/video_.cpp similarity index 99% rename from torchvision/csrc/io/video/Video.cpp rename to torchvision/csrc/io/video/video_.cpp index c1e19e0b5f5..46df284d105 100644 --- a/torchvision/csrc/io/video/Video.cpp +++ b/torchvision/csrc/io/video/video_.cpp @@ -1,4 +1,4 @@ -#include "Video.h" +#include "video_.h" #include #include #include "defs.h" diff --git a/torchvision/csrc/io/video/Video.h b/torchvision/csrc/io/video/video_.h similarity index 100% rename from torchvision/csrc/io/video/Video.h rename to torchvision/csrc/io/video/video_.h From 786f56f66028f18352f7ba6dcdf3eb708744bd24 Mon Sep 17 00:00:00 2001 From: Vasilis Vryniotis Date: Tue, 2 Feb 2021 10:04:26 -0800 Subject: [PATCH 179/357] Restructure the video/video_reader C++ codebase (#3311) Summary: * Moving registration of video methods in Video.cpp and removing unnecessary includes. * Rename files according to cpp styles. * Adding namespaces and moving private methods to anonymous namespaces. * Syncing method names. * Fixing minor issues. Reviewed By: fmassa Differential Revision: D26197746 fbshipit-source-id: dfeaa3144574899e5dfe32fee21575a8c3602cd0 --- torchvision/csrc/io/video/register.cpp | 14 -- .../csrc/io/video/{video_.cpp => video.cpp} | 43 ++-- .../csrc/io/video/{video_.h => video.h} | 22 +- .../csrc/io/video_reader/VideoReader.h | 3 - .../{VideoReader.cpp => video_reader.cpp} | 214 +++++++++--------- .../csrc/io/video_reader/video_reader.h | 55 +++++ 6 files changed, 202 insertions(+), 149 deletions(-) delete mode 100644 torchvision/csrc/io/video/register.cpp rename torchvision/csrc/io/video/{video_.cpp => video.cpp} (91%) rename torchvision/csrc/io/video/{video_.h => video.h} (85%) delete mode 100644 torchvision/csrc/io/video_reader/VideoReader.h rename torchvision/csrc/io/video_reader/{VideoReader.cpp => video_reader.cpp} (96%) create mode 100644 torchvision/csrc/io/video_reader/video_reader.h diff --git a/torchvision/csrc/io/video/register.cpp b/torchvision/csrc/io/video/register.cpp deleted file mode 100644 index 08902d427b0..00000000000 --- a/torchvision/csrc/io/video/register.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "Video.h" - -namespace { - -static auto registerVideo = - torch::class_

+ {% include "searchbox.html" %} +{% endblock %} From 0fa3d44363907c80ebdb1a973ec35a884b2e358f Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 229/357] add CI qualifier to push docs for new tags (#3373) Summary: Co-authored-by: Francisco Massa Reviewed By: NicolasHug Differential Revision: D26605324 fbshipit-source-id: 8387a229df2665f63f4cd1f915b0f54aa33bd755 --- .circleci/config.yml | 2 ++ .circleci/regenerate.py | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a3dffd4a6c2..1534625792c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1325,6 +1325,8 @@ workflows: branches: only: - nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ name: upload_docs python_version: '3.7' requires: diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 98c141dfebc..ec83c5b501d 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -22,6 +22,8 @@ PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] CUDA_VERSION = ["10.1", "10.2", "11.2"] +RC_PATTERN = r"/v[0-9]+(\.[0-9]+)*-rc[0-9]+/" + def build_workflows(prefix='', filter_branch=None, upload=False, indentation=6, windows_latest_only=False): w = [] @@ -91,7 +93,8 @@ def upload_doc_job(filter_branch): } if filter_branch: - job["filters"] = gen_filter_branch_tree(filter_branch) + job["filters"] = gen_filter_branch_tree(filter_branch, + tags_list=RC_PATTERN) return [{"upload_docs": job}] @@ -151,8 +154,11 @@ def generate_base_workflow(base_workflow_name, python_version, cu_version, return {w: d} -def gen_filter_branch_tree(*branches): - return {"branches": {"only": [b for b in branches]}} +def gen_filter_branch_tree(*branches, tags_list=None): + filter_dict = {"branches": {"only": [b for b in branches]}} + if tags_list is not None: + filter_dict["tags"] = {"only": tags_list} + return filter_dict def generate_upload_workflow(base_workflow_name, os_type, btype, cu_version, *, filter_branch=None): From 3c714c0cccaddaca049e4c2a58fb0d636cc09330 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 230/357] typo in link to versions.html (#3408) Reviewed By: NicolasHug Differential Revision: D26605311 fbshipit-source-id: 10dd9a0456dfbe2dc2002a4e32d95422f5e155a5 --- docs/source/_templates/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html index 18a5ccdae5a..aaa15d56e02 100644 --- a/docs/source/_templates/layout.html +++ b/docs/source/_templates/layout.html @@ -2,7 +2,7 @@ {% block sidebartitle %} {% include "searchbox.html" %} {% endblock %} From e9c881779b8367207cc78069e32375b67849ea52 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 231/357] Base class for dataset tests (#3402) Summary: * add base class for datasets tests * add better type hints * add documentation to subclasses * add utility functions to create files / folders of random images and videos * fix imports * remove class properties * fix smoke test * fix type hints * fix random size generation * add Caltech256 as example * add utility function to create grid of combinations * add CIFAR100? as example * lint * add missing import * improve documentation * create 1 frame videos by default * remove obsolete check * return path of files created with utility functions * [test] close PIL file handles before deletion * fix video folder creation * generalize file handle closing * fix lazy imports * add test for transforms * fix explanation comment * lint * force load opened PIL images * lint * copy default config to avoid inplace modification * enable additional arg forwarding Reviewed By: NicolasHug Differential Revision: D26605320 fbshipit-source-id: c54903ea5a6b57ddfa57c560e579e0834cf0cc11 --- test/common_utils.py | 8 + test/datasets_utils.py | 681 +++++++++++++++++++++++++++++++++++++++++ test/test_datasets.py | 96 +++++- 3 files changed, 784 insertions(+), 1 deletion(-) create mode 100644 test/datasets_utils.py diff --git a/test/common_utils.py b/test/common_utils.py index 76cdfdc006b..a0fb7781899 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -393,3 +393,11 @@ def int_dtypes(): def float_dtypes(): return torch.testing.floating_types() + + +@contextlib.contextmanager +def disable_console_output(): + with contextlib.ExitStack() as stack, open(os.devnull, "w") as devnull: + stack.enter_context(contextlib.redirect_stdout(devnull)) + stack.enter_context(contextlib.redirect_stderr(devnull)) + yield diff --git a/test/datasets_utils.py b/test/datasets_utils.py new file mode 100644 index 00000000000..aa3e3f61be3 --- /dev/null +++ b/test/datasets_utils.py @@ -0,0 +1,681 @@ +import collections.abc +import contextlib +import functools +import importlib +import inspect +import itertools +import os +import pathlib +import unittest +import unittest.mock +from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Tuple, Union + +import PIL +import PIL.Image + +import torch +import torchvision.datasets +import torchvision.io + +from common_utils import get_tmp_dir, disable_console_output + + +__all__ = [ + "UsageError", + "lazy_importer", + "test_all_configs", + "DatasetTestCase", + "ImageDatasetTestCase", + "VideoDatasetTestCase", + "create_image_or_video_tensor", + "create_image_file", + "create_image_folder", + "create_video_file", + "create_video_folder", +] + + +class UsageError(RuntimeError): + """Should be raised in case an error happens in the setup rather than the test.""" + + +class LazyImporter: + r"""Lazy importer for additional dependicies. + + Some datasets require additional packages that are no direct dependencies of torchvision. Instances of this class + provide modules listed in MODULES as attributes. They are only imported when accessed. + + """ + MODULES = ( + "av", + "lmdb", + "pandas", + "pycocotools", + "requests", + "scipy.io", + ) + + def __init__(self): + cls = type(self) + for module in self.MODULES: + # We need the quirky 'module=module' argument to the lambda since otherwise the lookup for 'module' in this + # scope would happen at runtime rather than at definition. Thus, without it, every property would try to + # import the last 'module' in MODULES. + setattr(cls, module.split(".", 1)[0], property(lambda self, module=module: LazyImporter._import(module))) + + @staticmethod + def _import(module): + try: + importlib.import_module(module) + return importlib.import_module(module.split(".", 1)[0]) + except ImportError as error: + raise UsageError( + f"Failed to import module '{module}'. " + f"This probably means that the current test case needs '{module}' installed, " + f"but it is not a dependency of torchvision. " + f"You need to install it manually, for example 'pip install {module}'." + ) from error + + +lazy_importer = LazyImporter() + + +def requires_lazy_imports(*modules): + def outer_wrapper(fn): + @functools.wraps(fn) + def inner_wrapper(*args, **kwargs): + for module in modules: + getattr(lazy_importer, module.replace(".", "_")) + return fn(*args, **kwargs) + + return inner_wrapper + + return outer_wrapper + + +# As of Python 3.7 this is provided by contextlib +# https://docs.python.org/3.7/library/contextlib.html#contextlib.nullcontext +# TODO: If the minimum Python requirement is >= 3.7, replace this +@contextlib.contextmanager +def nullcontext(enter_result=None): + yield enter_result + + +def test_all_configs(test): + """Decorator to run test against all configurations. + + Add this as decorator to an arbitrary test to run it against all configurations. The current configuration is + provided as the first parameter: + + .. code-block:: + + @test_all_configs + def test_foo(self, config): + pass + """ + + @functools.wraps(test) + def wrapper(self): + for config in self.CONFIGS: + with self.subTest(**config): + test(self, config) + + return wrapper + + +def combinations_grid(**kwargs): + """Creates a grid of input combinations. + + Each element in the returned sequence is a dictionary containing one possible combination as values. + + Example: + >>> combinations_grid(foo=("bar", "baz"), spam=("eggs", "ham")) + [ + {'foo': 'bar', 'spam': 'eggs'}, + {'foo': 'bar', 'spam': 'ham'}, + {'foo': 'baz', 'spam': 'eggs'}, + {'foo': 'baz', 'spam': 'ham'} + ] + """ + return [dict(zip(kwargs.keys(), values)) for values in itertools.product(*kwargs.values())] + + +class DatasetTestCase(unittest.TestCase): + """Abstract base class for all dataset testcases. + + You have to overwrite the following class attributes: + + - DATASET_CLASS (torchvision.datasets.VisionDataset): Class of dataset to be tested. + - FEATURE_TYPES (Sequence[Any]): Types of the elements returned by index access of the dataset. Instead of + providing these manually, you can instead subclass ``ImageDatasetTestCase`` or ``VideoDatasetTestCase```to + get a reasonable default, that should work for most cases. + + Optionally, you can overwrite the following class attributes: + + - CONFIGS (Sequence[Dict[str, Any]]): Additional configs that should be tested. Each dictonary can contain an + arbitrary combination of dataset parameters that are **not** ``transform``, ``target_transform``, + ``transforms``, or ``download``. The first element will be used as default configuration. + - REQUIRED_PACKAGES (Iterable[str]): Additional dependencies to use the dataset. If these packages are not + available, the tests are skipped. + + Additionally, you need to overwrite the ``inject_fake_data()`` method that provides the data that the tests rely on. + The fake data should resemble the original data as close as necessary, while containing only few examples. During + the creation of the dataset check-, download-, and extract-functions from ``torchvision.datasets.utils`` are + disabled. + + Without further configuration, the testcase will test if + + 1. the dataset raises a ``RuntimeError`` if the data files are not found, + 2. the dataset inherits from `torchvision.datasets.VisionDataset`, + 3. the dataset can be turned into a string, + 4. the feature types of a returned example matches ``FEATURE_TYPES``, + 5. the number of examples matches the injected fake data, and + 6. the dataset calls ``transform``, ``target_transform``, or ``transforms`` if available when accessing data. + + Case 3. to 6. are tested against all configurations in ``CONFIGS``. + + To add dataset-specific tests, create a new method that takes no arguments with ``test_`` as a name prefix: + + .. code-block:: + + def test_foo(self): + pass + + If you want to run the test against all configs, add the ``@test_all_configs`` decorator to the definition and + accept a single argument: + + .. code-block:: + + @test_all_configs + def test_bar(self, config): + pass + + Within the test you can use the ``create_dataset()`` method that yields the dataset as well as additional + information provided by the ``ìnject_fake_data()`` method: + + .. code-block:: + + def test_baz(self): + with self.create_dataset() as (dataset, info): + pass + """ + + DATASET_CLASS = None + FEATURE_TYPES = None + + CONFIGS = None + REQUIRED_PACKAGES = None + + _TRANSFORM_KWARGS = { + "transform", + "target_transform", + "transforms", + } + _SPECIAL_KWARGS = { + *_TRANSFORM_KWARGS, + "download", + } + _HAS_SPECIAL_KWARG = None + + _CHECK_FUNCTIONS = { + "check_md5", + "check_integrity", + } + _DOWNLOAD_EXTRACT_FUNCTIONS = { + "download_url", + "download_file_from_google_drive", + "extract_archive", + "download_and_extract_archive", + } + + def inject_fake_data( + self, tmpdir: str, config: Dict[str, Any] + ) -> Union[int, Dict[str, Any], Tuple[Sequence[Any], Union[int, Dict[str, Any]]]]: + """Inject fake data for dataset into a temporary directory. + + Args: + tmpdir (str): Path to a temporary directory. For most cases this acts as root directory for the dataset + to be created and in turn also for the fake data injected here. + config (Dict[str, Any]): Configuration that will be used to create the dataset. + + Needs to return one of the following: + + 1. (int): Number of examples in the dataset to be created, + 2. (Dict[str, Any]): Additional information about the injected fake data. Must contain the field + ``"num_examples"`` that corresponds to the number of examples in the dataset to be created, or + 3. (Tuple[Sequence[Any], Union[int, Dict[str, Any]]]): Additional required parameters that are passed to + the dataset constructor. The second element corresponds to cases 1. and 2. + + If no ``args`` is returned (case 1. and 2.), the ``tmp_dir`` is passed as first parameter to the dataset + constructor. In most cases this corresponds to ``root``. If the dataset has more parameters without default + values you need to explicitly pass them as explained in case 3. + """ + raise NotImplementedError("You need to provide fake data in order for the tests to run.") + + @contextlib.contextmanager + def create_dataset( + self, + config: Optional[Dict[str, Any]] = None, + inject_fake_data: bool = True, + disable_download_extract: Optional[bool] = None, + **kwargs: Any, + ) -> Iterator[Tuple[torchvision.datasets.VisionDataset, Dict[str, Any]]]: + r"""Create the dataset in a temporary directory. + + Args: + config (Optional[Dict[str, Any]]): Configuration that will be used to create the dataset. If omitted, the + default configuration is used. + inject_fake_data (bool): If ``True`` (default) inject the fake data with :meth:`.inject_fake_data` before + creating the dataset. + disable_download_extract (Optional[bool]): If ``True`` disable download and extract logic while creating + the dataset. If ``None`` (default) this takes the same value as ``inject_fake_data``. + **kwargs (Any): Additional parameters passed to the dataset. These parameters take precedence in case they + overlap with ``config``. + + Yields: + dataset (torchvision.dataset.VisionDataset): Dataset. + info (Dict[str, Any]): Additional information about the injected fake data. See :meth:`.inject_fake_data` + for details. + """ + if config is None: + config = self.CONFIGS[0].copy() + + special_kwargs, other_kwargs = self._split_kwargs(kwargs) + config.update(other_kwargs) + + if disable_download_extract is None: + disable_download_extract = inject_fake_data + + with get_tmp_dir() as tmpdir: + output = self.inject_fake_data(tmpdir, config) if inject_fake_data else None + if output is None: + raise UsageError( + "The method 'inject_fake_data' needs to return at least an integer indicating the number of " + "examples for the current configuration." + ) + + if isinstance(output, collections.abc.Sequence) and len(output) == 2: + args, info = output + else: + args = (tmpdir,) + info = output + + if isinstance(info, int): + info = dict(num_examples=info) + elif isinstance(info, dict): + if "num_examples" not in info: + raise UsageError( + "The information dictionary returned by the method 'inject_fake_data' must contain a " + "'num_examples' field that holds the number of examples for the current configuration." + ) + else: + raise UsageError( + f"The additional information returned by the method 'inject_fake_data' must be either an integer " + f"indicating the number of examples for the current configuration or a dictionary with the the " + f"same content. Got {type(info)} instead." + ) + + cm = self._disable_download_extract if disable_download_extract else nullcontext + with cm(special_kwargs), disable_console_output(): + dataset = self.DATASET_CLASS(*args, **config, **special_kwargs) + + yield dataset, info + + @classmethod + def setUpClass(cls): + cls._verify_required_public_class_attributes() + cls._populate_private_class_attributes() + cls._process_optional_public_class_attributes() + super().setUpClass() + + @classmethod + def _verify_required_public_class_attributes(cls): + if cls.DATASET_CLASS is None: + raise UsageError( + "The class attribute 'DATASET_CLASS' needs to be overwritten. " + "It should contain the class of the dataset to be tested." + ) + if cls.FEATURE_TYPES is None: + raise UsageError( + "The class attribute 'FEATURE_TYPES' needs to be overwritten. " + "It should contain a sequence of types that the dataset returns when accessed by index." + ) + + @classmethod + def _populate_private_class_attributes(cls): + argspec = inspect.getfullargspec(cls.DATASET_CLASS.__init__) + cls._HAS_SPECIAL_KWARG = {name for name in cls._SPECIAL_KWARGS if name in argspec.args} + + @classmethod + def _process_optional_public_class_attributes(cls): + argspec = inspect.getfullargspec(cls.DATASET_CLASS.__init__) + if cls.CONFIGS is None: + config = { + kwarg: default + for kwarg, default in zip(argspec.args[-len(argspec.defaults):], argspec.defaults) + if kwarg not in cls._SPECIAL_KWARGS + } + cls.CONFIGS = (config,) + + if cls.REQUIRED_PACKAGES is not None: + try: + for pkg in cls.REQUIRED_PACKAGES: + importlib.import_module(pkg) + except ImportError as error: + raise unittest.SkipTest( + f"The package '{error.name}' is required to load the dataset '{cls.DATASET_CLASS.__name__}' but is " + f"not installed." + ) + + def _split_kwargs(self, kwargs): + special_kwargs = kwargs.copy() + other_kwargs = {key: special_kwargs.pop(key) for key in set(special_kwargs.keys()) - self._SPECIAL_KWARGS} + return special_kwargs, other_kwargs + + @contextlib.contextmanager + def _disable_download_extract(self, special_kwargs): + inject_download_kwarg = "download" in self._HAS_SPECIAL_KWARG and "download" not in special_kwargs + if inject_download_kwarg: + special_kwargs["download"] = False + + module = inspect.getmodule(self.DATASET_CLASS).__name__ + with contextlib.ExitStack() as stack: + mocks = {} + for function, kwargs in itertools.chain( + zip(self._CHECK_FUNCTIONS, [dict(return_value=True)] * len(self._CHECK_FUNCTIONS)), + zip(self._DOWNLOAD_EXTRACT_FUNCTIONS, [dict()] * len(self._DOWNLOAD_EXTRACT_FUNCTIONS)), + ): + with contextlib.suppress(AttributeError): + patcher = unittest.mock.patch(f"{module}.{function}", **kwargs) + mocks[function] = stack.enter_context(patcher) + + try: + yield mocks + finally: + if inject_download_kwarg: + del special_kwargs["download"] + + def test_not_found(self): + with self.assertRaises(RuntimeError): + with self.create_dataset(inject_fake_data=False): + pass + + def test_smoke(self): + with self.create_dataset() as (dataset, _): + self.assertIsInstance(dataset, torchvision.datasets.VisionDataset) + + @test_all_configs + def test_str_smoke(self, config): + with self.create_dataset(config) as (dataset, _): + self.assertIsInstance(str(dataset), str) + + @test_all_configs + def test_feature_types(self, config): + with self.create_dataset(config) as (dataset, _): + example = dataset[0] + + actual = len(example) + expected = len(self.FEATURE_TYPES) + self.assertEqual( + actual, + expected, + f"The number of the returned features does not match the the number of elements in in FEATURE_TYPES: " + f"{actual} != {expected}", + ) + + for idx, (feature, expected_feature_type) in enumerate(zip(example, self.FEATURE_TYPES)): + with self.subTest(idx=idx): + self.assertIsInstance(feature, expected_feature_type) + + @test_all_configs + def test_num_examples(self, config): + with self.create_dataset(config) as (dataset, info): + self.assertEqual(len(dataset), info["num_examples"]) + + @test_all_configs + def test_transforms(self, config): + mock = unittest.mock.Mock(wraps=lambda *args: args[0] if len(args) == 1 else args) + for kwarg in self._TRANSFORM_KWARGS: + if kwarg not in self._HAS_SPECIAL_KWARG: + continue + + mock.reset_mock() + + with self.subTest(kwarg=kwarg): + with self.create_dataset(config, **{kwarg: mock}) as (dataset, _): + dataset[0] + + mock.assert_called() + + +class ImageDatasetTestCase(DatasetTestCase): + """Abstract base class for image dataset testcases. + + - Overwrites the FEATURE_TYPES class attribute to expect a :class:`PIL.Image.Image` and an integer label. + """ + + FEATURE_TYPES = (PIL.Image.Image, int) + + @contextlib.contextmanager + def create_dataset( + self, + config: Optional[Dict[str, Any]] = None, + inject_fake_data: bool = True, + disable_download_extract: Optional[bool] = None, + **kwargs: Any, + ) -> Iterator[Tuple[torchvision.datasets.VisionDataset, Dict[str, Any]]]: + with super().create_dataset( + config=config, + inject_fake_data=inject_fake_data, + disable_download_extract=disable_download_extract, + **kwargs, + ) as (dataset, info): + # PIL.Image.open() only loads the image meta data upfront and keeps the file open until the first access + # to the pixel data occurs. Trying to delete such a file results in an PermissionError on Windows. Thus, we + # force-load opened images. + # This problem only occurs during testing since some tests, e.g. DatasetTestCase.test_feature_types open an + # image, but never use the underlying data. During normal operation it is reasonable to assume that the + # user wants to work with the image he just opened rather than deleting the underlying file. + with self._force_load_images(): + yield dataset, info + + @contextlib.contextmanager + def _force_load_images(self): + open = PIL.Image.open + + def new(fp, *args, **kwargs): + image = open(fp, *args, **kwargs) + if isinstance(fp, (str, pathlib.Path)): + image.load() + return image + + with unittest.mock.patch("PIL.Image.open", new=new): + yield + + +class VideoDatasetTestCase(DatasetTestCase): + """Abstract base class for video dataset testcases. + + - Overwrites the FEATURE_TYPES class attribute to expect two :class:`torch.Tensor` s for the video and audio as + well as an integer label. + - Overwrites the REQUIRED_PACKAGES class attribute to require PyAV (``av``). + """ + + FEATURE_TYPES = (torch.Tensor, torch.Tensor, int) + REQUIRED_PACKAGES = ("av",) + + +def create_image_or_video_tensor(size: Sequence[int]) -> torch.Tensor: + r"""Create a random uint8 tensor. + + Args: + size (Sequence[int]): Size of the tensor. + """ + return torch.randint(0, 256, size, dtype=torch.uint8) + + +def create_image_file( + root: Union[pathlib.Path, str], name: Union[pathlib.Path, str], size: Union[Sequence[int], int] = 10, **kwargs: Any +) -> pathlib.Path: + """Create an image file from random data. + + Args: + root (Union[str, pathlib.Path]): Root directory the image file will be placed in. + name (Union[str, pathlib.Path]): Name of the image file. + size (Union[Sequence[int], int]): Size of the image that represents the ``(num_channels, height, width)``. If + scalar, the value is used for the height and width. If not provided, three channels are assumed. + kwargs (Any): Additional parameters passed to :meth:`PIL.Image.Image.save`. + + Returns: + pathlib.Path: Path to the created image file. + """ + if isinstance(size, int): + size = (size, size) + if len(size) == 2: + size = (3, *size) + if len(size) != 3: + raise UsageError( + f"The 'size' argument should either be an int or a sequence of length 2 or 3. Got {len(size)} instead" + ) + + image = create_image_or_video_tensor(size) + file = pathlib.Path(root) / name + PIL.Image.fromarray(image.permute(2, 1, 0).numpy()).save(file) + return file + + +def create_image_folder( + root: Union[pathlib.Path, str], + name: Union[pathlib.Path, str], + file_name_fn: Callable[[int], str], + num_examples: int, + size: Optional[Union[Sequence[int], int, Callable[[int], Union[Sequence[int], int]]]] = None, + **kwargs: Any, +) -> List[pathlib.Path]: + """Create a folder of random images. + + Args: + root (Union[str, pathlib.Path]): Root directory the image folder will be placed in. + name (Union[str, pathlib.Path]): Name of the image folder. + file_name_fn (Callable[[int], str]): Should return a file name if called with the file index. + num_examples (int): Number of images to create. + size (Optional[Union[Sequence[int], int, Callable[[int], Union[Sequence[int], int]]]]): Size of the images. If + callable, will be called with the index of the corresponding file. If omitted, a random height and width + between 3 and 10 pixels is selected on a per-image basis. + kwargs (Any): Additional parameters passed to :func:`create_image_file`. + + Returns: + List[pathlib.Path]: Paths to all created image files. + + .. seealso:: + + - :func:`create_image_file` + """ + if size is None: + + def size(idx: int) -> Tuple[int, int, int]: + num_channels = 3 + height, width = torch.randint(3, 11, size=(2,), dtype=torch.int).tolist() + return (num_channels, height, width) + + root = pathlib.Path(root) / name + os.makedirs(root) + + return [ + create_image_file(root, file_name_fn(idx), size=size(idx) if callable(size) else size, **kwargs) + for idx in range(num_examples) + ] + + +@requires_lazy_imports("av") +def create_video_file( + root: Union[pathlib.Path, str], + name: Union[pathlib.Path, str], + size: Union[Sequence[int], int] = (1, 3, 10, 10), + fps: float = 25, + **kwargs: Any, +) -> pathlib.Path: + """Create an video file from random data. + + Args: + root (Union[str, pathlib.Path]): Root directory the video file will be placed in. + name (Union[str, pathlib.Path]): Name of the video file. + size (Union[Sequence[int], int]): Size of the video that represents the + ``(num_frames, num_channels, height, width)``. If scalar, the value is used for the height and width. + If not provided, ``num_frames=1`` and ``num_channels=3`` are assumed. + fps (float): Frame rate in frames per second. + kwargs (Any): Additional parameters passed to :func:`torchvision.io.write_video`. + + Returns: + pathlib.Path: Path to the created image file. + + Raises: + UsageError: If PyAV is not available. + """ + if isinstance(size, int): + size = (size, size) + if len(size) == 2: + size = (3, *size) + if len(size) == 3: + size = (1, *size) + if len(size) != 4: + raise UsageError( + f"The 'size' argument should either be an int or a sequence of length 2, 3, or 4. Got {len(size)} instead" + ) + + video = create_image_or_video_tensor(size) + file = pathlib.Path(root) / name + torchvision.io.write_video(str(file), video.permute(0, 2, 3, 1), fps, **kwargs) + return file + + +@requires_lazy_imports("av") +def create_video_folder( + root: Union[str, pathlib.Path], + name: Union[str, pathlib.Path], + file_name_fn: Callable[[int], str], + num_examples: int, + size: Optional[Union[Sequence[int], int, Callable[[int], Union[Sequence[int], int]]]] = None, + fps=25, + **kwargs, +) -> List[pathlib.Path]: + """Create a folder of random videos. + + Args: + root (Union[str, pathlib.Path]): Root directory the image folder will be placed in. + name (Union[str, pathlib.Path]): Name of the image folder. + file_name_fn (Callable[[int], str]): Should return a file name if called with the file index. + num_examples (int): Number of images to create. + size (Optional[Union[Sequence[int], int, Callable[[int], Union[Sequence[int], int]]]]): Size of the videos. If + callable, will be called with the index of the corresponding file. If omitted, a random even height and + width between 4 and 10 pixels is selected on a per-video basis. + fps (float): Frame rate in frames per second. + kwargs (Any): Additional parameters passed to :func:`create_video_file`. + + Returns: + List[pathlib.Path]: Paths to all created video files. + + Raises: + UsageError: If PyAV is not available. + + .. seealso:: + + - :func:`create_video_file` + """ + if size is None: + + def size(idx): + num_frames = 1 + num_channels = 3 + # The 'libx264' video codec, which is the default of torchvision.io.write_video, requires the height and + # width of the video to be divisible by 2. + height, width = (torch.randint(2, 6, size=(2,), dtype=torch.int) * 2).tolist() + return (num_frames, num_channels, height, width) + + root = pathlib.Path(root) / name + os.makedirs(root) + + return [ + create_video_file(root, file_name_fn(idx), size=size(idx) if callable(size) else size) + for idx in range(num_examples) + ] diff --git a/test/test_datasets.py b/test/test_datasets.py index ff8e0281e7c..8ec5be7de19 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -15,6 +15,10 @@ import xml.etree.ElementTree as ET from urllib.request import Request, urlopen import itertools +import datasets_utils +import pathlib +import pickle +from torchvision import datasets try: @@ -466,5 +470,95 @@ def test_repr_smoke(self): self.assertIsInstance(repr(dataset), str) -if __name__ == '__main__': +class Caltech256TestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.Caltech256 + + def inject_fake_data(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) / "caltech256" / "256_ObjectCategories" + + categories = ((1, "ak47"), (127, "laptop-101"), (257, "clutter")) + num_images_per_category = 2 + + for idx, category in categories: + datasets_utils.create_image_folder( + tmpdir, + name=f"{idx:03d}.{category}", + file_name_fn=lambda image_idx: f"{idx:03d}_{image_idx + 1:04d}.jpg", + num_examples=num_images_per_category, + ) + + return num_images_per_category * len(categories) + + +class CIFAR10TestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.CIFAR10 + CONFIGS = datasets_utils.combinations_grid(train=(True, False)) + + _VERSION_CONFIG = dict( + base_folder="cifar-10-batches-py", + train_files=tuple(f"data_batch_{idx}" for idx in range(1, 6)), + test_files=("test_batch",), + labels_key="labels", + meta_file="batches.meta", + num_categories=10, + categories_key="label_names", + ) + + def inject_fake_data(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) / self._VERSION_CONFIG["base_folder"] + os.makedirs(tmpdir) + + num_images_per_file = 1 + for name in itertools.chain(self._VERSION_CONFIG["train_files"], self._VERSION_CONFIG["test_files"]): + self._create_batch_file(tmpdir, name, num_images_per_file) + + categories = self._create_meta_file(tmpdir) + + return dict( + num_examples=num_images_per_file + * len(self._VERSION_CONFIG["train_files"] if config["train"] else self._VERSION_CONFIG["test_files"]), + categories=categories, + ) + + def _create_batch_file(self, root, name, num_images): + data = datasets_utils.create_image_or_video_tensor((num_images, 32 * 32 * 3)) + labels = np.random.randint(0, self._VERSION_CONFIG["num_categories"], size=num_images).tolist() + self._create_binary_file(root, name, {"data": data, self._VERSION_CONFIG["labels_key"]: labels}) + + def _create_meta_file(self, root): + categories = [ + f"{idx:0{len(str(self._VERSION_CONFIG['num_categories'] - 1))}d}" + for idx in range(self._VERSION_CONFIG["num_categories"]) + ] + self._create_binary_file( + root, self._VERSION_CONFIG["meta_file"], {self._VERSION_CONFIG["categories_key"]: categories} + ) + return categories + + def _create_binary_file(self, root, name, content): + with open(pathlib.Path(root) / name, "wb") as fh: + pickle.dump(content, fh) + + def test_class_to_idx(self): + with self.create_dataset() as (dataset, info): + expected = {category: label for label, category in enumerate(info["categories"])} + actual = dataset.class_to_idx + self.assertEqual(actual, expected) + + +class CIFAR100(CIFAR10TestCase): + DATASET_CLASS = datasets.CIFAR100 + + _VERSION_CONFIG = dict( + base_folder="cifar-100-python", + train_files=("train",), + test_files=("test",), + labels_key="fine_labels", + meta_file="meta", + num_categories=100, + categories_key="fine_label_names", + ) + + +if __name__ == "__main__": unittest.main() From 6ba75eaf0e5dbb118e143d4000a365a9062a7cfc Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 232/357] Fix win arg patch for BUILD_SPLIT_CUDA=ON (#3419) Reviewed By: NicolasHug Differential Revision: D26605309 fbshipit-source-id: 157b3388361f5e81fbcc0dee643d236d615edf8d --- CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dee76a4cf8e..547ab7ddd2b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,15 @@ if(MSVC) string(APPEND CMAKE_CUDA_FLAGS " -Xcudafe --diag_suppress=${diag}") endforeach() CUDA_CONVERT_FLAGS(torch_cpu) - CUDA_CONVERT_FLAGS(torch_cuda) + if(TARGET torch_cuda) + CUDA_CONVERT_FLAGS(torch_cuda) + endif() + if(TARGET torch_cuda_cu) + CUDA_CONVERT_FLAGS(torch_cuda_cu) + endif() + if(TARGET torch_cuda_cpp) + CUDA_CONVERT_FLAGS(torch_cuda_cpp) + endif() endif() endif() From f5b33fa5e91de26f17a10fc8092fd8a1629809a9 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 233/357] Revert "Added "-fopenmp" cflags (#2783) (#3006)" (#3038) Summary: This reverts commit 74de51d6d478e289135d9274e6af550a9bfba137. Reviewed By: NicolasHug Differential Revision: D26605316 fbshipit-source-id: fc3c0e7f52f4831378cee236c356a5e53d96e474 --- setup.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 0317d6e6483..fd653fea0f8 100644 --- a/setup.py +++ b/setup.py @@ -181,9 +181,7 @@ def get_extensions(): define_macros = [] - extra_compile_args = { - 'cxx': [] - } + extra_compile_args = {} if (torch.cuda.is_available() and ((CUDA_HOME is not None) or is_rocm_pytorch)) \ or os.getenv('FORCE_CUDA', '0') == '1': extension = CUDAExtension @@ -198,13 +196,16 @@ def get_extensions(): else: define_macros += [('WITH_HIP', None)] nvcc_flags = [] - extra_compile_args['nvcc'] = nvcc_flags + extra_compile_args = { + 'cxx': [], + 'nvcc': nvcc_flags, + } if sys.platform == 'win32': define_macros += [('torchvision_EXPORTS', None)] + + extra_compile_args.setdefault('cxx', []) extra_compile_args['cxx'].append('/MP') - elif sys.platform == 'linux': - extra_compile_args['cxx'].append('-fopenmp') debug_mode = os.getenv('DEBUG', '0') == '1' if debug_mode: From bef96d7bbc81579af4e25fa01d8d532232680fab Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 234/357] add tests for Caltech101 (#3412) Summary: Co-authored-by: Francisco Massa Reviewed By: NicolasHug Differential Revision: D26605314 fbshipit-source-id: 691f7244feb02a8caa61706b5645c2bf54db2c94 --- test/test_datasets.py | 79 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index 8ec5be7de19..9e761c03aef 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -19,6 +19,7 @@ import pathlib import pickle from torchvision import datasets +import torch try: @@ -470,6 +471,84 @@ def test_repr_smoke(self): self.assertIsInstance(repr(dataset), str) +class Caltech101TestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.Caltech101 + FEATURE_TYPES = (PIL.Image.Image, (int, np.ndarray, tuple)) + + CONFIGS = datasets_utils.combinations_grid(target_type=("category", "annotation", ["category", "annotation"])) + REQUIRED_PACKAGES = ("scipy",) + + def inject_fake_data(self, tmpdir, config): + root = pathlib.Path(tmpdir) / "caltech101" + images = root / "101_ObjectCategories" + annotations = root / "Annotations" + + categories = (("Faces", "Faces_2"), ("helicopter", "helicopter"), ("ying_yang", "ying_yang")) + num_images_per_category = 2 + + for image_category, annotation_category in categories: + datasets_utils.create_image_folder( + root=images, + name=image_category, + file_name_fn=lambda idx: f"image_{idx + 1:04d}.jpg", + num_examples=num_images_per_category, + ) + self._create_annotation_folder( + root=annotations, + name=annotation_category, + file_name_fn=lambda idx: f"annotation_{idx + 1:04d}.mat", + num_examples=num_images_per_category, + ) + + # This is included in the original archive, but is removed by the dataset. Thus, an empty directory suffices. + os.makedirs(images / "BACKGROUND_Google") + + return num_images_per_category * len(categories) + + def _create_annotation_folder(self, root, name, file_name_fn, num_examples): + root = pathlib.Path(root) / name + os.makedirs(root) + + for idx in range(num_examples): + self._create_annotation_file(root, file_name_fn(idx)) + + def _create_annotation_file(self, root, name): + mdict = dict(obj_contour=torch.rand((2, torch.randint(3, 6, size=())), dtype=torch.float64).numpy()) + datasets_utils.lazy_importer.scipy.io.savemat(str(pathlib.Path(root) / name), mdict) + + def test_combined_targets(self): + target_types = ["category", "annotation"] + + individual_targets = [] + for target_type in target_types: + with self.create_dataset(target_type=target_type) as (dataset, _): + _, target = dataset[0] + individual_targets.append(target) + + with self.create_dataset(target_type=target_types) as (dataset, _): + _, combined_targets = dataset[0] + + actual = len(individual_targets) + expected = len(combined_targets) + self.assertEqual( + actual, + expected, + f"The number of the returned combined targets does not match the the number targets if requested " + f"individually: {actual} != {expected}", + ) + + for target_type, combined_target, individual_target in zip(target_types, combined_targets, individual_targets): + with self.subTest(target_type=target_type): + actual = type(combined_target) + expected = type(individual_target) + self.assertIs( + actual, + expected, + f"Type of the combined target does not match the type of the corresponding individual target: " + f"{actual} is not {expected}", + ) + + class Caltech256TestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.Caltech256 From 7024490ed60cd361f851bd4599f85909602cadf1 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 235/357] add tests for CelebA (#3413) Summary: Co-authored-by: Francisco Massa Reviewed By: NicolasHug Differential Revision: D26605312 fbshipit-source-id: 2731ae896f1c58f1376770e4f31b828b22c0a151 --- test/test_datasets.py | 117 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index 9e761c03aef..ca9217e0bf7 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -639,5 +639,122 @@ class CIFAR100(CIFAR10TestCase): ) +class CelebATestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.CelebA + FEATURE_TYPES = (PIL.Image.Image, (torch.Tensor, int, tuple, type(None))) + + CONFIGS = datasets_utils.combinations_grid( + split=("train", "valid", "test", "all"), + target_type=("attr", "identity", "bbox", "landmarks", ["attr", "identity"]), + ) + REQUIRED_PACKAGES = ("pandas",) + + _SPLIT_TO_IDX = dict(train=0, valid=1, test=2) + + def inject_fake_data(self, tmpdir, config): + base_folder = pathlib.Path(tmpdir) / "celeba" + os.makedirs(base_folder) + + num_images, num_images_per_split = self._create_split_txt(base_folder) + + datasets_utils.create_image_folder( + base_folder, "img_align_celeba", lambda idx: f"{idx + 1:06d}.jpg", num_images + ) + attr_names = self._create_attr_txt(base_folder, num_images) + self._create_identity_txt(base_folder, num_images) + self._create_bbox_txt(base_folder, num_images) + self._create_landmarks_txt(base_folder, num_images) + + return dict(num_examples=num_images_per_split[config["split"]], attr_names=attr_names) + + def _create_split_txt(self, root): + num_images_per_split = dict(train=3, valid=2, test=1) + + data = [ + [self._SPLIT_TO_IDX[split]] for split, num_images in num_images_per_split.items() for _ in range(num_images) + ] + self._create_txt(root, "list_eval_partition.txt", data) + + num_images_per_split["all"] = num_images = sum(num_images_per_split.values()) + return num_images, num_images_per_split + + def _create_attr_txt(self, root, num_images): + header = ("5_o_Clock_Shadow", "Young") + data = torch.rand((num_images, len(header))).ge(0.5).int().mul(2).sub(1).tolist() + self._create_txt(root, "list_attr_celeba.txt", data, header=header, add_num_examples=True) + return header + + def _create_identity_txt(self, root, num_images): + data = torch.randint(1, 4, size=(num_images, 1)).tolist() + self._create_txt(root, "identity_CelebA.txt", data) + + def _create_bbox_txt(self, root, num_images): + header = ("x_1", "y_1", "width", "height") + data = torch.randint(10, size=(num_images, len(header))).tolist() + self._create_txt( + root, "list_bbox_celeba.txt", data, header=header, add_num_examples=True, add_image_id_to_header=True + ) + + def _create_landmarks_txt(self, root, num_images): + header = ("lefteye_x", "rightmouth_y") + data = torch.randint(10, size=(num_images, len(header))).tolist() + self._create_txt(root, "list_landmarks_align_celeba.txt", data, header=header, add_num_examples=True) + + def _create_txt(self, root, name, data, header=None, add_num_examples=False, add_image_id_to_header=False): + with open(pathlib.Path(root) / name, "w") as fh: + if add_num_examples: + fh.write(f"{len(data)}\n") + + if header: + if add_image_id_to_header: + header = ("image_id", *header) + fh.write(f"{' '.join(header)}\n") + + for idx, line in enumerate(data, 1): + fh.write(f"{' '.join((f'{idx:06d}.jpg', *[str(value) for value in line]))}\n") + + def test_combined_targets(self): + target_types = ["attr", "identity", "bbox", "landmarks"] + + individual_targets = [] + for target_type in target_types: + with self.create_dataset(target_type=target_type) as (dataset, _): + _, target = dataset[0] + individual_targets.append(target) + + with self.create_dataset(target_type=target_types) as (dataset, _): + _, combined_targets = dataset[0] + + actual = len(individual_targets) + expected = len(combined_targets) + self.assertEqual( + actual, + expected, + f"The number of the returned combined targets does not match the the number targets if requested " + f"individually: {actual} != {expected}", + ) + + for target_type, combined_target, individual_target in zip(target_types, combined_targets, individual_targets): + with self.subTest(target_type=target_type): + actual = type(combined_target) + expected = type(individual_target) + self.assertIs( + actual, + expected, + f"Type of the combined target does not match the type of the corresponding individual target: " + f"{actual} is not {expected}", + ) + + def test_no_target(self): + with self.create_dataset(target_type=[]) as (dataset, _): + _, target = dataset[0] + + self.assertIsNone(target) + + def test_attr_names(self): + with self.create_dataset() as (dataset, info): + self.assertEqual(tuple(dataset.attr_names), info["attr_names"]) + + if __name__ == "__main__": unittest.main() From 8f70d1ce5cf55390e950a9f504098f13350a4572 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 236/357] Add tests for VOC(Segmentation|Detection) and fix existing bugs (#3415) Summary: * use common download utils in VOC and SBDataset * add tests for VOC * use common base class for VOC datasets * remove old voc test and fake data generation Reviewed By: NicolasHug Differential Revision: D26605321 fbshipit-source-id: b9fd280f138c5dc19cba7dda53982e8b508fad57 Co-authored-by: Francisco Massa --- test/fakedata_generation.py | 13 --- test/test_datasets.py | 149 +++++++++++++++++++------ torchvision/datasets/sbd.py | 5 +- torchvision/datasets/voc.py | 214 +++++++++++++++++------------------- 4 files changed, 216 insertions(+), 165 deletions(-) diff --git a/test/fakedata_generation.py b/test/fakedata_generation.py index 020b073febb..cdd6683b22b 100644 --- a/test/fakedata_generation.py +++ b/test/fakedata_generation.py @@ -369,19 +369,6 @@ def _make_mat(file): yield root -@contextlib.contextmanager -def voc_root(): - with get_tmp_dir() as tmp_dir: - voc_dir = os.path.join(tmp_dir, 'VOCdevkit', - 'VOC2012', 'ImageSets', 'Main') - os.makedirs(voc_dir) - train_file = os.path.join(voc_dir, 'train.txt') - with open(train_file, 'w') as f: - f.write('test') - - yield tmp_dir - - @contextlib.contextmanager def ucf101_root(): with get_tmp_dir() as tmp_dir: diff --git a/test/test_datasets.py b/test/test_datasets.py index ca9217e0bf7..3cb412d778d 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -11,7 +11,7 @@ from torchvision.datasets import utils from common_utils import get_tmp_dir from fakedata_generation import mnist_root, cifar_root, imagenet_root, \ - cityscapes_root, svhn_root, voc_root, ucf101_root, places365_root, widerface_root, stl10_root + cityscapes_root, svhn_root, ucf101_root, places365_root, widerface_root, stl10_root import xml.etree.ElementTree as ET from urllib.request import Request, urlopen import itertools @@ -20,6 +20,7 @@ import pickle from torchvision import datasets import torch +import shutil try: @@ -259,38 +260,6 @@ def test_svhn(self, mock_check): dataset = torchvision.datasets.SVHN(root, split="extra") self.generic_classification_dataset_test(dataset, num_images=2) - @mock.patch('torchvision.datasets.voc.download_extract') - def test_voc_parse_xml(self, mock_download_extract): - with voc_root() as root: - dataset = torchvision.datasets.VOCDetection(root) - - single_object_xml = """ - - cat - - """ - multiple_object_xml = """ - - cat - - - dog - - """ - - single_object_parsed = dataset.parse_voc_xml(ET.fromstring(single_object_xml)) - multiple_object_parsed = dataset.parse_voc_xml(ET.fromstring(multiple_object_xml)) - - self.assertEqual(single_object_parsed, {'annotation': {'object': [{'name': 'cat'}]}}) - self.assertEqual(multiple_object_parsed, - {'annotation': { - 'object': [{ - 'name': 'cat' - }, { - 'name': 'dog' - }] - }}) - @unittest.skipIf(not HAS_PYAV, "PyAV unavailable") def test_ucf101(self): cached_meta_data = None @@ -756,5 +725,119 @@ def test_attr_names(self): self.assertEqual(tuple(dataset.attr_names), info["attr_names"]) +class VOCSegmentationTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.VOCSegmentation + FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image) + + CONFIGS = ( + *datasets_utils.combinations_grid( + year=[f"20{year:02d}" for year in range(7, 13)], image_set=("train", "val", "trainval") + ), + dict(year="2007", image_set="test"), + dict(year="2007-test", image_set="test"), + ) + + def inject_fake_data(self, tmpdir, config): + year, is_test_set = ( + ("2007", True) + if config["year"] == "2007-test" or config["image_set"] == "test" + else (config["year"], False) + ) + image_set = config["image_set"] + + base_dir = pathlib.Path(tmpdir) + if year == "2011": + base_dir /= "TrainVal" + base_dir = base_dir / "VOCdevkit" / f"VOC{year}" + os.makedirs(base_dir) + + num_images, num_images_per_image_set = self._create_image_set_files(base_dir, "ImageSets", is_test_set) + datasets_utils.create_image_folder(base_dir, "JPEGImages", lambda idx: f"{idx:06d}.jpg", num_images) + + datasets_utils.create_image_folder(base_dir, "SegmentationClass", lambda idx: f"{idx:06d}.png", num_images) + annotation = self._create_annotation_files(base_dir, "Annotations", num_images) + + return dict(num_examples=num_images_per_image_set[image_set], annotation=annotation) + + def _create_image_set_files(self, root, name, is_test_set): + root = pathlib.Path(root) / name + src = pathlib.Path(root) / "Main" + os.makedirs(src, exist_ok=True) + + idcs = dict(train=(0, 1, 2), val=(3, 4), test=(5,)) + idcs["trainval"] = (*idcs["train"], *idcs["val"]) + + for image_set in ("test",) if is_test_set else ("train", "val", "trainval"): + self._create_image_set_file(src, image_set, idcs[image_set]) + + shutil.copytree(src, root / "Segmentation") + + num_images = max(itertools.chain(*idcs.values())) + 1 + num_images_per_image_set = dict([(image_set, len(idcs_)) for image_set, idcs_ in idcs.items()]) + return num_images, num_images_per_image_set + + def _create_image_set_file(self, root, image_set, idcs): + with open(pathlib.Path(root) / f"{image_set}.txt", "w") as fh: + fh.writelines([f"{idx:06d}\n" for idx in idcs]) + + def _create_annotation_files(self, root, name, num_images): + root = pathlib.Path(root) / name + os.makedirs(root) + + for idx in range(num_images): + annotation = self._create_annotation_file(root, f"{idx:06d}.xml") + + return annotation + + def _create_annotation_file(self, root, name): + def add_child(parent, name, text=None): + child = ET.SubElement(parent, name) + child.text = text + return child + + def add_name(obj, name="dog"): + add_child(obj, "name", name) + return name + + def add_bndbox(obj, bndbox=None): + if bndbox is None: + bndbox = {"xmin": "1", "xmax": "2", "ymin": "3", "ymax": "4"} + + obj = add_child(obj, "bndbox") + for name, text in bndbox.items(): + add_child(obj, name, text) + + return bndbox + + annotation = ET.Element("annotation") + obj = add_child(annotation, "object") + data = dict(name=add_name(obj), bndbox=add_bndbox(obj)) + + with open(pathlib.Path(root) / name, "wb") as fh: + fh.write(ET.tostring(annotation)) + + return data + + +class VOCDetectionTestCase(VOCSegmentationTestCase): + DATASET_CLASS = datasets.VOCDetection + FEATURE_TYPES = (PIL.Image.Image, dict) + + def test_annotations(self): + with self.create_dataset() as (dataset, info): + _, target = dataset[0] + + self.assertIn("annotation", target) + annotation = target["annotation"] + + self.assertIn("object", annotation) + objects = annotation["object"] + + self.assertEqual(len(objects), 1) + object = objects[0] + + self.assertEqual(object, info["annotation"]) + + if __name__ == "__main__": unittest.main() diff --git a/torchvision/datasets/sbd.py b/torchvision/datasets/sbd.py index 1c3e221f495..f6d7031a95e 100644 --- a/torchvision/datasets/sbd.py +++ b/torchvision/datasets/sbd.py @@ -6,8 +6,7 @@ import numpy as np from PIL import Image -from .utils import download_url, verify_str_arg -from .voc import download_extract +from .utils import download_url, verify_str_arg, download_and_extract_archive class SBDataset(VisionDataset): @@ -77,7 +76,7 @@ def __init__( mask_dir = os.path.join(sbd_root, 'cls') if download: - download_extract(self.url, self.root, self.filename, self.md5) + download_and_extract_archive(self.url, self.root, filename=self.filename, md5=self.md5) extracted_ds_root = os.path.join(self.root, "benchmark_RELEASE", "dataset") for f in ["cls", "img", "inst", "train.txt", "val.txt"]: old_path = os.path.join(extracted_ds_root, f) diff --git a/torchvision/datasets/voc.py b/torchvision/datasets/voc.py index 666bd01b5c2..b905ede7a0a 100644 --- a/torchvision/datasets/voc.py +++ b/torchvision/datasets/voc.py @@ -4,8 +4,9 @@ from .vision import VisionDataset import xml.etree.ElementTree as ET from PIL import Image -from typing import Any, Callable, Dict, Optional, Tuple -from .utils import download_url, verify_str_arg +from typing import Any, Callable, Dict, Optional, Tuple, List +from .utils import download_and_extract_archive, verify_str_arg +import warnings DATASET_YEAR_DICT = { '2012': { @@ -53,13 +54,83 @@ } -class VOCSegmentation(VisionDataset): +class _VOCBase(VisionDataset): + _SPLITS_DIR: str + _TARGET_DIR: str + _TARGET_FILE_EXT: str + + def __init__( + self, + root: str, + year: str = "2012", + image_set: str = "train", + download: bool = False, + transform: Optional[Callable] = None, + target_transform: Optional[Callable] = None, + transforms: Optional[Callable] = None, + ): + super().__init__(root, transforms, transform, target_transform) + if year == "2007-test": + if image_set == "test": + warnings.warn( + "Acessing the test image set of the year 2007 with year='2007-test' is deprecated. " + "Please use the combination year='2007' and image_set='test' instead." + ) + year = "2007" + else: + raise ValueError( + "In the test image set of the year 2007 only image_set='test' is allowed. " + "For all other image sets use year='2007' instead." + ) + self.year = year + + valid_image_sets = ["train", "trainval", "val"] + if year == "2007": + valid_image_sets.append("test") + key = "2007-test" + else: + key = year + self.image_set = verify_str_arg(image_set, "image_set", valid_image_sets) + dataset_year_dict = DATASET_YEAR_DICT[key] + + self.url = dataset_year_dict["url"] + self.filename = dataset_year_dict["filename"] + self.md5 = dataset_year_dict["md5"] + + base_dir = dataset_year_dict["base_dir"] + voc_root = os.path.join(self.root, base_dir) + + if download: + download_and_extract_archive(self.url, self.root, filename=self.filename, md5=self.md5) + + if not os.path.isdir(voc_root): + raise RuntimeError("Dataset not found or corrupted. You can use download=True to download it") + + splits_dir = os.path.join(voc_root, "ImageSets", self._SPLITS_DIR) + split_f = os.path.join(splits_dir, image_set.rstrip("\n") + ".txt") + with open(os.path.join(split_f), "r") as f: + file_names = [x.strip() for x in f.readlines()] + + image_dir = os.path.join(voc_root, "JPEGImages") + self.images = [os.path.join(image_dir, x + ".jpg") for x in file_names] + + target_dir = os.path.join(voc_root, self._TARGET_DIR) + self.targets = [os.path.join(target_dir, x + self._TARGET_FILE_EXT) for x in file_names] + + assert len(self.images) == len(self.targets) + + def __len__(self) -> int: + return len(self.images) + + +class VOCSegmentation(_VOCBase): """`Pascal VOC `_ Segmentation Dataset. Args: root (string): Root directory of the VOC Dataset. - year (string, optional): The dataset year, supports years 2007 to 2012. - image_set (string, optional): Select the image_set to use, ``train``, ``trainval`` or ``val`` + year (string, optional): The dataset year, supports years ``"2007"`` to ``"2012"``. + image_set (string, optional): Select the image_set to use, ``"train"``, ``"trainval"`` or ``"val"``. If + ``year=="2007"``, can also be ``"test"``. download (bool, optional): If true, downloads the dataset from the internet and puts it in root directory. If dataset is already downloaded, it is not downloaded again. @@ -71,49 +142,13 @@ class VOCSegmentation(VisionDataset): and returns a transformed version. """ - def __init__( - self, - root: str, - year: str = "2012", - image_set: str = "train", - download: bool = False, - transform: Optional[Callable] = None, - target_transform: Optional[Callable] = None, - transforms: Optional[Callable] = None, - ): - super(VOCSegmentation, self).__init__(root, transforms, transform, target_transform) - self.year = year - if year == "2007" and image_set == "test": - year = "2007-test" - self.url = DATASET_YEAR_DICT[year]['url'] - self.filename = DATASET_YEAR_DICT[year]['filename'] - self.md5 = DATASET_YEAR_DICT[year]['md5'] - valid_sets = ["train", "trainval", "val"] - if year == "2007-test": - valid_sets.append("test") - self.image_set = verify_str_arg(image_set, "image_set", valid_sets) - base_dir = DATASET_YEAR_DICT[year]['base_dir'] - voc_root = os.path.join(self.root, base_dir) - image_dir = os.path.join(voc_root, 'JPEGImages') - mask_dir = os.path.join(voc_root, 'SegmentationClass') - - if download: - download_extract(self.url, self.root, self.filename, self.md5) - - if not os.path.isdir(voc_root): - raise RuntimeError('Dataset not found or corrupted.' + - ' You can use download=True to download it') - - splits_dir = os.path.join(voc_root, 'ImageSets/Segmentation') - - split_f = os.path.join(splits_dir, image_set.rstrip('\n') + '.txt') + _SPLITS_DIR = "Segmentation" + _TARGET_DIR = "SegmentationClass" + _TARGET_FILE_EXT = ".png" - with open(os.path.join(split_f), "r") as f: - file_names = [x.strip() for x in f.readlines()] - - self.images = [os.path.join(image_dir, x + ".jpg") for x in file_names] - self.masks = [os.path.join(mask_dir, x + ".png") for x in file_names] - assert (len(self.images) == len(self.masks)) + @property + def masks(self) -> List[str]: + return self.targets def __getitem__(self, index: int) -> Tuple[Any, Any]: """ @@ -123,7 +158,7 @@ def __getitem__(self, index: int) -> Tuple[Any, Any]: Returns: tuple: (image, target) where target is the image segmentation. """ - img = Image.open(self.images[index]).convert('RGB') + img = Image.open(self.images[index]).convert("RGB") target = Image.open(self.masks[index]) if self.transforms is not None: @@ -131,17 +166,15 @@ def __getitem__(self, index: int) -> Tuple[Any, Any]: return img, target - def __len__(self) -> int: - return len(self.images) - -class VOCDetection(VisionDataset): +class VOCDetection(_VOCBase): """`Pascal VOC `_ Detection Dataset. Args: root (string): Root directory of the VOC Dataset. - year (string, optional): The dataset year, supports years 2007 to 2012. - image_set (string, optional): Select the image_set to use, ``train``, ``trainval`` or ``val`` + year (string, optional): The dataset year, supports years ``"2007"`` to ``"2012"``. + image_set (string, optional): Select the image_set to use, ``"train"``, ``"trainval"`` or ``"val"``. If + ``year=="2007"``, can also be ``"test"``. download (bool, optional): If true, downloads the dataset from the internet and puts it in root directory. If dataset is already downloaded, it is not downloaded again. @@ -154,50 +187,13 @@ class VOCDetection(VisionDataset): and returns a transformed version. """ - def __init__( - self, - root: str, - year: str = "2012", - image_set: str = "train", - download: bool = False, - transform: Optional[Callable] = None, - target_transform: Optional[Callable] = None, - transforms: Optional[Callable] = None, - ): - super(VOCDetection, self).__init__(root, transforms, transform, target_transform) - self.year = year - if year == "2007" and image_set == "test": - year = "2007-test" - self.url = DATASET_YEAR_DICT[year]['url'] - self.filename = DATASET_YEAR_DICT[year]['filename'] - self.md5 = DATASET_YEAR_DICT[year]['md5'] - valid_sets = ["train", "trainval", "val"] - if year == "2007-test": - valid_sets.append("test") - self.image_set = verify_str_arg(image_set, "image_set", valid_sets) - - base_dir = DATASET_YEAR_DICT[year]['base_dir'] - voc_root = os.path.join(self.root, base_dir) - image_dir = os.path.join(voc_root, 'JPEGImages') - annotation_dir = os.path.join(voc_root, 'Annotations') - - if download: - download_extract(self.url, self.root, self.filename, self.md5) - - if not os.path.isdir(voc_root): - raise RuntimeError('Dataset not found or corrupted.' + - ' You can use download=True to download it') - - splits_dir = os.path.join(voc_root, 'ImageSets/Main') - - split_f = os.path.join(splits_dir, image_set.rstrip('\n') + '.txt') - - with open(os.path.join(split_f), "r") as f: - file_names = [x.strip() for x in f.readlines()] + _SPLITS_DIR = "Main" + _TARGET_DIR = "Annotations" + _TARGET_FILE_EXT = ".xml" - self.images = [os.path.join(image_dir, x + ".jpg") for x in file_names] - self.annotations = [os.path.join(annotation_dir, x + ".xml") for x in file_names] - assert (len(self.images) == len(self.annotations)) + @property + def annotations(self) -> List[str]: + return self.targets def __getitem__(self, index: int) -> Tuple[Any, Any]: """ @@ -207,18 +203,14 @@ def __getitem__(self, index: int) -> Tuple[Any, Any]: Returns: tuple: (image, target) where target is a dictionary of the XML tree. """ - img = Image.open(self.images[index]).convert('RGB') - target = self.parse_voc_xml( - ET.parse(self.annotations[index]).getroot()) + img = Image.open(self.images[index]).convert("RGB") + target = self.parse_voc_xml(ET.parse(self.annotations[index]).getroot()) if self.transforms is not None: img, target = self.transforms(img, target) return img, target - def __len__(self) -> int: - return len(self.images) - def parse_voc_xml(self, node: ET.Element) -> Dict[str, Any]: voc_dict: Dict[str, Any] = {} children = list(node) @@ -227,21 +219,11 @@ def parse_voc_xml(self, node: ET.Element) -> Dict[str, Any]: for dc in map(self.parse_voc_xml, children): for ind, v in dc.items(): def_dic[ind].append(v) - if node.tag == 'annotation': - def_dic['object'] = [def_dic['object']] - voc_dict = { - node.tag: - {ind: v[0] if len(v) == 1 else v - for ind, v in def_dic.items()} - } + if node.tag == "annotation": + def_dic["object"] = [def_dic["object"]] + voc_dict = {node.tag: {ind: v[0] if len(v) == 1 else v for ind, v in def_dic.items()}} if node.text: text = node.text.strip() if not children: voc_dict[node.tag] = text return voc_dict - - -def download_extract(url: str, root: str, filename: str, md5: str) -> None: - download_url(url, root, filename, md5) - with tarfile.open(os.path.join(root, filename), "r") as tar: - tar.extractall(path=root) From a3107fae06d0da3ac475941bc297faff9f663bf7 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 237/357] add tests for Coco (#3416) Summary: Co-authored-by: Francisco Massa Reviewed By: NicolasHug Differential Revision: D26605326 fbshipit-source-id: df7d6e8c4a50d43b432906f643c55345e0d85915 --- test/test_datasets.py | 66 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index 3cb412d778d..265aa9b80dc 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -21,6 +21,7 @@ from torchvision import datasets import torch import shutil +import json try: @@ -839,5 +840,70 @@ def test_annotations(self): self.assertEqual(object, info["annotation"]) +class CocoDetectionTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.CocoDetection + FEATURE_TYPES = (PIL.Image.Image, list) + + REQUIRED_PACKAGES = ("pycocotools",) + + def inject_fake_data(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) + + num_images = 3 + num_annotations_per_image = 2 + + image_folder = tmpdir / "images" + files = datasets_utils.create_image_folder( + tmpdir, name="images", file_name_fn=lambda idx: f"{idx:012d}.jpg", num_examples=num_images + ) + file_names = [file.relative_to(image_folder) for file in files] + + annotation_folder = tmpdir / "annotations" + os.makedirs(annotation_folder) + annotation_file, info = self._create_annotation_file(annotation_folder, file_names, num_annotations_per_image) + + info["num_examples"] = num_images + return (str(image_folder), str(annotation_file)), info + + def _create_annotation_file(self, root, file_names, num_annotations_per_image): + image_ids = [int(file_name.stem) for file_name in file_names] + images = [dict(file_name=str(file_name), id=id) for file_name, id in zip(file_names, image_ids)] + + annotations, info = self._create_annotations(image_ids, num_annotations_per_image) + + content = dict(images=images, annotations=annotations) + return self._create_json(root, "annotations.json", content), info + + def _create_annotations(self, image_ids, num_annotations_per_image): + annotations = datasets_utils.combinations_grid( + image_id=image_ids, bbox=([1.0, 2.0, 3.0, 4.0],) * num_annotations_per_image + ) + for id, annotation in enumerate(annotations): + annotation["id"] = id + return annotations, dict() + + def _create_json(self, root, name, content): + file = pathlib.Path(root) / name + with open(file, "w") as fh: + json.dump(content, fh) + return file + + +class CocoCaptionsTestCase(CocoDetectionTestCase): + DATASET_CLASS = datasets.CocoCaptions + + def _create_annotations(self, image_ids, num_annotations_per_image): + captions = [str(idx) for idx in range(num_annotations_per_image)] + annotations = datasets_utils.combinations_grid(image_id=image_ids, caption=captions) + for id, annotation in enumerate(annotations): + annotation["id"] = id + return annotations, dict(captions=captions) + + def test_captions(self): + with self.create_dataset() as (dataset, info): + _, captions = dataset[0] + self.assertEqual(tuple(captions), tuple(info["captions"])) + + if __name__ == "__main__": unittest.main() From bbb9331c2b0f53187f5aed17dcbbd677a77bd6d0 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 238/357] improve Coco implementation (#3417) Summary: Co-authored-by: Francisco Massa Reviewed By: NicolasHug Differential Revision: D26605315 fbshipit-source-id: de287ccc33457722f82d2b4108a82388622ef039 --- torchvision/datasets/coco.py | 137 +++++++++++++---------------------- 1 file changed, 49 insertions(+), 88 deletions(-) diff --git a/torchvision/datasets/coco.py b/torchvision/datasets/coco.py index 81ef76b00e5..d59a23efb4d 100644 --- a/torchvision/datasets/coco.py +++ b/torchvision/datasets/coco.py @@ -2,11 +2,11 @@ from PIL import Image import os import os.path -from typing import Any, Callable, Optional, Tuple +from typing import Any, Callable, Optional, Tuple, List -class CocoCaptions(VisionDataset): - """`MS Coco Captions `_ Dataset. +class CocoDetection(VisionDataset): + """`MS Coco Detection `_ Dataset. Args: root (string): Root directory where images are downloaded to. @@ -17,77 +17,45 @@ class CocoCaptions(VisionDataset): target and transforms it. transforms (callable, optional): A function/transform that takes input sample and its target as entry and returns a transformed version. - - Example: - - .. code:: python - - import torchvision.datasets as dset - import torchvision.transforms as transforms - cap = dset.CocoCaptions(root = 'dir where images are', - annFile = 'json annotation file', - transform=transforms.ToTensor()) - - print('Number of samples: ', len(cap)) - img, target = cap[3] # load 4th sample - - print("Image Size: ", img.size()) - print(target) - - Output: :: - - Number of samples: 82783 - Image Size: (3L, 427L, 640L) - [u'A plane emitting smoke stream flying over a mountain.', - u'A plane darts across a bright blue sky behind a mountain covered in snow', - u'A plane leaves a contrail above the snowy mountain top.', - u'A mountain that has a plane flying overheard in the distance.', - u'A mountain view with a plume of smoke in the background'] - """ def __init__( - self, - root: str, - annFile: str, - transform: Optional[Callable] = None, - target_transform: Optional[Callable] = None, - transforms: Optional[Callable] = None, - ) -> None: - super(CocoCaptions, self).__init__(root, transforms, transform, target_transform) + self, + root: str, + annFile: str, + transform: Optional[Callable] = None, + target_transform: Optional[Callable] = None, + transforms: Optional[Callable] = None, + ): + super().__init__(root, transforms, transform, target_transform) from pycocotools.coco import COCO + self.coco = COCO(annFile) self.ids = list(sorted(self.coco.imgs.keys())) - def __getitem__(self, index: int) -> Tuple[Any, Any]: - """ - Args: - index (int): Index - - Returns: - tuple: Tuple (image, target). target is a list of captions for the image. - """ - coco = self.coco - img_id = self.ids[index] - ann_ids = coco.getAnnIds(imgIds=img_id) - anns = coco.loadAnns(ann_ids) - target = [ann['caption'] for ann in anns] + def _load_image(self, id: int) -> Image.Image: + path = self.coco.loadImgs(id)[0]["file_name"] + return Image.open(os.path.join(self.root, path)).convert("RGB") - path = coco.loadImgs(img_id)[0]['file_name'] + def _load_target(self, id) -> List[Any]: + return self.coco.loadAnns(self.coco.getAnnIds(id)) - img = Image.open(os.path.join(self.root, path)).convert('RGB') + def __getitem__(self, index: int) -> Tuple[Any, Any]: + id = self.ids[index] + image = self._load_image(id) + target = self._load_target(id) if self.transforms is not None: - img, target = self.transforms(img, target) + image, target = self.transforms(image, target) - return img, target + return image, target def __len__(self) -> int: return len(self.ids) -class CocoDetection(VisionDataset): - """`MS Coco Detection `_ Dataset. +class CocoCaptions(CocoDetection): + """`MS Coco Captions `_ Dataset. Args: root (string): Root directory where images are downloaded to. @@ -98,41 +66,34 @@ class CocoDetection(VisionDataset): target and transforms it. transforms (callable, optional): A function/transform that takes input sample and its target as entry and returns a transformed version. - """ - def __init__( - self, - root: str, - annFile: str, - transform: Optional[Callable] = None, - target_transform: Optional[Callable] = None, - transforms: Optional[Callable] = None, - ) -> None: - super(CocoDetection, self).__init__(root, transforms, transform, target_transform) - from pycocotools.coco import COCO - self.coco = COCO(annFile) - self.ids = list(sorted(self.coco.imgs.keys())) + Example: - def __getitem__(self, index: int) -> Tuple[Any, Any]: - """ - Args: - index (int): Index + .. code:: python + + import torchvision.datasets as dset + import torchvision.transforms as transforms + cap = dset.CocoCaptions(root = 'dir where images are', + annFile = 'json annotation file', + transform=transforms.ToTensor()) - Returns: - tuple: Tuple (image, target). target is the object returned by ``coco.loadAnns``. - """ - coco = self.coco - img_id = self.ids[index] - ann_ids = coco.getAnnIds(imgIds=img_id) - target = coco.loadAnns(ann_ids) + print('Number of samples: ', len(cap)) + img, target = cap[3] # load 4th sample - path = coco.loadImgs(img_id)[0]['file_name'] + print("Image Size: ", img.size()) + print(target) - img = Image.open(os.path.join(self.root, path)).convert('RGB') - if self.transforms is not None: - img, target = self.transforms(img, target) + Output: :: - return img, target + Number of samples: 82783 + Image Size: (3L, 427L, 640L) + [u'A plane emitting smoke stream flying over a mountain.', + u'A plane darts across a bright blue sky behind a mountain covered in snow', + u'A plane leaves a contrail above the snowy mountain top.', + u'A mountain that has a plane flying overheard in the distance.', + u'A mountain view with a plume of smoke in the background'] - def __len__(self) -> int: - return len(self.ids) + """ + + def _load_target(self, id) -> List[str]: + return [ann["caption"] for ann in super()._load_target(id)] From 9f0dadf59e2237f2df6ad8896d0cfccf4d52d932 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 239/357] Removed call to optimze_for_mobile (#3424) Summary: * removed call to optimze_for_mobile * removed unrelated changes Reviewed By: NicolasHug Differential Revision: D26605327 fbshipit-source-id: 7d1165d101fc337eb4993854dc5378d23508308b --- android/test_app/make_assets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/test_app/make_assets.py b/android/test_app/make_assets.py index 7860c759a57..ce5059b46ee 100644 --- a/android/test_app/make_assets.py +++ b/android/test_app/make_assets.py @@ -1,6 +1,5 @@ import torch import torchvision -from torch.utils.mobile_optimizer import optimize_for_mobile print(torch.__version__) @@ -13,5 +12,6 @@ model.eval() script_model = torch.jit.script(model) -opt_script_model = optimize_for_mobile(script_model) -opt_script_model.save("app/src/main/assets/frcnn_mnetv3.pt") +# TODO: put back call to optimize_for_mobile once +# https://github.com/pytorch/pytorch/issues/52463 is fixed +script_model.save("app/src/main/assets/frcnn_mnetv3.pt") From 8dc89f06df2983e64d456dfb160fbbde94092ee6 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 240/357] Specify coordinate constraints for box parameters (#3425) Summary: * Specify coordinate constraints * some more * flake8 Reviewed By: NicolasHug Differential Revision: D26605310 fbshipit-source-id: 91e4b592ae3b25db08c95e24bd917de9a0042e70 --- torchvision/models/detection/faster_rcnn.py | 16 +++++++------- torchvision/models/detection/keypoint_rcnn.py | 16 +++++++------- torchvision/models/detection/mask_rcnn.py | 16 +++++++------- torchvision/models/detection/retinanet.py | 16 +++++++------- torchvision/ops/boxes.py | 21 ++++++++++++------- torchvision/ops/poolers.py | 2 +- torchvision/ops/ps_roi_align.py | 4 +++- torchvision/ops/ps_roi_pool.py | 4 +++- torchvision/ops/roi_align.py | 4 +++- torchvision/ops/roi_pool.py | 4 +++- 10 files changed, 59 insertions(+), 44 deletions(-) diff --git a/torchvision/models/detection/faster_rcnn.py b/torchvision/models/detection/faster_rcnn.py index 0599d1da484..6781c965d18 100644 --- a/torchvision/models/detection/faster_rcnn.py +++ b/torchvision/models/detection/faster_rcnn.py @@ -32,8 +32,8 @@ class FasterRCNN(GeneralizedRCNN): During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: - - boxes (FloatTensor[N, 4]): the ground-truth boxes in [x1, y1, x2, y2] format, with values of x - between 0 and W and values of y between 0 and H + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (Int64Tensor[N]): the class label for each ground-truth box The model returns a Dict[Tensor] during training, containing the classification and regression @@ -42,8 +42,8 @@ class FasterRCNN(GeneralizedRCNN): During inference, the model requires only the input tensors, and returns the post-processed predictions as a List[Dict[Tensor]], one for each input image. The fields of the Dict are as follows: - - boxes (FloatTensor[N, 4]): the predicted boxes in [x1, y1, x2, y2] format, with values of x - between 0 and W and values of y between 0 and H + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (Int64Tensor[N]): the predicted labels for each image - scores (Tensor[N]): the scores or each prediction @@ -309,8 +309,8 @@ def fasterrcnn_resnet50_fpn(pretrained=False, progress=True, During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: - - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` - between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (``Int64Tensor[N]``): the class label for each ground-truth box The model returns a ``Dict[Tensor]`` during training, containing the classification and regression @@ -320,8 +320,8 @@ def fasterrcnn_resnet50_fpn(pretrained=False, progress=True, predictions as a ``List[Dict[Tensor]]``, one for each input image. The fields of the ``Dict`` are as follows: - - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` - between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (``Int64Tensor[N]``): the predicted labels for each image - scores (``Tensor[N]``): the scores or each prediction diff --git a/torchvision/models/detection/keypoint_rcnn.py b/torchvision/models/detection/keypoint_rcnn.py index f784273f5c2..0d460ade27c 100644 --- a/torchvision/models/detection/keypoint_rcnn.py +++ b/torchvision/models/detection/keypoint_rcnn.py @@ -27,8 +27,8 @@ class KeypointRCNN(FasterRCNN): During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: - - boxes (FloatTensor[N, 4]): the ground-truth boxes in [x1, y1, x2, y2] format, with values of x - between 0 and W and values of y between 0 and H + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (Int64Tensor[N]): the class label for each ground-truth box - keypoints (FloatTensor[N, K, 3]): the K keypoints location for each of the N instances, in the format [x, y, visibility], where visibility=0 means that the keypoint is not visible. @@ -40,8 +40,8 @@ class KeypointRCNN(FasterRCNN): predictions as a List[Dict[Tensor]], one for each input image. The fields of the Dict are as follows: - - boxes (FloatTensor[N, 4]): the predicted boxes in [x1, y1, x2, y2] format, with values of x - between 0 and W and values of y between 0 and H + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (Int64Tensor[N]): the predicted labels for each image - scores (Tensor[N]): the scores or each prediction - keypoints (FloatTensor[N, K, 3]): the locations of the predicted keypoints, in [x, y, v] format. @@ -286,8 +286,8 @@ def keypointrcnn_resnet50_fpn(pretrained=False, progress=True, During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: - - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` - between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (``Int64Tensor[N]``): the class label for each ground-truth box - keypoints (``FloatTensor[N, K, 3]``): the ``K`` keypoints location for each of the ``N`` instances, in the format ``[x, y, visibility]``, where ``visibility=0`` means that the keypoint is not visible. @@ -299,8 +299,8 @@ def keypointrcnn_resnet50_fpn(pretrained=False, progress=True, predictions as a ``List[Dict[Tensor]]``, one for each input image. The fields of the ``Dict`` are as follows: - - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` - between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (``Int64Tensor[N]``): the predicted labels for each image - scores (``Tensor[N]``): the scores or each prediction - keypoints (``FloatTensor[N, K, 3]``): the locations of the predicted keypoints, in ``[x, y, v]`` format. diff --git a/torchvision/models/detection/mask_rcnn.py b/torchvision/models/detection/mask_rcnn.py index 09be4fa684c..1e6fb77f07a 100644 --- a/torchvision/models/detection/mask_rcnn.py +++ b/torchvision/models/detection/mask_rcnn.py @@ -26,8 +26,8 @@ class MaskRCNN(FasterRCNN): During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: - - boxes (FloatTensor[N, 4]): the ground-truth boxes in [x1, y1, x2, y2] format, with values of x - between 0 and W and values of y between 0 and H + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (Int64Tensor[N]): the class label for each ground-truth box - masks (UInt8Tensor[N, H, W]): the segmentation binary masks for each instance @@ -37,8 +37,8 @@ class MaskRCNN(FasterRCNN): During inference, the model requires only the input tensors, and returns the post-processed predictions as a List[Dict[Tensor]], one for each input image. The fields of the Dict are as follows: - - boxes (FloatTensor[N, 4]): the predicted boxes in [x1, y1, x2, y2] format, with values of x - between 0 and W and values of y between 0 and H + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (Int64Tensor[N]): the predicted labels for each image - scores (Tensor[N]): the scores or each prediction - masks (UInt8Tensor[N, 1, H, W]): the predicted masks for each instance, in 0-1 range. In order to @@ -279,8 +279,8 @@ def maskrcnn_resnet50_fpn(pretrained=False, progress=True, During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: - - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` - between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (``Int64Tensor[N]``): the class label for each ground-truth box - masks (``UInt8Tensor[N, H, W]``): the segmentation binary masks for each instance @@ -291,8 +291,8 @@ def maskrcnn_resnet50_fpn(pretrained=False, progress=True, predictions as a ``List[Dict[Tensor]]``, one for each input image. The fields of the ``Dict`` are as follows: - - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with values of ``x`` - between ``0`` and ``W`` and values of ``y`` between ``0`` and ``H`` + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (``Int64Tensor[N]``): the predicted labels for each image - scores (``Tensor[N]``): the scores or each prediction - masks (``UInt8Tensor[N, 1, H, W]``): the predicted masks for each instance, in ``0-1`` range. In order to diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index 5c2850e8834..f34db4ce970 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -236,8 +236,8 @@ class RetinaNet(nn.Module): During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: - - boxes (FloatTensor[N, 4]): the ground-truth boxes in [x1, y1, x2, y2] format, with values - between 0 and H and 0 and W + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (Int64Tensor[N]): the class label for each ground-truth box The model returns a Dict[Tensor] during training, containing the classification and regression @@ -246,8 +246,8 @@ class RetinaNet(nn.Module): During inference, the model requires only the input tensors, and returns the post-processed predictions as a List[Dict[Tensor]], one for each input image. The fields of the Dict are as follows: - - boxes (FloatTensor[N, 4]): the predicted boxes in [x1, y1, x2, y2] format, with values between - 0 and H and 0 and W + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (Int64Tensor[N]): the predicted labels for each image - scores (Tensor[N]): the scores for each prediction @@ -576,8 +576,8 @@ def retinanet_resnet50_fpn(pretrained=False, progress=True, During training, the model expects both the input tensors, as well as a targets (list of dictionary), containing: - - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with values - between ``0`` and ``H`` and ``0`` and ``W`` + - boxes (``FloatTensor[N, 4]``): the ground-truth boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (``Int64Tensor[N]``): the class label for each ground-truth box The model returns a ``Dict[Tensor]`` during training, containing the classification and regression @@ -587,8 +587,8 @@ def retinanet_resnet50_fpn(pretrained=False, progress=True, predictions as a ``List[Dict[Tensor]]``, one for each input image. The fields of the ``Dict`` are as follows: - - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with values between - ``0`` and ``H`` and ``0`` and ``W`` + - boxes (``FloatTensor[N, 4]``): the predicted boxes in ``[x1, y1, x2, y2]`` format, with + ``0 <= x1 < x2 <= W`` and ``0 <= y1 < y2 <= H``. - labels (``Int64Tensor[N]``): the predicted labels for each image - scores (``Tensor[N]``): the scores or each prediction diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index 2cb1be93168..cfce618845a 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -22,7 +22,8 @@ def nms(boxes: Tensor, scores: Tensor, iou_threshold: float) -> Tensor: Args: boxes (Tensor[N, 4])): boxes to perform NMS on. They - are expected to be in (x1, y1, x2, y2) format + are expected to be in ``(x1, y1, x2, y2)`` format with ``0 <= x1 < x2`` and + ``0 <= y1 < y2``. scores (Tensor[N]): scores for each one of the boxes iou_threshold (float): discards all overlapping boxes with IoU > iou_threshold @@ -50,7 +51,8 @@ def batched_nms( Args: boxes (Tensor[N, 4]): boxes where NMS will be performed. They - are expected to be in (x1, y1, x2, y2) format + are expected to be in ``(x1, y1, x2, y2)`` format with ``0 <= x1 < x2`` and + ``0 <= y1 < y2``. scores (Tensor[N]): scores for each one of the boxes idxs (Tensor[N]): indices of the categories for each one of the boxes. iou_threshold (float): discards all overlapping boxes with IoU > iou_threshold @@ -79,7 +81,8 @@ def remove_small_boxes(boxes: Tensor, min_size: float) -> Tensor: Remove boxes which contains at least one side smaller than min_size. Args: - boxes (Tensor[N, 4]): boxes in (x1, y1, x2, y2) format + boxes (Tensor[N, 4]): boxes in ``(x1, y1, x2, y2)`` format + with ``0 <= x1 < x2`` and ``0 <= y1 < y2``. min_size (float): minimum size Returns: @@ -97,7 +100,8 @@ def clip_boxes_to_image(boxes: Tensor, size: Tuple[int, int]) -> Tensor: Clip boxes so that they lie inside an image of size `size`. Args: - boxes (Tensor[N, 4]): boxes in (x1, y1, x2, y2) format + boxes (Tensor[N, 4]): boxes in ``(x1, y1, x2, y2)`` format + with ``0 <= x1 < x2`` and ``0 <= y1 < y2``. size (Tuple[height, width]): size of the image Returns: @@ -185,7 +189,8 @@ def box_area(boxes: Tensor) -> Tensor: Args: boxes (Tensor[N, 4]): boxes for which the area will be computed. They - are expected to be in (x1, y1, x2, y2) format + are expected to be in (x1, y1, x2, y2) format with + ``0 <= x1 < x2`` and ``0 <= y1 < y2``. Returns: area (Tensor[N]): area for each box @@ -215,7 +220,8 @@ def box_iou(boxes1: Tensor, boxes2: Tensor) -> Tensor: """ Return intersection-over-union (Jaccard index) of boxes. - Both sets of boxes are expected to be in (x1, y1, x2, y2) format. + Both sets of boxes are expected to be in ``(x1, y1, x2, y2)`` format with + ``0 <= x1 < x2`` and ``0 <= y1 < y2``. Args: boxes1 (Tensor[N, 4]) @@ -234,7 +240,8 @@ def generalized_box_iou(boxes1: Tensor, boxes2: Tensor) -> Tensor: """ Return generalized intersection-over-union (Jaccard index) of boxes. - Both sets of boxes are expected to be in (x1, y1, x2, y2) format. + Both sets of boxes are expected to be in ``(x1, y1, x2, y2)`` format with + ``0 <= x1 < x2`` and ``0 <= y1 < y2``. Args: boxes1 (Tensor[N, 4]) diff --git a/torchvision/ops/poolers.py b/torchvision/ops/poolers.py index 25888afea76..a0ba5b42774 100644 --- a/torchvision/ops/poolers.py +++ b/torchvision/ops/poolers.py @@ -204,7 +204,7 @@ def forward( all the same number of channels, but they can have different sizes. boxes (List[Tensor[N, 4]]): boxes to be used to perform the pooling operation, in (x1, y1, x2, y2) format and in the image reference size, not the feature map - reference. + reference. The coordinate must satisfy ``0 <= x1 < x2`` and ``0 <= y1 < y2``. image_shapes (List[Tuple[height, width]]): the sizes of each image before they have been fed to a CNN to obtain feature maps. This allows us to infer the scale factor for each one of the levels to be pooled. diff --git a/torchvision/ops/ps_roi_align.py b/torchvision/ops/ps_roi_align.py index 46bcdbe4d91..d14f429785a 100644 --- a/torchvision/ops/ps_roi_align.py +++ b/torchvision/ops/ps_roi_align.py @@ -21,7 +21,9 @@ def ps_roi_align( Args: input (Tensor[N, C, H, W]): input tensor boxes (Tensor[K, 5] or List[Tensor[L, 4]]): the box coordinates in (x1, y1, x2, y2) - format where the regions will be taken from. If a single Tensor is passed, + format where the regions will be taken from. + The coordinate must satisfy ``0 <= x1 < x2`` and ``0 <= y1 < y2``. + If a single Tensor is passed, then the first column should contain the batch index. If a list of Tensors is passed, then each Tensor will correspond to the boxes for an element i in a batch diff --git a/torchvision/ops/ps_roi_pool.py b/torchvision/ops/ps_roi_pool.py index f434fbd0b9f..8c07eb864a8 100644 --- a/torchvision/ops/ps_roi_pool.py +++ b/torchvision/ops/ps_roi_pool.py @@ -20,7 +20,9 @@ def ps_roi_pool( Args: input (Tensor[N, C, H, W]): input tensor boxes (Tensor[K, 5] or List[Tensor[L, 4]]): the box coordinates in (x1, y1, x2, y2) - format where the regions will be taken from. If a single Tensor is passed, + format where the regions will be taken from. + The coordinate must satisfy ``0 <= x1 < x2`` and ``0 <= y1 < y2``. + If a single Tensor is passed, then the first column should contain the batch index. If a list of Tensors is passed, then each Tensor will correspond to the boxes for an element i in a batch diff --git a/torchvision/ops/roi_align.py b/torchvision/ops/roi_align.py index 81453ff921a..0f6c0be1729 100644 --- a/torchvision/ops/roi_align.py +++ b/torchvision/ops/roi_align.py @@ -22,7 +22,9 @@ def roi_align( Args: input (Tensor[N, C, H, W]): input tensor boxes (Tensor[K, 5] or List[Tensor[L, 4]]): the box coordinates in (x1, y1, x2, y2) - format where the regions will be taken from. If a single Tensor is passed, + format where the regions will be taken from. + The coordinate must satisfy ``0 <= x1 < x2`` and ``0 <= y1 < y2``. + If a single Tensor is passed, then the first column should contain the batch index. If a list of Tensors is passed, then each Tensor will correspond to the boxes for an element i in a batch diff --git a/torchvision/ops/roi_pool.py b/torchvision/ops/roi_pool.py index 9c150099455..fce6392fbfd 100644 --- a/torchvision/ops/roi_pool.py +++ b/torchvision/ops/roi_pool.py @@ -20,7 +20,9 @@ def roi_pool( Args: input (Tensor[N, C, H, W]): input tensor boxes (Tensor[K, 5] or List[Tensor[L, 4]]): the box coordinates in (x1, y1, x2, y2) - format where the regions will be taken from. If a single Tensor is passed, + format where the regions will be taken from. + The coordinate must satisfy ``0 <= x1 < x2`` and ``0 <= y1 < y2``. + If a single Tensor is passed, then the first column should contain the batch index. If a list of Tensors is passed, then each Tensor will correspond to the boxes for an element i in a batch From 8a12399c3d5487d05fbca252a4212e3fd31779da Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 241/357] .circleci: Downgrade CUDA 11.2 -> 11.1 (#3418) Reviewed By: NicolasHug Differential Revision: D26605322 fbshipit-source-id: 1dfe157d2094c1186c74b22eb1184d7fa498cc3f --- .circleci/config.yml | 337 ++++++++++---------- .circleci/config.yml.in | 1 + .circleci/regenerate.py | 6 +- packaging/pkg_helpers.bash | 17 + packaging/torchvision/meta.yaml | 6 +- packaging/windows/internal/cuda_install.bat | 22 ++ 6 files changed, 214 insertions(+), 175 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1534625792c..1f375c55d16 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -216,6 +216,7 @@ jobs: - designate_upload_channel - run: name: Build conda packages + no_output_timeout: 20m command: | set -ex source packaging/windows/internal/vc_install_helper.sh @@ -825,11 +826,11 @@ workflows: python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 - name: binary_linux_wheel_py3.6_cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 + name: binary_linux_wheel_py3.6_cu111 python_version: '3.6' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -849,11 +850,11 @@ workflows: python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 - name: binary_linux_wheel_py3.7_cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 + name: binary_linux_wheel_py3.7_cu111 python_version: '3.7' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -873,11 +874,11 @@ workflows: python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 - name: binary_linux_wheel_py3.8_cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 + name: binary_linux_wheel_py3.8_cu111 python_version: '3.8' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -897,11 +898,11 @@ workflows: python_version: '3.9' wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_wheel: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 - name: binary_linux_wheel_py3.9_cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 + name: binary_linux_wheel_py3.9_cu111 python_version: '3.9' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_macos_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -954,13 +955,13 @@ workflows: name: binary_win_wheel_py3.6_cu102 python_version: '3.6' - binary_win_wheel: - cu_version: cu112 + cu_version: cu111 filters: branches: only: master tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: binary_win_wheel_py3.6_cu112 + name: binary_win_wheel_py3.6_cu111 python_version: '3.6' - binary_win_wheel: cu_version: cpu @@ -990,13 +991,13 @@ workflows: name: binary_win_wheel_py3.7_cu102 python_version: '3.7' - binary_win_wheel: - cu_version: cu112 + cu_version: cu111 filters: branches: only: master tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: binary_win_wheel_py3.7_cu112 + name: binary_win_wheel_py3.7_cu111 python_version: '3.7' - binary_win_wheel: cu_version: cpu @@ -1026,13 +1027,13 @@ workflows: name: binary_win_wheel_py3.8_cu102 python_version: '3.8' - binary_win_wheel: - cu_version: cu112 + cu_version: cu111 filters: branches: only: master tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: binary_win_wheel_py3.8_cu112 + name: binary_win_wheel_py3.8_cu111 python_version: '3.8' - binary_win_wheel: cu_version: cpu @@ -1057,8 +1058,8 @@ workflows: name: binary_win_wheel_py3.9_cu102 python_version: '3.9' - binary_win_wheel: - cu_version: cu112 - name: binary_win_wheel_py3.9_cu112 + cu_version: cu111 + name: binary_win_wheel_py3.9_cu111 python_version: '3.9' - binary_linux_conda: conda_docker_image: pytorch/conda-builder:cpu @@ -1079,11 +1080,11 @@ workflows: python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 - name: binary_linux_conda_py3.6_cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 + name: binary_linux_conda_py3.6_cu111 python_version: '3.6' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_linux_conda: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1103,11 +1104,11 @@ workflows: python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 - name: binary_linux_conda_py3.7_cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 + name: binary_linux_conda_py3.7_cu111 python_version: '3.7' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_linux_conda: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1127,11 +1128,11 @@ workflows: python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 - name: binary_linux_conda_py3.8_cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 + name: binary_linux_conda_py3.8_cu111 python_version: '3.8' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_linux_conda: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1151,11 +1152,11 @@ workflows: python_version: '3.9' wheel_docker_image: pytorch/manylinux-cuda102 - binary_linux_conda: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 - name: binary_linux_conda_py3.9_cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 + name: binary_linux_conda_py3.9_cu111 python_version: '3.9' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_macos_conda: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1208,13 +1209,13 @@ workflows: name: binary_win_conda_py3.6_cu102 python_version: '3.6' - binary_win_conda: - cu_version: cu112 + cu_version: cu111 filters: branches: only: master tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: binary_win_conda_py3.6_cu112 + name: binary_win_conda_py3.6_cu111 python_version: '3.6' - binary_win_conda: cu_version: cpu @@ -1244,13 +1245,13 @@ workflows: name: binary_win_conda_py3.7_cu102 python_version: '3.7' - binary_win_conda: - cu_version: cu112 + cu_version: cu111 filters: branches: only: master tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: binary_win_conda_py3.7_cu112 + name: binary_win_conda_py3.7_cu111 python_version: '3.7' - binary_win_conda: cu_version: cpu @@ -1280,13 +1281,13 @@ workflows: name: binary_win_conda_py3.8_cu102 python_version: '3.8' - binary_win_conda: - cu_version: cu112 + cu_version: cu111 filters: branches: only: master tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: binary_win_conda_py3.8_cu112 + name: binary_win_conda_py3.8_cu111 python_version: '3.8' - binary_win_conda: cu_version: cpu @@ -1311,8 +1312,8 @@ workflows: name: binary_win_conda_py3.9_cu102 python_version: '3.9' - binary_win_conda: - cu_version: cu112 - name: binary_win_conda_py3.9_cu112 + cu_version: cu111 + name: binary_win_conda_py3.9_cu111 python_version: '3.9' - build_docs: name: build_docs @@ -1578,16 +1579,16 @@ workflows: requires: - nightly_binary_linux_wheel_py3.6_cu102_upload - binary_linux_wheel: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.6_cu112 + name: nightly_binary_linux_wheel_py3.6_cu111 python_version: '3.6' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_wheel_upload: context: org-member filters: @@ -1595,19 +1596,19 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.6_cu112_upload + name: nightly_binary_linux_wheel_py3.6_cu111_upload requires: - - nightly_binary_linux_wheel_py3.6_cu112 - subfolder: cu112/ + - nightly_binary_linux_wheel_py3.6_cu111 + subfolder: cu111/ - smoke_test_linux_pip: filters: branches: only: - nightly - name: nightly_binary_linux_wheel_py3.6_cu112_smoke_test_pip + name: nightly_binary_linux_wheel_py3.6_cu111_smoke_test_pip python_version: '3.6' requires: - - nightly_binary_linux_wheel_py3.6_cu112_upload + - nightly_binary_linux_wheel_py3.6_cu111_upload - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1702,16 +1703,16 @@ workflows: requires: - nightly_binary_linux_wheel_py3.7_cu102_upload - binary_linux_wheel: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.7_cu112 + name: nightly_binary_linux_wheel_py3.7_cu111 python_version: '3.7' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_wheel_upload: context: org-member filters: @@ -1719,19 +1720,19 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.7_cu112_upload + name: nightly_binary_linux_wheel_py3.7_cu111_upload requires: - - nightly_binary_linux_wheel_py3.7_cu112 - subfolder: cu112/ + - nightly_binary_linux_wheel_py3.7_cu111 + subfolder: cu111/ - smoke_test_linux_pip: filters: branches: only: - nightly - name: nightly_binary_linux_wheel_py3.7_cu112_smoke_test_pip + name: nightly_binary_linux_wheel_py3.7_cu111_smoke_test_pip python_version: '3.7' requires: - - nightly_binary_linux_wheel_py3.7_cu112_upload + - nightly_binary_linux_wheel_py3.7_cu111_upload - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1826,16 +1827,16 @@ workflows: requires: - nightly_binary_linux_wheel_py3.8_cu102_upload - binary_linux_wheel: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.8_cu112 + name: nightly_binary_linux_wheel_py3.8_cu111 python_version: '3.8' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_wheel_upload: context: org-member filters: @@ -1843,19 +1844,19 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.8_cu112_upload + name: nightly_binary_linux_wheel_py3.8_cu111_upload requires: - - nightly_binary_linux_wheel_py3.8_cu112 - subfolder: cu112/ + - nightly_binary_linux_wheel_py3.8_cu111 + subfolder: cu111/ - smoke_test_linux_pip: filters: branches: only: - nightly - name: nightly_binary_linux_wheel_py3.8_cu112_smoke_test_pip + name: nightly_binary_linux_wheel_py3.8_cu111_smoke_test_pip python_version: '3.8' requires: - - nightly_binary_linux_wheel_py3.8_cu112_upload + - nightly_binary_linux_wheel_py3.8_cu111_upload - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1950,16 +1951,16 @@ workflows: requires: - nightly_binary_linux_wheel_py3.9_cu102_upload - binary_linux_wheel: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.9_cu112 + name: nightly_binary_linux_wheel_py3.9_cu111 python_version: '3.9' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_wheel_upload: context: org-member filters: @@ -1967,19 +1968,19 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_wheel_py3.9_cu112_upload + name: nightly_binary_linux_wheel_py3.9_cu111_upload requires: - - nightly_binary_linux_wheel_py3.9_cu112 - subfolder: cu112/ + - nightly_binary_linux_wheel_py3.9_cu111 + subfolder: cu111/ - smoke_test_linux_pip: filters: branches: only: - nightly - name: nightly_binary_linux_wheel_py3.9_cu112_smoke_test_pip + name: nightly_binary_linux_wheel_py3.9_cu111_smoke_test_pip python_version: '3.9' requires: - - nightly_binary_linux_wheel_py3.9_cu112_upload + - nightly_binary_linux_wheel_py3.9_cu111_upload - binary_macos_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -2156,13 +2157,13 @@ workflows: requires: - nightly_binary_win_wheel_py3.6_cu102_upload - binary_win_wheel: - cu_version: cu112 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.6_cu112 + name: nightly_binary_win_wheel_py3.6_cu111 python_version: '3.6' - binary_wheel_upload: context: org-member @@ -2171,19 +2172,19 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.6_cu112_upload + name: nightly_binary_win_wheel_py3.6_cu111_upload requires: - - nightly_binary_win_wheel_py3.6_cu112 - subfolder: cu112/ + - nightly_binary_win_wheel_py3.6_cu111 + subfolder: cu111/ - smoke_test_win_pip: filters: branches: only: - nightly - name: nightly_binary_win_wheel_py3.6_cu112_smoke_test_pip + name: nightly_binary_win_wheel_py3.6_cu111_smoke_test_pip python_version: '3.6' requires: - - nightly_binary_win_wheel_py3.6_cu112_upload + - nightly_binary_win_wheel_py3.6_cu111_upload - binary_win_wheel: cu_version: cpu filters: @@ -2272,13 +2273,13 @@ workflows: requires: - nightly_binary_win_wheel_py3.7_cu102_upload - binary_win_wheel: - cu_version: cu112 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.7_cu112 + name: nightly_binary_win_wheel_py3.7_cu111 python_version: '3.7' - binary_wheel_upload: context: org-member @@ -2287,19 +2288,19 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.7_cu112_upload + name: nightly_binary_win_wheel_py3.7_cu111_upload requires: - - nightly_binary_win_wheel_py3.7_cu112 - subfolder: cu112/ + - nightly_binary_win_wheel_py3.7_cu111 + subfolder: cu111/ - smoke_test_win_pip: filters: branches: only: - nightly - name: nightly_binary_win_wheel_py3.7_cu112_smoke_test_pip + name: nightly_binary_win_wheel_py3.7_cu111_smoke_test_pip python_version: '3.7' requires: - - nightly_binary_win_wheel_py3.7_cu112_upload + - nightly_binary_win_wheel_py3.7_cu111_upload - binary_win_wheel: cu_version: cpu filters: @@ -2388,13 +2389,13 @@ workflows: requires: - nightly_binary_win_wheel_py3.8_cu102_upload - binary_win_wheel: - cu_version: cu112 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.8_cu112 + name: nightly_binary_win_wheel_py3.8_cu111 python_version: '3.8' - binary_wheel_upload: context: org-member @@ -2403,19 +2404,19 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.8_cu112_upload + name: nightly_binary_win_wheel_py3.8_cu111_upload requires: - - nightly_binary_win_wheel_py3.8_cu112 - subfolder: cu112/ + - nightly_binary_win_wheel_py3.8_cu111 + subfolder: cu111/ - smoke_test_win_pip: filters: branches: only: - nightly - name: nightly_binary_win_wheel_py3.8_cu112_smoke_test_pip + name: nightly_binary_win_wheel_py3.8_cu111_smoke_test_pip python_version: '3.8' requires: - - nightly_binary_win_wheel_py3.8_cu112_upload + - nightly_binary_win_wheel_py3.8_cu111_upload - binary_win_wheel: cu_version: cpu filters: @@ -2504,13 +2505,13 @@ workflows: requires: - nightly_binary_win_wheel_py3.9_cu102_upload - binary_win_wheel: - cu_version: cu112 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.9_cu112 + name: nightly_binary_win_wheel_py3.9_cu111 python_version: '3.9' - binary_wheel_upload: context: org-member @@ -2519,19 +2520,19 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_wheel_py3.9_cu112_upload + name: nightly_binary_win_wheel_py3.9_cu111_upload requires: - - nightly_binary_win_wheel_py3.9_cu112 - subfolder: cu112/ + - nightly_binary_win_wheel_py3.9_cu111 + subfolder: cu111/ - smoke_test_win_pip: filters: branches: only: - nightly - name: nightly_binary_win_wheel_py3.9_cu112_smoke_test_pip + name: nightly_binary_win_wheel_py3.9_cu111_smoke_test_pip python_version: '3.9' requires: - - nightly_binary_win_wheel_py3.9_cu112_upload + - nightly_binary_win_wheel_py3.9_cu111_upload - binary_linux_conda: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -2623,16 +2624,16 @@ workflows: requires: - nightly_binary_linux_conda_py3.6_cu102_upload - binary_linux_conda: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.6_cu112 + name: nightly_binary_linux_conda_py3.6_cu111 python_version: '3.6' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_conda_upload: context: org-member filters: @@ -2640,18 +2641,18 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.6_cu112_upload + name: nightly_binary_linux_conda_py3.6_cu111_upload requires: - - nightly_binary_linux_conda_py3.6_cu112 + - nightly_binary_linux_conda_py3.6_cu111 - smoke_test_linux_conda: filters: branches: only: - nightly - name: nightly_binary_linux_conda_py3.6_cu112_smoke_test_conda + name: nightly_binary_linux_conda_py3.6_cu111_smoke_test_conda python_version: '3.6' requires: - - nightly_binary_linux_conda_py3.6_cu112_upload + - nightly_binary_linux_conda_py3.6_cu111_upload - binary_linux_conda: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -2743,16 +2744,16 @@ workflows: requires: - nightly_binary_linux_conda_py3.7_cu102_upload - binary_linux_conda: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.7_cu112 + name: nightly_binary_linux_conda_py3.7_cu111 python_version: '3.7' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_conda_upload: context: org-member filters: @@ -2760,18 +2761,18 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.7_cu112_upload + name: nightly_binary_linux_conda_py3.7_cu111_upload requires: - - nightly_binary_linux_conda_py3.7_cu112 + - nightly_binary_linux_conda_py3.7_cu111 - smoke_test_linux_conda: filters: branches: only: - nightly - name: nightly_binary_linux_conda_py3.7_cu112_smoke_test_conda + name: nightly_binary_linux_conda_py3.7_cu111_smoke_test_conda python_version: '3.7' requires: - - nightly_binary_linux_conda_py3.7_cu112_upload + - nightly_binary_linux_conda_py3.7_cu111_upload - binary_linux_conda: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -2863,16 +2864,16 @@ workflows: requires: - nightly_binary_linux_conda_py3.8_cu102_upload - binary_linux_conda: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.8_cu112 + name: nightly_binary_linux_conda_py3.8_cu111 python_version: '3.8' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_conda_upload: context: org-member filters: @@ -2880,18 +2881,18 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.8_cu112_upload + name: nightly_binary_linux_conda_py3.8_cu111_upload requires: - - nightly_binary_linux_conda_py3.8_cu112 + - nightly_binary_linux_conda_py3.8_cu111 - smoke_test_linux_conda: filters: branches: only: - nightly - name: nightly_binary_linux_conda_py3.8_cu112_smoke_test_conda + name: nightly_binary_linux_conda_py3.8_cu111_smoke_test_conda python_version: '3.8' requires: - - nightly_binary_linux_conda_py3.8_cu112_upload + - nightly_binary_linux_conda_py3.8_cu111_upload - binary_linux_conda: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -2983,16 +2984,16 @@ workflows: requires: - nightly_binary_linux_conda_py3.9_cu102_upload - binary_linux_conda: - conda_docker_image: pytorch/conda-builder:cuda112 - cu_version: cu112 + conda_docker_image: pytorch/conda-builder:cuda111 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.9_cu112 + name: nightly_binary_linux_conda_py3.9_cu111 python_version: '3.9' - wheel_docker_image: pytorch/manylinux-cuda112 + wheel_docker_image: pytorch/manylinux-cuda111 - binary_conda_upload: context: org-member filters: @@ -3000,18 +3001,18 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_linux_conda_py3.9_cu112_upload + name: nightly_binary_linux_conda_py3.9_cu111_upload requires: - - nightly_binary_linux_conda_py3.9_cu112 + - nightly_binary_linux_conda_py3.9_cu111 - smoke_test_linux_conda: filters: branches: only: - nightly - name: nightly_binary_linux_conda_py3.9_cu112_smoke_test_conda + name: nightly_binary_linux_conda_py3.9_cu111_smoke_test_conda python_version: '3.9' requires: - - nightly_binary_linux_conda_py3.9_cu112_upload + - nightly_binary_linux_conda_py3.9_cu111_upload - binary_macos_conda: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -3181,13 +3182,13 @@ workflows: requires: - nightly_binary_win_conda_py3.6_cu102_upload - binary_win_conda: - cu_version: cu112 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.6_cu112 + name: nightly_binary_win_conda_py3.6_cu111 python_version: '3.6' - binary_conda_upload: context: org-member @@ -3196,18 +3197,18 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.6_cu112_upload + name: nightly_binary_win_conda_py3.6_cu111_upload requires: - - nightly_binary_win_conda_py3.6_cu112 + - nightly_binary_win_conda_py3.6_cu111 - smoke_test_win_conda: filters: branches: only: - nightly - name: nightly_binary_win_conda_py3.6_cu112_smoke_test_conda + name: nightly_binary_win_conda_py3.6_cu111_smoke_test_conda python_version: '3.6' requires: - - nightly_binary_win_conda_py3.6_cu112_upload + - nightly_binary_win_conda_py3.6_cu111_upload - binary_win_conda: cu_version: cpu filters: @@ -3293,13 +3294,13 @@ workflows: requires: - nightly_binary_win_conda_py3.7_cu102_upload - binary_win_conda: - cu_version: cu112 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.7_cu112 + name: nightly_binary_win_conda_py3.7_cu111 python_version: '3.7' - binary_conda_upload: context: org-member @@ -3308,18 +3309,18 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.7_cu112_upload + name: nightly_binary_win_conda_py3.7_cu111_upload requires: - - nightly_binary_win_conda_py3.7_cu112 + - nightly_binary_win_conda_py3.7_cu111 - smoke_test_win_conda: filters: branches: only: - nightly - name: nightly_binary_win_conda_py3.7_cu112_smoke_test_conda + name: nightly_binary_win_conda_py3.7_cu111_smoke_test_conda python_version: '3.7' requires: - - nightly_binary_win_conda_py3.7_cu112_upload + - nightly_binary_win_conda_py3.7_cu111_upload - binary_win_conda: cu_version: cpu filters: @@ -3405,13 +3406,13 @@ workflows: requires: - nightly_binary_win_conda_py3.8_cu102_upload - binary_win_conda: - cu_version: cu112 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.8_cu112 + name: nightly_binary_win_conda_py3.8_cu111 python_version: '3.8' - binary_conda_upload: context: org-member @@ -3420,18 +3421,18 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.8_cu112_upload + name: nightly_binary_win_conda_py3.8_cu111_upload requires: - - nightly_binary_win_conda_py3.8_cu112 + - nightly_binary_win_conda_py3.8_cu111 - smoke_test_win_conda: filters: branches: only: - nightly - name: nightly_binary_win_conda_py3.8_cu112_smoke_test_conda + name: nightly_binary_win_conda_py3.8_cu111_smoke_test_conda python_version: '3.8' requires: - - nightly_binary_win_conda_py3.8_cu112_upload + - nightly_binary_win_conda_py3.8_cu111_upload - binary_win_conda: cu_version: cpu filters: @@ -3517,13 +3518,13 @@ workflows: requires: - nightly_binary_win_conda_py3.9_cu102_upload - binary_win_conda: - cu_version: cu112 + cu_version: cu111 filters: branches: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.9_cu112 + name: nightly_binary_win_conda_py3.9_cu111 python_version: '3.9' - binary_conda_upload: context: org-member @@ -3532,18 +3533,18 @@ workflows: only: nightly tags: only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ - name: nightly_binary_win_conda_py3.9_cu112_upload + name: nightly_binary_win_conda_py3.9_cu111_upload requires: - - nightly_binary_win_conda_py3.9_cu112 + - nightly_binary_win_conda_py3.9_cu111 - smoke_test_win_conda: filters: branches: only: - nightly - name: nightly_binary_win_conda_py3.9_cu112_smoke_test_conda + name: nightly_binary_win_conda_py3.9_cu111_smoke_test_conda python_version: '3.9' requires: - - nightly_binary_win_conda_py3.9_cu112_upload + - nightly_binary_win_conda_py3.9_cu111_upload docker_build: triggers: - schedule: diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 50f26e72504..567fb9c756c 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -216,6 +216,7 @@ jobs: - designate_upload_channel - run: name: Build conda packages + no_output_timeout: 20m command: | set -ex source packaging/windows/internal/vc_install_helper.sh diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index ec83c5b501d..6dbc0648d6f 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -20,7 +20,6 @@ PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] -CUDA_VERSION = ["10.1", "10.2", "11.2"] RC_PATTERN = r"/v[0-9]+(\.[0-9]+)*-rc[0-9]+/" @@ -30,8 +29,8 @@ def build_workflows(prefix='', filter_branch=None, upload=False, indentation=6, for btype in ["wheel", "conda"]: for os_type in ["linux", "macos", "win"]: python_versions = PYTHON_VERSIONS - cu_versions_dict = {"linux": ["cpu", "cu101", "cu102", "cu112"], - "win": ["cpu", "cu101", "cu102", "cu112"], + cu_versions_dict = {"linux": ["cpu", "cu101", "cu102", "cu111"], + "win": ["cpu", "cu101", "cu102", "cu111"], "macos": ["cpu"]} cu_versions = cu_versions_dict[os_type] for python_version in python_versions: @@ -103,6 +102,7 @@ def upload_doc_job(filter_branch): "cu101": "pytorch/manylinux-cuda101", "cu102": "pytorch/manylinux-cuda102", "cu110": "pytorch/manylinux-cuda110", + "cu111": "pytorch/manylinux-cuda111", "cu112": "pytorch/manylinux-cuda112", } diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index 0c205ab81ac..c5e55423c79 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -60,6 +60,17 @@ setup_cuda() { # https://github.com/pytorch/pytorch/pull/23408 lands export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_80,code=sm_80 -gencode=arch=compute_86,code=sm_86 -gencode=arch=compute_50,code=compute_50" ;; + cu111) + if [[ "$OSTYPE" == "msys" ]]; then + export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.1" + else + export CUDA_HOME=/usr/local/cuda-11.1/ + fi + export FORCE_CUDA=1 + # Hard-coding gencode flags is temporary situation until + # https://github.com/pytorch/pytorch/pull/23408 lands + export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_80,code=sm_80 -gencode=arch=compute_86,code=sm_86 -gencode=arch=compute_50,code=compute_50" + ;; cu110) if [[ "$OSTYPE" == "msys" ]]; then export CUDA_HOME="C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v11.0" @@ -293,6 +304,9 @@ setup_conda_cudatoolkit_constraint() { cu112) export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=11.2,<11.3 # [not osx]" ;; + cu111) + export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=11.1,<11.2 # [not osx]" + ;; cu110) export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=11.0,<11.1 # [not osx]" ;; @@ -331,6 +345,9 @@ setup_conda_cudatoolkit_plain_constraint() { cu112) export CONDA_CUDATOOLKIT_CONSTRAINT="cudatoolkit=11.2" ;; + cu111) + export CONDA_CUDATOOLKIT_CONSTRAINT="cudatoolkit=11.1" + ;; cu102) export CONDA_CUDATOOLKIT_CONSTRAINT="cudatoolkit=10.2" ;; diff --git a/packaging/torchvision/meta.yaml b/packaging/torchvision/meta.yaml index 12f35c116be..834648c07dc 100644 --- a/packaging/torchvision/meta.yaml +++ b/packaging/torchvision/meta.yaml @@ -16,8 +16,7 @@ requirements: host: - python - setuptools - - numpy >=1.20 # [py>=39] - - numpy >=1.11 # [py!=39] + - defaults::numpy >=1.11 {{ environ.get('CONDA_PYTORCH_BUILD_CONSTRAINT') }} {{ environ.get('CONDA_CUDATOOLKIT_CONSTRAINT') }} {{ environ.get('CONDA_CPUONLY_FEATURE') }} @@ -28,8 +27,7 @@ requirements: - ffmpeg >=4.2 # [not win] - jpeg <=9b - pillow >=4.1.1 - - numpy >=1.20 # [py>=39] - - numpy >=1.11 # [py!=39] + - defaults::numpy >=1.11 {{ environ.get('CONDA_PYTORCH_CONSTRAINT') }} {{ environ.get('CONDA_CUDATOOLKIT_CONSTRAINT') }} diff --git a/packaging/windows/internal/cuda_install.bat b/packaging/windows/internal/cuda_install.bat index 2d1611c6fd7..9ca08e1cfbb 100644 --- a/packaging/windows/internal/cuda_install.bat +++ b/packaging/windows/internal/cuda_install.bat @@ -19,6 +19,7 @@ if %CUDA_VER% EQU 100 goto cuda100 if %CUDA_VER% EQU 101 goto cuda101 if %CUDA_VER% EQU 102 goto cuda102 if %CUDA_VER% EQU 110 goto cuda110 +if %CUDA_VER% EQU 111 goto cuda111 if %CUDA_VER% EQU 112 goto cuda112 echo CUDA %CUDA_VERSION_STR% is not supported @@ -108,6 +109,27 @@ if not exist "%SRC_DIR%\temp_build\cudnn-11.0-windows-x64-v8.0.4.30.zip" ( goto cuda_common +:cuda111 + +if not exist "%SRC_DIR%\temp_build\cuda_11.1.0_456.43_win10.exe" ( + curl -k -L https://ossci-windows.s3.amazonaws.com/cuda_11.1.0_456.43_win10.exe --output "%SRC_DIR%\temp_build\cuda_11.1.0_456.43_win10.exe" + if errorlevel 1 exit /b 1 + set "CUDA_SETUP_FILE=%SRC_DIR%\temp_build\cuda_11.1.0_456.43_win10.exe" + set "ARGS=nvcc_11.1 cuobjdump_11.1 nvprune_11.1 nvprof_11.1 cupti_11.1 cublas_11.1 cublas_dev_11.1 cudart_11.1 cufft_11.1 cufft_dev_11.1 curand_11.1 curand_dev_11.1 cusolver_11.1 cusolver_dev_11.1 cusparse_11.1 cusparse_dev_11.1 npp_11.1 npp_dev_11.1 nvrtc_11.1 nvrtc_dev_11.1 nvml_dev_11.1" +) + +@REM There is no downloadable driver for Tesla on CUDA 11.1 yet. We will use +@REM the driver inside CUDA +if "%JOB_EXECUTOR%" == "windows-with-nvidia-gpu" set "ARGS=%ARGS% Display.Driver" + +if not exist "%SRC_DIR%\temp_build\cudnn-11.1-windows-x64-v8.0.5.39.zip" ( + curl -k -L https://ossci-windows.s3.amazonaws.com/cudnn-11.1-windows-x64-v8.0.5.39.zip --output "%SRC_DIR%\temp_build\cudnn-11.1-windows-x64-v8.0.5.39.zip" + if errorlevel 1 exit /b 1 + set "CUDNN_SETUP_FILE=%SRC_DIR%\temp_build\cudnn-11.1-windows-x64-v8.0.5.39.zip" +) + +goto cuda_common + :cuda112 if not exist "%SRC_DIR%\temp_build\cuda_11.2.0_460.89_win10.exe" ( From fb8414b794635dff4eaa79c60fafeebd208ebf25 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 23 Feb 2021 09:12:52 -0800 Subject: [PATCH 242/357] Put back call to optimze_for_mobile (#3431) Summary: * put back * flake8 Reviewed By: NicolasHug Differential Revision: D26605313 fbshipit-source-id: 6bf2177761b181e285320eaee2fc0d0fb1f092cc --- android/test_app/make_assets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/test_app/make_assets.py b/android/test_app/make_assets.py index ce5059b46ee..7860c759a57 100644 --- a/android/test_app/make_assets.py +++ b/android/test_app/make_assets.py @@ -1,5 +1,6 @@ import torch import torchvision +from torch.utils.mobile_optimizer import optimize_for_mobile print(torch.__version__) @@ -12,6 +13,5 @@ model.eval() script_model = torch.jit.script(model) -# TODO: put back call to optimize_for_mobile once -# https://github.com/pytorch/pytorch/issues/52463 is fixed -script_model.save("app/src/main/assets/frcnn_mnetv3.pt") +opt_script_model = optimize_for_mobile(script_model) +opt_script_model.save("app/src/main/assets/frcnn_mnetv3.pt") From d98711d01c1d311737b07c357f3b695414af1604 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 243/357] Add tests for UCF101 (#3411) Summary: * enable default frames per clips for video test cases * add tests for UCF101 * remove old tests as well as fake data generation * better explain frames_per_clip overriding * lint Reviewed By: fmassa Differential Revision: D26756269 fbshipit-source-id: c3a6ae69a0e3155864bd3d09556a99f7f6771953 Co-authored-by: Francisco Massa --- test/datasets_utils.py | 34 +++++++++++++++- test/fakedata_generation.py | 44 --------------------- test/test_datasets.py | 77 +++++++++++++++++++++++++------------ 3 files changed, 85 insertions(+), 70 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index aa3e3f61be3..5789c8620dc 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -496,14 +496,44 @@ def new(fp, *args, **kwargs): class VideoDatasetTestCase(DatasetTestCase): """Abstract base class for video dataset testcases. - - Overwrites the FEATURE_TYPES class attribute to expect two :class:`torch.Tensor` s for the video and audio as + - Overwrites the 'FEATURE_TYPES' class attribute to expect two :class:`torch.Tensor` s for the video and audio as well as an integer label. - - Overwrites the REQUIRED_PACKAGES class attribute to require PyAV (``av``). + - Overwrites the 'REQUIRED_PACKAGES' class attribute to require PyAV (``av``). + - Adds the 'DEFAULT_FRAMES_PER_CLIP' class attribute. If no 'frames_per_clip' is provided by 'inject_fake_data()' + and it is the last parameter without a default value in the dataset constructor, the value of the + 'DEFAULT_FRAMES_PER_CLIP' class attribute is appended to the output. """ FEATURE_TYPES = (torch.Tensor, torch.Tensor, int) REQUIRED_PACKAGES = ("av",) + DEFAULT_FRAMES_PER_CLIP = 1 + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.inject_fake_data = self._set_default_frames_per_clip(self.inject_fake_data) + + def _set_default_frames_per_clip(self, inject_fake_data): + argspec = inspect.getfullargspec(self.DATASET_CLASS.__init__) + args_without_default = argspec.args[1:-len(argspec.defaults)] + frames_per_clip_last = args_without_default[-1] == "frames_per_clip" + only_root_and_frames_per_clip = (len(args_without_default) == 2) and frames_per_clip_last + + @functools.wraps(inject_fake_data) + def wrapper(tmpdir, config): + output = inject_fake_data(tmpdir, config) + if isinstance(output, collections.abc.Sequence) and len(output) == 2: + args, info = output + if frames_per_clip_last and len(args) == len(args_without_default) - 1: + args = (*args, self.DEFAULT_FRAMES_PER_CLIP) + return args, info + elif isinstance(output, (int, dict)) and only_root_and_frames_per_clip: + return (tmpdir, self.DEFAULT_FRAMES_PER_CLIP) + else: + return output + + return wrapper + def create_image_or_video_tensor(size: Sequence[int]) -> torch.Tensor: r"""Create a random uint8 tensor. diff --git a/test/fakedata_generation.py b/test/fakedata_generation.py index cdd6683b22b..dac415df110 100644 --- a/test/fakedata_generation.py +++ b/test/fakedata_generation.py @@ -369,50 +369,6 @@ def _make_mat(file): yield root -@contextlib.contextmanager -def ucf101_root(): - with get_tmp_dir() as tmp_dir: - ucf_dir = os.path.join(tmp_dir, 'UCF-101') - video_dir = os.path.join(ucf_dir, 'video') - annotations = os.path.join(ucf_dir, 'annotations') - - os.makedirs(ucf_dir) - os.makedirs(video_dir) - os.makedirs(annotations) - - fold_files = [] - for split in {'train', 'test'}: - for fold in range(1, 4): - fold_file = '{:s}list{:02d}.txt'.format(split, fold) - fold_files.append(os.path.join(annotations, fold_file)) - - file_handles = [open(x, 'w') for x in fold_files] - file_iter = cycle(file_handles) - - for i in range(0, 2): - current_class = 'class_{0}'.format(i + 1) - class_dir = os.path.join(video_dir, current_class) - os.makedirs(class_dir) - for group in range(0, 3): - for clip in range(0, 4): - # Save sample file - clip_name = 'v_{0}_g{1}_c{2}.avi'.format( - current_class, group, clip) - clip_path = os.path.join(class_dir, clip_name) - length = random.randrange(10, 21) - this_clip = torch.randint( - 0, 256, (length * 25, 320, 240, 3), dtype=torch.uint8) - write_video(clip_path, this_clip, 25) - # Add to annotations - ann_file = next(file_iter) - ann_file.write('{0}\n'.format( - os.path.join(current_class, clip_name))) - # Close all file descriptors - for f in file_handles: - f.close() - yield (video_dir, annotations) - - @contextlib.contextmanager def places365_root(split="train-standard", small=False): VARIANTS = { diff --git a/test/test_datasets.py b/test/test_datasets.py index 265aa9b80dc..37651ae7614 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -11,7 +11,7 @@ from torchvision.datasets import utils from common_utils import get_tmp_dir from fakedata_generation import mnist_root, cifar_root, imagenet_root, \ - cityscapes_root, svhn_root, ucf101_root, places365_root, widerface_root, stl10_root + cityscapes_root, svhn_root, places365_root, widerface_root, stl10_root import xml.etree.ElementTree as ET from urllib.request import Request, urlopen import itertools @@ -22,6 +22,7 @@ import torch import shutil import json +import random try: @@ -261,29 +262,6 @@ def test_svhn(self, mock_check): dataset = torchvision.datasets.SVHN(root, split="extra") self.generic_classification_dataset_test(dataset, num_images=2) - @unittest.skipIf(not HAS_PYAV, "PyAV unavailable") - def test_ucf101(self): - cached_meta_data = None - with ucf101_root() as (root, ann_root): - for split in {True, False}: - for fold in range(1, 4): - for length in {10, 15, 20}: - dataset = torchvision.datasets.UCF101(root, ann_root, length, fold=fold, train=split, - num_workers=2, _precomputed_metadata=cached_meta_data) - if cached_meta_data is None: - cached_meta_data = dataset.metadata - self.assertGreater(len(dataset), 0) - - video, audio, label = dataset[0] - self.assertEqual(video.size(), (length, 320, 240, 3)) - self.assertEqual(audio.numel(), 0) - self.assertEqual(label, 0) - - video, audio, label = dataset[len(dataset) - 1] - self.assertEqual(video.size(), (length, 320, 240, 3)) - self.assertEqual(audio.numel(), 0) - self.assertEqual(label, 1) - def test_places365(self): for split, small in itertools.product(("train-standard", "train-challenge", "val"), (False, True)): with places365_root(split=split, small=small) as places365: @@ -905,5 +883,56 @@ def test_captions(self): self.assertEqual(tuple(captions), tuple(info["captions"])) +class UCF101TestCase(datasets_utils.VideoDatasetTestCase): + DATASET_CLASS = datasets.UCF101 + + CONFIGS = datasets_utils.combinations_grid(fold=(1, 2, 3), train=(True, False)) + + def inject_fake_data(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) + + video_folder = tmpdir / "videos" + os.makedirs(video_folder) + video_files = self._create_videos(video_folder) + + annotations_folder = annotations_folder = tmpdir / "annotations" + os.makedirs(annotations_folder) + num_examples = self._create_annotation_files(annotations_folder, video_files, config["fold"], config["train"]) + + return (str(video_folder), str(annotations_folder)), num_examples + + def _create_videos(self, root, num_examples_per_class=3): + def file_name_fn(cls, idx, clips_per_group=2): + return f"v_{cls}_g{(idx // clips_per_group) + 1:02d}_c{(idx % clips_per_group) + 1:02d}.avi" + + video_files = [ + datasets_utils.create_video_folder(root, cls, lambda idx: file_name_fn(cls, idx), num_examples_per_class) + for cls in ("ApplyEyeMakeup", "YoYo") + ] + return [path.relative_to(root) for path in itertools.chain(*video_files)] + + def _create_annotation_files(self, root, video_files, fold, train): + current_videos = random.sample(video_files, random.randrange(1, len(video_files) - 1)) + current_annotation = self._annotation_file_name(fold, train) + self._create_annotation_file(root, current_annotation, current_videos) + + other_videos = set(video_files) - set(current_videos) + other_annotations = [ + self._annotation_file_name(fold, train) for fold, train in itertools.product((1, 2, 3), (True, False)) + ] + other_annotations.remove(current_annotation) + for name in other_annotations: + self._create_annotation_file(root, name, other_videos) + + return len(current_videos) + + def _annotation_file_name(self, fold, train): + return f"{'train' if train else 'test'}list{fold:02d}.txt" + + def _create_annotation_file(self, root, name, video_files): + with open(pathlib.Path(root) / name, "w") as fh: + fh.writelines(f"{file}\n" for file in sorted(video_files)) + + if __name__ == "__main__": unittest.main() From 44241713e1220ebf6f338e0a1bd2f008e28d9a06 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 244/357] Cleanup duplicate dependency (#3428) Summary: Co-authored-by: Francisco Massa Reviewed By: fmassa Differential Revision: D26756265 fbshipit-source-id: 7864539dcbc53ecf4379d8ba6b66bc8554c0479f --- android/test_app/app/build.gradle | 4 ---- 1 file changed, 4 deletions(-) diff --git a/android/test_app/app/build.gradle b/android/test_app/app/build.gradle index e95078c401d..cc6b4590261 100644 --- a/android/test_app/app/build.gradle +++ b/android/test_app/app/build.gradle @@ -69,9 +69,6 @@ android { aar { dimension "build" } - nightly { - dimension "build" - } local { dimension "build" } @@ -106,7 +103,6 @@ dependencies { implementation 'org.pytorch:pytorch_android:1.8.0-SNAPSHOT' implementation 'org.pytorch:pytorch_android_torchvision:1.8.0-SNAPSHOT' - implementation 'org.pytorch:torchvision_ops:0.0.1-SNAPSHOT' aarImplementation(name: 'pytorch_android-release', ext: 'aar') aarImplementation(name: 'pytorch_android_torchvision-release', ext: 'aar') From 4180ca175d4d1acc0c5db92b757268964113acf1 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 245/357] .circleci: Don't install numpy directly (#3444) Reviewed By: fmassa Differential Revision: D26756262 fbshipit-source-id: 10e420f8b6e446552c057c98eb413520c6042ee3 --- .circleci/config.yml | 4 +--- .circleci/config.yml.in | 4 +--- .circleci/smoke_test/docker/Dockerfile | 6 +++--- .circleci/unittest/linux/scripts/environment.yml | 2 +- .circleci/unittest/linux/scripts/install.sh | 2 +- .circleci/unittest/linux/scripts/setup_env.sh | 3 --- .circleci/unittest/windows/scripts/install.sh | 2 +- .circleci/unittest/windows/scripts/setup_env.sh | 5 ----- 8 files changed, 8 insertions(+), 20 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1f375c55d16..4ee1e59a1d5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -119,7 +119,7 @@ jobs: command: | sudo apt-get update -y sudo apt install -y libturbojpeg-dev - pip install --user --progress-bar off numpy mypy + pip install --user --progress-bar off mypy pip install --user --progress-bar off --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html pip install --user --progress-bar off --editable . mypy --config-file mypy.ini @@ -153,7 +153,6 @@ jobs: - checkout - run: command: | - pip install --user --progress-bar off numpy pip install --user --progress-bar off --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html # need to install torchvision dependencies due to transitive imports pip install --user --progress-bar off --editable . @@ -166,7 +165,6 @@ jobs: - checkout - run: command: | - pip install --user --progress-bar off numpy pip install --user --progress-bar off --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html # need to install torchvision dependencies due to transitive imports pip install --user --progress-bar off --editable . diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index 567fb9c756c..dcd511b8f80 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -119,7 +119,7 @@ jobs: command: | sudo apt-get update -y sudo apt install -y libturbojpeg-dev - pip install --user --progress-bar off numpy mypy + pip install --user --progress-bar off mypy pip install --user --progress-bar off --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html pip install --user --progress-bar off --editable . mypy --config-file mypy.ini @@ -153,7 +153,6 @@ jobs: - checkout - run: command: | - pip install --user --progress-bar off numpy pip install --user --progress-bar off --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html # need to install torchvision dependencies due to transitive imports pip install --user --progress-bar off --editable . @@ -166,7 +165,6 @@ jobs: - checkout - run: command: | - pip install --user --progress-bar off numpy pip install --user --progress-bar off --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html # need to install torchvision dependencies due to transitive imports pip install --user --progress-bar off --editable . diff --git a/.circleci/smoke_test/docker/Dockerfile b/.circleci/smoke_test/docker/Dockerfile index c5082c5971e..b6f25645620 100644 --- a/.circleci/smoke_test/docker/Dockerfile +++ b/.circleci/smoke_test/docker/Dockerfile @@ -30,7 +30,7 @@ RUN conda create -y --name python3.7 python=3.7 RUN conda create -y --name python3.8 python=3.8 SHELL [ "/bin/bash", "-c" ] RUN echo "source /usr/local/etc/profile.d/conda.sh" >> ~/.bashrc -RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.6 && conda install -y numpy Pillow -RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.7 && conda install -y numpy Pillow -RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.8 && conda install -y numpy Pillow +RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.6 && conda install -y Pillow +RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.7 && conda install -y Pillow +RUN source /usr/local/etc/profile.d/conda.sh && conda activate python3.8 && conda install -y Pillow CMD [ "/bin/bash"] diff --git a/.circleci/unittest/linux/scripts/environment.yml b/.circleci/unittest/linux/scripts/environment.yml index 2ad460f2d7c..dcad1abfa31 100644 --- a/.circleci/unittest/linux/scripts/environment.yml +++ b/.circleci/unittest/linux/scripts/environment.yml @@ -1,7 +1,7 @@ channels: - pytorch - defaults - # using conda-forge for python v3.9+ + # using conda-forge for python v3.9 - conda-forge dependencies: - pytest diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index 0e22ddf12c5..1a3e5c6f4d2 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -24,7 +24,7 @@ else fi printf "Installing PyTorch with %s\n" "${cudatoolkit}" -conda install -y -c "pytorch-${UPLOAD_CHANNEL}" -c conda-forge pytorch "${cudatoolkit}" +conda install -y -c "pytorch-${UPLOAD_CHANNEL}" -c conda-forge "pytorch-${UPLOAD_CHANNEL}"::pytorch "${cudatoolkit}" printf "* Installing torchvision\n" python setup.py develop diff --git a/.circleci/unittest/linux/scripts/setup_env.sh b/.circleci/unittest/linux/scripts/setup_env.sh index b44db0c42a8..773bd78f202 100755 --- a/.circleci/unittest/linux/scripts/setup_env.sh +++ b/.circleci/unittest/linux/scripts/setup_env.sh @@ -36,13 +36,10 @@ conda activate "${env_dir}" # 3. Install Conda dependencies printf "* Installing dependencies (except PyTorch)\n" -NUMPY_MIN_VER="1.11" FFMPEG_PIN="=4.2" if [[ "${PYTHON_VERSION}" = "3.9" ]]; then - NUMPY_MIN_VER="1.20" FFMPEG_PIN=">=4.2" fi -conda install -y -c conda-forge "numpy >=${NUMPY_MIN_VER}" conda install -y -c pytorch "ffmpeg${FFMPEG_PIN}" conda env update --file "${this_dir}/environment.yml" --prune diff --git a/.circleci/unittest/windows/scripts/install.sh b/.circleci/unittest/windows/scripts/install.sh index 72f55a61da0..9304b4b9b65 100644 --- a/.circleci/unittest/windows/scripts/install.sh +++ b/.circleci/unittest/windows/scripts/install.sh @@ -26,7 +26,7 @@ else fi printf "Installing PyTorch with %s\n" "${cudatoolkit}" -conda install -y -c "pytorch-${UPLOAD_CHANNEL}" -c conda-forge pytorch "${cudatoolkit}" +conda install -y -c "pytorch-${UPLOAD_CHANNEL}" -c conda-forge "pytorch-${UPLOAD_CHANNEL}"::pytorch "${cudatoolkit}" printf "* Installing torchvision\n" "$this_dir/vc_env_helper.bat" python setup.py develop diff --git a/.circleci/unittest/windows/scripts/setup_env.sh b/.circleci/unittest/windows/scripts/setup_env.sh index 61c3bc45bba..b0b70631112 100644 --- a/.circleci/unittest/windows/scripts/setup_env.sh +++ b/.circleci/unittest/windows/scripts/setup_env.sh @@ -36,9 +36,4 @@ conda activate "${env_dir}" # 3. Install Conda dependencies printf "* Installing dependencies (except PyTorch)\n" -NUMPY_MIN_VER="1.11" -if [[ "${PYTHON_VERSION}" = "3.9" ]]; then - NUMPY_MIN_VER="1.20" -fi -conda install -y -c conda-forge "numpy >=${NUMPY_MIN_VER}" conda env update --file "${this_dir}/environment.yml" --prune From 7d8d74b84556c28a4fba9f1c37be63d4a10ae433 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 246/357] Properly fix dataset test that passes by accident (#3434) Summary: * make UsageError an Exception rather than RuntimeError * separate fake data injection and dataset args handling * adapt tests for Coco * fix Coco implementation * add documentation * fix VideoDatasetTestCase * adapt UCF101 tests * cleanup * allow FileNotFoundError for test without fake data * Revert "fix Coco implementation" This reverts commit e2b693881654b3e2462a73e6d22bb01c1b738f8a. * lint * fix UCF101 tests Reviewed By: fmassa Differential Revision: D26756278 fbshipit-source-id: d2b3a7258e6dcf63595c5c4388453d2821746d79 --- test/datasets_utils.py | 98 +++++++++++++++++++++--------------------- test/test_datasets.py | 44 +++++++++++++------ 2 files changed, 82 insertions(+), 60 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 5789c8620dc..337a7382366 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -35,7 +35,7 @@ ] -class UsageError(RuntimeError): +class UsageError(Exception): """Should be raised in case an error happens in the setup rather than the test.""" @@ -165,7 +165,8 @@ class DatasetTestCase(unittest.TestCase): Without further configuration, the testcase will test if - 1. the dataset raises a ``RuntimeError`` if the data files are not found, + 1. the dataset raises a :class:`FileNotFoundError` or a :class:`RuntimeError` if the data files are not found or + corrupted, 2. the dataset inherits from `torchvision.datasets.VisionDataset`, 3. the dataset can be turned into a string, 4. the feature types of a returned example matches ``FEATURE_TYPES``, @@ -228,9 +229,25 @@ def test_baz(self): "download_and_extract_archive", } - def inject_fake_data( - self, tmpdir: str, config: Dict[str, Any] - ) -> Union[int, Dict[str, Any], Tuple[Sequence[Any], Union[int, Dict[str, Any]]]]: + def dataset_args(self, tmpdir: str, config: Dict[str, Any]) -> Sequence[Any]: + """Define positional arguments passed to the dataset. + + .. note:: + + The default behavior is only valid if the dataset to be tested has ``root`` as the only required parameter. + Otherwise you need to overwrite this method. + + Args: + tmpdir (str): Path to a temporary directory. For most cases this acts as root directory for the dataset + to be created and in turn also for the fake data injected here. + config (Dict[str, Any]): Configuration that will be used to create the dataset. + + Returns: + (Tuple[str]): ``tmpdir`` which corresponds to ``root`` for most datasets. + """ + return (tmpdir,) + + def inject_fake_data(self, tmpdir: str, config: Dict[str, Any]) -> Union[int, Dict[str, Any]]: """Inject fake data for dataset into a temporary directory. Args: @@ -240,15 +257,9 @@ def inject_fake_data( Needs to return one of the following: - 1. (int): Number of examples in the dataset to be created, + 1. (int): Number of examples in the dataset to be created, or 2. (Dict[str, Any]): Additional information about the injected fake data. Must contain the field - ``"num_examples"`` that corresponds to the number of examples in the dataset to be created, or - 3. (Tuple[Sequence[Any], Union[int, Dict[str, Any]]]): Additional required parameters that are passed to - the dataset constructor. The second element corresponds to cases 1. and 2. - - If no ``args`` is returned (case 1. and 2.), the ``tmp_dir`` is passed as first parameter to the dataset - constructor. In most cases this corresponds to ``root``. If the dataset has more parameters without default - values you need to explicitly pass them as explained in case 3. + ``"num_examples"`` that corresponds to the number of examples in the dataset to be created. """ raise NotImplementedError("You need to provide fake data in order for the tests to run.") @@ -287,33 +298,30 @@ def create_dataset( disable_download_extract = inject_fake_data with get_tmp_dir() as tmpdir: - output = self.inject_fake_data(tmpdir, config) if inject_fake_data else None - if output is None: - raise UsageError( - "The method 'inject_fake_data' needs to return at least an integer indicating the number of " - "examples for the current configuration." - ) - - if isinstance(output, collections.abc.Sequence) and len(output) == 2: - args, info = output - else: - args = (tmpdir,) - info = output + args = self.dataset_args(tmpdir, config) - if isinstance(info, int): - info = dict(num_examples=info) - elif isinstance(info, dict): - if "num_examples" not in info: + if inject_fake_data: + info = self.inject_fake_data(tmpdir, config) + if info is None: + raise UsageError( + "The method 'inject_fake_data' needs to return at least an integer indicating the number of " + "examples for the current configuration." + ) + elif isinstance(info, int): + info = dict(num_examples=info) + elif not isinstance(info, dict): + raise UsageError( + f"The additional information returned by the method 'inject_fake_data' must be either an " + f"integer indicating the number of examples for the current configuration or a dictionary with " + f"the same content. Got {type(info)} instead." + ) + elif "num_examples" not in info: raise UsageError( "The information dictionary returned by the method 'inject_fake_data' must contain a " "'num_examples' field that holds the number of examples for the current configuration." ) else: - raise UsageError( - f"The additional information returned by the method 'inject_fake_data' must be either an integer " - f"indicating the number of examples for the current configuration or a dictionary with the the " - f"same content. Got {type(info)} instead." - ) + info = None cm = self._disable_download_extract if disable_download_extract else nullcontext with cm(special_kwargs), disable_console_output(): @@ -395,8 +403,8 @@ def _disable_download_extract(self, special_kwargs): if inject_download_kwarg: del special_kwargs["download"] - def test_not_found(self): - with self.assertRaises(RuntimeError): + def test_not_found_or_corrupted(self): + with self.assertRaises((FileNotFoundError, RuntimeError)): with self.create_dataset(inject_fake_data=False): pass @@ -511,26 +519,20 @@ class VideoDatasetTestCase(DatasetTestCase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.inject_fake_data = self._set_default_frames_per_clip(self.inject_fake_data) + self.dataset_args = self._set_default_frames_per_clip(self.dataset_args) def _set_default_frames_per_clip(self, inject_fake_data): argspec = inspect.getfullargspec(self.DATASET_CLASS.__init__) args_without_default = argspec.args[1:-len(argspec.defaults)] frames_per_clip_last = args_without_default[-1] == "frames_per_clip" - only_root_and_frames_per_clip = (len(args_without_default) == 2) and frames_per_clip_last @functools.wraps(inject_fake_data) def wrapper(tmpdir, config): - output = inject_fake_data(tmpdir, config) - if isinstance(output, collections.abc.Sequence) and len(output) == 2: - args, info = output - if frames_per_clip_last and len(args) == len(args_without_default) - 1: - args = (*args, self.DEFAULT_FRAMES_PER_CLIP) - return args, info - elif isinstance(output, (int, dict)) and only_root_and_frames_per_clip: - return (tmpdir, self.DEFAULT_FRAMES_PER_CLIP) - else: - return output + args = inject_fake_data(tmpdir, config) + if frames_per_clip_last and len(args) == len(args_without_default) - 1: + args = (*args, self.DEFAULT_FRAMES_PER_CLIP) + + return args return wrapper diff --git a/test/test_datasets.py b/test/test_datasets.py index 37651ae7614..096dff97217 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -824,33 +824,44 @@ class CocoDetectionTestCase(datasets_utils.ImageDatasetTestCase): REQUIRED_PACKAGES = ("pycocotools",) + _IMAGE_FOLDER = "images" + _ANNOTATIONS_FOLDER = "annotations" + _ANNOTATIONS_FILE = "annotations.json" + + def dataset_args(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) + root = tmpdir / self._IMAGE_FOLDER + annotation_file = tmpdir / self._ANNOTATIONS_FOLDER / self._ANNOTATIONS_FILE + return root, annotation_file + def inject_fake_data(self, tmpdir, config): tmpdir = pathlib.Path(tmpdir) num_images = 3 num_annotations_per_image = 2 - image_folder = tmpdir / "images" files = datasets_utils.create_image_folder( - tmpdir, name="images", file_name_fn=lambda idx: f"{idx:012d}.jpg", num_examples=num_images + tmpdir, name=self._IMAGE_FOLDER, file_name_fn=lambda idx: f"{idx:012d}.jpg", num_examples=num_images ) - file_names = [file.relative_to(image_folder) for file in files] + file_names = [file.relative_to(tmpdir / self._IMAGE_FOLDER) for file in files] - annotation_folder = tmpdir / "annotations" + annotation_folder = tmpdir / self._ANNOTATIONS_FOLDER os.makedirs(annotation_folder) - annotation_file, info = self._create_annotation_file(annotation_folder, file_names, num_annotations_per_image) + info = self._create_annotation_file( + annotation_folder, self._ANNOTATIONS_FILE, file_names, num_annotations_per_image + ) info["num_examples"] = num_images - return (str(image_folder), str(annotation_file)), info + return info - def _create_annotation_file(self, root, file_names, num_annotations_per_image): + def _create_annotation_file(self, root, name, file_names, num_annotations_per_image): image_ids = [int(file_name.stem) for file_name in file_names] images = [dict(file_name=str(file_name), id=id) for file_name, id in zip(file_names, image_ids)] annotations, info = self._create_annotations(image_ids, num_annotations_per_image) + self._create_json(root, name, dict(images=images, annotations=annotations)) - content = dict(images=images, annotations=annotations) - return self._create_json(root, "annotations.json", content), info + return info def _create_annotations(self, image_ids, num_annotations_per_image): annotations = datasets_utils.combinations_grid( @@ -888,18 +899,27 @@ class UCF101TestCase(datasets_utils.VideoDatasetTestCase): CONFIGS = datasets_utils.combinations_grid(fold=(1, 2, 3), train=(True, False)) + _VIDEO_FOLDER = "videos" + _ANNOTATIONS_FOLDER = "annotations" + + def dataset_args(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) + root = tmpdir / self._VIDEO_FOLDER + annotation_path = tmpdir / self._ANNOTATIONS_FOLDER + return root, annotation_path + def inject_fake_data(self, tmpdir, config): tmpdir = pathlib.Path(tmpdir) - video_folder = tmpdir / "videos" + video_folder = tmpdir / self._VIDEO_FOLDER os.makedirs(video_folder) video_files = self._create_videos(video_folder) - annotations_folder = annotations_folder = tmpdir / "annotations" + annotations_folder = tmpdir / self._ANNOTATIONS_FOLDER os.makedirs(annotations_folder) num_examples = self._create_annotation_files(annotations_folder, video_files, config["fold"], config["train"]) - return (str(video_folder), str(annotations_folder)), num_examples + return num_examples def _create_videos(self, root, num_examples_per_class=3): def file_name_fn(cls, idx, clips_per_group=2): From aac1ce15397e76e9b93e2542068010edaa81a2b0 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 247/357] fix kwargs forwarding in fake data utility functions (#3459) Reviewed By: fmassa Differential Revision: D26756259 fbshipit-source-id: 6056b4e3ed1e4873971cfe7eab58ccf3e6d5421a --- test/datasets_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 337a7382366..4e3fd0ac0e3 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -572,7 +572,7 @@ def create_image_file( image = create_image_or_video_tensor(size) file = pathlib.Path(root) / name - PIL.Image.fromarray(image.permute(2, 1, 0).numpy()).save(file) + PIL.Image.fromarray(image.permute(2, 1, 0).numpy()).save(file, **kwargs) return file @@ -708,6 +708,6 @@ def size(idx): os.makedirs(root) return [ - create_video_file(root, file_name_fn(idx), size=size(idx) if callable(size) else size) + create_video_file(root, file_name_fn(idx), size=size(idx) if callable(size) else size, **kwargs) for idx in range(num_examples) ] From a1ce68219964f5626f221ab7c49de963f5413538 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 248/357] add version information to docstring of Phototour dataset (#3437) Summary: Co-authored-by: vfdev Reviewed By: fmassa Differential Revision: D26756266 fbshipit-source-id: 8f39e99a183456a8aa24fdcdf9cd592fdb3d8775 --- torchvision/datasets/phototour.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/torchvision/datasets/phototour.py b/torchvision/datasets/phototour.py index ce427e04883..a64287678df 100644 --- a/torchvision/datasets/phototour.py +++ b/torchvision/datasets/phototour.py @@ -10,7 +10,17 @@ class PhotoTour(VisionDataset): - """`Learning Local Image Descriptors Data `_ Dataset. + """`Multi-view Stereo Correspondence `_ Dataset. + + .. note:: + + We only provide the newer version of the dataset, since the authors state that it + + is more suitable for training descriptors based on difference of Gaussian, or Harris corners, as the + patches are centred on real interest point detections, rather than being projections of 3D points as is the + case in the old dataset. + + The original dataset is available under http://phototour.cs.washington.edu/patches/default.htm. Args: From e9bf0674a80fa14e008efb0e987cc6a935e54d74 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 249/357] Improve dataset test infrastructure (#3450) Summary: * always use default config as base * fix test_all_configs decorator * lint * add a utility function to create a random string * move output check of inject_fake_data to dedicated method * always disable download and extract functionality Reviewed By: fmassa Differential Revision: D26756261 fbshipit-source-id: a720dce48148d4d69678d43a2c5ec50ac92d69a0 --- test/datasets_utils.py | 149 ++++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 69 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 4e3fd0ac0e3..34190b2bfbc 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -6,6 +6,8 @@ import itertools import os import pathlib +import random +import string import unittest import unittest.mock from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Tuple, Union @@ -32,6 +34,7 @@ "create_image_folder", "create_video_file", "create_video_folder", + "create_random_string", ] @@ -93,14 +96,6 @@ def inner_wrapper(*args, **kwargs): return outer_wrapper -# As of Python 3.7 this is provided by contextlib -# https://docs.python.org/3.7/library/contextlib.html#contextlib.nullcontext -# TODO: If the minimum Python requirement is >= 3.7, replace this -@contextlib.contextmanager -def nullcontext(enter_result=None): - yield enter_result - - def test_all_configs(test): """Decorator to run test against all configurations. @@ -116,7 +111,7 @@ def test_foo(self, config): @functools.wraps(test) def wrapper(self): - for config in self.CONFIGS: + for config in self.CONFIGS or (self._DEFAULT_CONFIG,): with self.subTest(**config): test(self, config) @@ -207,6 +202,8 @@ def test_baz(self): CONFIGS = None REQUIRED_PACKAGES = None + _DEFAULT_CONFIG = None + _TRANSFORM_KWARGS = { "transform", "target_transform", @@ -268,7 +265,7 @@ def create_dataset( self, config: Optional[Dict[str, Any]] = None, inject_fake_data: bool = True, - disable_download_extract: Optional[bool] = None, + patch_checks: Optional[bool] = None, **kwargs: Any, ) -> Iterator[Tuple[torchvision.datasets.VisionDataset, Dict[str, Any]]]: r"""Create the dataset in a temporary directory. @@ -278,8 +275,8 @@ def create_dataset( default configuration is used. inject_fake_data (bool): If ``True`` (default) inject the fake data with :meth:`.inject_fake_data` before creating the dataset. - disable_download_extract (Optional[bool]): If ``True`` disable download and extract logic while creating - the dataset. If ``None`` (default) this takes the same value as ``inject_fake_data``. + patch_checks (Optional[bool]): If ``True`` disable integrity check logic while creating the dataset. If + omitted defaults to the same value as ``inject_fake_data``. **kwargs (Any): Additional parameters passed to the dataset. These parameters take precedence in case they overlap with ``config``. @@ -288,43 +285,28 @@ def create_dataset( info (Dict[str, Any]): Additional information about the injected fake data. See :meth:`.inject_fake_data` for details. """ - if config is None: - config = self.CONFIGS[0].copy() + default_config = self._DEFAULT_CONFIG.copy() + if config is not None: + default_config.update(config) + config = default_config + + if patch_checks is None: + patch_checks = inject_fake_data special_kwargs, other_kwargs = self._split_kwargs(kwargs) + if "download" in self._HAS_SPECIAL_KWARG: + special_kwargs["download"] = False config.update(other_kwargs) - if disable_download_extract is None: - disable_download_extract = inject_fake_data + patchers = self._patch_download_extract() + if patch_checks: + patchers.update(self._patch_checks()) with get_tmp_dir() as tmpdir: args = self.dataset_args(tmpdir, config) + info = self._inject_fake_data(tmpdir, config) if inject_fake_data else None - if inject_fake_data: - info = self.inject_fake_data(tmpdir, config) - if info is None: - raise UsageError( - "The method 'inject_fake_data' needs to return at least an integer indicating the number of " - "examples for the current configuration." - ) - elif isinstance(info, int): - info = dict(num_examples=info) - elif not isinstance(info, dict): - raise UsageError( - f"The additional information returned by the method 'inject_fake_data' must be either an " - f"integer indicating the number of examples for the current configuration or a dictionary with " - f"the same content. Got {type(info)} instead." - ) - elif "num_examples" not in info: - raise UsageError( - "The information dictionary returned by the method 'inject_fake_data' must contain a " - "'num_examples' field that holds the number of examples for the current configuration." - ) - else: - info = None - - cm = self._disable_download_extract if disable_download_extract else nullcontext - with cm(special_kwargs), disable_console_output(): + with self._maybe_apply_patches(patchers), disable_console_output(): dataset = self.DATASET_CLASS(*args, **config, **special_kwargs) yield dataset, info @@ -352,19 +334,17 @@ def _verify_required_public_class_attributes(cls): @classmethod def _populate_private_class_attributes(cls): argspec = inspect.getfullargspec(cls.DATASET_CLASS.__init__) + + cls._DEFAULT_CONFIG = { + kwarg: default + for kwarg, default in zip(argspec.args[-len(argspec.defaults):], argspec.defaults) + if kwarg not in cls._SPECIAL_KWARGS + } + cls._HAS_SPECIAL_KWARG = {name for name in cls._SPECIAL_KWARGS if name in argspec.args} @classmethod def _process_optional_public_class_attributes(cls): - argspec = inspect.getfullargspec(cls.DATASET_CLASS.__init__) - if cls.CONFIGS is None: - config = { - kwarg: default - for kwarg, default in zip(argspec.args[-len(argspec.defaults):], argspec.defaults) - if kwarg not in cls._SPECIAL_KWARGS - } - cls.CONFIGS = (config,) - if cls.REQUIRED_PACKAGES is not None: try: for pkg in cls.REQUIRED_PACKAGES: @@ -380,28 +360,44 @@ def _split_kwargs(self, kwargs): other_kwargs = {key: special_kwargs.pop(key) for key in set(special_kwargs.keys()) - self._SPECIAL_KWARGS} return special_kwargs, other_kwargs - @contextlib.contextmanager - def _disable_download_extract(self, special_kwargs): - inject_download_kwarg = "download" in self._HAS_SPECIAL_KWARG and "download" not in special_kwargs - if inject_download_kwarg: - special_kwargs["download"] = False + def _inject_fake_data(self, tmpdir, config): + info = self.inject_fake_data(tmpdir, config) + if info is None: + raise UsageError( + "The method 'inject_fake_data' needs to return at least an integer indicating the number of " + "examples for the current configuration." + ) + elif isinstance(info, int): + info = dict(num_examples=info) + elif not isinstance(info, dict): + raise UsageError( + f"The additional information returned by the method 'inject_fake_data' must be either an " + f"integer indicating the number of examples for the current configuration or a dictionary with " + f"the same content. Got {type(info)} instead." + ) + elif "num_examples" not in info: + raise UsageError( + "The information dictionary returned by the method 'inject_fake_data' must contain a " + "'num_examples' field that holds the number of examples for the current configuration." + ) + return info + + def _patch_download_extract(self): + module = inspect.getmodule(self.DATASET_CLASS).__name__ + return {unittest.mock.patch(f"{module}.{function}") for function in self._DOWNLOAD_EXTRACT_FUNCTIONS} + def _patch_checks(self): module = inspect.getmodule(self.DATASET_CLASS).__name__ + return {unittest.mock.patch(f"{module}.{function}", return_value=True) for function in self._CHECK_FUNCTIONS} + + @contextlib.contextmanager + def _maybe_apply_patches(self, patchers): with contextlib.ExitStack() as stack: mocks = {} - for function, kwargs in itertools.chain( - zip(self._CHECK_FUNCTIONS, [dict(return_value=True)] * len(self._CHECK_FUNCTIONS)), - zip(self._DOWNLOAD_EXTRACT_FUNCTIONS, [dict()] * len(self._DOWNLOAD_EXTRACT_FUNCTIONS)), - ): + for patcher in patchers: with contextlib.suppress(AttributeError): - patcher = unittest.mock.patch(f"{module}.{function}", **kwargs) - mocks[function] = stack.enter_context(patcher) - - try: - yield mocks - finally: - if inject_download_kwarg: - del special_kwargs["download"] + mocks[patcher.target] = stack.enter_context(patcher) + yield mocks def test_not_found_or_corrupted(self): with self.assertRaises((FileNotFoundError, RuntimeError)): @@ -469,13 +465,13 @@ def create_dataset( self, config: Optional[Dict[str, Any]] = None, inject_fake_data: bool = True, - disable_download_extract: Optional[bool] = None, + patch_checks: Optional[bool] = None, **kwargs: Any, ) -> Iterator[Tuple[torchvision.datasets.VisionDataset, Dict[str, Any]]]: with super().create_dataset( config=config, inject_fake_data=inject_fake_data, - disable_download_extract=disable_download_extract, + patch_checks=patch_checks, **kwargs, ) as (dataset, info): # PIL.Image.open() only loads the image meta data upfront and keeps the file open until the first access @@ -711,3 +707,18 @@ def size(idx): create_video_file(root, file_name_fn(idx), size=size(idx) if callable(size) else size, **kwargs) for idx in range(num_examples) ] + + +def create_random_string(length: int, *digits: str) -> str: + """Create a random string. + + Args: + length (int): Number of characters in the generated string. + *characters (str): Characters to sample from. If omitted defaults to :attr:`string.ascii_lowercase`. + """ + if not digits: + digits = string.ascii_lowercase + else: + digits = "".join(itertools.chain(*digits)) + + return "".join(random.choice(digits) for _ in range(length)) From ebcd2f3660c7b72ad53d22867e3d9b9c1ad52f33 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 250/357] Deprecate _transforms_video and _functional_video (#3441) Summary: * deprecate _video modules * flake8 Reviewed By: fmassa Differential Revision: D26756260 fbshipit-source-id: 12b4e96a0127ea10d5bf9ce3d348ba4e1df65a04 Co-authored-by: Vasilis Vryniotis --- test/test_transforms_video.py | 7 ++++++- torchvision/transforms/_functional_video.py | 6 ++++++ torchvision/transforms/_transforms_video.py | 6 ++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/test/test_transforms_video.py b/test/test_transforms_video.py index 269a54789ba..e0c7ab5260b 100644 --- a/test/test_transforms_video.py +++ b/test/test_transforms_video.py @@ -1,9 +1,9 @@ import torch -import torchvision.transforms._transforms_video as transforms from torchvision.transforms import Compose import unittest import random import numpy as np +import warnings try: from scipy import stats @@ -11,6 +11,11 @@ stats = None +with warnings.catch_warnings(record=True): + warnings.simplefilter("always") + import torchvision.transforms._transforms_video as transforms + + class TestVideoTransforms(unittest.TestCase): def test_random_crop_video(self): diff --git a/torchvision/transforms/_functional_video.py b/torchvision/transforms/_functional_video.py index 56eaa436188..709c2d781ae 100644 --- a/torchvision/transforms/_functional_video.py +++ b/torchvision/transforms/_functional_video.py @@ -1,4 +1,10 @@ import torch +import warnings + + +warnings.warn( + "The _functional_video module is deprecated. Please use the functional module instead." +) def _is_tensor_video_clip(clip): diff --git a/torchvision/transforms/_transforms_video.py b/torchvision/transforms/_transforms_video.py index b4752ff090b..bfef1b440d1 100644 --- a/torchvision/transforms/_transforms_video.py +++ b/torchvision/transforms/_transforms_video.py @@ -2,6 +2,7 @@ import numbers import random +import warnings from torchvision.transforms import ( RandomCrop, @@ -21,6 +22,11 @@ ] +warnings.warn( + "The _transforms_video module is deprecated. Please use the transforms module instead." +) + + class RandomCropVideo(RandomCrop): def __init__(self, size): if isinstance(size, numbers.Number): From 828395a1203444892891c155a25b46a4fa492073 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 251/357] Replace reshape with flatten (#3462) Summary: Current implementation is generating bad graph after onnx conversion. So replacing with flatten like in mobilenetv3 code. Reviewed By: fmassa Differential Revision: D26756271 fbshipit-source-id: 68751201436147c179532b4d35e1140cb0f56967 Co-authored-by: Vasilis Vryniotis --- torchvision/models/mobilenetv2.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/torchvision/models/mobilenetv2.py b/torchvision/models/mobilenetv2.py index c4e83fa364f..386513b4071 100644 --- a/torchvision/models/mobilenetv2.py +++ b/torchvision/models/mobilenetv2.py @@ -1,3 +1,4 @@ +import torch from torch import nn from torch import Tensor from .utils import load_state_dict_from_url @@ -189,8 +190,9 @@ def _forward_impl(self, x: Tensor) -> Tensor: # This exists since TorchScript doesn't support inheritance, so the superclass method # (this one) needs to have a name other than `forward` that can be accessed in a subclass x = self.features(x) - # Cannot use "squeeze" as batch-size can be 1 => must use reshape with x.shape[0] - x = nn.functional.adaptive_avg_pool2d(x, (1, 1)).reshape(x.shape[0], -1) + # Cannot use "squeeze" as batch-size can be 1 + x = nn.functional.adaptive_avg_pool2d(x, (1, 1)) + x = torch.flatten(x, 1) x = self.classifier(x) return x From 7283741a5023dbf5e52b4fabd8ac578941eb96cd Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 252/357] separate caching logic from download (#3448) Summary: Co-authored-by: Francisco Massa Reviewed By: fmassa Differential Revision: D26756282 fbshipit-source-id: bb63f0cc2bcba111dd5a7d215334fc49eca87955 --- torchvision/datasets/phototour.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/torchvision/datasets/phototour.py b/torchvision/datasets/phototour.py index a64287678df..2b657b8bfb6 100644 --- a/torchvision/datasets/phototour.py +++ b/torchvision/datasets/phototour.py @@ -92,8 +92,10 @@ def __init__( self.download() if not self._check_datafile_exists(): - raise RuntimeError('Dataset not found.' + - ' You can use download=True to download it') + try: + self.cache() + except Exception as error: + raise RuntimeError("Dataset not found. You can use download=True to download it") from error # load the serialized data self.data, self.labels, self.matches = torch.load(self.data_file) @@ -151,6 +153,7 @@ def download(self) -> None: os.unlink(fpath) + def cache(self) -> None: # process and save as torch files print('# Caching data {}'.format(self.data_file)) From 368c2edd5addaf7b495f132eb29d3f10c6a05d54 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 07:02:04 -0800 Subject: [PATCH 253/357] make LSUN OS agnostic (#3455) Summary: Reviewed By: fmassa Differential Revision: D26756279 fbshipit-source-id: 23411db624844e468614da63435688a3181dbdfc Co-authored-by: vfdev Co-authored-by: Francisco Massa --- torchvision/datasets/lsun.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/datasets/lsun.py b/torchvision/datasets/lsun.py index d437596b74e..75b284b597f 100644 --- a/torchvision/datasets/lsun.py +++ b/torchvision/datasets/lsun.py @@ -83,7 +83,7 @@ def __init__( self.dbs = [] for c in self.classes: self.dbs.append(LSUNClass( - root=root + '/' + c + '_lmdb', + root=os.path.join(root, f"{c}_lmdb"), transform=transform)) self.indices = [] From a4f3f6db70a603be2662bbc85b85d498474ab1fe Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 254/357] add tests for LSUN (#3454) Summary: Reviewed By: fmassa Differential Revision: D26756274 fbshipit-source-id: b489819c79dfb03393a7ee9c2638f9a5bc35c11e Co-authored-by: vfdev Co-authored-by: Francisco Massa --- test/test_datasets.py | 88 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index 096dff97217..dbde2e7f8b8 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -23,6 +23,8 @@ import shutil import json import random +import string +import io try: @@ -954,5 +956,91 @@ def _create_annotation_file(self, root, name, video_files): fh.writelines(f"{file}\n" for file in sorted(video_files)) +class LSUNTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.LSUN + + REQUIRED_PACKAGES = ("lmdb",) + CONFIGS = datasets_utils.combinations_grid( + classes=("train", "test", "val", ["bedroom_train", "church_outdoor_train"]) + ) + + _CATEGORIES = ( + "bedroom", + "bridge", + "church_outdoor", + "classroom", + "conference_room", + "dining_room", + "kitchen", + "living_room", + "restaurant", + "tower", + ) + + def inject_fake_data(self, tmpdir, config): + root = pathlib.Path(tmpdir) + + num_images = 0 + for cls in self._parse_classes(config["classes"]): + num_images += self._create_lmdb(root, cls) + + return num_images + + @contextlib.contextmanager + def create_dataset( + self, + *args, **kwargs + ): + with super().create_dataset(*args, **kwargs) as output: + yield output + # Currently datasets.LSUN caches the keys in the current directory rather than in the root directory. Thus, + # this creates a number of unique _cache_* files in the current directory that will not be removed together + # with the temporary directory + for file in os.listdir(os.getcwd()): + if file.startswith("_cache_"): + os.remove(file) + + def _parse_classes(self, classes): + if not isinstance(classes, str): + return classes + + split = classes + if split == "test": + return [split] + + return [f"{category}_{split}" for category in self._CATEGORIES] + + def _create_lmdb(self, root, cls): + lmdb = datasets_utils.lazy_importer.lmdb + hexdigits_lowercase = string.digits + string.ascii_lowercase[:6] + + folder = f"{cls}_lmdb" + + num_images = torch.randint(1, 4, size=()).item() + format = "png" + files = datasets_utils.create_image_folder(root, folder, lambda idx: f"{idx}.{format}", num_images) + + with lmdb.open(str(root / folder)) as env, env.begin(write=True) as txn: + for file in files: + key = "".join(random.choice(hexdigits_lowercase) for _ in range(40)).encode() + + buffer = io.BytesIO() + Image.open(file).save(buffer, format) + buffer.seek(0) + value = buffer.read() + + txn.put(key, value) + + os.remove(file) + + return num_images + + def test_not_found_or_corrupted(self): + # LSUN does not raise built-in exception, but a custom one. It is expressive enough to not 'cast' it to + # RuntimeError or FileNotFoundError that are normally checked by this test. + with self.assertRaises(datasets_utils.lazy_importer.lmdb.Error): + super().test_not_found_or_corrupted() + + if __name__ == "__main__": unittest.main() From bd06036104bf2fb9c5d9bee5403d0088c0cf8348 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 255/357] include intended structure of root directory in docstring of Kinetics400 (#3453) Summary: * include intended structure of root directory in docstring of Kinetics400 * fix syntax Reviewed By: fmassa Differential Revision: D26756276 fbshipit-source-id: 5e94eaff792f4f0ee4e83867bd4d24db66c403e0 Co-authored-by: Francisco Massa --- torchvision/datasets/kinetics.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/torchvision/datasets/kinetics.py b/torchvision/datasets/kinetics.py index 8be0ca8b5cd..e977fc42ba7 100644 --- a/torchvision/datasets/kinetics.py +++ b/torchvision/datasets/kinetics.py @@ -23,7 +23,18 @@ class Kinetics400(VisionDataset): Internally, it uses a VideoClips object to handle clip creation. Args: - root (string): Root directory of the Kinetics-400 Dataset. + root (string): Root directory of the Kinetics-400 Dataset. Should be structured as follows: + .. code:: + + root/ + ├── class1 + │ ├── clip1.avi + │ ├── clip2.avi + │ └── ... + └── class2 + ├── clipx.avi + └── ... + frames_per_clip (int): number of frames in a clip step_between_clips (int): number of frames between each clip transform (callable, optional): A function/transform that takes in a TxHxWxC video From 997cfb1862bf0ffcacc1c9ef805f8a128cfd3868 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 256/357] remove old CIFAR tests and fake data generation (#3447) Reviewed By: fmassa Differential Revision: D26756258 fbshipit-source-id: eaf36956b2f341276088ed7702a484a9b93d448e --- test/test_datasets.py | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/test/test_datasets.py b/test/test_datasets.py index dbde2e7f8b8..8e1af0f994c 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -10,7 +10,7 @@ import torchvision from torchvision.datasets import utils from common_utils import get_tmp_dir -from fakedata_generation import mnist_root, cifar_root, imagenet_root, \ +from fakedata_generation import mnist_root, imagenet_root, \ cityscapes_root, svhn_root, places365_root, widerface_root, stl10_root import xml.etree.ElementTree as ET from urllib.request import Request, urlopen @@ -173,38 +173,6 @@ def test_widerface(self, mock_check_integrity): img, target = dataset[0] self.assertTrue(isinstance(img, PIL.Image.Image)) - @mock.patch('torchvision.datasets.cifar.check_integrity') - @mock.patch('torchvision.datasets.cifar.CIFAR10._check_integrity') - def test_cifar10(self, mock_ext_check, mock_int_check): - mock_ext_check.return_value = True - mock_int_check.return_value = True - with cifar_root('CIFAR10') as root: - dataset = torchvision.datasets.CIFAR10(root, train=True, download=True) - self.generic_classification_dataset_test(dataset, num_images=5) - img, target = dataset[0] - self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) - - dataset = torchvision.datasets.CIFAR10(root, train=False, download=True) - self.generic_classification_dataset_test(dataset) - img, target = dataset[0] - self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) - - @mock.patch('torchvision.datasets.cifar.check_integrity') - @mock.patch('torchvision.datasets.cifar.CIFAR10._check_integrity') - def test_cifar100(self, mock_ext_check, mock_int_check): - mock_ext_check.return_value = True - mock_int_check.return_value = True - with cifar_root('CIFAR100') as root: - dataset = torchvision.datasets.CIFAR100(root, train=True, download=True) - self.generic_classification_dataset_test(dataset) - img, target = dataset[0] - self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) - - dataset = torchvision.datasets.CIFAR100(root, train=False, download=True) - self.generic_classification_dataset_test(dataset) - img, target = dataset[0] - self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') def test_cityscapes(self): with cityscapes_root() as root: From 1e39ab4f08913a63b2b0aee68241b6b77485322d Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 257/357] add tests for Kinetics400 (#3457) Summary: * add tests for Kinetics400 * use create_random_string() Reviewed By: fmassa Differential Revision: D26756281 fbshipit-source-id: a4fb2dde283a45cc8675db343d765881ceaba91d Co-authored-by: Philip Meier Co-authored-by: Francisco Massa --- test/test_datasets.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index 8e1af0f994c..d70768bd5bf 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1010,5 +1010,27 @@ def test_not_found_or_corrupted(self): super().test_not_found_or_corrupted() +class Kinetics400TestCase(datasets_utils.VideoDatasetTestCase): + DATASET_CLASS = datasets.Kinetics400 + + def inject_fake_data(self, tmpdir, config): + classes = ("Abseiling", "Zumba") + num_videos_per_class = 2 + + digits = string.ascii_letters + string.digits + "-_" + for cls in classes: + datasets_utils.create_video_folder( + tmpdir, + cls, + lambda _: f"{datasets_utils.create_random_string(11, digits)}.avi", + num_videos_per_class, + ) + + return num_videos_per_class * len(classes) + + def test_not_found_or_corrupted(self): + self.skipTest("Dataset currently does not handle the case of no found videos.") + + if __name__ == "__main__": unittest.main() From 0eaa49cc60ff4ad717a023f63048e0f8fd486abe Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 258/357] add tests for HMDB51 dataset (#3458) Summary: * add tests for HMDB51 dataset * lint Reviewed By: fmassa Differential Revision: D26756280 fbshipit-source-id: 9a13c7fd3f115da6b8051b7deeea81faccd36f0b Co-authored-by: Vasilis Vryniotis --- test/test_datasets.py | 60 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index d70768bd5bf..9f8bf963a7a 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1032,5 +1032,65 @@ def test_not_found_or_corrupted(self): self.skipTest("Dataset currently does not handle the case of no found videos.") +class HMDB51TestCase(datasets_utils.VideoDatasetTestCase): + DATASET_CLASS = datasets.HMDB51 + + CONFIGS = datasets_utils.combinations_grid(fold=(1, 2, 3), train=(True, False)) + + _VIDEO_FOLDER = "videos" + _SPLITS_FOLDER = "splits" + _CLASSES = ("brush_hair", "wave") + + def dataset_args(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) + root = tmpdir / self._VIDEO_FOLDER + annotation_path = tmpdir / self._SPLITS_FOLDER + return root, annotation_path + + def inject_fake_data(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) + + video_folder = tmpdir / self._VIDEO_FOLDER + os.makedirs(video_folder) + video_files = self._create_videos(video_folder) + + splits_folder = tmpdir / self._SPLITS_FOLDER + os.makedirs(splits_folder) + num_examples = self._create_split_files(splits_folder, video_files, config["fold"], config["train"]) + + return num_examples + + def _create_videos(self, root, num_examples_per_class=3): + def file_name_fn(cls, idx, clips_per_group=2): + return f"{cls}_{(idx // clips_per_group) + 1:d}_{(idx % clips_per_group) + 1:d}.avi" + + return [ + ( + cls, + datasets_utils.create_video_folder( + root, + cls, + lambda idx: file_name_fn(cls, idx), + num_examples_per_class, + ), + ) + for cls in self._CLASSES + ] + + def _create_split_files(self, root, video_files, fold, train): + num_videos = num_train_videos = 0 + + for cls, videos in video_files: + num_videos += len(videos) + + train_videos = set(random.sample(videos, random.randrange(1, len(videos) - 1))) + num_train_videos += len(train_videos) + + with open(pathlib.Path(root) / f"{cls}_test_split{fold}.txt", "w") as fh: + fh.writelines(f"{file.name} {1 if file in train_videos else 2}\n" for file in videos) + + return num_train_videos if train else (num_videos - num_train_videos) + + if __name__ == "__main__": unittest.main() From 13a56855c8b65092c9ad2b7502c587fed717e392 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 259/357] add tests for Omniglot dataset (#3461) Summary: Co-authored-by: Vasilis Vryniotis Reviewed By: fmassa Differential Revision: D26756277 fbshipit-source-id: 0774f16d657d4881fb4161348de41f329d5a2c6a --- test/test_datasets.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index 9f8bf963a7a..5f4828ef589 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1092,5 +1092,35 @@ def _create_split_files(self, root, video_files, fold, train): return num_train_videos if train else (num_videos - num_train_videos) +class OmniglotTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.Omniglot + + CONFIGS = datasets_utils.combinations_grid(background=(True, False)) + + def inject_fake_data(self, tmpdir, config): + target_folder = ( + pathlib.Path(tmpdir) / "omniglot-py" / f"images_{'background' if config['background'] else 'evaluation'}" + ) + os.makedirs(target_folder) + + num_images = 0 + for name in ("Alphabet_of_the_Magi", "Tifinagh"): + num_images += self._create_alphabet_folder(target_folder, name) + + return num_images + + def _create_alphabet_folder(self, root, name): + num_images_total = 0 + for idx in range(torch.randint(1, 4, size=()).item()): + num_images = torch.randint(1, 4, size=()).item() + num_images_total += num_images + + datasets_utils.create_image_folder( + root / name, f"character{idx:02d}", lambda image_idx: f"{image_idx:02d}.png", num_images + ) + + return num_images_total + + if __name__ == "__main__": unittest.main() From 9067df1bc9f0d71042fbdfbe95bfc7e7d3e194e3 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 260/357] add tests for SBU dataset (#3464) Summary: Co-authored-by: Vasilis Vryniotis Reviewed By: fmassa Differential Revision: D26756256 fbshipit-source-id: dd51a6882d37eef7ab9b7db927893b45188bd197 --- test/test_datasets.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index 5f4828ef589..fb069439763 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1122,5 +1122,38 @@ def _create_alphabet_folder(self, root, name): return num_images_total +class SBUTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.SBU + FEATURE_TYPES = (PIL.Image.Image, str) + + def inject_fake_data(self, tmpdir, config): + num_images = 3 + + dataset_folder = pathlib.Path(tmpdir) / "dataset" + images = datasets_utils.create_image_folder(tmpdir, "dataset", self._create_file_name, num_images) + + self._create_urls_txt(dataset_folder, images) + self._create_captions_txt(dataset_folder, num_images) + + return num_images + + def _create_file_name(self, idx): + part1 = datasets_utils.create_random_string(10, string.digits) + part2 = datasets_utils.create_random_string(10, string.ascii_lowercase, string.digits[:6]) + return f"{part1}_{part2}.jpg" + + def _create_urls_txt(self, root, images): + with open(root / "SBU_captioned_photo_dataset_urls.txt", "w") as fh: + for image in images: + fh.write( + f"http://static.flickr.com/{datasets_utils.create_random_string(4, string.digits)}/{image.name}\n" + ) + + def _create_captions_txt(self, root, num_images): + with open(root / "SBU_captioned_photo_dataset_captions.txt", "w") as fh: + for _ in range(num_images): + fh.write(f"{datasets_utils.create_random_string(10)}\n") + + if __name__ == "__main__": unittest.main() From 156f184d7dcbf49aae3351030502a4007d2e97a0 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 261/357] add tests for SEMEION dataset (#3465) Summary: * add tests for SEMEION dataset * add missing imports Reviewed By: fmassa Differential Revision: D26756272 fbshipit-source-id: 66effb201923400e89a37c69341d2683abc598e5 Co-authored-by: Vasilis Vryniotis --- test/test_datasets.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index fb069439763..6a71d537c07 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -23,6 +23,7 @@ import shutil import json import random +import torch.nn.functional as F import string import io @@ -1155,5 +1156,22 @@ def _create_captions_txt(self, root, num_images): fh.write(f"{datasets_utils.create_random_string(10)}\n") +class SEMEIONTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.SEMEION + + def inject_fake_data(self, tmpdir, config): + num_images = 3 + + images = torch.rand(num_images, 256) + labels = F.one_hot(torch.randint(10, size=(num_images,))) + with open(pathlib.Path(tmpdir) / "semeion.data", "w") as fh: + for image, one_hot_labels in zip(images, labels): + image_columns = " ".join([f"{pixel.item():.4f}" for pixel in image]) + labels_columns = " ".join([str(label.item()) for label in one_hot_labels]) + fh.write(f"{image_columns} {labels_columns}\n") + + return num_images + + if __name__ == "__main__": unittest.main() From ee8c7a0da8d34f41a7133cd84d0c570bbbc20615 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 262/357] add tests for USPS dataset (#3466) Summary: Co-authored-by: Vasilis Vryniotis Reviewed By: fmassa Differential Revision: D26756275 fbshipit-source-id: 52ed0b84541cde380a3ac539cc49c92d57bbebab --- test/test_datasets.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index 6a71d537c07..45cf432e72b 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -23,6 +23,7 @@ import shutil import json import random +import bz2 import torch.nn.functional as F import string import io @@ -1173,5 +1174,24 @@ def inject_fake_data(self, tmpdir, config): return num_images +class USPSTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.USPS + + CONFIGS = datasets_utils.combinations_grid(train=(True, False)) + + def inject_fake_data(self, tmpdir, config): + num_images = 2 if config["train"] else 1 + + images = torch.rand(num_images, 256) * 2 - 1 + labels = torch.randint(1, 11, size=(num_images,)) + + with bz2.open(pathlib.Path(tmpdir) / f"usps{'.t' if not config['train'] else ''}.bz2", "w") as fh: + for image, label in zip(images, labels): + line = " ".join((str(label.item()), *[f"{idx}:{pixel:.6f}" for idx, pixel in enumerate(image, 1)])) + fh.write(f"{line}\n".encode()) + + return num_images + + if __name__ == "__main__": unittest.main() From 44f48348e637815d639f7ac2e0fb70485d63b25e Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 263/357] set empty cxx flags as default (#3474) Summary: Reviewed By: fmassa Differential Revision: D26756255 fbshipit-source-id: 85a51d8732f46718f49c139c2ef920a28ed1c656 Co-authored-by: Philip Meier Co-authored-by: Francisco Massa --- setup.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index fd653fea0f8..c998118335b 100644 --- a/setup.py +++ b/setup.py @@ -181,7 +181,7 @@ def get_extensions(): define_macros = [] - extra_compile_args = {} + extra_compile_args = {'cxx': []} if (torch.cuda.is_available() and ((CUDA_HOME is not None) or is_rocm_pytorch)) \ or os.getenv('FORCE_CUDA', '0') == '1': extension = CUDAExtension @@ -196,15 +196,11 @@ def get_extensions(): else: define_macros += [('WITH_HIP', None)] nvcc_flags = [] - extra_compile_args = { - 'cxx': [], - 'nvcc': nvcc_flags, - } + extra_compile_args["nvcc"] = nvcc_flags if sys.platform == 'win32': define_macros += [('torchvision_EXPORTS', None)] - extra_compile_args.setdefault('cxx', []) extra_compile_args['cxx'].append('/MP') debug_mode = os.getenv('DEBUG', '0') == '1' From 70298394010e7f0fbc3a1bb40ec93092925db93b Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 264/357] add tests for SBDataset (#3467) Summary: Co-authored-by: Francisco Massa Reviewed By: fmassa Differential Revision: D26756273 fbshipit-source-id: 53f4cb3022a0d434104624fc26b7b6ad3dfbd8ae --- test/datasets_utils.py | 1 + test/test_datasets.py | 68 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 34190b2bfbc..374ab48b4b7 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -56,6 +56,7 @@ class LazyImporter: "pycocotools", "requests", "scipy.io", + "scipy.sparse", ) def __init__(self): diff --git a/test/test_datasets.py b/test/test_datasets.py index 45cf432e72b..fc2f658b632 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1193,5 +1193,73 @@ def inject_fake_data(self, tmpdir, config): return num_images +class SBDatasetTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.SBDataset + FEATURE_TYPES = (PIL.Image.Image, (np.ndarray, PIL.Image.Image)) + + REQUIRED_PACKAGES = ("scipy.io", "scipy.sparse") + + CONFIGS = datasets_utils.combinations_grid( + image_set=("train", "val", "train_noval"), mode=("boundaries", "segmentation") + ) + + _NUM_CLASSES = 20 + + def inject_fake_data(self, tmpdir, config): + num_images, num_images_per_image_set = self._create_split_files(tmpdir) + + sizes = self._create_target_folder(tmpdir, "cls", num_images) + + datasets_utils.create_image_folder( + tmpdir, "img", lambda idx: f"{self._file_stem(idx)}.jpg", num_images, size=lambda idx: sizes[idx] + ) + + return num_images_per_image_set[config["image_set"]] + + def _create_split_files(self, root): + root = pathlib.Path(root) + + splits = dict(train=(0, 1, 2), train_noval=(0, 2), val=(3,)) + + for split, idcs in splits.items(): + self._create_split_file(root, split, idcs) + + num_images = max(itertools.chain(*splits.values())) + 1 + num_images_per_split = dict([(split, len(idcs)) for split, idcs in splits.items()]) + return num_images, num_images_per_split + + def _create_split_file(self, root, name, idcs): + with open(root / f"{name}.txt", "w") as fh: + fh.writelines(f"{self._file_stem(idx)}\n" for idx in idcs) + + def _create_target_folder(self, root, name, num_images): + io = datasets_utils.lazy_importer.scipy.io + + target_folder = pathlib.Path(root) / name + os.makedirs(target_folder) + + sizes = [torch.randint(1, 4, size=(2,)).tolist() for _ in range(num_images)] + for idx, size in enumerate(sizes): + content = dict( + GTcls=dict(Boundaries=self._create_boundaries(size), Segmentation=self._create_segmentation(size)) + ) + io.savemat(target_folder / f"{self._file_stem(idx)}.mat", content) + + return sizes + + def _create_boundaries(self, size): + sparse = datasets_utils.lazy_importer.scipy.sparse + return [ + [sparse.csc_matrix(torch.randint(0, 2, size=size, dtype=torch.uint8).numpy())] + for _ in range(self._NUM_CLASSES) + ] + + def _create_segmentation(self, size): + return torch.randint(0, self._NUM_CLASSES + 1, size=size, dtype=torch.uint8).numpy() + + def _file_stem(self, idx): + return f"2008_{idx:06d}" + + if __name__ == "__main__": unittest.main() From ffd6a1bf092be6f6ace9cdfff115e88ea33a60fa Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 265/357] Run CI unittests in parallel (#3445) Summary: * enable parallel tests * disable parallelism for GPU tests * [test] limit maximum processes on linux * [debug] limit max processes even further * [test] use subprocesses over threads * [test] limit intra-op threads * only limit intra op threads for CPU tests * [poc] use low timeout for showcasing * [poc] fix syntax * set timeout to 5 minutes * fix timeout on windows Reviewed By: fmassa Differential Revision: D26756257 fbshipit-source-id: f2fc4753a67a1505f01116119926eec365693ab9 Co-authored-by: Francisco Massa --- .../unittest/linux/scripts/environment.yml | 2 ++ .circleci/unittest/linux/scripts/run_test.sh | 17 ++++++++++++++++- .../unittest/windows/scripts/environment.yml | 2 ++ .circleci/unittest/windows/scripts/run_test.sh | 17 ++++++++++++++++- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/.circleci/unittest/linux/scripts/environment.yml b/.circleci/unittest/linux/scripts/environment.yml index dcad1abfa31..04aa9007e88 100644 --- a/.circleci/unittest/linux/scripts/environment.yml +++ b/.circleci/unittest/linux/scripts/environment.yml @@ -5,6 +5,8 @@ channels: - conda-forge dependencies: - pytest + - pytest-xdist + - pytest-timeout - pytest-cov - codecov - pip diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh index 419b9eb562c..a0a2e0dae3f 100755 --- a/.circleci/unittest/linux/scripts/run_test.sh +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -6,5 +6,20 @@ eval "$(./conda/bin/conda shell.bash hook)" conda activate ./env export PYTORCH_TEST_WITH_SLOW='1' +if [ "${CU_VERSION:-}" == cpu ] ; then + NUMPROCESSES="auto" + export OMP_NUM_THREADS="1" +else + NUMPROCESSES="1" +fi + python -m torch.utils.collect_env -pytest --cov=torchvision --junitxml=test-results/junit.xml -v --durations 20 test --ignore=test/test_datasets_download.py +pytest \ + --numprocesses=$NUMPROCESSES \ + --timeout=300 \ + --cov=torchvision \ + --junitxml=test-results/junit.xml \ + --verbose \ + --durations 20 \ + --ignore=test/test_datasets_download.py \ + test diff --git a/.circleci/unittest/windows/scripts/environment.yml b/.circleci/unittest/windows/scripts/environment.yml index b4f32cb3cad..069d57e1e03 100644 --- a/.circleci/unittest/windows/scripts/environment.yml +++ b/.circleci/unittest/windows/scripts/environment.yml @@ -5,6 +5,8 @@ channels: - conda-forge dependencies: - pytest + - pytest-xdist + - pytest-timeout - pytest-cov - codecov - pip diff --git a/.circleci/unittest/windows/scripts/run_test.sh b/.circleci/unittest/windows/scripts/run_test.sh index 96d9cbd6b2d..a70956347ac 100644 --- a/.circleci/unittest/windows/scripts/run_test.sh +++ b/.circleci/unittest/windows/scripts/run_test.sh @@ -6,5 +6,20 @@ eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" conda activate ./env export PYTORCH_TEST_WITH_SLOW='1' +if [ "${CU_VERSION:-}" == cpu ] ; then + NUMPROCESSES="auto" + export OMP_NUM_THREADS="1" +else + NUMPROCESSES="1" +fi + python -m torch.utils.collect_env -pytest --cov=torchvision --junitxml=test-results/junit.xml -v --durations 20 test --ignore=test/test_datasets_download.py +pytest \ + --numprocesses=$NUMPROCESSES \ + --timeout=300 \ + --cov=torchvision \ + --junitxml=test-results/junit.xml \ + --verbose \ + --durations 20 \ + --ignore=test/test_datasets_download.py \ + test From 01ce86569fb31abc3f6f9bfdfe99007c045b3eba Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 266/357] add tests for FakeData dataset (#3468) Summary: * add tests for FakeData dataset * improve skip reason Reviewed By: fmassa Differential Revision: D26756267 fbshipit-source-id: 0b0479a1157b79943b95d02003dc075a1d14f3ac Co-authored-by: Vasilis Vryniotis --- test/test_datasets.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index fc2f658b632..09867278744 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1261,5 +1261,19 @@ def _file_stem(self, idx): return f"2008_{idx:06d}" +class FakeDataTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.FakeData + FEATURE_TYPES = (PIL.Image.Image, torch.Tensor) + + def dataset_args(self, tmpdir, config): + return () + + def inject_fake_data(self, tmpdir, config): + return config["size"] + + def test_not_found_or_corrupted(self): + self.skipTest("The data is generated at creation and thus cannot be non-existent or corrupted.") + + if __name__ == "__main__": unittest.main() From a47b112e57d6c42f4d02d0f77289b26527d0df22 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 267/357] Revert "Run CI unittests in parallel (#3445)" (#3480) Summary: This reverts commit 4fcaee0fe9af5ca2e4facaef69c292541fd34038. Reviewed By: fmassa Differential Revision: D26756268 fbshipit-source-id: ff1c180d64dede17412787e9edd4fc525c4aecb9 --- .../unittest/linux/scripts/environment.yml | 2 -- .circleci/unittest/linux/scripts/run_test.sh | 17 +---------------- .../unittest/windows/scripts/environment.yml | 2 -- .circleci/unittest/windows/scripts/run_test.sh | 17 +---------------- 4 files changed, 2 insertions(+), 36 deletions(-) diff --git a/.circleci/unittest/linux/scripts/environment.yml b/.circleci/unittest/linux/scripts/environment.yml index 04aa9007e88..dcad1abfa31 100644 --- a/.circleci/unittest/linux/scripts/environment.yml +++ b/.circleci/unittest/linux/scripts/environment.yml @@ -5,8 +5,6 @@ channels: - conda-forge dependencies: - pytest - - pytest-xdist - - pytest-timeout - pytest-cov - codecov - pip diff --git a/.circleci/unittest/linux/scripts/run_test.sh b/.circleci/unittest/linux/scripts/run_test.sh index a0a2e0dae3f..419b9eb562c 100755 --- a/.circleci/unittest/linux/scripts/run_test.sh +++ b/.circleci/unittest/linux/scripts/run_test.sh @@ -6,20 +6,5 @@ eval "$(./conda/bin/conda shell.bash hook)" conda activate ./env export PYTORCH_TEST_WITH_SLOW='1' -if [ "${CU_VERSION:-}" == cpu ] ; then - NUMPROCESSES="auto" - export OMP_NUM_THREADS="1" -else - NUMPROCESSES="1" -fi - python -m torch.utils.collect_env -pytest \ - --numprocesses=$NUMPROCESSES \ - --timeout=300 \ - --cov=torchvision \ - --junitxml=test-results/junit.xml \ - --verbose \ - --durations 20 \ - --ignore=test/test_datasets_download.py \ - test +pytest --cov=torchvision --junitxml=test-results/junit.xml -v --durations 20 test --ignore=test/test_datasets_download.py diff --git a/.circleci/unittest/windows/scripts/environment.yml b/.circleci/unittest/windows/scripts/environment.yml index 069d57e1e03..b4f32cb3cad 100644 --- a/.circleci/unittest/windows/scripts/environment.yml +++ b/.circleci/unittest/windows/scripts/environment.yml @@ -5,8 +5,6 @@ channels: - conda-forge dependencies: - pytest - - pytest-xdist - - pytest-timeout - pytest-cov - codecov - pip diff --git a/.circleci/unittest/windows/scripts/run_test.sh b/.circleci/unittest/windows/scripts/run_test.sh index a70956347ac..96d9cbd6b2d 100644 --- a/.circleci/unittest/windows/scripts/run_test.sh +++ b/.circleci/unittest/windows/scripts/run_test.sh @@ -6,20 +6,5 @@ eval "$(./conda/Scripts/conda.exe 'shell.bash' 'hook')" conda activate ./env export PYTORCH_TEST_WITH_SLOW='1' -if [ "${CU_VERSION:-}" == cpu ] ; then - NUMPROCESSES="auto" - export OMP_NUM_THREADS="1" -else - NUMPROCESSES="1" -fi - python -m torch.utils.collect_env -pytest \ - --numprocesses=$NUMPROCESSES \ - --timeout=300 \ - --cov=torchvision \ - --junitxml=test-results/junit.xml \ - --verbose \ - --durations 20 \ - --ignore=test/test_datasets_download.py \ - test +pytest --cov=torchvision --junitxml=test-results/junit.xml -v --durations 20 test --ignore=test/test_datasets_download.py From 31baa4abeef5978de413278b5369b5ba03e85b59 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 268/357] Increase tolerance in scripted models (#3479) Reviewed By: fmassa Differential Revision: D26756264 fbshipit-source-id: d9667961b4a4f6e02c7be6d571804b51f297b6de --- test/common_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/common_utils.py b/test/common_utils.py index a0fb7781899..6f9dc9af932 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -330,7 +330,7 @@ def assertExportImportModule(self, m, args): results = m(*args) with freeze_rng_state(): results_from_imported = m_import(*args) - self.assertEqual(results, results_from_imported) + self.assertEqual(results, results_from_imported, prec=3e-5) @contextlib.contextmanager From 87b2a98cf042c658ecee85420deaa6032f5e5576 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 269/357] Fix lazy importing for dataset tests (#3481) Reviewed By: fmassa Differential Revision: D26756263 fbshipit-source-id: 829bd945fdfe560a97f35c53111c5a875958e8e0 --- test/datasets_utils.py | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 374ab48b4b7..369aaca42dd 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -10,6 +10,7 @@ import string import unittest import unittest.mock +from collections import defaultdict from typing import Any, Callable, Dict, Iterator, List, Optional, Sequence, Tuple, Union import PIL @@ -60,26 +61,42 @@ class LazyImporter: ) def __init__(self): - cls = type(self) + modules = defaultdict(list) for module in self.MODULES: - # We need the quirky 'module=module' argument to the lambda since otherwise the lookup for 'module' in this - # scope would happen at runtime rather than at definition. Thus, without it, every property would try to - # import the last 'module' in MODULES. - setattr(cls, module.split(".", 1)[0], property(lambda self, module=module: LazyImporter._import(module))) + module, *submodules = module.split(".", 1) + if submodules: + modules[module].append(submodules[0]) + else: + # This introduces the module so that it is known when we later iterate over the dictionary. + modules.__missing__(module) + + for module, submodules in modules.items(): + # We need the quirky 'module=module' and submodules=submodules arguments to the lambda since otherwise the + # lookup for these would happen at runtime rather than at definition. Thus, without it, every property + # would try to import the last item in 'modules' + setattr( + type(self), + module, + property(lambda self, module=module, submodules=submodules: LazyImporter._import(module, submodules)), + ) @staticmethod - def _import(module): + def _import(package, subpackages): try: - importlib.import_module(module) - return importlib.import_module(module.split(".", 1)[0]) + module = importlib.import_module(package) except ImportError as error: raise UsageError( - f"Failed to import module '{module}'. " - f"This probably means that the current test case needs '{module}' installed, " + f"Failed to import module '{package}'. " + f"This probably means that the current test case needs '{package}' installed, " f"but it is not a dependency of torchvision. " - f"You need to install it manually, for example 'pip install {module}'." + f"You need to install it manually, for example 'pip install {package}'." ) from error + for name in subpackages: + importlib.import_module(f".{name}", package=package) + + return module + lazy_importer = LazyImporter() From 2b2fc2f27ffbded74cdca3840c435cabef66a8d2 Mon Sep 17 00:00:00 2001 From: George Guanheng Zhang Date: Thu, 4 Mar 2021 08:35:03 -0800 Subject: [PATCH 270/357] Add tests for the PhotoTour dataset (#3486) Summary: * add tests for PhotoTour dataset * fix grayscale image generation * fix test_feature_types for a examples of a single feature * make image size variable instead of hard coding it * make dataset length variable instead of hard coding it * replace numpy with torch * fix typo Reviewed By: fmassa Differential Revision: D26756270 fbshipit-source-id: 62a8a7508be74580ca462089131f1aff4dd020cb --- test/datasets_utils.py | 27 +++++++---- test/test_datasets.py | 79 +++++++++++++++++++++++++++++++ torchvision/datasets/phototour.py | 8 ++-- 3 files changed, 100 insertions(+), 14 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 369aaca42dd..577bdb2eb32 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -436,14 +436,17 @@ def test_feature_types(self, config): with self.create_dataset(config) as (dataset, _): example = dataset[0] - actual = len(example) - expected = len(self.FEATURE_TYPES) - self.assertEqual( - actual, - expected, - f"The number of the returned features does not match the the number of elements in in FEATURE_TYPES: " - f"{actual} != {expected}", - ) + if len(self.FEATURE_TYPES) > 1: + actual = len(example) + expected = len(self.FEATURE_TYPES) + self.assertEqual( + actual, + expected, + f"The number of the returned features does not match the the number of elements in FEATURE_TYPES: " + f"{actual} != {expected}", + ) + else: + example = (example,) for idx, (feature, expected_feature_type) in enumerate(zip(example, self.FEATURE_TYPES)): with self.subTest(idx=idx): @@ -586,7 +589,13 @@ def create_image_file( image = create_image_or_video_tensor(size) file = pathlib.Path(root) / name - PIL.Image.fromarray(image.permute(2, 1, 0).numpy()).save(file, **kwargs) + + # torch (num_channels x height x width) -> PIL (width x height x num_channels) + image = image.permute(2, 1, 0) + # For grayscale images PIL doesn't use a channel dimension + if image.shape[2] == 1: + image = torch.squeeze(image, 2) + PIL.Image.fromarray(image.numpy()).save(file, **kwargs) return file diff --git a/test/test_datasets.py b/test/test_datasets.py index 09867278744..859419df2b0 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -27,6 +27,7 @@ import torch.nn.functional as F import string import io +import zipfile try: @@ -1275,5 +1276,83 @@ def test_not_found_or_corrupted(self): self.skipTest("The data is generated at creation and thus cannot be non-existent or corrupted.") +class PhotoTourTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.PhotoTour + + # The PhotoTour dataset returns examples with different features with respect to the 'train' parameter. Thus, + # we overwrite 'FEATURE_TYPES' with a dummy value to satisfy the initial checks of the base class. Furthermore, we + # overwrite the 'test_feature_types()' method to select the correct feature types before the test is run. + FEATURE_TYPES = () + _TRAIN_FEATURE_TYPES = (torch.Tensor,) + _TEST_FEATURE_TYPES = (torch.Tensor, torch.Tensor, torch.Tensor) + + CONFIGS = datasets_utils.combinations_grid(train=(True, False)) + + _NAME = "liberty" + + def dataset_args(self, tmpdir, config): + return tmpdir, self._NAME + + def inject_fake_data(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) + + # In contrast to the original data, the fake images injected here comprise only a single patch. Thus, + # num_images == num_patches. + num_patches = 5 + + image_files = self._create_images(tmpdir, self._NAME, num_patches) + point_ids, info_file = self._create_info_file(tmpdir / self._NAME, num_patches) + num_matches, matches_file = self._create_matches_file(tmpdir / self._NAME, num_patches, point_ids) + + self._create_archive(tmpdir, self._NAME, *image_files, info_file, matches_file) + + return num_patches if config["train"] else num_matches + + def _create_images(self, root, name, num_images): + # The images in the PhotoTour dataset comprises of multiple grayscale patches of 64 x 64 pixels. Thus, the + # smallest fake image is 64 x 64 pixels and comprises a single patch. + return datasets_utils.create_image_folder( + root, name, lambda idx: f"patches{idx:04d}.bmp", num_images, size=(1, 64, 64) + ) + + def _create_info_file(self, root, num_images): + point_ids = torch.randint(num_images, size=(num_images,)).tolist() + + file = root / "info.txt" + with open(file, "w") as fh: + fh.writelines([f"{point_id} 0\n" for point_id in point_ids]) + + return point_ids, file + + def _create_matches_file(self, root, num_patches, point_ids): + lines = [ + f"{patch_id1} {point_ids[patch_id1]} 0 {patch_id2} {point_ids[patch_id2]} 0\n" + for patch_id1, patch_id2 in itertools.combinations(range(num_patches), 2) + ] + + file = root / "m50_100000_100000_0.txt" + with open(file, "w") as fh: + fh.writelines(lines) + + return len(lines), file + + def _create_archive(self, root, name, *files): + archive = root / f"{name}.zip" + with zipfile.ZipFile(archive, "w") as zip: + for file in files: + zip.write(file, arcname=file.relative_to(root)) + + return archive + + @datasets_utils.test_all_configs + def test_feature_types(self, config): + feature_types = self.FEATURE_TYPES + self.FEATURE_TYPES = self._TRAIN_FEATURE_TYPES if config["train"] else self._TEST_FEATURE_TYPES + try: + super().test_feature_types.__wrapped__(self, config) + finally: + self.FEATURE_TYPES = feature_types + + if __name__ == "__main__": unittest.main() diff --git a/torchvision/datasets/phototour.py b/torchvision/datasets/phototour.py index 2b657b8bfb6..dead2337495 100644 --- a/torchvision/datasets/phototour.py +++ b/torchvision/datasets/phototour.py @@ -121,9 +121,7 @@ def __getitem__(self, index: int) -> Union[torch.Tensor, Tuple[Any, Any, torch.T return data1, data2, m[2] def __len__(self) -> int: - if self.train: - return self.lens[self.name] - return len(self.matches) + return len(self.data if self.train else self.matches) def _check_datafile_exists(self) -> bool: return os.path.exists(self.data_file) @@ -194,8 +192,8 @@ def find_files(_data_dir: str, _image_ext: str) -> List[str]: for fpath in list_files: img = Image.open(fpath) - for y in range(0, 1024, 64): - for x in range(0, 1024, 64): + for y in range(0, img.height, 64): + for x in range(0, img.width, 64): patch = img.crop((x, y, x + 64, y + 64)) patches.append(PIL2array(patch)) return torch.ByteTensor(np.array(patches[:n])) From a68fa20ec3819db49e1a0bfadf8faccbce0275f7 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 271/357] [fbsync] fixed Gamma casting (#3472) Summary: * fixed origin head * fixed inconsistent casting * updated functional_tensor.py Modified the .to() method to convert_image_dtype() method. * Apply suggestions from code review Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945731 fbshipit-source-id: eab2e30c37bc1d29cae2d0921c869af22b49866a Co-authored-by: Vasilis Vryniotis --- torchvision/transforms/functional_tensor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/torchvision/transforms/functional_tensor.py b/torchvision/transforms/functional_tensor.py index 69445e6a231..d20d24a8413 100644 --- a/torchvision/transforms/functional_tensor.py +++ b/torchvision/transforms/functional_tensor.py @@ -227,7 +227,6 @@ def adjust_gamma(img: Tensor, gamma: float, gain: float = 1) -> Tensor: result = (gain * result ** gamma).clamp(0, 1) result = convert_image_dtype(result, dtype) - result = result.to(dtype) return result From 6715a72d27efc4c150b632571fee452c49b67346 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 272/357] [fbsync] add __repr__ for transforms.RandomErasing (#3491) Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945734 fbshipit-source-id: 608c2fa2bd7fc256484c9993c628ca568a4f23d0 --- test/test_transforms.py | 3 +++ torchvision/transforms/transforms.py | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/test/test_transforms.py b/test/test_transforms.py index 392978d988b..0b71bae788b 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -1991,6 +1991,9 @@ def test_random_erasing(self): p_value = stats.binom_test(count_bigger_then_ones, trial, p=0.5) self.assertGreater(p_value, 0.0001) + # Checking if RandomErasing can be printed as string + t.__repr__() + if __name__ == '__main__': unittest.main() diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 916956e29fd..4eb0ab23c92 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -1630,6 +1630,14 @@ def forward(self, img): return F.erase(img, x, y, h, w, v, self.inplace) return img + def __repr__(self): + s = '(p={}, '.format(self.p) + s += 'scale={}, '.format(self.scale) + s += 'ratio={}, '.format(self.ratio) + s += 'value={}, '.format(self.value) + s += 'inplace={})'.format(self.inplace) + return self.__class__.__name__ + s + class GaussianBlur(torch.nn.Module): """Blurs image with randomly chosen Gaussian blur. From d4ff1ba5fc2b6ef87461e61e4e1b4c1a2a616b62 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 273/357] [fbsync] add custom user agent for download_url (#3498) Summary: * add custom user agent for download_url * fix progress bar * lint * [test] use repo instead of nightly for download tests Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945735 fbshipit-source-id: 6030e0927dda95afb63f32aceacfc3b479bf3f9f --- .github/workflows/tests-schedule.yml | 9 +++++---- test/test_datasets_download.py | 7 ++++--- torchvision/datasets/utils.py | 29 ++++++++++++++++++---------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/.github/workflows/tests-schedule.yml b/.github/workflows/tests-schedule.yml index aede262fafe..65f805ce471 100644 --- a/.github/workflows/tests-schedule.yml +++ b/.github/workflows/tests-schedule.yml @@ -26,10 +26,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 - - name: Install PyTorch from the nightlies - run: | - pip install numpy - pip install --pre torch torchvision -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html + - name: Install torch nightly build + run: pip install --pre torch -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html + + - name: Install torchvision + run: pip install -e . - name: Install all optional dataset requirements run: pip install scipy pandas pycocotools lmdb requests diff --git a/test/test_datasets_download.py b/test/test_datasets_download.py index 82fce713f14..5c4fc54fd5d 100644 --- a/test/test_datasets_download.py +++ b/test/test_datasets_download.py @@ -14,7 +14,7 @@ import pytest from torchvision import datasets -from torchvision.datasets.utils import download_url, check_integrity, download_file_from_google_drive +from torchvision.datasets.utils import download_url, check_integrity, download_file_from_google_drive, USER_AGENT from common_utils import get_tmp_dir from fakedata_generation import places365_root @@ -150,7 +150,7 @@ def assert_server_response_ok(): def assert_url_is_accessible(url, timeout=5.0): - request = Request(url, headers=dict(method="HEAD")) + request = Request(url, headers={"method": "HEAD", "User-Agent": USER_AGENT}) with assert_server_response_ok(): urlopen(request, timeout=timeout) @@ -160,7 +160,8 @@ def assert_file_downloads_correctly(url, md5, timeout=5.0): file = path.join(root, path.basename(url)) with assert_server_response_ok(): with open(file, "wb") as fh: - response = urlopen(url, timeout=timeout) + request = Request(url, headers={"User-Agent": USER_AGENT}) + response = urlopen(request, timeout=timeout) fh.write(response.read()) assert check_integrity(file, md5=md5), "The MD5 checksums mismatch" diff --git a/torchvision/datasets/utils.py b/torchvision/datasets/utils.py index 1bd3d3c8053..a27363c533c 100644 --- a/torchvision/datasets/utils.py +++ b/torchvision/datasets/utils.py @@ -7,11 +7,28 @@ from typing import Any, Callable, List, Iterable, Optional, TypeVar from urllib.parse import urlparse import zipfile +import urllib +import urllib.request +import urllib.error import torch from torch.utils.model_zoo import tqdm +USER_AGENT = "pytorch/vision" + + +def _urlretrieve(url: str, filename: str, chunk_size: int = 1024) -> None: + with open(filename, "wb") as fh: + with urllib.request.urlopen(urllib.request.Request(url, headers={"User-Agent": USER_AGENT})) as response: + with tqdm(total=response.length) as pbar: + for chunk in iter(lambda: response.read(chunk_size), ""): + if not chunk: + break + pbar.update(chunk_size) + fh.write(chunk) + + def gen_bar_updater() -> Callable[[int, int, int], None]: pbar = tqdm(total=None) @@ -83,8 +100,6 @@ def download_url( md5 (str, optional): MD5 checksum of the download. If None, do not check max_redirect_hops (int, optional): Maximum number of redirect hops allowed """ - import urllib - root = os.path.expanduser(root) if not filename: filename = os.path.basename(url) @@ -108,19 +123,13 @@ def download_url( # download the file try: print('Downloading ' + url + ' to ' + fpath) - urllib.request.urlretrieve( - url, fpath, - reporthook=gen_bar_updater() - ) + _urlretrieve(url, fpath) except (urllib.error.URLError, IOError) as e: # type: ignore[attr-defined] if url[:5] == 'https': url = url.replace('https:', 'http:') print('Failed download. Trying https -> http instead.' ' Downloading ' + url + ' to ' + fpath) - urllib.request.urlretrieve( - url, fpath, - reporthook=gen_bar_updater() - ) + _urlretrieve(url, fpath) else: raise e # check integrity of downloaded file From e0e73afe73955a0b04c4638662fa44fca1bb957c Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 274/357] [fbsync] [TRANS, IMP] Add new max_size parameter to Resize (#3494) Summary: * WIP, still needs tests and docs * tests * flake8 * Docs + fixed some tests * proper error messages Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945732 fbshipit-source-id: 765c48af203ba27894881dea596f94d2f4a6794d --- test/test_functional_tensor.py | 72 ++++++++++++--------- test/test_transforms.py | 41 +++++++----- test/test_transforms_tensor.py | 30 ++++----- torchvision/transforms/functional.py | 15 ++++- torchvision/transforms/functional_pil.py | 39 +++++++---- torchvision/transforms/functional_tensor.py | 49 +++++++++----- torchvision/transforms/transforms.py | 16 ++++- 7 files changed, 164 insertions(+), 98 deletions(-) diff --git a/test/test_functional_tensor.py b/test/test_functional_tensor.py index c043e90129f..f1219ff7ce9 100644 --- a/test/test_functional_tensor.py +++ b/test/test_functional_tensor.py @@ -13,7 +13,7 @@ from common_utils import TransformsTester -from typing import Dict, List, Tuple +from typing import Dict, List, Sequence, Tuple NEAREST, BILINEAR, BICUBIC = InterpolationMode.NEAREST, InterpolationMode.BILINEAR, InterpolationMode.BICUBIC @@ -409,39 +409,44 @@ def test_resize(self): batch_tensors = batch_tensors.to(dt) for size in [32, 26, [32, ], [32, 32], (32, 32), [26, 35]]: - for interpolation in [BILINEAR, BICUBIC, NEAREST]: - resized_tensor = F.resize(tensor, size=size, interpolation=interpolation) - resized_pil_img = F.resize(pil_img, size=size, interpolation=interpolation) - - self.assertEqual( - resized_tensor.size()[1:], resized_pil_img.size[::-1], msg="{}, {}".format(size, interpolation) - ) - - if interpolation not in [NEAREST, ]: - # We can not check values if mode = NEAREST, as results are different - # E.g. resized_tensor = [[a, a, b, c, d, d, e, ...]] - # E.g. resized_pil_img = [[a, b, c, c, d, e, f, ...]] - resized_tensor_f = resized_tensor - # we need to cast to uint8 to compare with PIL image - if resized_tensor_f.dtype == torch.uint8: - resized_tensor_f = resized_tensor_f.to(torch.float) - - # Pay attention to high tolerance for MAE - self.approxEqualTensorToPIL( - resized_tensor_f, resized_pil_img, tol=8.0, msg="{}, {}".format(size, interpolation) + for max_size in (None, 33, 40, 1000): + if max_size is not None and isinstance(size, Sequence) and len(size) != 1: + continue # unsupported, see assertRaises below + for interpolation in [BILINEAR, BICUBIC, NEAREST]: + resized_tensor = F.resize(tensor, size=size, interpolation=interpolation, max_size=max_size) + resized_pil_img = F.resize(pil_img, size=size, interpolation=interpolation, max_size=max_size) + + self.assertEqual( + resized_tensor.size()[1:], resized_pil_img.size[::-1], + msg="{}, {}".format(size, interpolation) ) - if isinstance(size, int): - script_size = [size, ] - else: - script_size = size + if interpolation not in [NEAREST, ]: + # We can not check values if mode = NEAREST, as results are different + # E.g. resized_tensor = [[a, a, b, c, d, d, e, ...]] + # E.g. resized_pil_img = [[a, b, c, c, d, e, f, ...]] + resized_tensor_f = resized_tensor + # we need to cast to uint8 to compare with PIL image + if resized_tensor_f.dtype == torch.uint8: + resized_tensor_f = resized_tensor_f.to(torch.float) + + # Pay attention to high tolerance for MAE + self.approxEqualTensorToPIL( + resized_tensor_f, resized_pil_img, tol=8.0, msg="{}, {}".format(size, interpolation) + ) - resize_result = script_fn(tensor, size=script_size, interpolation=interpolation) - self.assertTrue(resized_tensor.equal(resize_result), msg="{}, {}".format(size, interpolation)) + if isinstance(size, int): + script_size = [size, ] + else: + script_size = size - self._test_fn_on_batch( - batch_tensors, F.resize, size=script_size, interpolation=interpolation - ) + resize_result = script_fn(tensor, size=script_size, interpolation=interpolation, + max_size=max_size) + self.assertTrue(resized_tensor.equal(resize_result), msg="{}, {}".format(size, interpolation)) + + self._test_fn_on_batch( + batch_tensors, F.resize, size=script_size, interpolation=interpolation, max_size=max_size + ) # assert changed type warning with self.assertWarnsRegex(UserWarning, r"Argument interpolation should be of type InterpolationMode"): @@ -449,6 +454,13 @@ def test_resize(self): res2 = F.resize(tensor, size=32, interpolation=BILINEAR) self.assertTrue(res1.equal(res2)) + for img in (tensor, pil_img): + exp_msg = "max_size should only be passed if size specifies the length of the smaller edge" + with self.assertRaisesRegex(ValueError, exp_msg): + F.resize(img, size=(32, 34), max_size=35) + with self.assertRaisesRegex(ValueError, "max_size = 32 must be strictly greater"): + F.resize(img, size=32, max_size=32) + def test_resized_crop(self): # test values of F.resized_crop in several cases: # 1) resize to the same size, crop to the same size => should be identity diff --git a/test/test_transforms.py b/test/test_transforms.py index 0b71bae788b..0a01247aa87 100644 --- a/test/test_transforms.py +++ b/test/test_transforms.py @@ -312,23 +312,30 @@ def test_resize(self): img = Image.new("RGB", size=(width, height), color=127) for osize in test_output_sizes_1: - - t = transforms.Resize(osize) - result = t(img) - - msg = "{}, {} - {}".format(height, width, osize) - osize = osize[0] if isinstance(osize, (list, tuple)) else osize - # If size is an int, smaller edge of the image will be matched to this number. - # i.e, if height > width, then image will be rescaled to (size * height / width, size). - if height < width: - expected_size = (int(osize * width / height), osize) # (w, h) - self.assertEqual(result.size, expected_size, msg=msg) - elif width < height: - expected_size = (osize, int(osize * height / width)) # (w, h) - self.assertEqual(result.size, expected_size, msg=msg) - else: - expected_size = (osize, osize) # (w, h) - self.assertEqual(result.size, expected_size, msg=msg) + for max_size in (None, 37, 1000): + + t = transforms.Resize(osize, max_size=max_size) + result = t(img) + + msg = "{}, {} - {} - {}".format(height, width, osize, max_size) + osize = osize[0] if isinstance(osize, (list, tuple)) else osize + # If size is an int, smaller edge of the image will be matched to this number. + # i.e, if height > width, then image will be rescaled to (size * height / width, size). + if height < width: + exp_w, exp_h = (int(osize * width / height), osize) # (w, h) + if max_size is not None and max_size < exp_w: + exp_w, exp_h = max_size, int(max_size * exp_h / exp_w) + self.assertEqual(result.size, (exp_w, exp_h), msg=msg) + elif width < height: + exp_w, exp_h = (osize, int(osize * height / width)) # (w, h) + if max_size is not None and max_size < exp_h: + exp_w, exp_h = int(max_size * exp_w / exp_h), max_size + self.assertEqual(result.size, (exp_w, exp_h), msg=msg) + else: + exp_w, exp_h = (osize, osize) # (w, h) + if max_size is not None and max_size < osize: + exp_w, exp_h = max_size, max_size + self.assertEqual(result.size, (exp_w, exp_h), msg=msg) for height, width in input_sizes: img = Image.new("RGB", size=(width, height), color=127) diff --git a/test/test_transforms_tensor.py b/test/test_transforms_tensor.py index 3263dd3e5dd..5ba63b9b6d3 100644 --- a/test/test_transforms_tensor.py +++ b/test/test_transforms_tensor.py @@ -7,6 +7,7 @@ import numpy as np import unittest +from typing import Sequence from common_utils import TransformsTester, get_tmp_dir, int_dtypes, float_dtypes @@ -322,32 +323,29 @@ def test_resize(self): tensor, _ = self._create_data(height=34, width=36, device=self.device) batch_tensors = torch.randint(0, 256, size=(4, 3, 44, 56), dtype=torch.uint8, device=self.device) - script_fn = torch.jit.script(F.resize) for dt in [None, torch.float32, torch.float64]: if dt is not None: # This is a trivial cast to float of uint8 data to test all cases tensor = tensor.to(dt) for size in [32, 34, [32, ], [32, 32], (32, 32), [34, 35]]: - for interpolation in [BILINEAR, BICUBIC, NEAREST]: + for max_size in (None, 35, 1000): + if max_size is not None and isinstance(size, Sequence) and len(size) != 1: + continue # Not supported + for interpolation in [BILINEAR, BICUBIC, NEAREST]: - resized_tensor = F.resize(tensor, size=size, interpolation=interpolation) + if isinstance(size, int): + script_size = [size, ] + else: + script_size = size - if isinstance(size, int): - script_size = [size, ] - else: - script_size = size - - s_resized_tensor = script_fn(tensor, size=script_size, interpolation=interpolation) - self.assertTrue(s_resized_tensor.equal(resized_tensor)) - - transform = T.Resize(size=script_size, interpolation=interpolation) - s_transform = torch.jit.script(transform) - self._test_transform_vs_scripted(transform, s_transform, tensor) - self._test_transform_vs_scripted_on_batch(transform, s_transform, batch_tensors) + transform = T.Resize(size=script_size, interpolation=interpolation, max_size=max_size) + s_transform = torch.jit.script(transform) + self._test_transform_vs_scripted(transform, s_transform, tensor) + self._test_transform_vs_scripted_on_batch(transform, s_transform, batch_tensors) with get_tmp_dir() as tmp_dir: - script_fn.save(os.path.join(tmp_dir, "t_resize.pt")) + s_transform.save(os.path.join(tmp_dir, "t_resize.pt")) def test_resized_crop(self): tensor = torch.randint(0, 256, size=(3, 44, 56), dtype=torch.uint8, device=self.device) diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 34ea8de6ad0..5b630e72c75 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -337,7 +337,8 @@ def normalize(tensor: Tensor, mean: List[float], std: List[float], inplace: bool return tensor -def resize(img: Tensor, size: List[int], interpolation: InterpolationMode = InterpolationMode.BILINEAR) -> Tensor: +def resize(img: Tensor, size: List[int], interpolation: InterpolationMode = InterpolationMode.BILINEAR, + max_size: Optional[int] = None) -> Tensor: r"""Resize the input image to the given size. If the image is torch Tensor, it is expected to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions @@ -355,6 +356,14 @@ def resize(img: Tensor, size: List[int], interpolation: InterpolationMode = Inte Default is ``InterpolationMode.BILINEAR``. If input is Tensor, only ``InterpolationMode.NEAREST``, ``InterpolationMode.BILINEAR`` and ``InterpolationMode.BICUBIC`` are supported. For backward compatibility integer values (e.g. ``PIL.Image.NEAREST``) are still acceptable. + max_size (int, optional): The maximum allowed for the longer edge of + the resized image: if the longer edge of the image is greater + than ``max_size`` after being resized according to ``size``, then + the image is resized again so that the longer edge is equal to + ``max_size``. As a result, ```size` might be overruled, i.e the + smaller edge may be shorter than ``size``. This is only supported + if ``size`` is an int (or a sequence of length 1 in torchscript + mode). Returns: PIL Image or Tensor: Resized image. @@ -372,9 +381,9 @@ def resize(img: Tensor, size: List[int], interpolation: InterpolationMode = Inte if not isinstance(img, torch.Tensor): pil_interpolation = pil_modes_mapping[interpolation] - return F_pil.resize(img, size=size, interpolation=pil_interpolation) + return F_pil.resize(img, size=size, interpolation=pil_interpolation, max_size=max_size) - return F_t.resize(img, size=size, interpolation=interpolation.value) + return F_t.resize(img, size=size, interpolation=interpolation.value, max_size=max_size) def scale(*args, **kwargs): diff --git a/torchvision/transforms/functional_pil.py b/torchvision/transforms/functional_pil.py index 6999a2acf5f..42d7db9f260 100644 --- a/torchvision/transforms/functional_pil.py +++ b/torchvision/transforms/functional_pil.py @@ -204,27 +204,40 @@ def crop(img: Image.Image, top: int, left: int, height: int, width: int) -> Imag @torch.jit.unused -def resize(img, size, interpolation=Image.BILINEAR): +def resize(img, size, interpolation=Image.BILINEAR, max_size=None): if not _is_pil_image(img): raise TypeError('img should be PIL Image. Got {}'.format(type(img))) if not (isinstance(size, int) or (isinstance(size, Sequence) and len(size) in (1, 2))): raise TypeError('Got inappropriate size arg: {}'.format(size)) - if isinstance(size, int) or len(size) == 1: - if isinstance(size, Sequence): - size = size[0] + if isinstance(size, Sequence) and len(size) == 1: + size = size[0] + if isinstance(size, int): w, h = img.size - if (w <= h and w == size) or (h <= w and h == size): + + short, long = (w, h) if w <= h else (h, w) + if short == size: return img - if w < h: - ow = size - oh = int(size * h / w) - return img.resize((ow, oh), interpolation) - else: - oh = size - ow = int(size * w / h) - return img.resize((ow, oh), interpolation) + + new_short, new_long = size, int(size * long / short) + + if max_size is not None: + if max_size <= size: + raise ValueError( + f"max_size = {max_size} must be strictly greater than the requested " + f"size for the smaller edge size = {size}" + ) + if new_long > max_size: + new_short, new_long = int(max_size * new_short / new_long), max_size + + new_w, new_h = (new_short, new_long) if w <= h else (new_long, new_short) + return img.resize((new_w, new_h), interpolation) else: + if max_size is not None: + raise ValueError( + "max_size should only be passed if size specifies the length of the smaller edge, " + "i.e. size should be an int or a sequence of length 1 in torchscript mode." + ) return img.resize(size[::-1], interpolation) diff --git a/torchvision/transforms/functional_tensor.py b/torchvision/transforms/functional_tensor.py index d20d24a8413..f4358bb6c8c 100644 --- a/torchvision/transforms/functional_tensor.py +++ b/torchvision/transforms/functional_tensor.py @@ -470,7 +470,7 @@ def pad(img: Tensor, padding: List[int], fill: int = 0, padding_mode: str = "con return img -def resize(img: Tensor, size: List[int], interpolation: str = "bilinear") -> Tensor: +def resize(img: Tensor, size: List[int], interpolation: str = "bilinear", max_size: Optional[int] = None) -> Tensor: _assert_image_tensor(img) if not isinstance(size, (int, tuple, list)): @@ -484,34 +484,51 @@ def resize(img: Tensor, size: List[int], interpolation: str = "bilinear") -> Ten if isinstance(size, tuple): size = list(size) - if isinstance(size, list) and len(size) not in [1, 2]: - raise ValueError("Size must be an int or a 1 or 2 element tuple/list, not a " - "{} element tuple/list".format(len(size))) + if isinstance(size, list): + if len(size) not in [1, 2]: + raise ValueError("Size must be an int or a 1 or 2 element tuple/list, not a " + "{} element tuple/list".format(len(size))) + if max_size is not None and len(size) != 1: + raise ValueError( + "max_size should only be passed if size specifies the length of the smaller edge, " + "i.e. size should be an int or a sequence of length 1 in torchscript mode." + ) w, h = _get_image_size(img) - if isinstance(size, int): - size_w, size_h = size, size - elif len(size) < 2: - size_w, size_h = size[0], size[0] - else: - size_w, size_h = size[1], size[0] # Convention (h, w) + if isinstance(size, int) or len(size) == 1: # specified size only for the smallest edge + short, long = (w, h) if w <= h else (h, w) - if isinstance(size, int) or len(size) < 2: - if w < h: - size_h = int(size_w * h / w) + if isinstance(size, int): + requested_new_short = size else: - size_w = int(size_h * w / h) + requested_new_short = size[0] - if (w <= h and w == size_w) or (h <= w and h == size_h): + if short == requested_new_short: return img + new_short, new_long = requested_new_short, int(requested_new_short * long / short) + + if max_size is not None: + if max_size <= requested_new_short: + raise ValueError( + f"max_size = {max_size} must be strictly greater than the requested " + f"size for the smaller edge size = {size}" + ) + if new_long > max_size: + new_short, new_long = int(max_size * new_short / new_long), max_size + + new_w, new_h = (new_short, new_long) if w <= h else (new_long, new_short) + + else: # specified both h and w + new_w, new_h = size[1], size[0] + img, need_cast, need_squeeze, out_dtype = _cast_squeeze_in(img, [torch.float32, torch.float64]) # Define align_corners to avoid warnings align_corners = False if interpolation in ["bilinear", "bicubic"] else None - img = interpolate(img, size=[size_h, size_w], mode=interpolation, align_corners=align_corners) + img = interpolate(img, size=[new_h, new_w], mode=interpolation, align_corners=align_corners) if interpolation == "bicubic" and out_dtype == torch.uint8: img = img.clamp(min=0, max=255) diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 4eb0ab23c92..5a62adbedd3 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -241,16 +241,25 @@ class Resize(torch.nn.Module): If input is Tensor, only ``InterpolationMode.NEAREST``, ``InterpolationMode.BILINEAR`` and ``InterpolationMode.BICUBIC`` are supported. For backward compatibility integer values (e.g. ``PIL.Image.NEAREST``) are still acceptable. + max_size (int, optional): The maximum allowed for the longer edge of + the resized image: if the longer edge of the image is greater + than ``max_size`` after being resized according to ``size``, then + the image is resized again so that the longer edge is equal to + ``max_size``. As a result, ```size` might be overruled, i.e the + smaller edge may be shorter than ``size``. This is only supported + if ``size`` is an int (or a sequence of length 1 in torchscript + mode). """ - def __init__(self, size, interpolation=InterpolationMode.BILINEAR): + def __init__(self, size, interpolation=InterpolationMode.BILINEAR, max_size=None): super().__init__() if not isinstance(size, (int, Sequence)): raise TypeError("Size should be int or sequence. Got {}".format(type(size))) if isinstance(size, Sequence) and len(size) not in (1, 2): raise ValueError("If size is a sequence, it should have 1 or 2 values") self.size = size + self.max_size = max_size # Backward compatibility with integer value if isinstance(interpolation, int): @@ -270,11 +279,12 @@ def forward(self, img): Returns: PIL Image or Tensor: Rescaled image. """ - return F.resize(img, self.size, self.interpolation) + return F.resize(img, self.size, self.interpolation, self.max_size) def __repr__(self): interpolate_str = self.interpolation.value - return self.__class__.__name__ + '(size={0}, interpolation={1})'.format(self.size, interpolate_str) + return self.__class__.__name__ + '(size={0}, interpolation={1}, max_size={2})'.format( + self.size, interpolate_str, self.max_size) class Scale(Resize): From 691e6d8fb044ce5b8229e29f8e7f20ddebb040a7 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 275/357] [fbsync] [OPS, TEST] Add onnx test for batched_nms (#3483) Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945730 fbshipit-source-id: 7fe6a13a97821754c8411b1bf50fb944407644c9 --- test/test_onnx.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/test/test_onnx.py b/test/test_onnx.py index b2a7624fc61..6145e139086 100644 --- a/test/test_onnx.py +++ b/test/test_onnx.py @@ -82,9 +82,10 @@ def to_numpy(tensor): raise def test_nms(self): - boxes = torch.rand(5, 4) - boxes[:, 2:] += torch.rand(5, 2) - scores = torch.randn(5) + num_boxes = 100 + boxes = torch.rand(num_boxes, 4) + boxes[:, 2:] += boxes[:, :2] + scores = torch.randn(num_boxes) class Module(torch.nn.Module): def forward(self, boxes, scores): @@ -92,6 +93,19 @@ def forward(self, boxes, scores): self.run_model(Module(), [(boxes, scores)]) + def test_batched_nms(self): + num_boxes = 100 + boxes = torch.rand(num_boxes, 4) + boxes[:, 2:] += boxes[:, :2] + scores = torch.randn(num_boxes) + idxs = torch.randint(0, 5, size=(num_boxes,)) + + class Module(torch.nn.Module): + def forward(self, boxes, scores, idxs): + return ops.batched_nms(boxes, scores, idxs, 0.5) + + self.run_model(Module(), [(boxes, scores, idxs)]) + def test_clip_boxes_to_image(self): boxes = torch.randn(5, 4) * 500 boxes[:, 2:] += boxes[:, :2] From 892a2dd2e467d725c58d917e820469d28d77ad87 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 276/357] [fbsync] [OPS, IMP] New batched_nms implementation (#3426) Summary: * new batched_nms implem * flake8 * hopefully fix torchscipt tests * Use where instead of nonzero * Use same threshold (4k) for CPU and GPU * Remove use of argsort * use views again * remove print * trying stuff, I don't know what's going on * previous passed onnx checks so the error isn't in _vanilla func. Trying to return vanilla now * add tracing decorators * cleanup * wip * ignore new path with ONNX * use vanilla if tracing...???? * Remove script_if_tracing decorator as it was conflicting with _is_tracing * flake8 * Improve coverage Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945728 fbshipit-source-id: 118a41e03da2939a726e5bd18f5f77b7c0ce6339 Co-authored-by: Francisco Massa --- test/test_onnx.py | 14 ++++++----- test/test_ops.py | 22 +++++++++++++++++ torchvision/ops/boxes.py | 53 +++++++++++++++++++++++++++++++--------- 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/test/test_onnx.py b/test/test_onnx.py index 6145e139086..a4170b5242f 100644 --- a/test/test_onnx.py +++ b/test/test_onnx.py @@ -1,3 +1,11 @@ +# onnxruntime requires python 3.5 or above +try: + # This import should be before that of torch + # see https://github.com/onnx/onnx/issues/2394#issuecomment-581638840 + import onnxruntime +except ImportError: + onnxruntime = None + from common_utils import set_rng_seed import io import torch @@ -13,12 +21,6 @@ from collections import OrderedDict -# onnxruntime requires python 3.5 or above -try: - import onnxruntime -except ImportError: - onnxruntime = None - import unittest from torchvision.ops._register_onnx_ops import _onnx_opset_version diff --git a/test/test_ops.py b/test/test_ops.py index 244960cebcc..24e488d0db0 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -461,6 +461,28 @@ def test_nms_cuda_float16(self): keep16 = ops.nms(boxes.to(torch.float16), scores.to(torch.float16), iou_thres) self.assertTrue(torch.all(torch.eq(keep32, keep16))) + def test_batched_nms_implementations(self): + """Make sure that both implementations of batched_nms yield identical results""" + + num_boxes = 1000 + iou_threshold = .9 + + boxes = torch.cat((torch.rand(num_boxes, 2), torch.rand(num_boxes, 2) + 10), dim=1) + assert max(boxes[:, 0]) < min(boxes[:, 2]) # x1 < x2 + assert max(boxes[:, 1]) < min(boxes[:, 3]) # y1 < y2 + + scores = torch.rand(num_boxes) + idxs = torch.randint(0, 4, size=(num_boxes,)) + keep_vanilla = ops.boxes._batched_nms_vanilla(boxes, scores, idxs, iou_threshold) + keep_trick = ops.boxes._batched_nms_coordinate_trick(boxes, scores, idxs, iou_threshold) + + err_msg = "The vanilla and the trick implementation yield different nms outputs." + self.assertTrue(torch.allclose(keep_vanilla, keep_trick), err_msg) + + # Also make sure an empty tensor is returned if boxes is empty + empty = torch.empty((0,), dtype=torch.int64) + self.assertTrue(torch.allclose(empty, ops.batched_nms(empty, None, None, None))) + class DeformConvTester(OpTester, unittest.TestCase): def expected_fn(self, x, weight, offset, mask, bias, stride=1, padding=0, dilation=1): diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index cfce618845a..47142d51527 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -1,6 +1,6 @@ import torch from torch import Tensor -from typing import Tuple +from typing import List, Tuple from ._box_convert import _box_cxcywh_to_xyxy, _box_xyxy_to_cxcywh, _box_xywh_to_xyxy, _box_xyxy_to_xywh import torchvision from torchvision.extension import _assert_has_ops @@ -36,7 +36,6 @@ def nms(boxes: Tensor, scores: Tensor, iou_threshold: float) -> Tensor: return torch.ops.torchvision.nms(boxes, scores, iou_threshold) -@torch.jit._script_if_tracing def batched_nms( boxes: Tensor, scores: Tensor, @@ -62,18 +61,50 @@ def batched_nms( the elements that have been kept by NMS, sorted in decreasing order of scores """ - if boxes.numel() == 0: - return torch.empty((0,), dtype=torch.int64, device=boxes.device) - # strategy: in order to perform NMS independently per class. + # Benchmarks that drove the following thresholds are at + # https://github.com/pytorch/vision/issues/1311#issuecomment-781329339 + # Ideally for GPU we'd use a higher threshold + if boxes.numel() > 4_000 and not torchvision._is_tracing(): + return _batched_nms_vanilla(boxes, scores, idxs, iou_threshold) + else: + return _batched_nms_coordinate_trick(boxes, scores, idxs, iou_threshold) + + +@torch.jit._script_if_tracing +def _batched_nms_coordinate_trick( + boxes: Tensor, + scores: Tensor, + idxs: Tensor, + iou_threshold: float, +) -> Tensor: + # strategy: in order to perform NMS independently per class, # we add an offset to all the boxes. The offset is dependent # only on the class idx, and is large enough so that boxes # from different classes do not overlap - else: - max_coordinate = boxes.max() - offsets = idxs.to(boxes) * (max_coordinate + torch.tensor(1).to(boxes)) - boxes_for_nms = boxes + offsets[:, None] - keep = nms(boxes_for_nms, scores, iou_threshold) - return keep + if boxes.numel() == 0: + return torch.empty((0,), dtype=torch.int64, device=boxes.device) + max_coordinate = boxes.max() + offsets = idxs.to(boxes) * (max_coordinate + torch.tensor(1).to(boxes)) + boxes_for_nms = boxes + offsets[:, None] + keep = nms(boxes_for_nms, scores, iou_threshold) + return keep + + +@torch.jit._script_if_tracing +def _batched_nms_vanilla( + boxes: Tensor, + scores: Tensor, + idxs: Tensor, + iou_threshold: float, +) -> Tensor: + # Based on Detectron2 implementation, just manually call nms() on each class independently + keep_mask = torch.zeros_like(scores, dtype=torch.bool) + for class_id in torch.unique(idxs): + curr_indices = torch.where(idxs == class_id)[0] + curr_keep_indices = nms(boxes[curr_indices], scores[curr_indices], iou_threshold) + keep_mask[curr_indices[curr_keep_indices]] = True + keep_indices = torch.where(keep_mask)[0] + return keep_indices[scores[keep_indices].sort(descending=True)[1]] def remove_small_boxes(boxes: Tensor, min_size: float) -> Tensor: From 196c5ef92230b85813332b008060a25a93653aff Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 277/357] [fbsync] Speed up equalize transform: use bincount instead of histc (#3493) Summary: * use bincount instead of hist * only use bincount when on CPU * Added equality test for CPU vs cuda * Fix flake8 and tests * tuple instead of int for size Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945736 fbshipit-source-id: 5b13a01e1b04d8c92317d3478bf9c9bb1c7d1375 --- test/test_functional_tensor.py | 12 ++++++++++++ torchvision/transforms/functional_tensor.py | 9 ++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/test/test_functional_tensor.py b/test/test_functional_tensor.py index f1219ff7ce9..42d44dfdbd9 100644 --- a/test/test_functional_tensor.py +++ b/test/test_functional_tensor.py @@ -977,6 +977,18 @@ class CUDATester(Tester): def setUp(self): self.device = "cuda" + def test_scale_channel(self): + """Make sure that _scale_channel gives the same results on CPU and GPU as + histc or bincount are used depending on the device. + """ + # TODO: when # https://github.com/pytorch/pytorch/issues/53194 is fixed, + # only use bincount and remove that test. + size = (1_000,) + img_chan = torch.randint(0, 256, size=size).to('cpu') + scaled_cpu = F_t._scale_channel(img_chan) + scaled_cuda = F_t._scale_channel(img_chan.to('cuda')) + self.assertTrue(scaled_cpu.equal(scaled_cuda.to('cpu'))) + if __name__ == '__main__': unittest.main() diff --git a/torchvision/transforms/functional_tensor.py b/torchvision/transforms/functional_tensor.py index f4358bb6c8c..b87e16c7548 100644 --- a/torchvision/transforms/functional_tensor.py +++ b/torchvision/transforms/functional_tensor.py @@ -902,7 +902,14 @@ def autocontrast(img: Tensor) -> Tensor: def _scale_channel(img_chan): - hist = torch.histc(img_chan.to(torch.float32), bins=256, min=0, max=255) + # TODO: we should expect bincount to always be faster than histc, but this + # isn't always the case. Once + # https://github.com/pytorch/pytorch/issues/53194 is fixed, remove the if + # block and only use bincount. + if img_chan.is_cuda: + hist = torch.histc(img_chan.to(torch.float32), bins=256, min=0, max=255) + else: + hist = torch.bincount(img_chan.view(-1), minlength=256) nonzero_hist = hist[hist != 0] step = nonzero_hist[:-1].sum() // 255 From 2f50c07daba90c861586460374fed766675740eb Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 278/357] [fbsync] add 0.9.0 to compatibility table (#3530) Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945737 fbshipit-source-id: c22df40ef8947666c493225d02015bd9dfaf1f9a --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index fdd1e5094f3..17b5e40af55 100644 --- a/README.rst +++ b/README.rst @@ -26,6 +26,8 @@ supported Python versions. +==========================+==========================+=================================+ | ``master`` / ``nightly`` | ``master`` / ``nightly`` | ``>=3.6`` | +--------------------------+--------------------------+---------------------------------+ +| ``1.8.0`` | ``0.9.0`` | ``>=3.6`` | ++--------------------------+--------------------------+---------------------------------+ | ``1.7.1`` | ``0.8.2`` | ``>=3.6`` | +--------------------------+--------------------------+---------------------------------+ | ``1.7.0`` | ``0.8.1`` | ``>=3.6`` | From 8903c62d03fafd6b7ae4181c477ed07326fae109 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 279/357] [fbsync] Update conf.py (#3513) Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945726 fbshipit-source-id: 937cf99c865a2f3ebd989186de679f29f7c8e17f --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 8b4d098f66b..adcdc9208c4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -83,7 +83,7 @@ def _googleanalytics_setup_wrapper(app): # General information about the project. project = 'Torchvision' -copyright = '2017, Torch Contributors' +copyright = '2017-present, Torch Contributors' author = 'Torch Contributors' # The version info for the project you're documenting, acts as replacement for From 23f9adb348199d6f4a0b0aaea97ba3bfd529612c Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 280/357] [fbsync] feat(docs): navigate with left/right arrow keys (#3490) Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945727 fbshipit-source-id: 1764d6e3f3ee574f1066bb0c7e66cd25f51995f3 --- docs/source/conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index adcdc9208c4..606bc34f841 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -133,6 +133,7 @@ def _googleanalytics_setup_wrapper(app): 'display_version': True, 'logo_only': True, 'pytorch_project': 'docs', + 'navigation_with_keys': True, } html_logo = '_static/img/pytorch-logo-dark.svg' From 5ba7471c71e2ecd4c104d7352614346fb82718e5 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 281/357] [fbsync] use ternary if (#3533) Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945739 fbshipit-source-id: f615dde8c293f736f68826676446c04a13897b21 --- torchvision/transforms/functional_tensor.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/torchvision/transforms/functional_tensor.py b/torchvision/transforms/functional_tensor.py index b87e16c7548..ea96fed512f 100644 --- a/torchvision/transforms/functional_tensor.py +++ b/torchvision/transforms/functional_tensor.py @@ -498,11 +498,7 @@ def resize(img: Tensor, size: List[int], interpolation: str = "bilinear", max_si if isinstance(size, int) or len(size) == 1: # specified size only for the smallest edge short, long = (w, h) if w <= h else (h, w) - - if isinstance(size, int): - requested_new_short = size - else: - requested_new_short = size[0] + requested_new_short = size if isinstance(size, int) else size[0] if short == requested_new_short: return img From 129e3ba4d9b8f12f96cf4eb1450e3bf7b943f74e Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 282/357] [fbsync] Updating tests for the new videoAPI (#2916) Summary: * Stash commit * Refactoring the current tests in a simpler file * Addressing Francisco's comments, attempt 1 * Remove old tests * audio changes * adding some comments * Stash commit * Refactoring the current tests in a simpler file * Addressing Francisco's comments, attempt 1 * Remove old tests * audio changes * adding some comments * adding the py39 check stuff Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945733 fbshipit-source-id: 8812330fd261bf41f77954c061094048d0750b0b Co-authored-by: Bruno Korbar Co-authored-by: Francisco Massa --- test/test_video.py | 411 ---------------------------- test/test_videoapi.py | 200 ++++++++++++++ torchvision/csrc/io/video/video.cpp | 15 +- 3 files changed, 212 insertions(+), 414 deletions(-) delete mode 100644 test/test_video.py create mode 100644 test/test_videoapi.py diff --git a/test/test_video.py b/test/test_video.py deleted file mode 100644 index c2e15c8d883..00000000000 --- a/test/test_video.py +++ /dev/null @@ -1,411 +0,0 @@ -import os -import collections -import contextlib -import tempfile -import unittest -import random -import sys - -import itertools - - -import numpy as np - -import torch -import torchvision -from torchvision.io import _HAS_VIDEO_OPT, VideoReader -from common_utils import PY39_SKIP - -try: - import av - - # Do a version test too - torchvision.io.video._check_av_available() -except ImportError: - av = None - - -VIDEO_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "videos") - -CheckerConfig = [ - "duration", - "video_fps", - "audio_sample_rate", - # We find for some videos (e.g. HMDB51 videos), the decoded audio frames and pts are - # slightly different between TorchVision decoder and PyAv decoder. So omit it during check - "check_aframes", - "check_aframe_pts", -] -GroundTruth = collections.namedtuple("GroundTruth", " ".join(CheckerConfig)) - -all_check_config = GroundTruth( - duration=0, - video_fps=0, - audio_sample_rate=0, - check_aframes=True, - check_aframe_pts=True, -) - -test_videos = { - "RATRACE_wave_f_nm_np1_fr_goo_37.avi": GroundTruth( - duration=2.0, - video_fps=30.0, - audio_sample_rate=None, - check_aframes=True, - check_aframe_pts=True, - ), - "SchoolRulesHowTheyHelpUs_wave_f_nm_np1_ba_med_0.avi": GroundTruth( - duration=2.0, - video_fps=30.0, - audio_sample_rate=None, - check_aframes=True, - check_aframe_pts=True, - ), - "TrumanShow_wave_f_nm_np1_fr_med_26.avi": GroundTruth( - duration=2.0, - video_fps=30.0, - audio_sample_rate=None, - check_aframes=True, - check_aframe_pts=True, - ), - "v_SoccerJuggling_g23_c01.avi": GroundTruth( - duration=8.0, - video_fps=29.97, - audio_sample_rate=None, - check_aframes=True, - check_aframe_pts=True, - ), - "v_SoccerJuggling_g24_c01.avi": GroundTruth( - duration=8.0, - video_fps=29.97, - audio_sample_rate=None, - check_aframes=True, - check_aframe_pts=True, - ), - # Last three test segfault on video reader (see issues) - "R6llTwEh07w.mp4": GroundTruth( - duration=10.0, - video_fps=30.0, - audio_sample_rate=44100, - # PyAv miss one audio frame at the beginning (pts=0) - check_aframes=False, - check_aframe_pts=False, - ), - "SOX5yA1l24A.mp4": GroundTruth( - duration=11.0, - video_fps=29.97, - audio_sample_rate=48000, - # PyAv miss one audio frame at the beginning (pts=0) - check_aframes=False, - check_aframe_pts=False, - ), - "WUzgd7C1pWA.mp4": GroundTruth( - duration=11.0, - video_fps=29.97, - audio_sample_rate=48000, - # PyAv miss one audio frame at the beginning (pts=0) - check_aframes=False, - check_aframe_pts=False, - ), -} - -DecoderResult = collections.namedtuple( - "DecoderResult", "vframes vframe_pts vtimebase aframes aframe_pts atimebase" -) - - -def _read_from_stream( - container, start_pts, end_pts, stream, stream_name, buffer_size=4 -): - """ - Args: - container: pyav container - start_pts/end_pts: the starting/ending Presentation TimeStamp where - frames are read - stream: pyav stream - stream_name: a dictionary of streams. For example, {"video": 0} means - video stream at stream index 0 - buffer_size: pts of frames decoded by PyAv is not guaranteed to be in - ascending order. We need to decode more frames even when we meet end - pts - """ - # seeking in the stream is imprecise. Thus, seek to an ealier PTS by a margin - margin = 1 - seek_offset = max(start_pts - margin, 0) - - container.seek(seek_offset, any_frame=False, backward=True, stream=stream) - frames = {} - buffer_count = 0 - for frame in container.decode(**stream_name): - if frame.pts < start_pts: - continue - if frame.pts <= end_pts: - frames[frame.pts] = frame - else: - buffer_count += 1 - if buffer_count >= buffer_size: - break - result = [frames[pts] for pts in sorted(frames)] - - return result - - -def _fraction_to_tensor(fraction): - ret = torch.zeros([2], dtype=torch.int32) - ret[0] = fraction.numerator - ret[1] = fraction.denominator - return ret - - -def _decode_frames_by_av_module( - full_path, - video_start_pts=0, - video_end_pts=None, - audio_start_pts=0, - audio_end_pts=None, -): - """ - Use PyAv to decode video frames. This provides a reference for our decoder - to compare the decoding results. - Input arguments: - full_path: video file path - video_start_pts/video_end_pts: the starting/ending Presentation TimeStamp where - frames are read - """ - if video_end_pts is None: - video_end_pts = float("inf") - if audio_end_pts is None: - audio_end_pts = float("inf") - container = av.open(full_path) - - video_frames = [] - vtimebase = torch.zeros([0], dtype=torch.int32) - if container.streams.video: - video_frames = _read_from_stream( - container, - video_start_pts, - video_end_pts, - container.streams.video[0], - {"video": 0}, - ) - # container.streams.video[0].average_rate is not a reliable estimator of - # frame rate. It can be wrong for certain codec, such as VP80 - # So we do not return video fps here - vtimebase = _fraction_to_tensor(container.streams.video[0].time_base) - - audio_frames = [] - atimebase = torch.zeros([0], dtype=torch.int32) - if container.streams.audio: - audio_frames = _read_from_stream( - container, - audio_start_pts, - audio_end_pts, - container.streams.audio[0], - {"audio": 0}, - ) - atimebase = _fraction_to_tensor(container.streams.audio[0].time_base) - - container.close() - vframes = [frame.to_rgb().to_ndarray() for frame in video_frames] - vframes = torch.as_tensor(np.stack(vframes)) - - vframe_pts = torch.tensor([frame.pts for frame in video_frames], dtype=torch.int64) - - aframes = [frame.to_ndarray() for frame in audio_frames] - if aframes: - aframes = np.transpose(np.concatenate(aframes, axis=1)) - aframes = torch.as_tensor(aframes) - else: - aframes = torch.empty((1, 0), dtype=torch.float32) - - aframe_pts = torch.tensor( - [audio_frame.pts for audio_frame in audio_frames], dtype=torch.int64 - ) - - return DecoderResult( - vframes=vframes.permute(0, 3, 1, 2), - vframe_pts=vframe_pts, - vtimebase=vtimebase, - aframes=aframes, - aframe_pts=aframe_pts, - atimebase=atimebase, - ) - - -def _template_read_video(video_object, s=0, e=None): - - if e is None: - e = float("inf") - if e < s: - raise ValueError( - "end time should be larger than start time, got " - "start time={} and end time={}".format(s, e) - ) - video_object.set_current_stream("video") - video_object.seek(s) - video_frames = torch.empty(0) - frames = [] - video_pts = [] - for frame in itertools.takewhile(lambda x: x['pts'] <= e, video_object): - if frame['pts'] < s: - continue - frames.append(frame['data']) - video_pts.append(frame['pts']) - if len(frames) > 0: - video_frames = torch.stack(frames, 0) - - video_object.set_current_stream("audio") - video_object.seek(s) - audio_frames = torch.empty(0) - frames = [] - audio_pts = [] - for frame in itertools.takewhile(lambda x: x['pts'] <= e, video_object): - if frame['pts'] < s: - continue - frames.append(frame['data']) - audio_pts.append(frame['pts']) - if len(frames) > 0: - audio_frames = torch.stack(frames, 0) - - return DecoderResult( - vframes=video_frames, - vframe_pts=video_pts, - vtimebase=None, - aframes=audio_frames, - aframe_pts=audio_pts, - atimebase=None, - ) - return video_frames, audio_frames, video_object.get_metadata() - - -@unittest.skipIf(_HAS_VIDEO_OPT is False, "Didn't compile with ffmpeg") -class TestVideo(unittest.TestCase): - @PY39_SKIP - @unittest.skipIf(av is None, "PyAV unavailable") - def test_read_video_tensor(self): - """ - Check if reading the video using the `next` based API yields the - same sized tensors as the pyav alternative. - """ - torchvision.set_video_backend("pyav") - for test_video, config in test_videos.items(): - full_path = os.path.join(VIDEO_DIR, test_video) - # pass 1: decode all frames using existing TV decoder - tv_result, _, _ = torchvision.io.read_video(full_path, pts_unit="sec") - tv_result = tv_result.permute(0, 3, 1, 2) - # pass 2: decode all frames using new api - reader = VideoReader(full_path, "video") - frames = [] - for frame in reader: - frames.append(frame['data']) - new_api = torch.stack(frames, 0) - self.assertEqual(tv_result.size(), new_api.size()) - - # def test_partial_video_reading_fn(self): - # torchvision.set_video_backend("video_reader") - # for test_video, config in test_videos.items(): - # full_path = os.path.join(VIDEO_DIR, test_video) - - # # select two random points between 0 and duration - # r = [] - # r.append(random.uniform(0, config.duration)) - # r.append(random.uniform(0, config.duration)) - # s = min(r) - # e = max(r) - - # reader = VideoReader(full_path, "video") - # results = _template_read_video(reader, s, e) - # tv_video, tv_audio, info = torchvision.io.read_video( - # full_path, start_pts=s, end_pts=e, pts_unit="sec" - # ) - # self.assertAlmostEqual(tv_video.size(0), results.vframes.size(0), delta=2.0) - - # def test_pts(self): - # """ - # Check if every frame read from - # """ - # torchvision.set_video_backend("video_reader") - # for test_video, config in test_videos.items(): - # full_path = os.path.join(VIDEO_DIR, test_video) - - # tv_timestamps, _ = torchvision.io.read_video_timestamps( - # full_path, pts_unit="sec" - # ) - # # pass 2: decode all frames using new api - # reader = VideoReader(full_path, "video") - # pts = [] - # t, p = next(reader) - # while t.numel() > 0: # THIS NEEDS TO BE FIXED - # pts.append(p) - # t, p = next(reader) - - # tv_timestamps = [float(p) for p in tv_timestamps] - # napi_pts = [float(p) for p in pts] - # for i in range(len(napi_pts)): - # self.assertAlmostEqual(napi_pts[i], tv_timestamps[i], delta=0.001) - # # check if pts of video frames are sorted in ascending order - # for i in range(len(napi_pts) - 1): - # self.assertEqual(napi_pts[i] < napi_pts[i + 1], True) - - @unittest.skipIf(av is None, "PyAV unavailable") - def test_metadata(self): - """ - Test that the metadata returned via pyav corresponds to the one returned - by the new video decoder API - """ - torchvision.set_video_backend("pyav") - for test_video, config in test_videos.items(): - full_path = os.path.join(VIDEO_DIR, test_video) - reader = VideoReader(full_path, "video") - reader_md = reader.get_metadata() - self.assertAlmostEqual( - config.video_fps, reader_md["video"]["fps"][0], delta=0.0001 - ) - self.assertAlmostEqual( - config.duration, reader_md["video"]["duration"][0], delta=0.5 - ) - - @PY39_SKIP - @unittest.skipIf(av is None, "PyAV unavailable") - def test_video_reading_fn(self): - """ - Test that the outputs of the pyav and ffmpeg outputs are mostly the same - """ - for test_video, config in test_videos.items(): - full_path = os.path.join(VIDEO_DIR, test_video) - - ref_result = _decode_frames_by_av_module(full_path) - - reader = VideoReader(full_path, "video") - newapi_result = _template_read_video(reader) - - # First we check if the frames are approximately the same - # (note that every codec context has signature artefacts which - # make a direct comparison not feasible) - if newapi_result.vframes.numel() > 0 and ref_result.vframes.numel() > 0: - mean_delta = torch.mean( - torch.abs( - newapi_result.vframes.float() - ref_result.vframes.float() - ) - ) - self.assertAlmostEqual(mean_delta, 0, delta=8.0) - - # Just a sanity check: are the two of the correct size? - self.assertEqual(newapi_result.vframes.size(), ref_result.vframes.size()) - - # Lastly, we compare the resulting audio streams - if ( - config.check_aframes - and newapi_result.aframes.numel() > 0 - and ref_result.aframes.numel() > 0 - ): - """Audio stream is available and audio frame is required to return - from decoder""" - is_same = torch.all( - torch.eq(newapi_result.aframes, ref_result.aframes) - ).item() - self.assertEqual(is_same, True) - - -if __name__ == "__main__": - unittest.main() diff --git a/test/test_videoapi.py b/test/test_videoapi.py new file mode 100644 index 00000000000..da73c7cd17d --- /dev/null +++ b/test/test_videoapi.py @@ -0,0 +1,200 @@ +import collections +import os +import unittest + +import torch +import torchvision +from torchvision.io import _HAS_VIDEO_OPT, VideoReader +from torchvision.datasets.utils import download_url + +from common_utils import PY39_SKIP + +try: + import av + + # Do a version test too + torchvision.io.video._check_av_available() +except ImportError: + av = None + + +VIDEO_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "videos") + +CheckerConfig = ["duration", "video_fps", "audio_sample_rate"] +GroundTruth = collections.namedtuple("GroundTruth", " ".join(CheckerConfig)) + + +def fate(name, path="."): + """Download and return a path to a sample from the FFmpeg test suite. + See the `FFmpeg Automated Test Environment `_ + """ + + file_name = name.split("/")[1] + download_url("http://fate.ffmpeg.org/fate-suite/" + name, path, file_name) + return os.path.join(path, file_name) + + +test_videos = { + "RATRACE_wave_f_nm_np1_fr_goo_37.avi": GroundTruth( + duration=2.0, video_fps=30.0, audio_sample_rate=None + ), + "SchoolRulesHowTheyHelpUs_wave_f_nm_np1_ba_med_0.avi": GroundTruth( + duration=2.0, video_fps=30.0, audio_sample_rate=None + ), + "TrumanShow_wave_f_nm_np1_fr_med_26.avi": GroundTruth( + duration=2.0, video_fps=30.0, audio_sample_rate=None + ), + "v_SoccerJuggling_g23_c01.avi": GroundTruth( + duration=8.0, video_fps=29.97, audio_sample_rate=None + ), + "v_SoccerJuggling_g24_c01.avi": GroundTruth( + duration=8.0, video_fps=29.97, audio_sample_rate=None + ), + "R6llTwEh07w.mp4": GroundTruth( + duration=10.0, video_fps=30.0, audio_sample_rate=44100 + ), + "SOX5yA1l24A.mp4": GroundTruth( + duration=11.0, video_fps=29.97, audio_sample_rate=48000 + ), + "WUzgd7C1pWA.mp4": GroundTruth( + duration=11.0, video_fps=29.97, audio_sample_rate=48000 + ), +} + + +@unittest.skipIf(_HAS_VIDEO_OPT is False, "Didn't compile with ffmpeg") +@PY39_SKIP +class TestVideoApi(unittest.TestCase): + @unittest.skipIf(av is None, "PyAV unavailable") + def test_frame_reading(self): + for test_video, config in test_videos.items(): + full_path = os.path.join(VIDEO_DIR, test_video) + + av_reader = av.open(full_path) + + if av_reader.streams.video: + video_reader = VideoReader(full_path, "video") + for av_frame in av_reader.decode(av_reader.streams.video[0]): + vr_frame = next(video_reader) + + self.assertAlmostEqual( + float(av_frame.pts * av_frame.time_base), + vr_frame["pts"], + delta=0.1, + ) + + av_array = torch.tensor(av_frame.to_rgb().to_ndarray()).permute( + 2, 0, 1 + ) + vr_array = vr_frame["data"] + mean_delta = torch.mean( + torch.abs(av_array.float() - vr_array.float()) + ) + # on average the difference is very small and caused + # by decoding (around 1%) + # TODO: asses empirically how to set this? atm it's 1% + # averaged over all frames + self.assertTrue(mean_delta.item() < 2.5) + + av_reader = av.open(full_path) + if av_reader.streams.audio: + video_reader = VideoReader(full_path, "audio") + for av_frame in av_reader.decode(av_reader.streams.audio[0]): + vr_frame = next(video_reader) + self.assertAlmostEqual( + float(av_frame.pts * av_frame.time_base), + vr_frame["pts"], + delta=0.1, + ) + + av_array = torch.tensor(av_frame.to_ndarray()).permute(1, 0) + vr_array = vr_frame["data"] + + max_delta = torch.max( + torch.abs(av_array.float() - vr_array.float()) + ) + # we assure that there is never more than 1% difference in signal + self.assertTrue(max_delta.item() < 0.001) + + def test_metadata(self): + """ + Test that the metadata returned via pyav corresponds to the one returned + by the new video decoder API + """ + for test_video, config in test_videos.items(): + full_path = os.path.join(VIDEO_DIR, test_video) + reader = VideoReader(full_path, "video") + reader_md = reader.get_metadata() + self.assertAlmostEqual( + config.video_fps, reader_md["video"]["fps"][0], delta=0.0001 + ) + self.assertAlmostEqual( + config.duration, reader_md["video"]["duration"][0], delta=0.5 + ) + + def test_seek_start(self): + for test_video, config in test_videos.items(): + full_path = os.path.join(VIDEO_DIR, test_video) + + video_reader = VideoReader(full_path, "video") + num_frames = 0 + for frame in video_reader: + num_frames += 1 + + # now seek the container to 0 and do it again + # It's often that starting seek can be inprecise + # this way and it doesn't start at 0 + video_reader.seek(0) + start_num_frames = 0 + for frame in video_reader: + start_num_frames += 1 + + self.assertEqual(start_num_frames, num_frames) + + # now seek the container to < 0 to check for unexpected behaviour + video_reader.seek(-1) + start_num_frames = 0 + for frame in video_reader: + start_num_frames += 1 + + self.assertEqual(start_num_frames, num_frames) + + def test_accurateseek_middle(self): + for test_video, config in test_videos.items(): + full_path = os.path.join(VIDEO_DIR, test_video) + + stream = "video" + video_reader = VideoReader(full_path, stream) + md = video_reader.get_metadata() + duration = md[stream]["duration"][0] + if duration is not None: + + num_frames = 0 + for frame in video_reader: + num_frames += 1 + + video_reader.seek(duration / 2) + middle_num_frames = 0 + for frame in video_reader: + middle_num_frames += 1 + + self.assertTrue(middle_num_frames < num_frames) + self.assertAlmostEqual(middle_num_frames, num_frames // 2, delta=1) + + video_reader.seek(duration / 2) + frame = next(video_reader) + lb = duration / 2 - 1 / md[stream]["fps"][0] + ub = duration / 2 + 1 / md[stream]["fps"][0] + self.assertTrue((lb <= frame["pts"]) & (ub >= frame["pts"])) + + def test_fate_suite(self): + video_path = fate("sub/MovText_capability_tester.mp4", VIDEO_DIR) + vr = VideoReader(video_path) + metadata = vr.get_metadata() + + self.assertTrue(metadata["subtitles"]["duration"] is not None) + os.remove(video_path) + + +if __name__ == "__main__": + unittest.main() diff --git a/torchvision/csrc/io/video/video.cpp b/torchvision/csrc/io/video/video.cpp index 73167e4fff6..d7d28a51770 100644 --- a/torchvision/csrc/io/video/video.cpp +++ b/torchvision/csrc/io/video/video.cpp @@ -172,11 +172,13 @@ Video::Video(std::string videoPath, std::string stream) { logMessage = videoPath; // locals - std::vector audioFPS, videoFPS, ccFPS, subsFPS; + std::vector audioFPS, videoFPS; std::vector audioDuration, videoDuration, ccDuration, subsDuration; std::vector audioTB, videoTB, ccTB, subsTB; c10::Dict> audioMetadata; c10::Dict> videoMetadata; + c10::Dict> ccMetadata; + c10::Dict> subsMetadata; // calback and metadata defined in struct succeeded = decoder.init(params, std::move(callback), &metadata); @@ -192,20 +194,27 @@ Video::Video(std::string videoPath, std::string stream) { audioFPS.push_back(fps); audioDuration.push_back(duration); } else if (header.format.type == TYPE_CC) { - ccFPS.push_back(fps); ccDuration.push_back(duration); } else if (header.format.type == TYPE_SUBTITLE) { - subsFPS.push_back(fps); subsDuration.push_back(duration); }; } } + // audio audioMetadata.insert("duration", audioDuration); audioMetadata.insert("framerate", audioFPS); + // video videoMetadata.insert("duration", videoDuration); videoMetadata.insert("fps", videoFPS); + // subs + subsMetadata.insert("duration", subsDuration); + // cc + ccMetadata.insert("duration", ccDuration); + // put all to a data streamsMetadata.insert("video", videoMetadata); streamsMetadata.insert("audio", audioMetadata); + streamsMetadata.insert("subtitles", subsMetadata); + streamsMetadata.insert("cc", ccMetadata); succeeded = Video::setCurrentStream(stream); LOG(INFO) << "\nDecoder inited with: " << succeeded << "\n"; From a198fc37a01efc00a2df6db39cd1c91c0a5991d1 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 283/357] [fbsync] Use pytorch smooth_l1_loss and remove private custom implem (#3539) Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945725 fbshipit-source-id: c7f300b6eb54e496947cda4502bcdcd4fc1d6bc7 --- torchvision/models/detection/_utils.py | 13 ------------- torchvision/models/detection/roi_heads.py | 4 ++-- torchvision/models/detection/rpn.py | 4 ++-- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/torchvision/models/detection/_utils.py b/torchvision/models/detection/_utils.py index db9711760dc..24dc9399fd6 100644 --- a/torchvision/models/detection/_utils.py +++ b/torchvision/models/detection/_utils.py @@ -344,19 +344,6 @@ def set_low_quality_matches_(self, matches, all_matches, match_quality_matrix): matches[pred_inds_to_update] = all_matches[pred_inds_to_update] -def smooth_l1_loss(input, target, beta: float = 1. / 9, size_average: bool = True): - """ - very similar to the smooth_l1_loss from pytorch, but with - the extra beta parameter - """ - n = torch.abs(input - target) - cond = n < beta - loss = torch.where(cond, 0.5 * n ** 2 / beta, n - 0.5 * beta) - if size_average: - return loss.mean() - return loss.sum() - - def overwrite_eps(model, eps): """ This method overwrites the default eps values of all the diff --git a/torchvision/models/detection/roi_heads.py b/torchvision/models/detection/roi_heads.py index 5f476f63827..ab6e87a86e0 100644 --- a/torchvision/models/detection/roi_heads.py +++ b/torchvision/models/detection/roi_heads.py @@ -42,11 +42,11 @@ def fastrcnn_loss(class_logits, box_regression, labels, regression_targets): N, num_classes = class_logits.shape box_regression = box_regression.reshape(N, box_regression.size(-1) // 4, 4) - box_loss = det_utils.smooth_l1_loss( + box_loss = F.smooth_l1_loss( box_regression[sampled_pos_inds_subset, labels_pos], regression_targets[sampled_pos_inds_subset], beta=1 / 9, - size_average=False, + reduction='sum', ) box_loss = box_loss / labels.numel() diff --git a/torchvision/models/detection/rpn.py b/torchvision/models/detection/rpn.py index 736c82a9009..9f9bf9da5f5 100644 --- a/torchvision/models/detection/rpn.py +++ b/torchvision/models/detection/rpn.py @@ -304,11 +304,11 @@ def compute_loss(self, objectness, pred_bbox_deltas, labels, regression_targets) labels = torch.cat(labels, dim=0) regression_targets = torch.cat(regression_targets, dim=0) - box_loss = det_utils.smooth_l1_loss( + box_loss = F.smooth_l1_loss( pred_bbox_deltas[sampled_pos_inds], regression_targets[sampled_pos_inds], beta=1 / 9, - size_average=False, + reduction='sum', ) / (sampled_inds.numel()) objectness_loss = F.binary_cross_entropy_with_logits( From 67cdd617d11c645f618bb0c6fbc837bbcd437c07 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 284/357] [fbsync] [DOC] Adds Documentation for AutoAugmentation (#3529) Summary: * add _all for autoaugment * adds docs * add docs, test locally * refactored as per code review Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945738 fbshipit-source-id: 2087286808c8698532b75bbb700d0f285134cd09 --- docs/source/transforms.rst | 17 +++++++++++++++++ torchvision/transforms/autoaugment.py | 3 +++ 2 files changed, 20 insertions(+) diff --git a/docs/source/transforms.rst b/docs/source/transforms.rst index 517ede35dbf..6efc2dba5a2 100644 --- a/docs/source/transforms.rst +++ b/docs/source/transforms.rst @@ -57,6 +57,7 @@ Compositions of transforms .. autoclass:: Compose + Transforms on PIL Image and torch.\*Tensor ------------------------------------------ @@ -156,6 +157,22 @@ Generic Transforms :members: +AutoAugment Transforms +---------------------- + +`AutoAugment `_ is a common Data Augmentation technique that can improve the accuracy of Image Classification models. +Though the data augmentation policies are directly linked to their trained dataset, empirical studies show that +ImageNet policies provide significant improvements when applied to other datasets. +In TorchVision we implemented 3 policies learned on the following datasets: ImageNet, CIFAR10 and SVHN. +The new transform can be used standalone or mixed-and-matched with existing transforms: + +.. autoclass:: AutoAugmentPolicy + :members: + +.. autoclass:: AutoAugment + :members: + + Functional Transforms --------------------- diff --git a/torchvision/transforms/autoaugment.py b/torchvision/transforms/autoaugment.py index a179ac8ccb9..1889a62e948 100644 --- a/torchvision/transforms/autoaugment.py +++ b/torchvision/transforms/autoaugment.py @@ -7,9 +7,12 @@ from . import functional as F, InterpolationMode +__all__ = ["AutoAugmentPolicy", "AutoAugment"] + class AutoAugmentPolicy(Enum): """AutoAugment policies learned on different datasets. + Available policies are IMAGENET, CIFAR10 and SVHN. """ IMAGENET = "imagenet" CIFAR10 = "cifar10" From 52e91194831ff4029b2c333608e8379b443ff95d Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Wed, 10 Mar 2021 09:04:20 -0800 Subject: [PATCH 285/357] [fbsync] add tests for Flickr(8|30)k datasets (#3489) Summary: * add tests for Flickr8k dataset * add tests for FLickr30k dataset * lint Reviewed By: NicolasHug, cpuhrsch Differential Revision: D26945729 fbshipit-source-id: e8bae59242d72611eed607c61985ea8e309bca72 Co-authored-by: Francisco Massa --- test/test_datasets.py | 87 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index 859419df2b0..56f0d6707bc 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1354,5 +1354,92 @@ def test_feature_types(self, config): self.FEATURE_TYPES = feature_types +class Flickr8kTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.Flickr8k + + FEATURE_TYPES = (PIL.Image.Image, list) + + _IMAGES_FOLDER = "images" + _ANNOTATIONS_FILE = "captions.html" + + def dataset_args(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) + root = tmpdir / self._IMAGES_FOLDER + ann_file = tmpdir / self._ANNOTATIONS_FILE + return str(root), str(ann_file) + + def inject_fake_data(self, tmpdir, config): + num_images = 3 + num_captions_per_image = 3 + + tmpdir = pathlib.Path(tmpdir) + + images = self._create_images(tmpdir, self._IMAGES_FOLDER, num_images) + self._create_annotations_file(tmpdir, self._ANNOTATIONS_FILE, images, num_captions_per_image) + + return dict(num_examples=num_images, captions=self._create_captions(num_captions_per_image)) + + def _create_images(self, root, name, num_images): + return datasets_utils.create_image_folder(root, name, self._image_file_name, num_images) + + def _image_file_name(self, idx): + id = datasets_utils.create_random_string(10, string.digits) + checksum = datasets_utils.create_random_string(10, string.digits, string.ascii_lowercase[:6]) + size = datasets_utils.create_random_string(1, "qwcko") + return f"{id}_{checksum}_{size}.jpg" + + def _create_annotations_file(self, root, name, images, num_captions_per_image): + with open(root / name, "w") as fh: + fh.write("") + for image in (None, *images): + self._add_image(fh, image, num_captions_per_image) + fh.write("
") + + def _add_image(self, fh, image, num_captions_per_image): + fh.write("") + self._add_image_header(fh, image) + fh.write("
    ") + self._add_image_captions(fh, num_captions_per_image) + fh.write("
") + + def _add_image_header(self, fh, image=None): + if image: + url = f"http://www.flickr.com/photos/user/{image.name.split('_')[0]}/" + data = f'{url}' + else: + data = "Image Not Found" + fh.write(f"{data}") + + def _add_image_captions(self, fh, num_captions_per_image): + for caption in self._create_captions(num_captions_per_image): + fh.write(f"
  • {caption}") + + def _create_captions(self, num_captions_per_image): + return [str(idx) for idx in range(num_captions_per_image)] + + def test_captions(self): + with self.create_dataset() as (dataset, info): + _, captions = dataset[0] + self.assertSequenceEqual(captions, info["captions"]) + + +class Flickr30kTestCase(Flickr8kTestCase): + DATASET_CLASS = datasets.Flickr30k + + FEATURE_TYPES = (PIL.Image.Image, list) + + _ANNOTATIONS_FILE = "captions.token" + + def _image_file_name(self, idx): + return f"{idx}.jpg" + + def _create_annotations_file(self, root, name, images, num_captions_per_image): + with open(root / name, "w") as fh: + for image, (idx, caption) in itertools.product( + images, enumerate(self._create_captions(num_captions_per_image)) + ): + fh.write(f"{image.name}#{idx}\t{caption}\n") + + if __name__ == "__main__": unittest.main() From 0ee11885f6359fb3e63f98b7b9a98c4ca1a9cd08 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 07:29:07 -0700 Subject: [PATCH 286/357] [fbsync] Added test for aligned=True (#3540) Reviewed By: fmassa Differential Revision: D27127997 fbshipit-source-id: 1d7eefa632c5a3e52dced0d2a757bce6c4ced20e --- test/test_ops.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index 24e488d0db0..9b28276fec2 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -54,7 +54,7 @@ def _test_backward(self, device, contiguous): class RoIOpTester(OpTester): - def _test_forward(self, device, contiguous, x_dtype=None, rois_dtype=None): + def _test_forward(self, device, contiguous, x_dtype=None, rois_dtype=None, **kwargs): x_dtype = self.dtype if x_dtype is None else x_dtype rois_dtype = self.dtype if rois_dtype is None else rois_dtype pool_size = 5 @@ -70,11 +70,11 @@ def _test_forward(self, device, contiguous, x_dtype=None, rois_dtype=None): dtype=rois_dtype, device=device) pool_h, pool_w = pool_size, pool_size - y = self.fn(x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1) + y = self.fn(x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwargs) # the following should be true whether we're running an autocast test or not. self.assertTrue(y.dtype == x.dtype) gt_y = self.expected_fn(x, rois, pool_h, pool_w, spatial_scale=1, - sampling_ratio=-1, device=device, dtype=self.dtype) + sampling_ratio=-1, device=device, dtype=self.dtype, **kwargs) tol = 1e-3 if (x_dtype is torch.half or rois_dtype is torch.half) else 1e-5 self.assertTrue(torch.allclose(gt_y.to(y.dtype), y, rtol=tol, atol=tol)) @@ -304,6 +304,10 @@ def expected_fn(self, in_data, rois, pool_h, pool_w, spatial_scale=1, sampling_r def _test_boxes_shape(self): self._helper_boxes_shape(ops.roi_align) + def _test_forward(self, device, contiguous, x_dtype=None, rois_dtype=None, **kwargs): + for aligned in (True, False): + super()._test_forward(device, contiguous, x_dtype, rois_dtype, aligned=aligned) + class PSRoIAlignTester(RoIOpTester, unittest.TestCase): def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwargs): From d93c6f82645605a0203374ddcf62932f60e7be1d Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 07:29:07 -0700 Subject: [PATCH 287/357] [fbsync] simplify _get_script_fn (#3541) Summary: Co-authored-by: Francisco Massa Reviewed By: fmassa Differential Revision: D27128008 fbshipit-source-id: 54d196b7e08943eca229e175d3132f22ed59cdbc --- test/test_ops.py | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/test/test_ops.py b/test/test_ops.py index 9b28276fec2..8c938ae0e79 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -135,11 +135,8 @@ def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwar return ops.RoIPool((pool_h, pool_w), spatial_scale)(x, rois) def get_script_fn(self, rois, pool_size): - @torch.jit.script - def script_fn(input, rois, pool_size): - # type: (Tensor, Tensor, int) -> Tensor - return ops.roi_pool(input, rois, pool_size, 1.0)[0] - return lambda x: script_fn(x, rois, pool_size) + scriped = torch.jit.script(ops.roi_pool) + return lambda x: scriped(x, rois, pool_size) def expected_fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, device=None, dtype=torch.float64): @@ -177,11 +174,8 @@ def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwar return ops.PSRoIPool((pool_h, pool_w), 1)(x, rois) def get_script_fn(self, rois, pool_size): - @torch.jit.script - def script_fn(input, rois, pool_size): - # type: (Tensor, Tensor, int) -> Tensor - return ops.ps_roi_pool(input, rois, pool_size, 1.0)[0] - return lambda x: script_fn(x, rois, pool_size) + scriped = torch.jit.script(ops.ps_roi_pool) + return lambda x: scriped(x, rois, pool_size) def expected_fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, device=None, dtype=torch.float64): @@ -257,11 +251,8 @@ def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, aligne sampling_ratio=sampling_ratio, aligned=aligned)(x, rois) def get_script_fn(self, rois, pool_size): - @torch.jit.script - def script_fn(input, rois, pool_size): - # type: (Tensor, Tensor, int) -> Tensor - return ops.roi_align(input, rois, pool_size, 1.0)[0] - return lambda x: script_fn(x, rois, pool_size) + scriped = torch.jit.script(ops.roi_align) + return lambda x: scriped(x, rois, pool_size) def expected_fn(self, in_data, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, aligned=False, device=None, dtype=torch.float64): @@ -315,11 +306,8 @@ def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwar sampling_ratio=sampling_ratio)(x, rois) def get_script_fn(self, rois, pool_size): - @torch.jit.script - def script_fn(input, rois, pool_size): - # type: (Tensor, Tensor, int) -> Tensor - return ops.ps_roi_align(input, rois, pool_size, 1.0)[0] - return lambda x: script_fn(x, rois, pool_size) + scriped = torch.jit.script(ops.ps_roi_align) + return lambda x: scriped(x, rois, pool_size) def expected_fn(self, in_data, rois, pool_h, pool_w, device, spatial_scale=1, sampling_ratio=-1, dtype=torch.float64): From 83b89053921d01220532d7b6fd018b8c76b9e0a7 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 288/357] [fbsync] remove redundant path.join in Places365 (#3545) Reviewed By: fmassa Differential Revision: D27127986 fbshipit-source-id: db8bf200e8d91cf1bd412ff50a6e5c2b69ed8d48 --- torchvision/datasets/places365.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/datasets/places365.py b/torchvision/datasets/places365.py index 0a184aff73d..2ee9cdbe8c4 100644 --- a/torchvision/datasets/places365.py +++ b/torchvision/datasets/places365.py @@ -162,7 +162,7 @@ def _verify_split(self, split: str) -> str: return verify_str_arg(split, "split", self._SPLITS) def _check_integrity(self, file: str, md5: str, download: bool) -> bool: - integrity = check_integrity(path.join(self.root, file), md5=md5) + integrity = check_integrity(file, md5=md5) if not integrity and not download: raise RuntimeError( f"The file {file} does not exist or is corrupted. You can set download=True to download it." From 61ce622d9d3a5824e7aea192832de4ea8c010802 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 289/357] [fbsync] fix test_extract_(zip|tar|tar_xz|gzip) on windows (#3542) Summary: * fix test_extract_(zip|tar|tar_xz|gzip) on windows * lint Reviewed By: fmassa Differential Revision: D27127988 fbshipit-source-id: 62394146aef72ca5baf86ae86d52cf82f77c07aa Co-authored-by: Francisco Massa --- test/test_datasets_utils.py | 127 ++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 48 deletions(-) diff --git a/test/test_datasets_utils.py b/test/test_datasets_utils.py index f0edbaba08f..b1a8e1eda0f 100644 --- a/test/test_datasets_utils.py +++ b/test/test_datasets_utils.py @@ -1,6 +1,4 @@ import os -import sys -import tempfile import torchvision.datasets.utils as utils import unittest import unittest.mock @@ -102,62 +100,95 @@ def test_download_url_dispatch_download_from_google_drive(self, mock): mock.assert_called_once_with(id, root, filename, md5) - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') def test_extract_zip(self): + def create_archive(root, content="this is the content"): + file = os.path.join(root, "dst.txt") + archive = os.path.join(root, "archive.zip") + + with zipfile.ZipFile(archive, "w") as zf: + zf.writestr(os.path.basename(file), content) + + return archive, file, content + with get_tmp_dir() as temp_dir: - with tempfile.NamedTemporaryFile(suffix='.zip') as f: - with zipfile.ZipFile(f, 'w') as zf: - zf.writestr('file.tst', 'this is the content') - utils.extract_archive(f.name, temp_dir) - self.assertTrue(os.path.exists(os.path.join(temp_dir, 'file.tst'))) - with open(os.path.join(temp_dir, 'file.tst'), 'r') as nf: - data = nf.read() - self.assertEqual(data, 'this is the content') - - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') + archive, file, content = create_archive(temp_dir) + + utils.extract_archive(archive, temp_dir) + + self.assertTrue(os.path.exists(file)) + + with open(file, "r") as fh: + self.assertEqual(fh.read(), content) + def test_extract_tar(self): + def create_archive(root, ext, mode, content="this is the content"): + src = os.path.join(root, "src.txt") + dst = os.path.join(root, "dst.txt") + archive = os.path.join(root, f"archive{ext}") + + with open(src, "w") as fh: + fh.write(content) + + with tarfile.open(archive, mode=mode) as fh: + fh.add(src, arcname=os.path.basename(dst)) + + return archive, dst, content + for ext, mode in zip(['.tar', '.tar.gz', '.tgz'], ['w', 'w:gz', 'w:gz']): with get_tmp_dir() as temp_dir: - with tempfile.NamedTemporaryFile() as bf: - bf.write("this is the content".encode()) - bf.seek(0) - with tempfile.NamedTemporaryFile(suffix=ext) as f: - with tarfile.open(f.name, mode=mode) as zf: - zf.add(bf.name, arcname='file.tst') - utils.extract_archive(f.name, temp_dir) - self.assertTrue(os.path.exists(os.path.join(temp_dir, 'file.tst'))) - with open(os.path.join(temp_dir, 'file.tst'), 'r') as nf: - data = nf.read() - self.assertEqual(data, 'this is the content') - - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') + archive, file, content = create_archive(temp_dir, ext, mode) + + utils.extract_archive(archive, temp_dir) + + self.assertTrue(os.path.exists(file)) + + with open(file, "r") as fh: + self.assertEqual(fh.read(), content) + def test_extract_tar_xz(self): + def create_archive(root, ext, mode, content="this is the content"): + src = os.path.join(root, "src.txt") + dst = os.path.join(root, "dst.txt") + archive = os.path.join(root, f"archive{ext}") + + with open(src, "w") as fh: + fh.write(content) + + with tarfile.open(archive, mode=mode) as fh: + fh.add(src, arcname=os.path.basename(dst)) + + return archive, dst, content + for ext, mode in zip(['.tar.xz'], ['w:xz']): with get_tmp_dir() as temp_dir: - with tempfile.NamedTemporaryFile() as bf: - bf.write("this is the content".encode()) - bf.seek(0) - with tempfile.NamedTemporaryFile(suffix=ext) as f: - with tarfile.open(f.name, mode=mode) as zf: - zf.add(bf.name, arcname='file.tst') - utils.extract_archive(f.name, temp_dir) - self.assertTrue(os.path.exists(os.path.join(temp_dir, 'file.tst'))) - with open(os.path.join(temp_dir, 'file.tst'), 'r') as nf: - data = nf.read() - self.assertEqual(data, 'this is the content') - - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') + archive, file, content = create_archive(temp_dir, ext, mode) + + utils.extract_archive(archive, temp_dir) + + self.assertTrue(os.path.exists(file)) + + with open(file, "r") as fh: + self.assertEqual(fh.read(), content) + def test_extract_gzip(self): + def create_compressed(root, content="this is the content"): + file = os.path.join(root, "file") + compressed = f"{file}.gz" + + with gzip.GzipFile(compressed, "wb") as fh: + fh.write(content.encode()) + + return compressed, file, content + with get_tmp_dir() as temp_dir: - with tempfile.NamedTemporaryFile(suffix='.gz') as f: - with gzip.GzipFile(f.name, 'wb') as zf: - zf.write('this is the content'.encode()) - utils.extract_archive(f.name, temp_dir) - f_name = os.path.join(temp_dir, os.path.splitext(os.path.basename(f.name))[0]) - self.assertTrue(os.path.exists(f_name)) - with open(os.path.join(f_name), 'r') as nf: - data = nf.read() - self.assertEqual(data, 'this is the content') + compressed, file, content = create_compressed(temp_dir) + + utils.extract_archive(compressed, temp_dir) + + self.assertTrue(os.path.exists(file)) + + with open(file, "r") as fh: + self.assertEqual(fh.read(), content) def test_verify_str_arg(self): self.assertEqual("a", utils.verify_str_arg("a", "arg", ("a",))) From 08a68ee7382c2efce459cffe64e5e61bc46b0bb6 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 290/357] [fbsync] remove imprecise error handling in PhotoTour dataset (#3488) Summary: Co-authored-by: Francisco Massa Reviewed By: fmassa Differential Revision: D27127993 fbshipit-source-id: fea968bbea5f305e4d69aacbdd0b9d528950666d --- torchvision/datasets/phototour.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/torchvision/datasets/phototour.py b/torchvision/datasets/phototour.py index dead2337495..abb89701e1e 100644 --- a/torchvision/datasets/phototour.py +++ b/torchvision/datasets/phototour.py @@ -92,10 +92,7 @@ def __init__( self.download() if not self._check_datafile_exists(): - try: - self.cache() - except Exception as error: - raise RuntimeError("Dataset not found. You can use download=True to download it") from error + self.cache() # load the serialized data self.data, self.labels, self.matches = torch.load(self.data_file) From 2609420477e95ded3be3a905e26ad5f370645327 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 291/357] [fbsync] datasets: Fallback to our own mirrors for mnist (#3544) Summary: We are experiencing 403s when trying to download from the main mnist site so lets fallback to our own mirror on failure. Signed-off-by: Eli Uriegas Reviewed By: fmassa Differential Revision: D27127998 fbshipit-source-id: 552a022845eae39e9a7cc3255bf8b6f8eb2c07e7 Co-authored-by: Francisco Massa --- torchvision/datasets/mnist.py | 37 ++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index e798894089b..e87cd46eefe 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -10,6 +10,7 @@ import gzip import lzma from typing import Any, Callable, Dict, IO, List, Optional, Tuple, Union +from urllib.error import URLError from .utils import download_url, download_and_extract_archive, extract_archive, \ verify_str_arg @@ -31,11 +32,16 @@ class MNIST(VisionDataset): target and transforms it. """ + mirrors = [ + 'http://yann.lecun.com/exdb/mnist/', + 'https://ossci-datasets.s3.amazonaws.com/mnist/', + ] + resources = [ - ("http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz", "f68b3c2dcbeaaa9fbdd348bbdeb94873"), - ("http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz", "d53e105ee54ea40749a09fcbcd1e9432"), - ("http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz", "9fb629c4189551a2d022fa330f9573f3"), - ("http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz", "ec29112dd5afa0611ce80d1b7f02629c") + ("train-images-idx3-ubyte.gz", "f68b3c2dcbeaaa9fbdd348bbdeb94873"), + ("train-labels-idx1-ubyte.gz", "d53e105ee54ea40749a09fcbcd1e9432"), + ("t10k-images-idx3-ubyte.gz", "9fb629c4189551a2d022fa330f9573f3"), + ("t10k-labels-idx1-ubyte.gz", "ec29112dd5afa0611ce80d1b7f02629c") ] training_file = 'training.pt' @@ -141,9 +147,26 @@ def download(self) -> None: os.makedirs(self.processed_folder, exist_ok=True) # download files - for url, md5 in self.resources: - filename = url.rpartition('/')[2] - download_and_extract_archive(url, download_root=self.raw_folder, filename=filename, md5=md5) + for filename, md5 in self.resources: + for mirror in self.mirrors: + url = "{}{}".format(mirror, filename) + try: + print("Downloading {}".format(url)) + download_and_extract_archive( + url, download_root=self.raw_folder, + filename=filename, + md5=md5 + ) + except URLError as error: + print( + "Failed to download (trying next):\n{}".format(error) + ) + continue + finally: + print() + break + else: + raise RuntimeError("Error downloading {}".format(filename)) # process and save as torch files print('Processing...') From dc62ac30c0ee4e250da48f081a2d7a53fbd66d82 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 292/357] [fbsync] New tests for ImageNet dataset (#3543) Reviewed By: fmassa Differential Revision: D27127989 fbshipit-source-id: c21ba8a29c71a4bb9efa4bb1ab8713c3a9809842 --- test/datasets_utils.py | 3 +- test/fakedata_generation.py | 70 ------------------------------------- test/test_datasets.py | 43 +++++++++++++++++------ 3 files changed, 34 insertions(+), 82 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 577bdb2eb32..12f761c070e 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -312,7 +312,8 @@ def create_dataset( patch_checks = inject_fake_data special_kwargs, other_kwargs = self._split_kwargs(kwargs) - if "download" in self._HAS_SPECIAL_KWARG: + if "download" in self._HAS_SPECIAL_KWARG and special_kwargs.get("download", False): + # override download param to False param if its default is truthy special_kwargs["download"] = False config.update(other_kwargs) diff --git a/test/fakedata_generation.py b/test/fakedata_generation.py index dac415df110..473c15d19c4 100644 --- a/test/fakedata_generation.py +++ b/test/fakedata_generation.py @@ -143,76 +143,6 @@ def _make_meta_file(file, classes_key): yield root -@contextlib.contextmanager -def imagenet_root(): - import scipy.io as sio - - WNID = 'n01234567' - CLS = 'fakedata' - - def _make_image(file): - PIL.Image.fromarray(np.zeros((32, 32, 3), dtype=np.uint8)).save(file) - - def _make_tar(archive, content, arcname=None, compress=False): - mode = 'w:gz' if compress else 'w' - if arcname is None: - arcname = os.path.basename(content) - with tarfile.open(archive, mode) as fh: - fh.add(content, arcname=arcname) - - def _make_train_archive(root): - with get_tmp_dir() as tmp: - wnid_dir = os.path.join(tmp, WNID) - os.mkdir(wnid_dir) - - _make_image(os.path.join(wnid_dir, WNID + '_1.JPEG')) - - wnid_archive = wnid_dir + '.tar' - _make_tar(wnid_archive, wnid_dir) - - train_archive = os.path.join(root, 'ILSVRC2012_img_train.tar') - _make_tar(train_archive, wnid_archive) - - def _make_val_archive(root): - with get_tmp_dir() as tmp: - val_image = os.path.join(tmp, 'ILSVRC2012_val_00000001.JPEG') - _make_image(val_image) - - val_archive = os.path.join(root, 'ILSVRC2012_img_val.tar') - _make_tar(val_archive, val_image) - - def _make_devkit_archive(root): - with get_tmp_dir() as tmp: - data_dir = os.path.join(tmp, 'data') - os.mkdir(data_dir) - - meta_file = os.path.join(data_dir, 'meta.mat') - synsets = np.core.records.fromarrays([ - (0.0, 1.0), - (WNID, ''), - (CLS, ''), - ('fakedata for the torchvision testsuite', ''), - (0.0, 1.0), - ], names=['ILSVRC2012_ID', 'WNID', 'words', 'gloss', 'num_children']) - sio.savemat(meta_file, {'synsets': synsets}) - - groundtruth_file = os.path.join(data_dir, - 'ILSVRC2012_validation_ground_truth.txt') - with open(groundtruth_file, 'w') as fh: - fh.write('0\n') - - devkit_name = 'ILSVRC2012_devkit_t12' - devkit_archive = os.path.join(root, devkit_name + '.tar.gz') - _make_tar(devkit_archive, tmp, arcname=devkit_name, compress=True) - - with get_tmp_dir() as root: - _make_train_archive(root) - _make_val_archive(root) - _make_devkit_archive(root) - - yield root - - @contextlib.contextmanager def widerface_root(): """ diff --git a/test/test_datasets.py b/test/test_datasets.py index 56f0d6707bc..11114ae5b36 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -10,7 +10,7 @@ import torchvision from torchvision.datasets import utils from common_utils import get_tmp_dir -from fakedata_generation import mnist_root, imagenet_root, \ +from fakedata_generation import mnist_root, \ cityscapes_root, svhn_root, places365_root, widerface_root, stl10_root import xml.etree.ElementTree as ET from urllib.request import Request, urlopen @@ -146,16 +146,6 @@ def test_fashionmnist(self, mock_download_extract): img, target = dataset[0] self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) - @mock.patch('torchvision.datasets.imagenet._verify_archive') - @unittest.skipIf(not HAS_SCIPY, "scipy unavailable") - def test_imagenet(self, mock_verify): - with imagenet_root() as root: - dataset = torchvision.datasets.ImageNet(root, split='train') - self.generic_classification_dataset_test(dataset) - - dataset = torchvision.datasets.ImageNet(root, split='val') - self.generic_classification_dataset_test(dataset) - @mock.patch('torchvision.datasets.WIDERFace._check_integrity') @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') def test_widerface(self, mock_check_integrity): @@ -490,6 +480,37 @@ def inject_fake_data(self, tmpdir, config): return num_images_per_category * len(categories) +class ImageNetTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.ImageNet + REQUIRED_PACKAGES = ('scipy',) + CONFIGS = datasets_utils.combinations_grid(split=('train', 'val')) + + def inject_fake_data(self, tmpdir, config): + tmpdir = pathlib.Path(tmpdir) + + wnid = 'n01234567' + if config['split'] == 'train': + num_examples = 3 + datasets_utils.create_image_folder( + root=tmpdir, + name=tmpdir / 'train' / wnid / wnid, + file_name_fn=lambda image_idx: f"{wnid}_{image_idx}.JPEG", + num_examples=num_examples, + ) + else: + num_examples = 1 + datasets_utils.create_image_folder( + root=tmpdir, + name=tmpdir / 'val' / wnid, + file_name_fn=lambda image_ifx: "ILSVRC2012_val_0000000{image_idx}.JPEG", + num_examples=num_examples, + ) + + wnid_to_classes = {wnid: [1]} + torch.save((wnid_to_classes, None), tmpdir / 'meta.bin') + return num_examples + + class CIFAR10TestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.CIFAR10 CONFIGS = datasets_utils.combinations_grid(train=(True, False)) From 9acebc55c852f67c7c21513ca71cec8651c653c4 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 293/357] [fbsync] Fix (Fashion|K)MNIST download and MNIST download test (#3557) Summary: * add mirrors to (Fashion|K)MNIST * fix download tests for MNIST Reviewed By: fmassa Differential Revision: D27128007 fbshipit-source-id: 2ca4bba7d8e823cdca3174f408f14e9e6e2e8346 --- test/test_datasets_download.py | 3 ++- torchvision/datasets/mnist.py | 28 ++++++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/test/test_datasets_download.py b/test/test_datasets_download.py index 5c4fc54fd5d..e81677baa0d 100644 --- a/test/test_datasets_download.py +++ b/test/test_datasets_download.py @@ -249,7 +249,8 @@ def voc(): def mnist(): - return collect_download_configs(lambda: datasets.MNIST(ROOT, download=True), name="MNIST") + with unittest.mock.patch.object(datasets.MNIST, "mirrors", datasets.MNIST.mirrors[-1:]): + return collect_download_configs(lambda: datasets.MNIST(ROOT, download=True), name="MNIST") def fashion_mnist(): diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index e87cd46eefe..4bba625ee3e 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -206,15 +206,15 @@ class FashionMNIST(MNIST): target_transform (callable, optional): A function/transform that takes in the target and transforms it. """ + mirrors = [ + "http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/" + ] + resources = [ - ("http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz", - "8d4fb7e6c68d591d4c3dfef9ec88bf0d"), - ("http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz", - "25c81989df183df01b3e8a0aad5dffbe"), - ("http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz", - "bef4ecab320f06d8554ea6380940ec79"), - ("http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz", - "bb300cfdad3c16e7a12a480ee83cd310") + ("train-images-idx3-ubyte.gz", "8d4fb7e6c68d591d4c3dfef9ec88bf0d"), + ("train-labels-idx1-ubyte.gz", "25c81989df183df01b3e8a0aad5dffbe"), + ("t10k-images-idx3-ubyte.gz", "bef4ecab320f06d8554ea6380940ec79"), + ("t10k-labels-idx1-ubyte.gz", "bb300cfdad3c16e7a12a480ee83cd310") ] classes = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'] @@ -236,11 +236,15 @@ class KMNIST(MNIST): target_transform (callable, optional): A function/transform that takes in the target and transforms it. """ + mirrors = [ + "http://codh.rois.ac.jp/kmnist/dataset/kmnist/" + ] + resources = [ - ("http://codh.rois.ac.jp/kmnist/dataset/kmnist/train-images-idx3-ubyte.gz", "bdb82020997e1d708af4cf47b453dcf7"), - ("http://codh.rois.ac.jp/kmnist/dataset/kmnist/train-labels-idx1-ubyte.gz", "e144d726b3acfaa3e44228e80efcd344"), - ("http://codh.rois.ac.jp/kmnist/dataset/kmnist/t10k-images-idx3-ubyte.gz", "5c965bf0a639b31b8f53240b1b52f4d7"), - ("http://codh.rois.ac.jp/kmnist/dataset/kmnist/t10k-labels-idx1-ubyte.gz", "7320c461ea6c1c855c0b718fb2a4b134") + ("train-images-idx3-ubyte.gz", "bdb82020997e1d708af4cf47b453dcf7"), + ("train-labels-idx1-ubyte.gz", "e144d726b3acfaa3e44228e80efcd344"), + ("t10k-images-idx3-ubyte.gz", "5c965bf0a639b31b8f53240b1b52f4d7"), + ("t10k-labels-idx1-ubyte.gz", "7320c461ea6c1c855c0b718fb2a4b134") ] classes = ['o', 'ki', 'su', 'tsu', 'na', 'ha', 'ma', 'ya', 're', 'wo'] From 4ed48e8ae630b70ccf69ff8c2d3eef8c8c605e43 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 294/357] [fbsync] better cond (#3548) Summary: Co-authored-by: Vasilis Vryniotis Reviewed By: fmassa Differential Revision: D27128002 fbshipit-source-id: eb3ecdca811d5ec965234f45e937c759a4a70361 --- test/test_datasets.py | 4 ++-- test/test_utils.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test_datasets.py b/test/test_datasets.py index 11114ae5b36..8bac2e9dd4c 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -147,7 +147,7 @@ def test_fashionmnist(self, mock_download_extract): self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) @mock.patch('torchvision.datasets.WIDERFace._check_integrity') - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') + @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') def test_widerface(self, mock_check_integrity): mock_check_integrity.return_value = True with widerface_root() as root: @@ -166,7 +166,7 @@ def test_widerface(self, mock_check_integrity): img, target = dataset[0] self.assertTrue(isinstance(img, PIL.Image.Image)) - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') + @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') def test_cityscapes(self): with cityscapes_root() as root: diff --git a/test/test_utils.py b/test/test_utils.py index 662ad2a0cce..1fcee7ce489 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -42,21 +42,21 @@ def test_normalize_in_make_grid(self): self.assertTrue(torch.equal(norm_max, rounded_grid_max), 'Normalized max is not equal to 1') self.assertTrue(torch.equal(norm_min, rounded_grid_min), 'Normalized min is not equal to 0') - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') + @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') def test_save_image(self): with tempfile.NamedTemporaryFile(suffix='.png') as f: t = torch.rand(2, 3, 64, 64) utils.save_image(t, f.name) self.assertTrue(os.path.exists(f.name), 'The image is not present after save') - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') + @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') def test_save_image_single_pixel(self): with tempfile.NamedTemporaryFile(suffix='.png') as f: t = torch.rand(1, 3, 1, 1) utils.save_image(t, f.name) self.assertTrue(os.path.exists(f.name), 'The pixel image is not present after save') - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') + @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') def test_save_image_file_object(self): with tempfile.NamedTemporaryFile(suffix='.png') as f: t = torch.rand(2, 3, 64, 64) @@ -68,7 +68,7 @@ def test_save_image_file_object(self): self.assertTrue(torch.equal(F.to_tensor(img_orig), F.to_tensor(img_bytes)), 'Image not stored in file object') - @unittest.skipIf('win' in sys.platform, 'temporarily disabled on Windows') + @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') def test_save_image_single_pixel_file_object(self): with tempfile.NamedTemporaryFile(suffix='.png') as f: t = torch.rand(1, 3, 1, 1) From 68c1c22b42beb75139fc2c1637872d062668f984 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 295/357] [fbsync] [DOC] Add docs for missing datasets (#3536) Summary: * add missing docs * tries fixing docs * fixes docs * fixes ..code Reviewed By: fmassa Differential Revision: D27127991 fbshipit-source-id: 305a1695d6339df5f10ed03df4f96dcc07cbecac Co-authored-by: Vasilis Vryniotis --- docs/source/datasets.rst | 25 +++++++++++++++++++++++++ torchvision/datasets/kinetics.py | 1 + torchvision/datasets/semeion.py | 5 ++++- torchvision/datasets/widerface.py | 4 ++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index 6341e00fca0..ceb517ced8f 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -24,6 +24,18 @@ All the datasets have almost similar API. They all have two common arguments: .. currentmodule:: torchvision.datasets + +Caltech +~~~~~~~ + +.. autoclass:: Caltech101 + :members: __getitem__ + :special-members: + +.. autoclass:: Caltech256 + :members: __getitem__ + :special-members: + CelebA ~~~~~~ @@ -192,6 +204,13 @@ SBU :members: __getitem__ :special-members: +SEMEION +~~~~~~~ + +.. autoclass:: SEMEION + :members: __getitem__ + :special-members: + STL10 ~~~~~ @@ -231,3 +250,9 @@ VOC :members: __getitem__ :special-members: +WIDERFace +~~~~~~~~~ + +.. autoclass:: WIDERFace + :members: __getitem__ + :special-members: diff --git a/torchvision/datasets/kinetics.py b/torchvision/datasets/kinetics.py index e977fc42ba7..f459b526ca4 100644 --- a/torchvision/datasets/kinetics.py +++ b/torchvision/datasets/kinetics.py @@ -24,6 +24,7 @@ class Kinetics400(VisionDataset): Args: root (string): Root directory of the Kinetics-400 Dataset. Should be structured as follows: + .. code:: root/ diff --git a/torchvision/datasets/semeion.py b/torchvision/datasets/semeion.py index dad530ffa15..20ce4e5f5d5 100644 --- a/torchvision/datasets/semeion.py +++ b/torchvision/datasets/semeion.py @@ -8,7 +8,8 @@ class SEMEION(VisionDataset): - """`SEMEION `_ Dataset. + r"""`SEMEION `_ Dataset. + Args: root (string): Root directory of dataset where directory ``semeion.py`` exists. @@ -19,6 +20,7 @@ class SEMEION(VisionDataset): download (bool, optional): If true, downloads the dataset from the internet and puts it in root directory. If dataset is already downloaded, it is not downloaded again. + """ url = "http://archive.ics.uci.edu/ml/machine-learning-databases/semeion/semeion.data" filename = "semeion.data" @@ -53,6 +55,7 @@ def __getitem__(self, index: int) -> Tuple[Any, Any]: """ Args: index (int): Index + Returns: tuple: (image, target) where target is index of the target class. """ diff --git a/torchvision/datasets/widerface.py b/torchvision/datasets/widerface.py index 5e826183f57..55ad6d1e76a 100644 --- a/torchvision/datasets/widerface.py +++ b/torchvision/datasets/widerface.py @@ -14,6 +14,9 @@ class WIDERFace(VisionDataset): Args: root (string): Root directory where images and annotations are downloaded to. Expects the following folder structure if download=False: + + .. code:: + └── widerface ├── wider_face_split ('wider_face_split.zip' if compressed) @@ -29,6 +32,7 @@ class WIDERFace(VisionDataset): download (bool, optional): If true, downloads the dataset from the internet and puts it in root directory. If dataset is already downloaded, it is not downloaded again. + """ BASE_FOLDER = "widerface" From f0ff109e9e5659e4d0d246ebb1917a41a78d248b Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 296/357] [fbsync] Fix ternary operator to decide to store an image in Grayscale or RGB (#3553) Summary: Co-authored-by: Vasilis Vryniotis Reviewed By: fmassa Differential Revision: D27127992 fbshipit-source-id: 76ef726f854788ce71e785a838637e521d1f422c --- torchvision/csrc/io/image/cpu/encode_png.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/csrc/io/image/cpu/encode_png.cpp b/torchvision/csrc/io/image/cpu/encode_png.cpp index 3cf5de6955b..d28bad95890 100644 --- a/torchvision/csrc/io/image/cpu/encode_png.cpp +++ b/torchvision/csrc/io/image/cpu/encode_png.cpp @@ -128,7 +128,7 @@ torch::Tensor encode_png(const torch::Tensor& data, int64_t compression_level) { png_set_write_fn(png_write, &buf_info, torch_png_write_data, NULL); // Set output image information - auto color_type = PNG_COLOR_TYPE_GRAY ? channels == 1 : PNG_COLOR_TYPE_RGB; + auto color_type = channels == 1 ? PNG_COLOR_TYPE_GRAY : PNG_COLOR_TYPE_RGB; png_set_IHDR( png_write, info_ptr, From 93f5298c694254a601faf764e38f2e19685c5069 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 297/357] [fbsync] [ONNX] Fix roi_align ONNX export (#3355) Summary: * add tests * fix bug * remove tests * fix comment * fix comment * add warning * fix syntax error * fix python lint Reviewed By: fmassa Differential Revision: D27127999 fbshipit-source-id: c416f4de87a50a6d5fe3d006341fb84500f2a20d Co-authored-by: Vasilis Vryniotis --- test/test_onnx.py | 10 ++++++++++ torchvision/ops/_register_onnx_ops.py | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/test/test_onnx.py b/test/test_onnx.py index a4170b5242f..63f182004b8 100644 --- a/test/test_onnx.py +++ b/test/test_onnx.py @@ -129,6 +129,11 @@ def test_roi_align(self): model = ops.RoIAlign((5, 5), 1, 2) self.run_model(model, [(x, single_roi)]) + x = torch.rand(1, 1, 10, 10, dtype=torch.float32) + single_roi = torch.tensor([[0, 0, 0, 4, 4]], dtype=torch.float32) + model = ops.RoIAlign((5, 5), 1, -1) + self.run_model(model, [(x, single_roi)]) + def test_roi_align_aligned(self): x = torch.rand(1, 1, 10, 10, dtype=torch.float32) single_roi = torch.tensor([[0, 1.5, 1.5, 3, 3]], dtype=torch.float32) @@ -150,6 +155,11 @@ def test_roi_align_aligned(self): model = ops.RoIAlign((2, 2), 2.5, 0, aligned=True) self.run_model(model, [(x, single_roi)]) + x = torch.rand(1, 1, 10, 10, dtype=torch.float32) + single_roi = torch.tensor([[0, 0.2, 0.3, 4.5, 3.5]], dtype=torch.float32) + model = ops.RoIAlign((2, 2), 2.5, -1, aligned=True) + self.run_model(model, [(x, single_roi)]) + @unittest.skip # Issue in exporting ROIAlign with aligned = True for malformed boxes def test_roi_align_malformed_boxes(self): x = torch.randn(1, 1, 10, 10, dtype=torch.float32) diff --git a/torchvision/ops/_register_onnx_ops.py b/torchvision/ops/_register_onnx_ops.py index 02013844aac..8e8ed331803 100644 --- a/torchvision/ops/_register_onnx_ops.py +++ b/torchvision/ops/_register_onnx_ops.py @@ -29,6 +29,12 @@ def roi_align(g, input, rois, spatial_scale, pooled_height, pooled_width, sampli " ONNX forces ROIs to be 1x1 or larger.") scale = torch.tensor(0.5 / spatial_scale).to(dtype=torch.float) rois = g.op("Sub", rois, scale) + + # ONNX doesn't support negative sampling_ratio + if sampling_ratio < 0: + warnings.warn("ONNX doesn't support negative sampling ratio," + "therefore is is set to 0 in order to be exported.") + sampling_ratio = 0 return g.op('RoiAlign', input, rois, batch_indices, spatial_scale_f=spatial_scale, output_height_i=pooled_height, output_width_i=pooled_width, sampling_ratio_i=sampling_ratio) From 719e55c67a5d593cb9f7833dedc2f44668746e6e Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Thu, 18 Mar 2021 11:14:13 -0700 Subject: [PATCH 298/357] [fbsync] [android] gradle wrapper + publish to maven central (#3561) Summary: * [android] gradle wrapper [ghstack-poisoned] * [android] publishing to maven central [ghstack-poisoned] Reviewed By: fmassa Differential Revision: D27127994 fbshipit-source-id: f06dd18df9cc40d3a96986b0ecbebfa59ecb7aee Co-authored-by: Ivan Kobzarev --- android/.gitignore | 2 - android/build.gradle | 6 +- android/gradle.properties | 8 +- android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 56177 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + .../android_maven_install.gradle | 38 ---- android/gradle_scripts/android_tasks.gradle | 94 +--------- android/gradle_scripts/bintray.gradle | 64 ------- .../gradle_scripts/gradle_maven_push.gradle | 99 ---------- android/gradle_scripts/release.gradle | 4 +- android/gradle_scripts/release_bintray.gradle | 32 ---- android/gradlew | 172 ++++++++++++++++++ android/gradlew.bat | 84 +++++++++ 13 files changed, 271 insertions(+), 337 deletions(-) create mode 100644 android/gradle/wrapper/gradle-wrapper.jar create mode 100644 android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 android/gradle_scripts/android_maven_install.gradle delete mode 100644 android/gradle_scripts/bintray.gradle delete mode 100644 android/gradle_scripts/gradle_maven_push.gradle delete mode 100644 android/gradle_scripts/release_bintray.gradle create mode 100755 android/gradlew create mode 100644 android/gradlew.bat diff --git a/android/.gitignore b/android/.gitignore index b4d6d617645..adcfad04c91 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -1,8 +1,6 @@ local.properties **/*.iml .gradle -gradlew* -gradle/wrapper .idea/* .externalNativeBuild build diff --git a/android/build.gradle b/android/build.gradle index c3393e047e4..8e5fb09f827 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -24,10 +24,8 @@ allprojects { } dependencies { - classpath 'com.android.tools.build:gradle:3.3.2' - classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:${GRADLE_BINTRAY_PLUGIN_VERSION}" - classpath "com.github.dcendents:android-maven-gradle-plugin:${ANDROID_MAVEN_GRADLE_PLUGIN_VERSION}" - classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.9.8" + classpath 'com.android.tools.build:gradle:4.1.2' + classpath 'com.vanniktech:gradle-maven-publish-plugin:0.14.2' } } diff --git a/android/gradle.properties b/android/gradle.properties index bd5ed6bbd98..e9bf9f0522d 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,8 +1,9 @@ ABI_FILTERS=armeabi-v7a,arm64-v8a,x86,x86_64 -VERSION_NAME=0.0.1-SNAPSHOT +VERSION_NAME=0.9.0-SNAPSHOT GROUP=org.pytorch MAVEN_GROUP=org.pytorch +SONATYPE_STAGING_PROFILE=orgpytorch POM_URL=https://github.com/pytorch/vision/ POM_SCM_URL=https://github.com/pytorch/vision.git POM_SCM_CONNECTION=scm:git:https://github.com/pytorch/vision @@ -13,11 +14,6 @@ POM_ISSUES_URL=https://github.com/pytorch/vision/issues POM_LICENSE_DIST=repo POM_DEVELOPER_ID=pytorch POM_DEVELOPER_NAME=pytorch -syncWithMavenCentral=true - -GRADLE_BINTRAY_PLUGIN_VERSION=1.8.0 -GRADLE_VERSIONS_PLUGIN_VERSION=0.15.0 -ANDROID_MAVEN_GRADLE_PLUGIN_VERSION=2.1 # Gradle internals android.useAndroidX=true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..94336fcae912db8a11d55634156fa011f4686124 GIT binary patch literal 56177 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 i;x|p)^~-yfPOPa3(|vBayXKz if (POM_PACKAGING == 'aar') { - task androidJavadoc(type: Javadoc, dependsOn: assembleDebug) { - source += files(android.sourceSets.main.java.srcDirs) - failOnError false - // This task will try to compile *everything* it finds in the above directory and - // will choke on text files it doesn't understand. - exclude '**/BUCK' - exclude '**/*.md' - } - - task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) { - classifier = 'javadoc' - from androidJavadoc.destinationDir - } - - task androidSourcesJar(type: Jar) { - classifier = 'sources' - from android.sourceSets.main.java.srcDirs - } - - android.libraryVariants.all { variant -> - def name = variant.name.capitalize() - task "jar${name}"(type: Jar, dependsOn: variant.javaCompileProvider) { - from variant.javaCompileProvider.get().destinationDir - } - - androidJavadoc.doFirst { - classpath += files(android.bootClasspath) - classpath += files(variant.javaCompileProvider.get().classpath.files) - // This is generated by `assembleDebug` and holds the JARs generated by the APT. - classpath += fileTree(dir: "$buildDir/intermediates/bundles/debug/", include: '**/*.jar') - - // Process AAR dependencies - def aarDependencies = classpath.filter { it.name.endsWith('.aar') } - classpath -= aarDependencies - aarDependencies.each { aar -> - // Extract classes.jar from the AAR dependency, and add it to the javadoc classpath - def outputPath = "$buildDir/tmp/aarJar/${aar.name.replace('.aar', '.jar')}" - classpath += files(outputPath) - - // Use a task so the actual extraction only happens before the javadoc task is run - dependsOn task(name: "extract ${aar.name}").doLast { - extractEntry(aar, 'classes.jar', outputPath) - } - } - } - } - - artifacts.add('archives', androidJavadocJar) - artifacts.add('archives', androidSourcesJar) - } - - if (POM_PACKAGING == 'jar') { - task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir - } - - task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' - from sourceSets.main.allSource - } - - artifacts.add('archives', javadocJar) - artifacts.add('archives', sourcesJar) - } -} - -// Utility method to extract only one entry in a zip file -private def extractEntry(archive, entryPath, outputPath) { - if (!archive.exists()) { - throw new GradleException("archive $archive not found") - } - - def zip = new ZipFile(archive) - zip.entries().each { - if (it.name == entryPath) { - def path = Paths.get(outputPath) - if (!Files.exists(path)) { - Files.createDirectories(path.getParent()) - Files.copy(zip.getInputStream(it), path) + task headersJar(type: Jar) { + archiveClassifier.set('headers') + from("$rootDir/cxx/") { + include '**/*.h' } } + artifacts.add('archives', headersJar) } - zip.close() } diff --git a/android/gradle_scripts/bintray.gradle b/android/gradle_scripts/bintray.gradle deleted file mode 100644 index c20073964f7..00000000000 --- a/android/gradle_scripts/bintray.gradle +++ /dev/null @@ -1,64 +0,0 @@ -apply plugin: 'com.jfrog.bintray' - -def getBintrayUsername() { - return project.hasProperty('bintrayUsername') ? property('bintrayUsername') : System.getenv('BINTRAY_USERNAME') -} - -def getBintrayApiKey() { - return project.hasProperty('bintrayApiKey') ? property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY') -} - -def getBintrayGpgPassword() { - return project.hasProperty('bintrayGpgPassword') ? property('bintrayGpgPassword') : System.getenv('BINTRAY_GPG_PASSWORD') -} - -def getMavenCentralUsername() { - return project.hasProperty('mavenCentralUsername') ? property('mavenCentralUsername') : System.getenv('MAVEN_CENTRAL_USERNAME') -} - -def getMavenCentralPassword() { - return project.hasProperty('mavenCentralPassword') ? property('mavenCentralPassword') : System.getenv('MAVEN_CENTRAL_PASSWORD') -} - -def shouldSyncWithMavenCentral() { - return project.hasProperty('syncWithMavenCentral') ? property('syncWithMavenCentral').toBoolean() : false -} - -def dryRunOnly() { - return project.hasProperty('dryRun') ? property('dryRun').toBoolean() : false -} - -bintray { - user = getBintrayUsername() - key = getBintrayApiKey() - override = false - configurations = ['archives'] - pkg { - repo = bintrayRepo - userOrg = bintrayUserOrg - name = bintrayName - desc = bintrayDescription - websiteUrl = projectUrl - issueTrackerUrl = issuesUrl - vcsUrl = scmUrl - licenses = [ POM_LICENSE_NAME ] - dryRun = dryRunOnly() - override = false - publish = true - publicDownloadNumbers = true - version { - name = versionName - desc = bintrayDescription - gpg { - sign = true - passphrase = getBintrayGpgPassword() - } - mavenCentralSync { - sync = shouldSyncWithMavenCentral() - user = getMavenCentralUsername() - password = getMavenCentralPassword() - close = '1' // If set to 0, you have to manually click release - } - } - } -} diff --git a/android/gradle_scripts/gradle_maven_push.gradle b/android/gradle_scripts/gradle_maven_push.gradle deleted file mode 100644 index 5fdd8fbc6a0..00000000000 --- a/android/gradle_scripts/gradle_maven_push.gradle +++ /dev/null @@ -1,99 +0,0 @@ -apply plugin: 'signing' - -version = VERSION_NAME -group = MAVEN_GROUP - -def isReleaseBuild() { - return !VERSION_NAME.contains('SNAPSHOT') -} - -def getReleaseRepositoryUrl() { - return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL - : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" -} - -def getSnapshotRepositoryUrl() { - return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL - : "https://oss.sonatype.org/content/repositories/snapshots/" -} - -def getRepositoryUsername() { - return hasProperty('SONATYPE_NEXUS_USERNAME') ? SONATYPE_NEXUS_USERNAME : "" -} - -def getRepositoryPassword() { - return hasProperty('SONATYPE_NEXUS_PASSWORD') ? SONATYPE_NEXUS_PASSWORD : "" -} - -def getHttpProxyHost() { - return project.properties['systemProp.http.proxyHost'] -} - -def getHttpProxyPort() { - return project.properties['systemProp.http.proxyPort'] -} - -def needProxy() { - return (getHttpProxyHost() != null) && (getHttpProxyPort() != null) -} - -afterEvaluate { project -> - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - pom.groupId = MAVEN_GROUP - pom.artifactId = POM_ARTIFACT_ID - pom.version = VERSION_NAME - - repository(url: getReleaseRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - if (needProxy()) { - proxy(host: getHttpProxyHost(), port: getHttpProxyPort() as Integer, type: 'http') - } - } - snapshotRepository(url: getSnapshotRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - if (needProxy()) { - proxy(host: getHttpProxyHost(), port: getHttpProxyPort() as Integer, type: 'http') - } - } - - pom.project { - name POM_NAME - packaging POM_PACKAGING - description POM_DESCRIPTION - url POM_URL - - scm { - url POM_SCM_URL - connection POM_SCM_CONNECTION - developerConnection POM_SCM_DEV_CONNECTION - } - - licenses { - license { - name POM_LICENSE_NAME - url POM_LICENSE_URL - distribution POM_LICENSE_DIST - } - } - - developers { - developer { - id POM_DEVELOPER_ID - name POM_DEVELOPER_NAME - } - } - } - } - } - } - - signing { - required { isReleaseBuild() && gradle.taskGraph.hasTask('uploadArchives') } - sign configurations.archives - } - -} diff --git a/android/gradle_scripts/release.gradle b/android/gradle_scripts/release.gradle index d4e3aef4a22..ada97f33964 100644 --- a/android/gradle_scripts/release.gradle +++ b/android/gradle_scripts/release.gradle @@ -1,5 +1,3 @@ apply from: rootProject.file('gradle_scripts/android_tasks.gradle') -apply from: rootProject.file('gradle_scripts/release_bintray.gradle') - -apply from: rootProject.file('gradle_scripts/gradle_maven_push.gradle') +apply plugin: 'com.vanniktech.maven.publish' diff --git a/android/gradle_scripts/release_bintray.gradle b/android/gradle_scripts/release_bintray.gradle deleted file mode 100644 index 9b2af121a94..00000000000 --- a/android/gradle_scripts/release_bintray.gradle +++ /dev/null @@ -1,32 +0,0 @@ -ext { - bintrayRepo = 'maven' - bintrayUserOrg = 'pytorch' - bintrayName = "${GROUP}:${POM_ARTIFACT_ID}" - bintrayDescription = POM_DESCRIPTION - projectUrl = POM_URL - issuesUrl = POM_ISSUES_URL - scmUrl = POM_SCM_URL - scmConnection = POM_SCM_CONNECTION - scmDeveloperConnection = POM_SCM_DEV_CONNECTION - - publishedGroupId = GROUP - libraryName = 'torchvision' - artifact = 'torchvision' - - developerId = POM_DEVELOPER_ID - developerName = POM_DEVELOPER_NAME - - versionName = VERSION_NAME - - projectLicenses = { - license = { - name = POM_LICENSE_NAME - url = POM_LICENSE_URL - distribution = POM_LICENSE_DIST - } - } -} - -apply from: rootProject.file('gradle_scripts/android_maven_install.gradle') - -apply from: rootProject.file('gradle_scripts/bintray.gradle') diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 00000000000..cccdd3d517f --- /dev/null +++ b/android/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 00000000000..e95643d6a2c --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega From abffef6985181ecb0796f5e991bd13ce87188e71 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 299/357] [fbsync] Fix redirect behavior of datasets.utils.download_url (#3564) Summary: * use head request for redirects * remove requests dependency Reviewed By: fmassa Differential Revision: D27127987 fbshipit-source-id: 097cacc7c472dbe3fb52215313bc8549a3e691e5 --- torchvision/datasets/utils.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/torchvision/datasets/utils.py b/torchvision/datasets/utils.py index a27363c533c..e2ac22200d3 100644 --- a/torchvision/datasets/utils.py +++ b/torchvision/datasets/utils.py @@ -61,18 +61,20 @@ def check_integrity(fpath: str, md5: Optional[str] = None) -> bool: return check_md5(fpath, md5) -def _get_redirect_url(url: str, max_hops: int = 10) -> str: - import requests - - for hop in range(max_hops + 1): - response = requests.get(url) +def _get_redirect_url(url: str, max_hops: int = 3) -> str: + initial_url = url + headers = {"Method": "HEAD", "User-Agent": USER_AGENT} - if response.url == url or response.url is None: - return url + for _ in range(max_hops + 1): + with urllib.request.urlopen(urllib.request.Request(url, headers=headers)) as response: + if response.url == url or response.url is None: + return url - url = response.url + url = response.url else: - raise RecursionError(f"Too many redirects: {max_hops + 1})") + raise RecursionError( + f"Request to {initial_url} exceeded {max_hops} redirects. The last redirect points to {url}." + ) def _get_google_drive_file_id(url: str) -> Optional[str]: From d9a99ffd936a50ae636ef374d114a502fb067e6b Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 300/357] [fbsync] Separate extraction and decompression logic in datasets.utils.extract_archive (#3443) Summary: * generalize extract_archive * [test] re-enable extraction tests on windows * add tests for detect_file_type * add error messages to detect_file_type * Revert "[test] re-enable extraction tests on windows" This reverts commit 7fafebb0f6b4c49bd72c4b5e0a0b4b8c432bce57. * add utility functions for better mock call checking * add tests for decompress * simplify logic by using pathlib * lint * Apply suggestions from code review * make decompress private * remove unnecessary checks * add error message * fix mocking * add remaining tests * lint Reviewed By: fmassa Differential Revision: D27128004 fbshipit-source-id: 73f7d8a43eca5dbc9c7e63d8b1ff6e0859915d92 Co-authored-by: Francisco Massa Co-authored-by: Francisco Massa --- test/common_utils.py | 18 ++++ test/test_datasets_utils.py | 132 +++++++++++++++++++++++----- torchvision/datasets/utils.py | 158 +++++++++++++++++++++++++++------- 3 files changed, 254 insertions(+), 54 deletions(-) diff --git a/test/common_utils.py b/test/common_utils.py index 6f9dc9af932..7e16864d56c 100644 --- a/test/common_utils.py +++ b/test/common_utils.py @@ -10,6 +10,7 @@ import warnings import __main__ import random +import inspect from numbers import Number from torch._six import string_classes @@ -401,3 +402,20 @@ def disable_console_output(): stack.enter_context(contextlib.redirect_stdout(devnull)) stack.enter_context(contextlib.redirect_stderr(devnull)) yield + + +def call_args_to_kwargs_only(call_args, *callable_or_arg_names): + callable_or_arg_name = callable_or_arg_names[0] + if callable(callable_or_arg_name): + argspec = inspect.getfullargspec(callable_or_arg_name) + arg_names = argspec.args + if isinstance(callable_or_arg_name, type): + # remove self + arg_names.pop(0) + else: + arg_names = callable_or_arg_names + + args, kwargs = call_args + kwargs_only = kwargs.copy() + kwargs_only.update(dict(zip(arg_names, args))) + return kwargs_only diff --git a/test/test_datasets_utils.py b/test/test_datasets_utils.py index b1a8e1eda0f..be9299483fc 100644 --- a/test/test_datasets_utils.py +++ b/test/test_datasets_utils.py @@ -8,8 +8,10 @@ import warnings from torch._utils_internal import get_file_path_2 from urllib.error import URLError +import itertools +import lzma -from common_utils import get_tmp_dir +from common_utils import get_tmp_dir, call_args_to_kwargs_only TEST_FILE = get_file_path_2( @@ -100,6 +102,114 @@ def test_download_url_dispatch_download_from_google_drive(self, mock): mock.assert_called_once_with(id, root, filename, md5) + def test_detect_file_type(self): + for file, expected in [ + ("foo.tar.xz", (".tar.xz", ".tar", ".xz")), + ("foo.tar", (".tar", ".tar", None)), + ("foo.tar.gz", (".tar.gz", ".tar", ".gz")), + ("foo.tgz", (".tgz", ".tar", ".gz")), + ("foo.gz", (".gz", None, ".gz")), + ("foo.zip", (".zip", ".zip", None)), + ("foo.xz", (".xz", None, ".xz")), + ]: + with self.subTest(file=file): + self.assertSequenceEqual(utils._detect_file_type(file), expected) + + def test_detect_file_type_no_ext(self): + with self.assertRaises(RuntimeError): + utils._detect_file_type("foo") + + def test_detect_file_type_to_many_exts(self): + with self.assertRaises(RuntimeError): + utils._detect_file_type("foo.bar.tar.gz") + + def test_detect_file_type_unknown_archive_type(self): + with self.assertRaises(RuntimeError): + utils._detect_file_type("foo.bar.gz") + + def test_detect_file_type_unknown_compression(self): + with self.assertRaises(RuntimeError): + utils._detect_file_type("foo.tar.baz") + + def test_detect_file_type_unknown_partial_ext(self): + with self.assertRaises(RuntimeError): + utils._detect_file_type("foo.bar") + + def test_decompress_gzip(self): + def create_compressed(root, content="this is the content"): + file = os.path.join(root, "file") + compressed = f"{file}.gz" + + with gzip.open(compressed, "wb") as fh: + fh.write(content.encode()) + + return compressed, file, content + + with get_tmp_dir() as temp_dir: + compressed, file, content = create_compressed(temp_dir) + + utils._decompress(compressed) + + self.assertTrue(os.path.exists(file)) + + with open(file, "r") as fh: + self.assertEqual(fh.read(), content) + + def test_decompress_lzma(self): + def create_compressed(root, content="this is the content"): + file = os.path.join(root, "file") + compressed = f"{file}.xz" + + with lzma.open(compressed, "wb") as fh: + fh.write(content.encode()) + + return compressed, file, content + + with get_tmp_dir() as temp_dir: + compressed, file, content = create_compressed(temp_dir) + + utils.extract_archive(compressed, temp_dir) + + self.assertTrue(os.path.exists(file)) + + with open(file, "r") as fh: + self.assertEqual(fh.read(), content) + + def test_decompress_no_compression(self): + with self.assertRaises(RuntimeError): + utils._decompress("foo.tar") + + def test_decompress_remove_finished(self): + def create_compressed(root, content="this is the content"): + file = os.path.join(root, "file") + compressed = f"{file}.gz" + + with gzip.open(compressed, "wb") as fh: + fh.write(content.encode()) + + return compressed, file, content + + with get_tmp_dir() as temp_dir: + compressed, file, content = create_compressed(temp_dir) + + utils.extract_archive(compressed, temp_dir, remove_finished=True) + + self.assertFalse(os.path.exists(compressed)) + + def test_extract_archive_defer_to_decompress(self): + filename = "foo" + for ext, remove_finished in itertools.product((".gz", ".xz"), (True, False)): + with self.subTest(ext=ext, remove_finished=remove_finished): + with unittest.mock.patch("torchvision.datasets.utils._decompress") as mock: + file = f"{filename}{ext}" + utils.extract_archive(file, remove_finished=remove_finished) + + mock.assert_called_once() + self.assertEqual( + call_args_to_kwargs_only(mock.call_args, utils._decompress), + dict(from_path=file, to_path=filename, remove_finished=remove_finished), + ) + def test_extract_zip(self): def create_archive(root, content="this is the content"): file = os.path.join(root, "dst.txt") @@ -170,26 +280,6 @@ def create_archive(root, ext, mode, content="this is the content"): with open(file, "r") as fh: self.assertEqual(fh.read(), content) - def test_extract_gzip(self): - def create_compressed(root, content="this is the content"): - file = os.path.join(root, "file") - compressed = f"{file}.gz" - - with gzip.GzipFile(compressed, "wb") as fh: - fh.write(content.encode()) - - return compressed, file, content - - with get_tmp_dir() as temp_dir: - compressed, file, content = create_compressed(temp_dir) - - utils.extract_archive(compressed, temp_dir) - - self.assertTrue(os.path.exists(file)) - - with open(file, "r") as fh: - self.assertEqual(fh.read(), content) - def test_verify_str_arg(self): self.assertEqual("a", utils.verify_str_arg("a", "arg", ("a",))) self.assertRaises(ValueError, utils.verify_str_arg, 0, ("a",), "arg") diff --git a/torchvision/datasets/utils.py b/torchvision/datasets/utils.py index e2ac22200d3..8da26d6e98e 100644 --- a/torchvision/datasets/utils.py +++ b/torchvision/datasets/utils.py @@ -4,12 +4,15 @@ import gzip import re import tarfile -from typing import Any, Callable, List, Iterable, Optional, TypeVar +from typing import Any, Callable, List, Iterable, Optional, TypeVar, Dict, IO, Tuple from urllib.parse import urlparse import zipfile +import lzma +import contextlib import urllib import urllib.request import urllib.error +import pathlib import torch from torch.utils.model_zoo import tqdm @@ -242,56 +245,145 @@ def _save_response_content( pbar.close() -def _is_tarxz(filename: str) -> bool: - return filename.endswith(".tar.xz") +def _extract_tar(from_path: str, to_path: str, compression: Optional[str]) -> None: + with tarfile.open(from_path, f"r:{compression[1:]}" if compression else "r") as tar: + tar.extractall(to_path) -def _is_tar(filename: str) -> bool: - return filename.endswith(".tar") +_ZIP_COMPRESSION_MAP: Dict[str, int] = { + ".xz": zipfile.ZIP_LZMA, +} -def _is_targz(filename: str) -> bool: - return filename.endswith(".tar.gz") +def _extract_zip(from_path: str, to_path: str, compression: Optional[str]) -> None: + with zipfile.ZipFile( + from_path, "r", compression=_ZIP_COMPRESSION_MAP[compression] if compression else zipfile.ZIP_STORED + ) as zip: + zip.extractall(to_path) -def _is_tgz(filename: str) -> bool: - return filename.endswith(".tgz") +_ARCHIVE_EXTRACTORS: Dict[str, Callable[[str, str, Optional[str]], None]] = { + ".tar": _extract_tar, + ".zip": _extract_zip, +} +_COMPRESSED_FILE_OPENERS: Dict[str, Callable[..., IO]] = {".gz": gzip.open, ".xz": lzma.open} +_FILE_TYPE_ALIASES: Dict[str, Tuple[Optional[str], Optional[str]]] = {".tgz": (".tar", ".gz")} -def _is_gzip(filename: str) -> bool: - return filename.endswith(".gz") and not filename.endswith(".tar.gz") +def _verify_archive_type(archive_type: str) -> None: + if archive_type not in _ARCHIVE_EXTRACTORS.keys(): + valid_types = "', '".join(_ARCHIVE_EXTRACTORS.keys()) + raise RuntimeError(f"Unknown archive type '{archive_type}'. Known archive types are '{valid_types}'.") -def _is_zip(filename: str) -> bool: - return filename.endswith(".zip") +def _verify_compression(compression: str) -> None: + if compression not in _COMPRESSED_FILE_OPENERS.keys(): + valid_types = "', '".join(_COMPRESSED_FILE_OPENERS.keys()) + raise RuntimeError(f"Unknown compression '{compression}'. Known compressions are '{valid_types}'.") -def extract_archive(from_path: str, to_path: Optional[str] = None, remove_finished: bool = False) -> None: +def _detect_file_type(file: str) -> Tuple[str, Optional[str], Optional[str]]: + path = pathlib.Path(file) + suffix = path.suffix + suffixes = pathlib.Path(file).suffixes + if not suffixes: + raise RuntimeError( + f"File '{file}' has no suffixes that could be used to detect the archive type and compression." + ) + elif len(suffixes) > 2: + raise RuntimeError( + "Archive type and compression detection only works for 1 or 2 suffixes. " f"Got {len(suffixes)} instead." + ) + elif len(suffixes) == 2: + # if we have exactly two suffixes we assume the first one is the archive type and the second on is the + # compression + archive_type, compression = suffixes + _verify_archive_type(archive_type) + _verify_compression(compression) + return "".join(suffixes), archive_type, compression + + # check if the suffix is a known alias + with contextlib.suppress(KeyError): + return (suffix, *_FILE_TYPE_ALIASES[suffix]) + + # check if the suffix is an archive type + with contextlib.suppress(RuntimeError): + _verify_archive_type(suffix) + return suffix, suffix, None + + # check if the suffix is a compression + with contextlib.suppress(RuntimeError): + _verify_compression(suffix) + return suffix, None, suffix + + raise RuntimeError(f"Suffix '{suffix}' is neither recognized as archive type nor as compression.") + + +def _decompress(from_path: str, to_path: Optional[str] = None, remove_finished: bool = False) -> str: + r"""Decompress a file. + + The compression is automatically detected from the file name. + + Args: + from_path (str): Path to the file to be decompressed. + to_path (str): Path to the decompressed file. If omitted, ``from_path`` without compression extension is used. + remove_finished (bool): If ``True``, remove the file after the extraction. + + Returns: + (str): Path to the decompressed file. + """ + suffix, archive_type, compression = _detect_file_type(from_path) + if not compression: + raise RuntimeError(f"Couldn't detect a compression from suffix {suffix}.") + if to_path is None: - to_path = os.path.dirname(from_path) + to_path = from_path.replace(suffix, archive_type if archive_type is not None else "") - if _is_tar(from_path): - with tarfile.open(from_path, 'r') as tar: - tar.extractall(path=to_path) - elif _is_targz(from_path) or _is_tgz(from_path): - with tarfile.open(from_path, 'r:gz') as tar: - tar.extractall(path=to_path) - elif _is_tarxz(from_path): - with tarfile.open(from_path, 'r:xz') as tar: - tar.extractall(path=to_path) - elif _is_gzip(from_path): - to_path = os.path.join(to_path, os.path.splitext(os.path.basename(from_path))[0]) - with open(to_path, "wb") as out_f, gzip.GzipFile(from_path) as zip_f: - out_f.write(zip_f.read()) - elif _is_zip(from_path): - with zipfile.ZipFile(from_path, 'r') as z: - z.extractall(to_path) - else: - raise ValueError("Extraction of {} not supported".format(from_path)) + # We don't need to check for a missing key here, since this was already done in _detect_file_type() + compressed_file_opener = _COMPRESSED_FILE_OPENERS[compression] + + with compressed_file_opener(from_path, "rb") as rfh, open(to_path, "wb") as wfh: + wfh.write(rfh.read()) if remove_finished: os.remove(from_path) + return to_path + + +def extract_archive(from_path: str, to_path: Optional[str] = None, remove_finished: bool = False) -> str: + """Extract an archive. + + The archive type and a possible compression is automatically detected from the file name. If the file is compressed + but not an archive the call is dispatched to :func:`decompress`. + + Args: + from_path (str): Path to the file to be extracted. + to_path (str): Path to the directory the file will be extracted to. If omitted, the directory of the file is + used. + remove_finished (bool): If ``True``, remove the file after the extraction. + + Returns: + (str): Path to the directory the file was extracted to. + """ + if to_path is None: + to_path = os.path.dirname(from_path) + + suffix, archive_type, compression = _detect_file_type(from_path) + if not archive_type: + return _decompress( + from_path, + os.path.join(to_path, os.path.basename(from_path).replace(suffix, "")), + remove_finished=remove_finished, + ) + + # We don't need to check for a missing key here, since this was already done in _detect_file_type() + extractor = _ARCHIVE_EXTRACTORS[archive_type] + + extractor(from_path, to_path, compression) + + return to_path + def download_and_extract_archive( url: str, From 571471420e7f928e2b1238adfe292c316851510f Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 301/357] [fbsync] New tests for WIDERFace dataset (#3550) Summary: * New test for widerface * linting * create all 3 folders irrespective of split * Create different number of images for each split Reviewed By: fmassa Differential Revision: D27128003 fbshipit-source-id: fa92e2e940acd06794056bae7c3ed543ad44cc7d Co-authored-by: Francisco Massa --- test/datasets_utils.py | 3 +- test/test_datasets.py | 76 +++++++++++++++++++++++++++++++----------- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 12f761c070e..db5a37d98d5 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -161,7 +161,8 @@ class DatasetTestCase(unittest.TestCase): - DATASET_CLASS (torchvision.datasets.VisionDataset): Class of dataset to be tested. - FEATURE_TYPES (Sequence[Any]): Types of the elements returned by index access of the dataset. Instead of providing these manually, you can instead subclass ``ImageDatasetTestCase`` or ``VideoDatasetTestCase```to - get a reasonable default, that should work for most cases. + get a reasonable default, that should work for most cases. Each entry of the sequence may be a tuple, + to indicate multiple possible values. Optionally, you can overwrite the following class attributes: diff --git a/test/test_datasets.py b/test/test_datasets.py index 8bac2e9dd4c..ce99412f26f 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -146,26 +146,6 @@ def test_fashionmnist(self, mock_download_extract): img, target = dataset[0] self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) - @mock.patch('torchvision.datasets.WIDERFace._check_integrity') - @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') - def test_widerface(self, mock_check_integrity): - mock_check_integrity.return_value = True - with widerface_root() as root: - dataset = torchvision.datasets.WIDERFace(root, split='train') - self.assertEqual(len(dataset), 1) - img, target = dataset[0] - self.assertTrue(isinstance(img, PIL.Image.Image)) - - dataset = torchvision.datasets.WIDERFace(root, split='val') - self.assertEqual(len(dataset), 1) - img, target = dataset[0] - self.assertTrue(isinstance(img, PIL.Image.Image)) - - dataset = torchvision.datasets.WIDERFace(root, split='test') - self.assertEqual(len(dataset), 1) - img, target = dataset[0] - self.assertTrue(isinstance(img, PIL.Image.Image)) - @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') def test_cityscapes(self): with cityscapes_root() as root: @@ -480,6 +460,62 @@ def inject_fake_data(self, tmpdir, config): return num_images_per_category * len(categories) +@unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') +class WIDERFaceTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.WIDERFace + FEATURE_TYPES = (PIL.Image.Image, (dict, type(None))) # test split returns None as target + CONFIGS = datasets_utils.combinations_grid(split=('train', 'val', 'test')) + + def inject_fake_data(self, tmpdir, config): + widerface_dir = pathlib.Path(tmpdir) / 'widerface' + annotations_dir = widerface_dir / 'wider_face_split' + os.makedirs(annotations_dir) + + split_to_idx = split_to_num_examples = { + "train": 1, + "val": 2, + "test": 3, + } + + # We need to create all folders regardless of the split in config + for split in ('train', 'val', 'test'): + split_idx = split_to_idx[split] + num_examples = split_to_num_examples[split] + + datasets_utils.create_image_folder( + root=tmpdir, + name=widerface_dir / f'WIDER_{split}' / 'images' / '0--Parade', + file_name_fn=lambda image_idx: f"0_Parade_marchingband_1_{split_idx + image_idx}.jpg", + num_examples=num_examples, + ) + + annotation_file_name = { + 'train': annotations_dir / 'wider_face_train_bbx_gt.txt', + 'val': annotations_dir / 'wider_face_val_bbx_gt.txt', + 'test': annotations_dir / 'wider_face_test_filelist.txt', + }[split] + + annotation_content = { + "train": "".join( + f"0--Parade/0_Parade_marchingband_1_{split_idx + image_idx}.jpg\n1\n449 330 122 149 0 0 0 0 0 0\n" + for image_idx in range(num_examples) + ), + "val": "".join( + f"0--Parade/0_Parade_marchingband_1_{split_idx + image_idx}.jpg\n1\n501 160 285 443 0 0 0 0 0 0\n" + for image_idx in range(num_examples) + ), + "test": "".join( + f"0--Parade/0_Parade_marchingband_1_{split_idx + image_idx}.jpg\n" + for image_idx in range(num_examples) + ), + }[split] + + with open(annotation_file_name, "w") as annotation_file: + annotation_file.write(annotation_content) + + return split_to_num_examples[config["split"]] + + class ImageNetTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.ImageNet REQUIRED_PACKAGES = ('scipy',) From 805e71776de8ee5cf70dde0f5fae110e15de4460 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 302/357] [fbsync] update EMNIST url (#3567) Reviewed By: fmassa Differential Revision: D27128006 fbshipit-source-id: c6175a0b0cc903d1eac641dc32f98b98795b9d46 --- torchvision/datasets/mnist.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index 4bba625ee3e..123ce40cb8e 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -268,11 +268,7 @@ class EMNIST(MNIST): target_transform (callable, optional): A function/transform that takes in the target and transforms it. """ - # Updated URL from https://www.nist.gov/node/1298471/emnist-dataset since the - # _official_ download link - # https://cloudstor.aarnet.edu.au/plus/s/ZNmuFiuQTqZlu9W/download - # is (currently) unavailable - url = 'http://www.itl.nist.gov/iaui/vip/cs_links/EMNIST/gzip.zip' + url = 'https://www.itl.nist.gov/iaui/vip/cs_links/EMNIST/gzip.zip' md5 = "58c8d27c78d21e728a6bc7b3cc06412e" splits = ('byclass', 'bymerge', 'balanced', 'letters', 'digits', 'mnist') # Merged Classes assumes Same structure for both uppercase and lowercase version From 7702df22f5020bea44c5e8d8706dbda801100e41 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 303/357] [fbsync] Fixed typo on line 12 (#3537) Summary: Co-authored-by: Francisco Massa Reviewed By: fmassa Differential Revision: D27128001 fbshipit-source-id: 504afd9a3ec1a1f18e603f8612223a7705d51293 --- torchvision/transforms/_functional_video.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/transforms/_functional_video.py b/torchvision/transforms/_functional_video.py index 709c2d781ae..9eba0463a4f 100644 --- a/torchvision/transforms/_functional_video.py +++ b/torchvision/transforms/_functional_video.py @@ -9,7 +9,7 @@ def _is_tensor_video_clip(clip): if not torch.is_tensor(clip): - raise TypeError("clip should be Tesnor. Got %s" % type(clip)) + raise TypeError("clip should be Tensor. Got %s" % type(clip)) if not clip.ndimension() == 4: raise ValueError("clip should be 4D. Got %dD" % clip.dim()) From cb77aa328075cc1dee2ceead13c521f7bab38627 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 304/357] [fbsync] Add explanation for injected fake data in dataset tests (#3576) Reviewed By: fmassa Differential Revision: D27127996 fbshipit-source-id: 64a9bbf801010555b0fa91ea72b8ff158c7260e1 --- test/datasets_utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index db5a37d98d5..ad700a717a7 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -266,6 +266,10 @@ def dataset_args(self, tmpdir: str, config: Dict[str, Any]) -> Sequence[Any]: def inject_fake_data(self, tmpdir: str, config: Dict[str, Any]) -> Union[int, Dict[str, Any]]: """Inject fake data for dataset into a temporary directory. + During the creation of the dataset the download and extract logic is disabled. Thus, the fake data injected + here needs to resemble the raw data, i.e. the state of the dataset directly after the files are downloaded and + potentially extracted. + Args: tmpdir (str): Path to a temporary directory. For most cases this acts as root directory for the dataset to be created and in turn also for the fake data injected here. From b67100168b87fd65dce65717b3c4197a16ecc675 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 305/357] [fbsync] Remove caching from MNIST and variants (#3420) Summary: * remove caching from (Fashion|K)?MNIST * remove unnecessary lazy import * remove false check of binaries against the md5 of archives * remove caching from EMNIST * remove caching from QMNIST * lint * fix EMNIST * streamline QMNIST download Reviewed By: fmassa Differential Revision: D27127995 fbshipit-source-id: 3f53be72b5e7c8abe191edb1e4467e3ef33741dd --- test/test_datasets.py | 9 +- torchvision/datasets/mnist.py | 196 ++++++++++++++++------------------ 2 files changed, 101 insertions(+), 104 deletions(-) diff --git a/test/test_datasets.py b/test/test_datasets.py index ce99412f26f..a947df16c4b 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -120,7 +120,8 @@ def test_imagefolder_empty(self): ) @mock.patch('torchvision.datasets.mnist.download_and_extract_archive') - def test_mnist(self, mock_download_extract): + @mock.patch('torchvision.datasets.mnist.check_integrity', return_value=True) + def test_mnist(self, mock_download_extract, mock_check_integrity): num_examples = 30 with mnist_root(num_examples, "MNIST") as root: dataset = torchvision.datasets.MNIST(root, download=True) @@ -129,7 +130,8 @@ def test_mnist(self, mock_download_extract): self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) @mock.patch('torchvision.datasets.mnist.download_and_extract_archive') - def test_kmnist(self, mock_download_extract): + @mock.patch('torchvision.datasets.mnist.check_integrity', return_value=True) + def test_kmnist(self, mock_download_extract, mock_check_integrity): num_examples = 30 with mnist_root(num_examples, "KMNIST") as root: dataset = torchvision.datasets.KMNIST(root, download=True) @@ -138,7 +140,8 @@ def test_kmnist(self, mock_download_extract): self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) @mock.patch('torchvision.datasets.mnist.download_and_extract_archive') - def test_fashionmnist(self, mock_download_extract): + @mock.patch('torchvision.datasets.mnist.check_integrity', return_value=True) + def test_fashionmnist(self, mock_download_extract, mock_check_integrity): num_examples = 30 with mnist_root(num_examples, "FashionMNIST") as root: dataset = torchvision.datasets.FashionMNIST(root, download=True) diff --git a/torchvision/datasets/mnist.py b/torchvision/datasets/mnist.py index 123ce40cb8e..e356f17dd1b 100644 --- a/torchvision/datasets/mnist.py +++ b/torchvision/datasets/mnist.py @@ -7,12 +7,10 @@ import torch import codecs import string -import gzip -import lzma -from typing import Any, Callable, Dict, IO, List, Optional, Tuple, Union +from typing import Any, Callable, Dict, List, Optional, Tuple from urllib.error import URLError -from .utils import download_url, download_and_extract_archive, extract_archive, \ - verify_str_arg +from .utils import download_and_extract_archive, extract_archive, verify_str_arg, check_integrity +import shutil class MNIST(VisionDataset): @@ -81,6 +79,10 @@ def __init__( target_transform=target_transform) self.train = train # training set or test set + if self._check_legacy_exist(): + self.data, self.targets = self._load_legacy_data() + return + if download: self.download() @@ -88,11 +90,31 @@ def __init__( raise RuntimeError('Dataset not found.' + ' You can use download=True to download it') - if self.train: - data_file = self.training_file - else: - data_file = self.test_file - self.data, self.targets = torch.load(os.path.join(self.processed_folder, data_file)) + self.data, self.targets = self._load_data() + + def _check_legacy_exist(self): + processed_folder_exists = os.path.exists(self.processed_folder) + if not processed_folder_exists: + return False + + return all( + check_integrity(os.path.join(self.processed_folder, file)) for file in (self.training_file, self.test_file) + ) + + def _load_legacy_data(self): + # This is for BC only. We no longer cache the data in a custom binary, but simply read from the raw data + # directly. + data_file = self.training_file if self.train else self.test_file + return torch.load(os.path.join(self.processed_folder, data_file)) + + def _load_data(self): + image_file = f"{'train' if self.train else 't10k'}-images-idx3-ubyte" + data = read_image_file(os.path.join(self.raw_folder, image_file)) + + label_file = f"{'train' if self.train else 't10k'}-labels-idx1-ubyte" + targets = read_label_file(os.path.join(self.raw_folder, label_file)) + + return data, targets def __getitem__(self, index: int) -> Tuple[Any, Any]: """ @@ -132,19 +154,18 @@ def class_to_idx(self) -> Dict[str, int]: return {_class: i for i, _class in enumerate(self.classes)} def _check_exists(self) -> bool: - return (os.path.exists(os.path.join(self.processed_folder, - self.training_file)) and - os.path.exists(os.path.join(self.processed_folder, - self.test_file))) + return all( + check_integrity(os.path.join(self.raw_folder, os.path.splitext(os.path.basename(url))[0])) + for url, _ in self.resources + ) def download(self) -> None: - """Download the MNIST data if it doesn't exist in processed_folder already.""" + """Download the MNIST data if it doesn't exist already.""" if self._check_exists(): return os.makedirs(self.raw_folder, exist_ok=True) - os.makedirs(self.processed_folder, exist_ok=True) # download files for filename, md5 in self.resources: @@ -168,24 +189,6 @@ def download(self) -> None: else: raise RuntimeError("Error downloading {}".format(filename)) - # process and save as torch files - print('Processing...') - - training_set = ( - read_image_file(os.path.join(self.raw_folder, 'train-images-idx3-ubyte')), - read_label_file(os.path.join(self.raw_folder, 'train-labels-idx1-ubyte')) - ) - test_set = ( - read_image_file(os.path.join(self.raw_folder, 't10k-images-idx3-ubyte')), - read_label_file(os.path.join(self.raw_folder, 't10k-labels-idx1-ubyte')) - ) - with open(os.path.join(self.processed_folder, self.training_file), 'wb') as f: - torch.save(training_set, f) - with open(os.path.join(self.processed_folder, self.test_file), 'wb') as f: - torch.save(test_set, f) - - print('Done!') - def extra_repr(self) -> str: return "Split: {}".format("Train" if self.train is True else "Test") @@ -298,44 +301,39 @@ def _training_file(split) -> str: def _test_file(split) -> str: return 'test_{}.pt'.format(split) + @property + def _file_prefix(self) -> str: + return f"emnist-{self.split}-{'train' if self.train else 'test'}" + + @property + def images_file(self) -> str: + return os.path.join(self.raw_folder, f"{self._file_prefix}-images-idx3-ubyte") + + @property + def labels_file(self) -> str: + return os.path.join(self.raw_folder, f"{self._file_prefix}-labels-idx1-ubyte") + + def _load_data(self): + return read_image_file(self.images_file), read_label_file(self.labels_file) + + def _check_exists(self) -> bool: + return all(check_integrity(file) for file in (self.images_file, self.labels_file)) + def download(self) -> None: - """Download the EMNIST data if it doesn't exist in processed_folder already.""" - import shutil + """Download the EMNIST data if it doesn't exist already.""" if self._check_exists(): return os.makedirs(self.raw_folder, exist_ok=True) - os.makedirs(self.processed_folder, exist_ok=True) - # download files - print('Downloading and extracting zip archive') - download_and_extract_archive(self.url, download_root=self.raw_folder, filename="emnist.zip", - remove_finished=True, md5=self.md5) + download_and_extract_archive(self.url, download_root=self.raw_folder, md5=self.md5) gzip_folder = os.path.join(self.raw_folder, 'gzip') for gzip_file in os.listdir(gzip_folder): if gzip_file.endswith('.gz'): - extract_archive(os.path.join(gzip_folder, gzip_file), gzip_folder) - - # process and save as torch files - for split in self.splits: - print('Processing ' + split) - training_set = ( - read_image_file(os.path.join(gzip_folder, 'emnist-{}-train-images-idx3-ubyte'.format(split))), - read_label_file(os.path.join(gzip_folder, 'emnist-{}-train-labels-idx1-ubyte'.format(split))) - ) - test_set = ( - read_image_file(os.path.join(gzip_folder, 'emnist-{}-test-images-idx3-ubyte'.format(split))), - read_label_file(os.path.join(gzip_folder, 'emnist-{}-test-labels-idx1-ubyte'.format(split))) - ) - with open(os.path.join(self.processed_folder, self._training_file(split)), 'wb') as f: - torch.save(training_set, f) - with open(os.path.join(self.processed_folder, self._test_file(split)), 'wb') as f: - torch.save(test_set, f) + extract_archive(os.path.join(gzip_folder, gzip_file), self.raw_folder) shutil.rmtree(gzip_folder) - print('Done!') - class QMNIST(MNIST): """`QMNIST `_ Dataset. @@ -404,40 +402,51 @@ def __init__( self.test_file = self.data_file super(QMNIST, self).__init__(root, train, **kwargs) + @property + def images_file(self) -> str: + (url, _), _ = self.resources[self.subsets[self.what]] + return os.path.join(self.raw_folder, os.path.splitext(os.path.basename(url))[0]) + + @property + def labels_file(self) -> str: + _, (url, _) = self.resources[self.subsets[self.what]] + return os.path.join(self.raw_folder, os.path.splitext(os.path.basename(url))[0]) + + def _check_exists(self) -> bool: + return all(check_integrity(file) for file in (self.images_file, self.labels_file)) + + def _load_data(self): + data = read_sn3_pascalvincent_tensor(self.images_file) + assert (data.dtype == torch.uint8) + assert (data.ndimension() == 3) + + targets = read_sn3_pascalvincent_tensor(self.labels_file).long() + assert (targets.ndimension() == 2) + + if self.what == 'test10k': + data = data[0:10000, :, :].clone() + targets = targets[0:10000, :].clone() + elif self.what == 'test50k': + data = data[10000:, :, :].clone() + targets = targets[10000:, :].clone() + + return data, targets + def download(self) -> None: - """Download the QMNIST data if it doesn't exist in processed_folder already. + """Download the QMNIST data if it doesn't exist already. Note that we only download what has been asked for (argument 'what'). """ if self._check_exists(): return + os.makedirs(self.raw_folder, exist_ok=True) - os.makedirs(self.processed_folder, exist_ok=True) split = self.resources[self.subsets[self.what]] - files = [] - # download data files if not already there for url, md5 in split: filename = url.rpartition('/')[2] file_path = os.path.join(self.raw_folder, filename) if not os.path.isfile(file_path): - download_url(url, root=self.raw_folder, filename=filename, md5=md5) - files.append(file_path) - - # process and save as torch files - print('Processing...') - data = read_sn3_pascalvincent_tensor(files[0]) - assert(data.dtype == torch.uint8) - assert(data.ndimension() == 3) - targets = read_sn3_pascalvincent_tensor(files[1]).long() - assert(targets.ndimension() == 2) - if self.what == 'test10k': - data = data[0:10000, :, :].clone() - targets = targets[0:10000, :].clone() - if self.what == 'test50k': - data = data[10000:, :, :].clone() - targets = targets[10000:, :].clone() - with open(os.path.join(self.processed_folder, self.data_file), 'wb') as f: - torch.save((data, targets), f) + download_and_extract_archive(url, self.raw_folder, filename=filename, md5=md5) def __getitem__(self, index: int) -> Tuple[Any, Any]: # redefined to handle the compat flag @@ -459,19 +468,6 @@ def get_int(b: bytes) -> int: return int(codecs.encode(b, 'hex'), 16) -def open_maybe_compressed_file(path: Union[str, IO]) -> Union[IO, gzip.GzipFile]: - """Return a file object that possibly decompresses 'path' on the fly. - Decompression occurs when argument `path` is a string and ends with '.gz' or '.xz'. - """ - if not isinstance(path, torch._six.string_classes): - return path - if path.endswith('.gz'): - return gzip.open(path, 'rb') - if path.endswith('.xz'): - return lzma.open(path, 'rb') - return open(path, 'rb') - - SN3_PASCALVINCENT_TYPEMAP = { 8: (torch.uint8, np.uint8, np.uint8), 9: (torch.int8, np.int8, np.int8), @@ -482,12 +478,12 @@ def open_maybe_compressed_file(path: Union[str, IO]) -> Union[IO, gzip.GzipFile] } -def read_sn3_pascalvincent_tensor(path: Union[str, IO], strict: bool = True) -> torch.Tensor: +def read_sn3_pascalvincent_tensor(path: str, strict: bool = True) -> torch.Tensor: """Read a SN3 file in "Pascal Vincent" format (Lush file 'libidx/idx-io.lsh'). Argument may be a filename, compressed filename, or file object. """ # read - with open_maybe_compressed_file(path) as f: + with open(path, "rb") as f: data = f.read() # parse magic = get_int(data[0:4]) @@ -503,16 +499,14 @@ def read_sn3_pascalvincent_tensor(path: Union[str, IO], strict: bool = True) -> def read_label_file(path: str) -> torch.Tensor: - with open(path, 'rb') as f: - x = read_sn3_pascalvincent_tensor(f, strict=False) + x = read_sn3_pascalvincent_tensor(path, strict=False) assert(x.dtype == torch.uint8) assert(x.ndimension() == 1) return x.long() def read_image_file(path: str) -> torch.Tensor: - with open(path, 'rb') as f: - x = read_sn3_pascalvincent_tensor(f, strict=False) + x = read_sn3_pascalvincent_tensor(path, strict=False) assert(x.dtype == torch.uint8) assert(x.ndimension() == 3) return x From 4973734e19d8e661aeb102015598340af6575879 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 306/357] [fbsync] Move internet tests in single file (#3579) Summary: * Put internet tests in single file * adding the file * edit contirbuting guide * restore videoapi test Reviewed By: fmassa Differential Revision: D27127990 fbshipit-source-id: bb68aba1c422d31f158390d963e683116ca35858 --- CONTRIBUTING.md | 3 ++ test/test_datasets_utils.py | 53 --------------------------- test/test_internet.py | 71 +++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 53 deletions(-) create mode 100644 test/test_internet.py diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a825a3c7172..3fd20df6ca1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -99,6 +99,9 @@ If you would like to run all tests: pytest test -vvv ``` +Tests that require internet access should be in +`test/test_internet.py`. + ### Documentation Torchvision uses [Google style](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) diff --git a/test/test_datasets_utils.py b/test/test_datasets_utils.py index be9299483fc..949026d31cb 100644 --- a/test/test_datasets_utils.py +++ b/test/test_datasets_utils.py @@ -37,18 +37,6 @@ def test_check_integrity(self): self.assertTrue(utils.check_integrity(existing_fpath)) self.assertFalse(utils.check_integrity(nonexisting_fpath)) - def test_get_redirect_url(self): - url = "http://www.vision.caltech.edu/visipedia-data/CUB-200-2011/CUB_200_2011.tgz" - expected = "https://drive.google.com/file/d/1hbzc_P1FuxMkcabkgn9ZKinBwW683j45/view" - - actual = utils._get_redirect_url(url) - assert actual == expected - - def test_get_redirect_url_max_hops_exceeded(self): - url = "http://www.vision.caltech.edu/visipedia-data/CUB-200-2011/CUB_200_2011.tgz" - with self.assertRaises(RecursionError): - utils._get_redirect_url(url, max_hops=0) - def test_get_google_drive_file_id(self): url = "https://drive.google.com/file/d/1hbzc_P1FuxMkcabkgn9ZKinBwW683j45/view" expected = "1hbzc_P1FuxMkcabkgn9ZKinBwW683j45" @@ -61,47 +49,6 @@ def test_get_google_drive_file_id_invalid_url(self): assert utils._get_google_drive_file_id(url) is None - def test_download_url(self): - with get_tmp_dir() as temp_dir: - url = "http://github.com/pytorch/vision/archive/master.zip" - try: - utils.download_url(url, temp_dir) - self.assertFalse(len(os.listdir(temp_dir)) == 0) - except URLError: - msg = "could not download test file '{}'".format(url) - warnings.warn(msg, RuntimeWarning) - raise unittest.SkipTest(msg) - - def test_download_url_retry_http(self): - with get_tmp_dir() as temp_dir: - url = "https://github.com/pytorch/vision/archive/master.zip" - try: - utils.download_url(url, temp_dir) - self.assertFalse(len(os.listdir(temp_dir)) == 0) - except URLError: - msg = "could not download test file '{}'".format(url) - warnings.warn(msg, RuntimeWarning) - raise unittest.SkipTest(msg) - - def test_download_url_dont_exist(self): - with get_tmp_dir() as temp_dir: - url = "http://github.com/pytorch/vision/archive/this_doesnt_exist.zip" - with self.assertRaises(URLError): - utils.download_url(url, temp_dir) - - @unittest.mock.patch("torchvision.datasets.utils.download_file_from_google_drive") - def test_download_url_dispatch_download_from_google_drive(self, mock): - url = "https://drive.google.com/file/d/1hbzc_P1FuxMkcabkgn9ZKinBwW683j45/view" - - id = "1hbzc_P1FuxMkcabkgn9ZKinBwW683j45" - filename = "filename" - md5 = "md5" - - with get_tmp_dir() as root: - utils.download_url(url, root, filename, md5) - - mock.assert_called_once_with(id, root, filename, md5) - def test_detect_file_type(self): for file, expected in [ ("foo.tar.xz", (".tar.xz", ".tar", ".xz")), diff --git a/test/test_internet.py b/test/test_internet.py new file mode 100644 index 00000000000..05496752c7f --- /dev/null +++ b/test/test_internet.py @@ -0,0 +1,71 @@ +"""This file should contain all tests that need access to the internet (apart +from the ones in test_datasets_download.py) + +We want to bundle all internet-related tests in one file, so the file can be +cleanly ignored in FB internal test infra. +""" + +import os +import unittest +import unittest.mock +import warnings +from urllib.error import URLError + +import torchvision.datasets.utils as utils +from common_utils import get_tmp_dir + + +class DatasetUtilsTester(unittest.TestCase): + + def test_get_redirect_url(self): + url = "http://www.vision.caltech.edu/visipedia-data/CUB-200-2011/CUB_200_2011.tgz" + expected = "https://drive.google.com/file/d/1hbzc_P1FuxMkcabkgn9ZKinBwW683j45/view" + + actual = utils._get_redirect_url(url) + assert actual == expected + + def test_get_redirect_url_max_hops_exceeded(self): + url = "http://www.vision.caltech.edu/visipedia-data/CUB-200-2011/CUB_200_2011.tgz" + with self.assertRaises(RecursionError): + utils._get_redirect_url(url, max_hops=0) + + def test_download_url(self): + with get_tmp_dir() as temp_dir: + url = "http://github.com/pytorch/vision/archive/master.zip" + try: + utils.download_url(url, temp_dir) + self.assertFalse(len(os.listdir(temp_dir)) == 0) + except URLError: + msg = "could not download test file '{}'".format(url) + warnings.warn(msg, RuntimeWarning) + raise unittest.SkipTest(msg) + + def test_download_url_retry_http(self): + with get_tmp_dir() as temp_dir: + url = "https://github.com/pytorch/vision/archive/master.zip" + try: + utils.download_url(url, temp_dir) + self.assertFalse(len(os.listdir(temp_dir)) == 0) + except URLError: + msg = "could not download test file '{}'".format(url) + warnings.warn(msg, RuntimeWarning) + raise unittest.SkipTest(msg) + + def test_download_url_dont_exist(self): + with get_tmp_dir() as temp_dir: + url = "http://github.com/pytorch/vision/archive/this_doesnt_exist.zip" + with self.assertRaises(URLError): + utils.download_url(url, temp_dir) + + @unittest.mock.patch("torchvision.datasets.utils.download_file_from_google_drive") + def test_download_url_dispatch_download_from_google_drive(self, mock): + url = "https://drive.google.com/file/d/1hbzc_P1FuxMkcabkgn9ZKinBwW683j45/view" + + id = "1hbzc_P1FuxMkcabkgn9ZKinBwW683j45" + filename = "filename" + md5 = "md5" + + with get_tmp_dir() as root: + utils.download_url(url, root, filename, md5) + + mock.assert_called_once_with(id, root, filename, md5) From 4cf3b063eded3d300a79e6f1a910d786db3ffcd8 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 307/357] [fbsync] fix redirection in download tests (#3568) Summary: Co-authored-by: Francisco Massa Reviewed By: fmassa Differential Revision: D27128005 fbshipit-source-id: fdafdf85a8286a2bbd7e379229cccfdd84b47513 --- test/test_datasets_download.py | 38 ++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/test/test_datasets_download.py b/test/test_datasets_download.py index e81677baa0d..6ff3a33bcc9 100644 --- a/test/test_datasets_download.py +++ b/test/test_datasets_download.py @@ -14,7 +14,13 @@ import pytest from torchvision import datasets -from torchvision.datasets.utils import download_url, check_integrity, download_file_from_google_drive, USER_AGENT +from torchvision.datasets.utils import ( + download_url, + check_integrity, + download_file_from_google_drive, + _get_redirect_url, + USER_AGENT, +) from common_utils import get_tmp_dir from fakedata_generation import places365_root @@ -48,22 +54,28 @@ def inner_wrapper(request, *args, **kwargs): urlopen = limit_requests_per_time()(urlopen) -def resolve_redirects(max_redirects=3): +def resolve_redirects(max_hops=3): def outer_wrapper(fn): def inner_wrapper(request, *args, **kwargs): - url = initial_url = request.full_url if isinstance(request, Request) else request + initial_url = request.full_url if isinstance(request, Request) else request + url = _get_redirect_url(initial_url, max_hops=max_hops) - for _ in range(max_redirects + 1): - response = fn(request, *args, **kwargs) + if url == initial_url: + return fn(request, *args, **kwargs) - if response.url == url or response.url is None: - if url != initial_url: - warnings.warn(f"The URL {initial_url} ultimately redirects to {url}.") - return response + warnings.warn(f"The URL {initial_url} ultimately redirects to {url}.") - url = response.url - else: - raise RecursionError(f"Request to {initial_url} exceeded {max_redirects} redirects.") + if not isinstance(request, Request): + return fn(url, *args, **kwargs) + + request_attrs = { + attr: getattr(request, attr) for attr in ("data", "headers", "origin_req_host", "unverifiable") + } + # the 'method' attribute does only exist if the request was created with it + if hasattr(request, "method"): + request_attrs["method"] = request.method + + return fn(Request(url, **request_attrs), *args, **kwargs) return inner_wrapper @@ -150,7 +162,7 @@ def assert_server_response_ok(): def assert_url_is_accessible(url, timeout=5.0): - request = Request(url, headers={"method": "HEAD", "User-Agent": USER_AGENT}) + request = Request(url, headers={"User-Agent": USER_AGENT}, method="HEAD") with assert_server_response_ok(): urlopen(request, timeout=timeout) From 2849ae3f99521f08b0be55626afd7c9db84f5b91 Mon Sep 17 00:00:00 2001 From: Vincent Quenneville-Belair Date: Fri, 19 Mar 2021 08:50:27 -0700 Subject: [PATCH 308/357] [fbsync] fix VOC datasets for 2007 (#3572) Summary: Co-authored-by: Francisco Massa Reviewed By: fmassa Differential Revision: D27128000 fbshipit-source-id: b918dd8eff9beb621551a077b64b0d7f4deb3bbf --- torchvision/datasets/voc.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/torchvision/datasets/voc.py b/torchvision/datasets/voc.py index b905ede7a0a..9f6685e865c 100644 --- a/torchvision/datasets/voc.py +++ b/torchvision/datasets/voc.py @@ -87,10 +87,9 @@ def __init__( valid_image_sets = ["train", "trainval", "val"] if year == "2007": valid_image_sets.append("test") - key = "2007-test" - else: - key = year self.image_set = verify_str_arg(image_set, "image_set", valid_image_sets) + + key = "2007-test" if year == "2007" and image_set == "test" else year dataset_year_dict = DATASET_YEAR_DICT[key] self.url = dataset_year_dict["url"] From 09f21eb228dc14ac5c1fe10a1f9e8b480e9a7833 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 19:33:00 -0700 Subject: [PATCH 309/357] [fbsync] Clarify docstring of RandomResizedCrop (#3584) Reviewed By: fmassa Differential Revision: D27433914 fbshipit-source-id: 390360a31a5998d9c2e2052dcdef60b5ecb8eb9d --- torchvision/transforms/transforms.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 5a62adbedd3..2f7956523a3 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -773,22 +773,23 @@ def __repr__(self): class RandomResizedCrop(torch.nn.Module): - """Crop the given image to random size and aspect ratio. + """Crop a random portion of image and resize it to a given size. + If the image is torch Tensor, it is expected to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions - A crop of random size (default: of 0.08 to 1.0) of the original size and a random - aspect ratio (default: of 3/4 to 4/3) of the original aspect ratio is made. This crop - is finally resized to given size. - This is popularly used to train the Inception networks. + A crop of the original image is made: the crop has a random area (H * W) + and a random aspect ratio. This crop is finally resized to the given + size. This is popularly used to train the Inception networks. Args: - size (int or sequence): expected output size of each edge. If size is an + size (int or sequence): expected output size of the crop, for each edge. If size is an int instead of sequence like (h, w), a square output size ``(size, size)`` is made. If provided a sequence of length 1, it will be interpreted as (size[0], size[0]). In torchscript mode size as single int is not supported, use a sequence of length 1: ``[size, ]``. - scale (tuple of float): scale range of the cropped image before resizing, relatively to the origin image. - ratio (tuple of float): aspect ratio range of the cropped image before resizing. + scale (tuple of float): lower and upper bounds for the random area of the crop, before resizing. + ratio (tuple of float): lower and upper bounds for the random aspect ratio of the crop, before + resizing. interpolation (InterpolationMode): Desired interpolation enum defined by :class:`torchvision.transforms.InterpolationMode`. Default is ``InterpolationMode.BILINEAR``. If input is Tensor, only ``InterpolationMode.NEAREST``, ``InterpolationMode.BILINEAR`` and From ad819c29da5c877fa7c1cfa00a08ba66bfc85dc9 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 19:33:00 -0700 Subject: [PATCH 310/357] [fbsync] enable tests for WIDERFace on Windows (#3589) Reviewed By: fmassa Differential Revision: D27433920 fbshipit-source-id: b96ab35b06652aeaddd364cd045891367217cf29 --- test/test_datasets.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test_datasets.py b/test/test_datasets.py index a947df16c4b..9e606021e1c 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -463,7 +463,6 @@ def inject_fake_data(self, tmpdir, config): return num_images_per_category * len(categories) -@unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') class WIDERFaceTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.WIDERFace FEATURE_TYPES = (PIL.Image.Image, (dict, type(None))) # test split returns None as target From 498705ff791f53ce2cd7dff14be886fbaaf7018b Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 19:54:17 -0700 Subject: [PATCH 311/357] [fbsync] more correct (#3586) Summary: Co-authored-by: Vasilis Vryniotis Reviewed By: fmassa Differential Revision: D27433922 fbshipit-source-id: ded39ffc095a5f9f0ed078552c588c00f6a57e61 --- torchvision/transforms/transforms.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 2f7956523a3..2c4a10598b4 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -787,7 +787,8 @@ class RandomResizedCrop(torch.nn.Module): int instead of sequence like (h, w), a square output size ``(size, size)`` is made. If provided a sequence of length 1, it will be interpreted as (size[0], size[0]). In torchscript mode size as single int is not supported, use a sequence of length 1: ``[size, ]``. - scale (tuple of float): lower and upper bounds for the random area of the crop, before resizing. + scale (tuple of float): Specifies the lower and upper bounds for the random area of the crop, + before resizing. The scale is defined with respect to the area of the original image. ratio (tuple of float): lower and upper bounds for the random aspect ratio of the crop, before resizing. interpolation (InterpolationMode): Desired interpolation enum defined by From a935f9998fdfbf4997d552bb05860f7b37043786 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:19:09 -0700 Subject: [PATCH 312/357] [fbsync] removed duplicate as (#3591) Summary: Reviewed By: fmassa Differential Revision: D27433930 fbshipit-source-id: c22b94f487967de4c59f2f264bbd421629012ca0 Co-authored-by: urmi22 Co-authored-by: Vasilis Vryniotis --- torchvision/models/detection/transform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/models/detection/transform.py b/torchvision/models/detection/transform.py index 215005637eb..5e962f4bad9 100644 --- a/torchvision/models/detection/transform.py +++ b/torchvision/models/detection/transform.py @@ -84,7 +84,7 @@ def forward(self, if targets is not None: # make a copy of targets to avoid modifying it in-place # once torchscript supports dict comprehension - # this can be simplified as as follows + # this can be simplified as follows # targets = [{k: v for k,v in t.items()} for t in targets] targets_copy: List[Dict[str, Tensor]] = [] for t in targets: From 808971eb4a5314eb32133df98fbc7e8a55a6e318 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:19:09 -0700 Subject: [PATCH 313/357] [fbsync] .item() added to the 'target' variable in fakedataset.py (#3587) Summary: * added .item() for target inside getitem * changed fakedataset's expected return type Reviewed By: fmassa Differential Revision: D27433929 fbshipit-source-id: 0e88193718a23f53249d35e71980c24cc3eaeafa Co-authored-by: Vasilis Vryniotis --- test/test_datasets.py | 2 +- torchvision/datasets/fakedata.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_datasets.py b/test/test_datasets.py index 9e606021e1c..375cd55cc88 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1323,7 +1323,7 @@ def _file_stem(self, idx): class FakeDataTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.FakeData - FEATURE_TYPES = (PIL.Image.Image, torch.Tensor) + FEATURE_TYPES = (PIL.Image.Image, int) def dataset_args(self, tmpdir, config): return () diff --git a/torchvision/datasets/fakedata.py b/torchvision/datasets/fakedata.py index 64a450aa18d..aa5dc66f1f7 100644 --- a/torchvision/datasets/fakedata.py +++ b/torchvision/datasets/fakedata.py @@ -60,7 +60,7 @@ def __getitem__(self, index: int) -> Tuple[Any, Any]: if self.target_transform is not None: target = self.target_transform(target) - return img, target + return img, target.item() def __len__(self) -> int: return self.size From 23f24210e5865584c1e7f5c044f3a82aed8ded5e Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:19:09 -0700 Subject: [PATCH 314/357] [fbsync] update squeezenet urls (#3581) Summary: Co-authored-by: Vasilis Vryniotis Reviewed By: fmassa Differential Revision: D27433921 fbshipit-source-id: d2dae04c0b3a90c163f991898a19a22e0bc5493c --- torchvision/models/squeezenet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/torchvision/models/squeezenet.py b/torchvision/models/squeezenet.py index 603eaa04a74..7830e4b70ef 100644 --- a/torchvision/models/squeezenet.py +++ b/torchvision/models/squeezenet.py @@ -7,8 +7,8 @@ __all__ = ['SqueezeNet', 'squeezenet1_0', 'squeezenet1_1'] model_urls = { - 'squeezenet1_0': 'https://download.pytorch.org/models/squeezenet1_0-a815701f.pth', - 'squeezenet1_1': 'https://download.pytorch.org/models/squeezenet1_1-f364aa15.pth', + 'squeezenet1_0': 'https://download.pytorch.org/models/squeezenet1_0-b66bff10.pth', + 'squeezenet1_1': 'https://download.pytorch.org/models/squeezenet1_1-b8a52dc0.pth', } From bb4ce5f303e751f80d1b9a138af7326b6c9cfad3 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:19:09 -0700 Subject: [PATCH 315/357] [fbsync] Enable custom default config for dataset tests (#3578) Reviewed By: fmassa Differential Revision: D27433915 fbshipit-source-id: 70d5fcd0a8b68c2de7362ddf4f63a072cf658d7c --- test/datasets_utils.py | 166 ++++++++++++++++++++++++++++++++--------- test/test_datasets.py | 28 +++---- 2 files changed, 145 insertions(+), 49 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index ad700a717a7..8ba55c21f60 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -117,19 +117,45 @@ def inner_wrapper(*args, **kwargs): def test_all_configs(test): """Decorator to run test against all configurations. - Add this as decorator to an arbitrary test to run it against all configurations. The current configuration is - provided as the first parameter: + Add this as decorator to an arbitrary test to run it against all configurations. This includes + :attr:`DatasetTestCase.DEFAULT_CONFIG` and :attr:`DatasetTestCase.ADDITIONAL_CONFIGS`. + + The current configuration is provided as the first parameter for the test: .. code-block:: - @test_all_configs + @test_all_configs() def test_foo(self, config): pass + + .. note:: + + This will try to remove duplicate configurations. During this process it will not not preserve a potential + ordering of the configurations or an inner ordering of a configuration. """ + def maybe_remove_duplicates(configs): + try: + return [dict(config_) for config_ in set(tuple(sorted(config.items())) for config in configs)] + except TypeError: + # A TypeError will be raised if a value of any config is not hashable, e.g. a list. In that case duplicate + # removal would be a lot more elaborate and we simply bail out. + return configs + @functools.wraps(test) def wrapper(self): - for config in self.CONFIGS or (self._DEFAULT_CONFIG,): + configs = [] + if self.DEFAULT_CONFIG is not None: + configs.append(self.DEFAULT_CONFIG) + if self.ADDITIONAL_CONFIGS is not None: + configs.extend(self.ADDITIONAL_CONFIGS) + + if not configs: + configs = [self._KWARG_DEFAULTS.copy()] + else: + configs = maybe_remove_duplicates(configs) + + for config in configs: with self.subTest(**config): test(self, config) @@ -166,9 +192,13 @@ class DatasetTestCase(unittest.TestCase): Optionally, you can overwrite the following class attributes: - - CONFIGS (Sequence[Dict[str, Any]]): Additional configs that should be tested. Each dictonary can contain an - arbitrary combination of dataset parameters that are **not** ``transform``, ``target_transform``, - ``transforms``, or ``download``. The first element will be used as default configuration. + - DEFAULT_CONFIG (Dict[str, Any]): Config that will be used by default. If omitted, this defaults to all + keyword arguments of the dataset minus ``transform``, ``target_transform``, ``transforms``, and + ``download``. Overwrite this if you want to use a default value for a parameter for which the dataset does + not provide one. + - ADDITIONAL_CONFIGS (Sequence[Dict[str, Any]]): Additional configs that should be tested. Each dictionary can + contain an arbitrary combination of dataset parameters that are **not** ``transform``, ``target_transform``, + ``transforms``, or ``download``. - REQUIRED_PACKAGES (Iterable[str]): Additional dependencies to use the dataset. If these packages are not available, the tests are skipped. @@ -218,22 +248,31 @@ def test_baz(self): DATASET_CLASS = None FEATURE_TYPES = None - CONFIGS = None + DEFAULT_CONFIG = None + ADDITIONAL_CONFIGS = None REQUIRED_PACKAGES = None - _DEFAULT_CONFIG = None - + # These keyword arguments are checked by test_transforms in case they are available in DATASET_CLASS. _TRANSFORM_KWARGS = { "transform", "target_transform", "transforms", } + # These keyword arguments get a 'special' treatment and should not be set in DEFAULT_CONFIG or ADDITIONAL_CONFIGS. _SPECIAL_KWARGS = { *_TRANSFORM_KWARGS, "download", } + + # These fields are populated during setupClass() within _populate_private_class_attributes() + + # This will be a dictionary containing all keyword arguments with their respective default values extracted from + # the dataset constructor. + _KWARG_DEFAULTS = None + # This will be a set of all _SPECIAL_KWARGS that the dataset constructor takes. _HAS_SPECIAL_KWARG = None + # These functions are disabled during dataset creation in create_dataset(). _CHECK_FUNCTIONS = { "check_md5", "check_integrity", @@ -256,7 +295,8 @@ def dataset_args(self, tmpdir: str, config: Dict[str, Any]) -> Sequence[Any]: Args: tmpdir (str): Path to a temporary directory. For most cases this acts as root directory for the dataset to be created and in turn also for the fake data injected here. - config (Dict[str, Any]): Configuration that will be used to create the dataset. + config (Dict[str, Any]): Configuration that will be passed to the dataset constructor. It provides at least + fields for all dataset parameters with default values. Returns: (Tuple[str]): ``tmpdir`` which corresponds to ``root`` for most datasets. @@ -273,7 +313,8 @@ def inject_fake_data(self, tmpdir: str, config: Dict[str, Any]) -> Union[int, Di Args: tmpdir (str): Path to a temporary directory. For most cases this acts as root directory for the dataset to be created and in turn also for the fake data injected here. - config (Dict[str, Any]): Configuration that will be used to create the dataset. + config (Dict[str, Any]): Configuration that will be passed to the dataset constructor. It provides at least + fields for all dataset parameters with default values. Needs to return one of the following: @@ -293,9 +334,16 @@ def create_dataset( ) -> Iterator[Tuple[torchvision.datasets.VisionDataset, Dict[str, Any]]]: r"""Create the dataset in a temporary directory. + The configuration passed to the dataset is populated to contain at least all parameters with default values. + For this the following order of precedence is used: + + 1. Parameters in :attr:`kwargs`. + 2. Configuration in :attr:`config`. + 3. Configuration in :attr:`~DatasetTestCase.DEFAULT_CONFIG`. + 4. Default parameters of the dataset. + Args: - config (Optional[Dict[str, Any]]): Configuration that will be used to create the dataset. If omitted, the - default configuration is used. + config (Optional[Dict[str, Any]]): Configuration that will be used to create the dataset. inject_fake_data (bool): If ``True`` (default) inject the fake data with :meth:`.inject_fake_data` before creating the dataset. patch_checks (Optional[bool]): If ``True`` disable integrity check logic while creating the dataset. If @@ -308,30 +356,33 @@ def create_dataset( info (Dict[str, Any]): Additional information about the injected fake data. See :meth:`.inject_fake_data` for details. """ - default_config = self._DEFAULT_CONFIG.copy() - if config is not None: - default_config.update(config) - config = default_config - if patch_checks is None: patch_checks = inject_fake_data special_kwargs, other_kwargs = self._split_kwargs(kwargs) + + complete_config = self._KWARG_DEFAULTS.copy() + if self.DEFAULT_CONFIG: + complete_config.update(self.DEFAULT_CONFIG) + if config: + complete_config.update(config) + if other_kwargs: + complete_config.update(other_kwargs) + if "download" in self._HAS_SPECIAL_KWARG and special_kwargs.get("download", False): # override download param to False param if its default is truthy special_kwargs["download"] = False - config.update(other_kwargs) patchers = self._patch_download_extract() if patch_checks: patchers.update(self._patch_checks()) with get_tmp_dir() as tmpdir: - args = self.dataset_args(tmpdir, config) - info = self._inject_fake_data(tmpdir, config) if inject_fake_data else None + args = self.dataset_args(tmpdir, complete_config) + info = self._inject_fake_data(tmpdir, complete_config) if inject_fake_data else None with self._maybe_apply_patches(patchers), disable_console_output(): - dataset = self.DATASET_CLASS(*args, **config, **special_kwargs) + dataset = self.DATASET_CLASS(*args, **complete_config, **special_kwargs) yield dataset, info @@ -357,26 +408,69 @@ def _verify_required_public_class_attributes(cls): @classmethod def _populate_private_class_attributes(cls): - argspec = inspect.getfullargspec(cls.DATASET_CLASS.__init__) + defaults = [] + for cls_ in cls.DATASET_CLASS.__mro__: + if cls_ is torchvision.datasets.VisionDataset: + break - cls._DEFAULT_CONFIG = { - kwarg: default - for kwarg, default in zip(argspec.args[-len(argspec.defaults):], argspec.defaults) - if kwarg not in cls._SPECIAL_KWARGS - } + argspec = inspect.getfullargspec(cls_.__init__) - cls._HAS_SPECIAL_KWARG = {name for name in cls._SPECIAL_KWARGS if name in argspec.args} + if not argspec.defaults: + continue + + defaults.append( + {kwarg: default for kwarg, default in zip(argspec.args[-len(argspec.defaults):], argspec.defaults)} + ) + + if not argspec.varkw: + break + + kwarg_defaults = dict() + for config in reversed(defaults): + kwarg_defaults.update(config) + + has_special_kwargs = set() + for name in cls._SPECIAL_KWARGS: + if name not in kwarg_defaults: + continue + + del kwarg_defaults[name] + has_special_kwargs.add(name) + + cls._KWARG_DEFAULTS = kwarg_defaults + cls._HAS_SPECIAL_KWARG = has_special_kwargs @classmethod def _process_optional_public_class_attributes(cls): - if cls.REQUIRED_PACKAGES is not None: - try: - for pkg in cls.REQUIRED_PACKAGES: + def check_config(config, name): + special_kwargs = tuple(f"'{name}'" for name in cls._SPECIAL_KWARGS if name in config) + if special_kwargs: + raise UsageError( + f"{name} contains a value for the parameter(s) {', '.join(special_kwargs)}. " + f"These are handled separately by the test case and should not be set here. " + f"If you need to test some custom behavior regarding these parameters, " + f"you need to write a custom test (*not* test case), e.g. test_custom_transform()." + ) + + if cls.DEFAULT_CONFIG is not None: + check_config(cls.DEFAULT_CONFIG, "DEFAULT_CONFIG") + + if cls.ADDITIONAL_CONFIGS is not None: + for idx, config in enumerate(cls.ADDITIONAL_CONFIGS): + check_config(config, f"CONFIGS[{idx}]") + + if cls.REQUIRED_PACKAGES: + missing_pkgs = [] + for pkg in cls.REQUIRED_PACKAGES: + try: importlib.import_module(pkg) - except ImportError as error: + except ImportError: + missing_pkgs.append(f"'{pkg}'") + + if missing_pkgs: raise unittest.SkipTest( - f"The package '{error.name}' is required to load the dataset '{cls.DATASET_CLASS.__name__}' but is " - f"not installed." + f"The package(s) {', '.join(missing_pkgs)} are required to load the dataset " + f"'{cls.DATASET_CLASS.__name__}', but are not installed." ) def _split_kwargs(self, kwargs): diff --git a/test/test_datasets.py b/test/test_datasets.py index 375cd55cc88..c53a5f9cd54 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -369,7 +369,9 @@ class Caltech101TestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.Caltech101 FEATURE_TYPES = (PIL.Image.Image, (int, np.ndarray, tuple)) - CONFIGS = datasets_utils.combinations_grid(target_type=("category", "annotation", ["category", "annotation"])) + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid( + target_type=("category", "annotation", ["category", "annotation"]) + ) REQUIRED_PACKAGES = ("scipy",) def inject_fake_data(self, tmpdir, config): @@ -466,7 +468,7 @@ def inject_fake_data(self, tmpdir, config): class WIDERFaceTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.WIDERFace FEATURE_TYPES = (PIL.Image.Image, (dict, type(None))) # test split returns None as target - CONFIGS = datasets_utils.combinations_grid(split=('train', 'val', 'test')) + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(split=('train', 'val', 'test')) def inject_fake_data(self, tmpdir, config): widerface_dir = pathlib.Path(tmpdir) / 'widerface' @@ -521,7 +523,7 @@ def inject_fake_data(self, tmpdir, config): class ImageNetTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.ImageNet REQUIRED_PACKAGES = ('scipy',) - CONFIGS = datasets_utils.combinations_grid(split=('train', 'val')) + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(split=('train', 'val')) def inject_fake_data(self, tmpdir, config): tmpdir = pathlib.Path(tmpdir) @@ -551,7 +553,7 @@ def inject_fake_data(self, tmpdir, config): class CIFAR10TestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.CIFAR10 - CONFIGS = datasets_utils.combinations_grid(train=(True, False)) + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(train=(True, False)) _VERSION_CONFIG = dict( base_folder="cifar-10-batches-py", @@ -623,7 +625,7 @@ class CelebATestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.CelebA FEATURE_TYPES = (PIL.Image.Image, (torch.Tensor, int, tuple, type(None))) - CONFIGS = datasets_utils.combinations_grid( + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid( split=("train", "valid", "test", "all"), target_type=("attr", "identity", "bbox", "landmarks", ["attr", "identity"]), ) @@ -740,7 +742,7 @@ class VOCSegmentationTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.VOCSegmentation FEATURE_TYPES = (PIL.Image.Image, PIL.Image.Image) - CONFIGS = ( + ADDITIONAL_CONFIGS = ( *datasets_utils.combinations_grid( year=[f"20{year:02d}" for year in range(7, 13)], image_set=("train", "val", "trainval") ), @@ -929,7 +931,7 @@ def test_captions(self): class UCF101TestCase(datasets_utils.VideoDatasetTestCase): DATASET_CLASS = datasets.UCF101 - CONFIGS = datasets_utils.combinations_grid(fold=(1, 2, 3), train=(True, False)) + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(fold=(1, 2, 3), train=(True, False)) _VIDEO_FOLDER = "videos" _ANNOTATIONS_FOLDER = "annotations" @@ -990,7 +992,7 @@ class LSUNTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.LSUN REQUIRED_PACKAGES = ("lmdb",) - CONFIGS = datasets_utils.combinations_grid( + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid( classes=("train", "test", "val", ["bedroom_train", "church_outdoor_train"]) ) @@ -1097,7 +1099,7 @@ def test_not_found_or_corrupted(self): class HMDB51TestCase(datasets_utils.VideoDatasetTestCase): DATASET_CLASS = datasets.HMDB51 - CONFIGS = datasets_utils.combinations_grid(fold=(1, 2, 3), train=(True, False)) + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(fold=(1, 2, 3), train=(True, False)) _VIDEO_FOLDER = "videos" _SPLITS_FOLDER = "splits" @@ -1157,7 +1159,7 @@ def _create_split_files(self, root, video_files, fold, train): class OmniglotTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.Omniglot - CONFIGS = datasets_utils.combinations_grid(background=(True, False)) + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(background=(True, False)) def inject_fake_data(self, tmpdir, config): target_folder = ( @@ -1237,7 +1239,7 @@ def inject_fake_data(self, tmpdir, config): class USPSTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.USPS - CONFIGS = datasets_utils.combinations_grid(train=(True, False)) + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(train=(True, False)) def inject_fake_data(self, tmpdir, config): num_images = 2 if config["train"] else 1 @@ -1259,7 +1261,7 @@ class SBDatasetTestCase(datasets_utils.ImageDatasetTestCase): REQUIRED_PACKAGES = ("scipy.io", "scipy.sparse") - CONFIGS = datasets_utils.combinations_grid( + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid( image_set=("train", "val", "train_noval"), mode=("boundaries", "segmentation") ) @@ -1345,7 +1347,7 @@ class PhotoTourTestCase(datasets_utils.ImageDatasetTestCase): _TRAIN_FEATURE_TYPES = (torch.Tensor,) _TEST_FEATURE_TYPES = (torch.Tensor, torch.Tensor, torch.Tensor) - CONFIGS = datasets_utils.combinations_grid(train=(True, False)) + datasets_utils.combinations_grid(train=(True, False)) _NAME = "liberty" From cbd68d71f5fc16828939f44f689af7758bc58733 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:19:09 -0700 Subject: [PATCH 316/357] [fbsync] add ROCm binary wheels (#3575) Summary: * add ROCm binary wheels * fix lint error Reviewed By: fmassa Differential Revision: D27433917 fbshipit-source-id: 8c5845c28d3bd705d7d5028552d3787d0aebdd5f Co-authored-by: Eli Uriegas <1700823+seemethere@users.noreply.github.com> Co-authored-by: Francisco Massa --- .circleci/config.yml | 140 +++++++++++++++++++++++++++++++++++++ .circleci/regenerate.py | 23 ++++-- packaging/pkg_helpers.bash | 3 + 3 files changed, 159 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4ee1e59a1d5..1223abc9129 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -829,6 +829,11 @@ workflows: name: binary_linux_wheel_py3.6_cu111 python_version: '3.6' wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cu_version: rocm4.0.1 + name: binary_linux_wheel_py3.6_rocm4.0.1 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-rocm:4.0.1 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -853,6 +858,11 @@ workflows: name: binary_linux_wheel_py3.7_cu111 python_version: '3.7' wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cu_version: rocm4.0.1 + name: binary_linux_wheel_py3.7_rocm4.0.1 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-rocm:4.0.1 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -877,6 +887,11 @@ workflows: name: binary_linux_wheel_py3.8_cu111 python_version: '3.8' wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cu_version: rocm4.0.1 + name: binary_linux_wheel_py3.8_rocm4.0.1 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-rocm:4.0.1 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -901,6 +916,11 @@ workflows: name: binary_linux_wheel_py3.9_cu111 python_version: '3.9' wheel_docker_image: pytorch/manylinux-cuda111 + - binary_linux_wheel: + cu_version: rocm4.0.1 + name: binary_linux_wheel_py3.9_rocm4.0.1 + python_version: '3.9' + wheel_docker_image: pytorch/manylinux-rocm:4.0.1 - binary_macos_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1607,6 +1627,36 @@ workflows: python_version: '3.6' requires: - nightly_binary_linux_wheel_py3.6_cu111_upload + - binary_linux_wheel: + cu_version: rocm4.0.1 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_rocm4.0.1 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-rocm:4.0.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_rocm4.0.1_upload + requires: + - nightly_binary_linux_wheel_py3.6_rocm4.0.1 + subfolder: rocm4.0.1/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.6_rocm4.0.1_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_linux_wheel_py3.6_rocm4.0.1_upload - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1731,6 +1781,36 @@ workflows: python_version: '3.7' requires: - nightly_binary_linux_wheel_py3.7_cu111_upload + - binary_linux_wheel: + cu_version: rocm4.0.1 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_rocm4.0.1 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-rocm:4.0.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_rocm4.0.1_upload + requires: + - nightly_binary_linux_wheel_py3.7_rocm4.0.1 + subfolder: rocm4.0.1/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.7_rocm4.0.1_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_linux_wheel_py3.7_rocm4.0.1_upload - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1855,6 +1935,36 @@ workflows: python_version: '3.8' requires: - nightly_binary_linux_wheel_py3.8_cu111_upload + - binary_linux_wheel: + cu_version: rocm4.0.1 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_rocm4.0.1 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-rocm:4.0.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_rocm4.0.1_upload + requires: + - nightly_binary_linux_wheel_py3.8_rocm4.0.1 + subfolder: rocm4.0.1/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.8_rocm4.0.1_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_linux_wheel_py3.8_rocm4.0.1_upload - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1979,6 +2089,36 @@ workflows: python_version: '3.9' requires: - nightly_binary_linux_wheel_py3.9_cu111_upload + - binary_linux_wheel: + cu_version: rocm4.0.1 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9_rocm4.0.1 + python_version: '3.9' + wheel_docker_image: pytorch/manylinux-rocm:4.0.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9_rocm4.0.1_upload + requires: + - nightly_binary_linux_wheel_py3.9_rocm4.0.1 + subfolder: rocm4.0.1/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.9_rocm4.0.1_smoke_test_pip + python_version: '3.9' + requires: + - nightly_binary_linux_wheel_py3.9_rocm4.0.1_upload - binary_macos_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 6dbc0648d6f..24f663db9cb 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -29,12 +29,15 @@ def build_workflows(prefix='', filter_branch=None, upload=False, indentation=6, for btype in ["wheel", "conda"]: for os_type in ["linux", "macos", "win"]: python_versions = PYTHON_VERSIONS - cu_versions_dict = {"linux": ["cpu", "cu101", "cu102", "cu111"], + cu_versions_dict = {"linux": ["cpu", "cu101", "cu102", "cu111", "rocm4.0.1"], "win": ["cpu", "cu101", "cu102", "cu111"], "macos": ["cpu"]} cu_versions = cu_versions_dict[os_type] for python_version in python_versions: for cu_version in cu_versions: + # ROCm conda packages not yet supported + if cu_version.startswith('rocm') and btype == "conda": + continue for unicode in ([False, True] if btype == "wheel" and python_version == "2.7" else [False]): fb = filter_branch if windows_latest_only and os_type == "win" and filter_branch is None and \ @@ -108,18 +111,22 @@ def upload_doc_job(filter_branch): def get_manylinux_image(cu_version): - cu_suffix = "102" - if cu_version.startswith('cu'): + if cu_version == "cpu": + return "pytorch/manylinux-cuda102" + elif cu_version.startswith('cu'): cu_suffix = cu_version[len('cu'):] - return f"pytorch/manylinux-cuda{cu_suffix}" + return f"pytorch/manylinux-cuda{cu_suffix}" + elif cu_version.startswith('rocm'): + rocm_suffix = cu_version[len('rocm'):] + return f"pytorch/manylinux-rocm:{rocm_suffix}" def get_conda_image(cu_version): if cu_version == "cpu": return "pytorch/conda-builder:cpu" - if cu_version.startswith('cu'): + elif cu_version.startswith('cu'): cu_suffix = cu_version[len('cu'):] - return f"pytorch/conda-builder:cuda{cu_suffix}" + return f"pytorch/conda-builder:cuda{cu_suffix}" def generate_base_workflow(base_workflow_name, python_version, cu_version, @@ -136,7 +143,9 @@ def generate_base_workflow(base_workflow_name, python_version, cu_version, if os_type != "win": d["wheel_docker_image"] = get_manylinux_image(cu_version) - d["conda_docker_image"] = get_conda_image(cu_version) + # ROCm conda packages not yet supported + if "rocm" not in cu_version: + d["conda_docker_image"] = get_conda_image(cu_version) if filter_branch is not None: d["filters"] = { diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index c5e55423c79..da2c3e4fa7f 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -126,6 +126,9 @@ setup_cuda() { ;; cpu) ;; + rocm*) + export FORCE_CUDA=1 + ;; *) echo "Unrecognized CU_VERSION=$CU_VERSION" exit 1 From b9a704ee3c802f17aaf4f4b51f91e61703808b51 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:19:09 -0700 Subject: [PATCH 317/357] [fbsync] Added utility to draw segmentation masks (#3330) Summary: * add draw segm masks * rewrites with new api * fix flaky colors * fix resize bug * resize for sanity * cleanup * project the image * Minor refactor to adopt num classes * add uint8 in docstring * adds alpha and docstring * move code a bit down * Minor fix * fix type check * Fixing resize bug. * Fix type of alpha. * Remove unnecessary RGBA conversions. * update docs to supported only rgb * minor edits * adds tests * shifts masks up * change tests and impelementation for bool * change mode to L * convert to float * fixes docs Reviewed By: fmassa Differential Revision: D27433933 fbshipit-source-id: 26e72b4f8471218631b26cc555422890b0f6b81d Co-authored-by: Vasilis Vryniotis Co-authored-by: Vasilis Vryniotis Co-authored-by: Francisco Massa --- docs/source/utils.rst | 4 +- .../fakedata/draw_segm_masks_colors_util.png | Bin 0 -> 88 bytes .../draw_segm_masks_no_colors_util.png | Bin 0 -> 106 bytes test/test_utils.py | 53 +++++++++++++++ torchvision/utils.py | 62 +++++++++++++++++- 5 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 test/assets/fakedata/draw_segm_masks_colors_util.png create mode 100644 test/assets/fakedata/draw_segm_masks_no_colors_util.png diff --git a/docs/source/utils.rst b/docs/source/utils.rst index 0ae450487e3..acaf785d817 100644 --- a/docs/source/utils.rst +++ b/docs/source/utils.rst @@ -7,4 +7,6 @@ torchvision.utils .. autofunction:: save_image -.. autofunction:: draw_bounding_boxes \ No newline at end of file +.. autofunction:: draw_bounding_boxes + +.. autofunction:: draw_segmentation_masks diff --git a/test/assets/fakedata/draw_segm_masks_colors_util.png b/test/assets/fakedata/draw_segm_masks_colors_util.png new file mode 100644 index 0000000000000000000000000000000000000000..454b35556317dc1da1707fb234cf8563c1e8c707 GIT binary patch literal 88 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61SFYwH*Nw_@}4e^Ar*6yP5$MdX<(7~Fa6*B l;o_6Vh6|XE{XeGhiNULzE&Y{;O%+fngQu&X%Q~loCIFN+8JPe8 literal 0 HcmV?d00001 diff --git a/test/assets/fakedata/draw_segm_masks_no_colors_util.png b/test/assets/fakedata/draw_segm_masks_no_colors_util.png new file mode 100644 index 0000000000000000000000000000000000000000..f048d2469d2414d6e1e864111a6117a30a7d210b GIT binary patch literal 106 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjyLr)jSkcv6UCi5Pib torch.Tensor: + + """ + Draws segmentation masks on given RGB image. + The values of the input image should be uint8 between 0 and 255. + + Args: + image (Tensor): Tensor of shape (3 x H x W) and dtype uint8. + masks (Tensor): Tensor of shape (num_masks, H, W). Each containing probability of predicted class. + alpha (float): Float number between 0 and 1 denoting factor of transpaerency of masks. + colors (List[Union[str, Tuple[int, int, int]]]): List containing the colors of masks. The colors can + be represented as `str` or `Tuple[int, int, int]`. + """ + + if not isinstance(image, torch.Tensor): + raise TypeError(f"Tensor expected, got {type(image)}") + elif image.dtype != torch.uint8: + raise ValueError(f"Tensor uint8 expected, got {image.dtype}") + elif image.dim() != 3: + raise ValueError("Pass individual images, not batches") + elif image.size()[0] != 3: + raise ValueError("Pass an RGB image. Other Image formats are not supported") + + num_masks = masks.size()[0] + masks = masks.argmax(0) + + if colors is None: + palette = torch.tensor([2 ** 25 - 1, 2 ** 15 - 1, 2 ** 21 - 1]) + colors_t = torch.as_tensor([i for i in range(num_masks)])[:, None] * palette + color_arr = (colors_t % 255).numpy().astype("uint8") + else: + color_list = [] + for color in colors: + if isinstance(color, str): + # This will automatically raise Error if rgb cannot be parsed. + fill_color = ImageColor.getrgb(color) + color_list.append(fill_color) + elif isinstance(color, tuple): + color_list.append(color) + + color_arr = np.array(color_list).astype("uint8") + + _, h, w = image.size() + img_to_draw = Image.fromarray(masks.byte().cpu().numpy()).resize((w, h)) + img_to_draw.putpalette(color_arr) + + img_to_draw = torch.from_numpy(np.array(img_to_draw.convert('RGB'))) + img_to_draw = img_to_draw.permute((2, 0, 1)) + + return (image.float() * alpha + img_to_draw.float() * (1.0 - alpha)).to(dtype=torch.uint8) From d1a437855885e98de91601d7cef8130969cd40d0 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:19:09 -0700 Subject: [PATCH 318/357] [fbsync] Improve error handling in make_dataset (#3496) Summary: * factor out find_classes * use find_classes in video datasets * adapt old tests Reviewed By: fmassa Differential Revision: D27433918 fbshipit-source-id: 60d8da2f222a19e0757197f5d38b6a9cce7694a8 --- test/test_datasets.py | 7 +-- torchvision/datasets/folder.py | 90 +++++++++++++++++++++++--------- torchvision/datasets/hmdb51.py | 6 +-- torchvision/datasets/kinetics.py | 6 +-- torchvision/datasets/ucf101.py | 6 +-- 5 files changed, 73 insertions(+), 42 deletions(-) diff --git a/test/test_datasets.py b/test/test_datasets.py index c53a5f9cd54..03edba57559 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -111,10 +111,10 @@ def test_imagefolder(self): def test_imagefolder_empty(self): with get_tmp_dir() as root: - with self.assertRaises(RuntimeError): + with self.assertRaises(FileNotFoundError): torchvision.datasets.ImageFolder(root, loader=lambda x: x) - with self.assertRaises(RuntimeError): + with self.assertRaises(FileNotFoundError): torchvision.datasets.ImageFolder( root, loader=lambda x: x, is_valid_file=lambda x: False ) @@ -1092,9 +1092,6 @@ def inject_fake_data(self, tmpdir, config): return num_videos_per_class * len(classes) - def test_not_found_or_corrupted(self): - self.skipTest("Dataset currently does not handle the case of no found videos.") - class HMDB51TestCase(datasets_utils.VideoDatasetTestCase): DATASET_CLASS = datasets.HMDB51 diff --git a/torchvision/datasets/folder.py b/torchvision/datasets/folder.py index ef3ae7af896..fb4861e637a 100644 --- a/torchvision/datasets/folder.py +++ b/torchvision/datasets/folder.py @@ -32,9 +32,43 @@ def is_image_file(filename: str) -> bool: return has_file_allowed_extension(filename, IMG_EXTENSIONS) +def find_classes(directory: str) -> Tuple[List[str], Dict[str, int]]: + """Finds the class folders in a dataset structured as follows: + + .. code:: + + directory/ + ├── class_x + │ ├── xxx.ext + │ ├── xxy.ext + │ └── ... + │ └── xxz.ext + └── class_y + ├── 123.ext + ├── nsdf3.ext + └── ... + └── asd932_.ext + + Args: + directory (str): Root directory path. + + Raises: + FileNotFoundError: If ``directory`` has no class folders. + + Returns: + (Tuple[List[str], Dict[str, int]]): List of all classes and dictionary mapping each class to an index. + """ + classes = sorted(entry.name for entry in os.scandir(directory) if entry.is_dir()) + if not classes: + raise FileNotFoundError(f"Couldn't find any class folder in {directory}.") + + class_to_idx = {cls_name: i for i, cls_name in enumerate(classes)} + return classes, class_to_idx + + def make_dataset( directory: str, - class_to_idx: Dict[str, int], + class_to_idx: Optional[Dict[str, int]] = None, extensions: Optional[Tuple[str, ...]] = None, is_valid_file: Optional[Callable[[str], bool]] = None, ) -> List[Tuple[str, int]]: @@ -42,7 +76,8 @@ def make_dataset( Args: directory (str): root dataset directory - class_to_idx (Dict[str, int]): dictionary mapping class name to class index + class_to_idx (Optional[Dict[str, int]]): Dictionary mapping class name to class index. If omitted, is generated + by :func:`find_classes`. extensions (optional): A list of allowed extensions. Either extensions or is_valid_file should be passed. Defaults to None. is_valid_file (optional): A function that takes path of a file @@ -51,21 +86,34 @@ def make_dataset( is_valid_file should not be passed. Defaults to None. Raises: + ValueError: In case ``class_to_idx`` is empty. ValueError: In case ``extensions`` and ``is_valid_file`` are None or both are not None. + FileNotFoundError: In case no valid file was found for any class. Returns: List[Tuple[str, int]]: samples of a form (path_to_sample, class) """ - instances = [] directory = os.path.expanduser(directory) + + if class_to_idx is None: + _, class_to_idx = find_classes(directory) + elif not class_to_idx: + raise ValueError("'class_to_index' must have at least one entry to collect any samples.") + both_none = extensions is None and is_valid_file is None both_something = extensions is not None and is_valid_file is not None if both_none or both_something: raise ValueError("Both extensions and is_valid_file cannot be None or not None at the same time") + if extensions is not None: + def is_valid_file(x: str) -> bool: return has_file_allowed_extension(x, cast(Tuple[str, ...], extensions)) + is_valid_file = cast(Callable[[str], bool], is_valid_file) + + instances = [] + available_classes = set() for target_class in sorted(class_to_idx.keys()): class_index = class_to_idx[target_class] target_dir = os.path.join(directory, target_class) @@ -77,6 +125,17 @@ def is_valid_file(x: str) -> bool: if is_valid_file(path): item = path, class_index instances.append(item) + + if target_class not in available_classes: + available_classes.add(target_class) + + empty_classes = available_classes - set(class_to_idx.keys()) + if empty_classes: + msg = f"Found no valid file for the classes {', '.join(sorted(empty_classes))}. " + if extensions is not None: + msg += f"Supported extensions are: {', '.join(extensions)}" + raise FileNotFoundError(msg) + return instances @@ -125,11 +184,6 @@ def __init__( target_transform=target_transform) classes, class_to_idx = self._find_classes(self.root) samples = self.make_dataset(self.root, class_to_idx, extensions, is_valid_file) - if len(samples) == 0: - msg = "Found 0 files in subfolders of: {}\n".format(self.root) - if extensions is not None: - msg += "Supported extensions are: {}".format(",".join(extensions)) - raise RuntimeError(msg) self.loader = loader self.extensions = extensions @@ -148,23 +202,9 @@ def make_dataset( ) -> List[Tuple[str, int]]: return make_dataset(directory, class_to_idx, extensions=extensions, is_valid_file=is_valid_file) - def _find_classes(self, dir: str) -> Tuple[List[str], Dict[str, int]]: - """ - Finds the class folders in a dataset. - - Args: - dir (string): Root directory path. - - Returns: - tuple: (classes, class_to_idx) where classes are relative to (dir), and class_to_idx is a dictionary. - - Ensures: - No class is a subdirectory of another. - """ - classes = [d.name for d in os.scandir(dir) if d.is_dir()] - classes.sort() - class_to_idx = {cls_name: i for i, cls_name in enumerate(classes)} - return classes, class_to_idx + @staticmethod + def _find_classes(dir: str) -> Tuple[List[str], Dict[str, int]]: + return find_classes(dir) def __getitem__(self, index: int) -> Tuple[Any, Any]: """ diff --git a/torchvision/datasets/hmdb51.py b/torchvision/datasets/hmdb51.py index 621630cf264..113186b71b9 100644 --- a/torchvision/datasets/hmdb51.py +++ b/torchvision/datasets/hmdb51.py @@ -2,7 +2,7 @@ import os from .utils import list_dir -from .folder import make_dataset +from .folder import find_classes, make_dataset from .video_utils import VideoClips from .vision import VisionDataset @@ -62,8 +62,7 @@ def __init__(self, root, annotation_path, frames_per_clip, step_between_clips=1, raise ValueError("fold should be between 1 and 3, got {}".format(fold)) extensions = ('avi',) - classes = sorted(list_dir(root)) - class_to_idx = {class_: i for (i, class_) in enumerate(classes)} + self.classes, class_to_idx = find_classes(self.root) self.samples = make_dataset( self.root, class_to_idx, @@ -89,7 +88,6 @@ def __init__(self, root, annotation_path, frames_per_clip, step_between_clips=1, self.full_video_clips = video_clips self.fold = fold self.train = train - self.classes = classes self.indices = self._select_fold(video_paths, annotation_path, fold, train) self.video_clips = video_clips.subset(self.indices) self.transform = transform diff --git a/torchvision/datasets/kinetics.py b/torchvision/datasets/kinetics.py index f459b526ca4..a8986986c17 100644 --- a/torchvision/datasets/kinetics.py +++ b/torchvision/datasets/kinetics.py @@ -1,5 +1,5 @@ from .utils import list_dir -from .folder import make_dataset +from .folder import find_classes, make_dataset from .video_utils import VideoClips from .vision import VisionDataset @@ -56,10 +56,8 @@ def __init__(self, root, frames_per_clip, step_between_clips=1, frame_rate=None, _video_min_dimension=0, _audio_samples=0, _audio_channels=0): super(Kinetics400, self).__init__(root) - classes = list(sorted(list_dir(root))) - class_to_idx = {classes[i]: i for i in range(len(classes))} + self.classes, class_to_idx = find_classes(self.root) self.samples = make_dataset(self.root, class_to_idx, extensions, is_valid_file=None) - self.classes = classes video_list = [x[0] for x in self.samples] self.video_clips = VideoClips( video_list, diff --git a/torchvision/datasets/ucf101.py b/torchvision/datasets/ucf101.py index e5cf11d7fa2..709151c2fcb 100644 --- a/torchvision/datasets/ucf101.py +++ b/torchvision/datasets/ucf101.py @@ -1,7 +1,7 @@ import os from .utils import list_dir -from .folder import make_dataset +from .folder import find_classes, make_dataset from .video_utils import VideoClips from .vision import VisionDataset @@ -55,10 +55,8 @@ def __init__(self, root, annotation_path, frames_per_clip, step_between_clips=1, self.fold = fold self.train = train - classes = list(sorted(list_dir(root))) - class_to_idx = {classes[i]: i for i in range(len(classes))} + self.classes, class_to_idx = find_classes(self.root) self.samples = make_dataset(self.root, class_to_idx, extensions, is_valid_file=None) - self.classes = classes video_list = [x[0] for x in self.samples] video_clips = VideoClips( video_list, From 1401f86c1b49b6387d76022a2ad08b6e85a588a8 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:19:09 -0700 Subject: [PATCH 319/357] [fbsync] add tests for MNIST and variants (#3423) Summary: * add tests for MNIST and variants * remove old tests and fakedata generation * fix default config detection for if dataset has variable keywords * use split="mnist" as default for EMNIST * fix QMNIST tests * lint * fix special kwargs detection * Revert "use split="mnist" as default for EMNIST" This reverts commit 62c9b23597f4a391cad409cbd93edac1b3474acf. * fix tests * fix QMNIST test case name * remove dead code from test * Revert "remove old tests and fakedata generation" This reverts commit a285b97c4827566a5bc06c288f5bba8d614a4f7a. * remove old tests * readd removed import Reviewed By: fmassa Differential Revision: D27433912 fbshipit-source-id: 2af75d5531880266286cd2a4045fcdee594da548 --- test/test_datasets.py | 161 +++++++++++++++++++++++++++++++++--------- 1 file changed, 128 insertions(+), 33 deletions(-) diff --git a/test/test_datasets.py b/test/test_datasets.py index 03edba57559..d7e7827542b 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -10,8 +10,8 @@ import torchvision from torchvision.datasets import utils from common_utils import get_tmp_dir -from fakedata_generation import mnist_root, \ - cityscapes_root, svhn_root, places365_root, widerface_root, stl10_root + +from fakedata_generation import cityscapes_root, svhn_root, places365_root, widerface_root, stl10_root import xml.etree.ElementTree as ET from urllib.request import Request, urlopen import itertools @@ -119,37 +119,6 @@ def test_imagefolder_empty(self): root, loader=lambda x: x, is_valid_file=lambda x: False ) - @mock.patch('torchvision.datasets.mnist.download_and_extract_archive') - @mock.patch('torchvision.datasets.mnist.check_integrity', return_value=True) - def test_mnist(self, mock_download_extract, mock_check_integrity): - num_examples = 30 - with mnist_root(num_examples, "MNIST") as root: - dataset = torchvision.datasets.MNIST(root, download=True) - self.generic_classification_dataset_test(dataset, num_images=num_examples) - img, target = dataset[0] - self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) - - @mock.patch('torchvision.datasets.mnist.download_and_extract_archive') - @mock.patch('torchvision.datasets.mnist.check_integrity', return_value=True) - def test_kmnist(self, mock_download_extract, mock_check_integrity): - num_examples = 30 - with mnist_root(num_examples, "KMNIST") as root: - dataset = torchvision.datasets.KMNIST(root, download=True) - self.generic_classification_dataset_test(dataset, num_images=num_examples) - img, target = dataset[0] - self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) - - @mock.patch('torchvision.datasets.mnist.download_and_extract_archive') - @mock.patch('torchvision.datasets.mnist.check_integrity', return_value=True) - def test_fashionmnist(self, mock_download_extract, mock_check_integrity): - num_examples = 30 - with mnist_root(num_examples, "FashionMNIST") as root: - dataset = torchvision.datasets.FashionMNIST(root, download=True) - self.generic_classification_dataset_test(dataset, num_images=num_examples) - img, target = dataset[0] - self.assertEqual(dataset.class_to_idx[dataset.classes[0]], target) - - @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') def test_cityscapes(self): with cityscapes_root() as root: @@ -1499,5 +1468,131 @@ def _create_annotations_file(self, root, name, images, num_captions_per_image): fh.write(f"{image.name}#{idx}\t{caption}\n") +class MNISTTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.MNIST + + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(train=(True, False)) + + _MAGIC_DTYPES = { + torch.uint8: 8, + torch.int8: 9, + torch.int16: 11, + torch.int32: 12, + torch.float32: 13, + torch.float64: 14, + } + + _IMAGES_SIZE = (28, 28) + _IMAGES_DTYPE = torch.uint8 + + _LABELS_SIZE = () + _LABELS_DTYPE = torch.uint8 + + def inject_fake_data(self, tmpdir, config): + raw_dir = pathlib.Path(tmpdir) / self.DATASET_CLASS.__name__ / "raw" + os.makedirs(raw_dir, exist_ok=True) + + num_images = self._num_images(config) + self._create_binary_file( + raw_dir, self._images_file(config), (num_images, *self._IMAGES_SIZE), self._IMAGES_DTYPE + ) + self._create_binary_file( + raw_dir, self._labels_file(config), (num_images, *self._LABELS_SIZE), self._LABELS_DTYPE + ) + return num_images + + def _num_images(self, config): + return 2 if config["train"] else 1 + + def _images_file(self, config): + return f"{self._prefix(config)}-images-idx3-ubyte" + + def _labels_file(self, config): + return f"{self._prefix(config)}-labels-idx1-ubyte" + + def _prefix(self, config): + return "train" if config["train"] else "t10k" + + def _create_binary_file(self, root, filename, size, dtype): + with open(pathlib.Path(root) / filename, "wb") as fh: + for meta in (self._magic(dtype, len(size)), *size): + fh.write(self._encode(meta)) + + # If ever an MNIST variant is added that uses floating point data, this should be adapted. + data = torch.randint(0, torch.iinfo(dtype).max + 1, size, dtype=dtype) + fh.write(data.numpy().tobytes()) + + def _magic(self, dtype, dims): + return self._MAGIC_DTYPES[dtype] * 256 + dims + + def _encode(self, v): + return torch.tensor(v, dtype=torch.int32).numpy().tobytes()[::-1] + + +class FashionMNISTTestCase(MNISTTestCase): + DATASET_CLASS = datasets.FashionMNIST + + +class KMNISTTestCase(MNISTTestCase): + DATASET_CLASS = datasets.KMNIST + + +class EMNISTTestCase(MNISTTestCase): + DATASET_CLASS = datasets.EMNIST + + DEFAULT_CONFIG = dict(split="byclass") + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid( + split=("byclass", "bymerge", "balanced", "letters", "digits", "mnist"), train=(True, False) + ) + + def _prefix(self, config): + return f"emnist-{config['split']}-{'train' if config['train'] else 'test'}" + + +class QMNISTTestCase(MNISTTestCase): + DATASET_CLASS = datasets.QMNIST + + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(what=("train", "test", "test10k", "nist")) + + _LABELS_SIZE = (8,) + _LABELS_DTYPE = torch.int32 + + def _num_images(self, config): + if config["what"] == "nist": + return 3 + elif config["what"] == "train": + return 2 + elif config["what"] == "test50k": + # The split 'test50k' is defined as the last 50k images beginning at index 10000. Thus, we need to create + # more than 10000 images for the dataset to not be empty. Since this takes significantly longer than the + # creation of all other splits, this is excluded from the 'ADDITIONAL_CONFIGS' and is tested only once in + # 'test_num_examples_test50k'. + return 10001 + else: + return 1 + + def _labels_file(self, config): + return f"{self._prefix(config)}-labels-idx2-int" + + def _prefix(self, config): + if config["what"] == "nist": + return "xnist" + + if config["what"] is None: + what = "train" if config["train"] else "test" + elif config["what"].startswith("test"): + what = "test" + else: + what = config["what"] + + return f"qmnist-{what}" + + def test_num_examples_test50k(self): + with self.create_dataset(what="test50k") as (dataset, info): + # Since the split 'test50k' selects all images beginning from the index 10000, we subtract the number of + # created examples by this. + self.assertEqual(len(dataset), info["num_examples"] - 10000) + + if __name__ == "__main__": unittest.main() From 35d0853d372a2b16b7384a51be13e6869c2146f7 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:19:09 -0700 Subject: [PATCH 320/357] [fbsync] Bump nightlies to 0.10.0 (#3599) Reviewed By: fmassa Differential Revision: D27433926 fbshipit-source-id: f5053a19626d55e1cd13f835bf656c54631c7106 --- android/gradle.properties | 2 +- packaging/build_cmake.sh | 2 +- packaging/build_conda.sh | 2 +- packaging/build_wheel.sh | 2 +- packaging/windows/internal/nightly_defaults.bat | 2 +- version.txt | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/android/gradle.properties b/android/gradle.properties index e9bf9f0522d..87804c30107 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,6 +1,6 @@ ABI_FILTERS=armeabi-v7a,arm64-v8a,x86,x86_64 -VERSION_NAME=0.9.0-SNAPSHOT +VERSION_NAME=0.10.0-SNAPSHOT GROUP=org.pytorch MAVEN_GROUP=org.pytorch SONATYPE_STAGING_PROFILE=orgpytorch diff --git a/packaging/build_cmake.sh b/packaging/build_cmake.sh index 3726a0aed2d..da758f4b7dc 100755 --- a/packaging/build_cmake.sh +++ b/packaging/build_cmake.sh @@ -15,7 +15,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" . "$script_dir/pkg_helpers.bash" export BUILD_TYPE=conda -setup_env 0.9.0 +setup_env 0.10.0 export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint setup_conda_cudatoolkit_plain_constraint diff --git a/packaging/build_conda.sh b/packaging/build_conda.sh index fa155359935..5f2239aae7e 100755 --- a/packaging/build_conda.sh +++ b/packaging/build_conda.sh @@ -5,7 +5,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" . "$script_dir/pkg_helpers.bash" export BUILD_TYPE=conda -setup_env 0.9.0 +setup_env 0.10.0 export SOURCE_ROOT_DIR="$PWD" setup_conda_pytorch_constraint setup_conda_cudatoolkit_constraint diff --git a/packaging/build_wheel.sh b/packaging/build_wheel.sh index 371c4e71a12..72acdf01fbe 100755 --- a/packaging/build_wheel.sh +++ b/packaging/build_wheel.sh @@ -5,7 +5,7 @@ script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" . "$script_dir/pkg_helpers.bash" export BUILD_TYPE=wheel -setup_env 0.9.0 +setup_env 0.10.0 setup_wheel_python pip_install numpy pyyaml future ninja setup_pip_pytorch_version diff --git a/packaging/windows/internal/nightly_defaults.bat b/packaging/windows/internal/nightly_defaults.bat index 68f04fdbccf..c02ac8518f3 100644 --- a/packaging/windows/internal/nightly_defaults.bat +++ b/packaging/windows/internal/nightly_defaults.bat @@ -144,7 +144,7 @@ if "%CUDA_VERSION%" == "cpu" ( :: pytorch-nightly==1.0.0.dev20180908 :: or in manylinux like :: torch_nightly-1.0.0.dev20180908-cp27-cp27m-linux_x86_64.whl -if "%TORCHVISION_BUILD_VERSION%" == "" set TORCHVISION_BUILD_VERSION=0.9.0.dev%NIGHTLIES_DATE_COMPACT% +if "%TORCHVISION_BUILD_VERSION%" == "" set TORCHVISION_BUILD_VERSION=0.10.0.dev%NIGHTLIES_DATE_COMPACT% if "%~1" == "Wheels" ( if not "%CUDA_VERSION%" == "102" ( diff --git a/version.txt b/version.txt index 657e7c07f92..37f1777fc35 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.9.0a0 +0.10.0a0 From 00f8b7cd40049775c407d6197805e3666be28eb7 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 20:55:53 -0700 Subject: [PATCH 321/357] [fbsync] put back skip windows (#3605) Reviewed By: fmassa Differential Revision: D27433919 fbshipit-source-id: d23e51407e119fdad24fd4fee46a5f9decbe7e5e --- test/test_datasets.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_datasets.py b/test/test_datasets.py index d7e7827542b..77efc9c2504 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -119,6 +119,7 @@ def test_imagefolder_empty(self): root, loader=lambda x: x, is_valid_file=lambda x: False ) + @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') def test_cityscapes(self): with cityscapes_root() as root: From 5aa76e4a0a682f4aa0e14d532093264f97858153 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Wed, 31 Mar 2021 21:28:16 -0700 Subject: [PATCH 322/357] [fbsync] .circleci: Fix windows cmath issues (#3609) Summary: Signed-off-by: Eli Uriegas Reviewed By: fmassa Differential Revision: D27433932 fbshipit-source-id: aa924160020b23b1041c5fc85f3c7410d191cce2 --- .circleci/config.yml | 14 ++++++++++++++ .circleci/config.yml.in | 14 ++++++++++++++ .circleci/scripts/vs_install_cmath.ps1 | 5 +++++ 3 files changed, 33 insertions(+) create mode 100644 .circleci/scripts/vs_install_cmath.ps1 diff --git a/.circleci/config.yml b/.circleci/config.yml index 1223abc9129..0f7e2394236 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -45,6 +45,14 @@ commands: our_upload_channel=test fi echo "export UPLOAD_CHANNEL=${our_upload_channel}" >> ${BASH_ENV} + install_cuda_compatible_cmath: + description: "Install CUDA compatible cmath" + steps: + - run: + name: _HACK_ Install CUDA compatible cmath + no_output_timeout: 1m + command: | + powershell .circleci/scripts/vs_install_cmath.ps1 binary_common: &binary_common parameters: @@ -212,6 +220,7 @@ jobs: steps: - checkout_merge - designate_upload_channel + - install_cuda_compatible_cmath - run: name: Build conda packages no_output_timeout: 20m @@ -239,6 +248,7 @@ jobs: steps: - checkout_merge - designate_upload_channel + - install_cuda_compatible_cmath - run: name: Build wheel packages command: | @@ -546,6 +556,7 @@ jobs: steps: - checkout - designate_upload_channel + - install_cuda_compatible_cmath - run: name: Generate cache key # This will refresh cache on Sundays, nightly build should generate new cache. @@ -587,6 +598,7 @@ jobs: steps: - checkout - designate_upload_channel + - install_cuda_compatible_cmath - run: name: Generate cache key # This will refresh cache on Sundays, nightly build should generate new cache. @@ -716,6 +728,7 @@ jobs: steps: - checkout_merge - designate_upload_channel + - install_cuda_compatible_cmath - run: command: | set -ex @@ -729,6 +742,7 @@ jobs: steps: - checkout_merge - designate_upload_channel + - install_cuda_compatible_cmath - run: command: | set -ex diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index dcd511b8f80..bddc7d4312d 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -45,6 +45,14 @@ commands: our_upload_channel=test fi echo "export UPLOAD_CHANNEL=${our_upload_channel}" >> ${BASH_ENV} + install_cuda_compatible_cmath: + description: "Install CUDA compatible cmath" + steps: + - run: + name: _HACK_ Install CUDA compatible cmath + no_output_timeout: 1m + command: | + powershell .circleci/scripts/vs_install_cmath.ps1 binary_common: &binary_common parameters: @@ -212,6 +220,7 @@ jobs: steps: - checkout_merge - designate_upload_channel + - install_cuda_compatible_cmath - run: name: Build conda packages no_output_timeout: 20m @@ -239,6 +248,7 @@ jobs: steps: - checkout_merge - designate_upload_channel + - install_cuda_compatible_cmath - run: name: Build wheel packages command: | @@ -546,6 +556,7 @@ jobs: steps: - checkout - designate_upload_channel + - install_cuda_compatible_cmath - run: name: Generate cache key # This will refresh cache on Sundays, nightly build should generate new cache. @@ -587,6 +598,7 @@ jobs: steps: - checkout - designate_upload_channel + - install_cuda_compatible_cmath - run: name: Generate cache key # This will refresh cache on Sundays, nightly build should generate new cache. @@ -716,6 +728,7 @@ jobs: steps: - checkout_merge - designate_upload_channel + - install_cuda_compatible_cmath - run: command: | set -ex @@ -729,6 +742,7 @@ jobs: steps: - checkout_merge - designate_upload_channel + - install_cuda_compatible_cmath - run: command: | set -ex diff --git a/.circleci/scripts/vs_install_cmath.ps1 b/.circleci/scripts/vs_install_cmath.ps1 new file mode 100644 index 00000000000..c2998eba252 --- /dev/null +++ b/.circleci/scripts/vs_install_cmath.ps1 @@ -0,0 +1,5 @@ +$CMATH_DOWNLOAD_LINK = "https://raw.githubusercontent.com/microsoft/STL/12c684bba78f9b032050526abdebf14f58ca26a3/stl/inc/cmath" +$VC14_28_INSTALL_PATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29910\include" + +curl.exe --retry 3 -kL $CMATH_DOWNLOAD_LINK --output "$home\cmath" +Move-Item -Path "$home\cmath" -Destination "$VC14_28_INSTALL_PATH" -Force From 794522c1a939ca0f3446c3750675d5c30e5dfc09 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Fri, 2 Apr 2021 07:34:11 -0700 Subject: [PATCH 323/357] [fbsync] Add quantized version of nms (#3601) Summary: * Add quantized version of nms * Added tests * Compute areas only once * remove calls to dequantize_val * fix return type for empty tensor * flake8 * remove use of scale as it gets cancelled out * simpler int convertion in tests * explicitly set ovr to double * add tests for more values of scale and zero_point * comment about underflow * remove unnecessary accessor * properly convert to float for division * Add comments about underflow * explicitely cast coordinates to float to allow vectorization * clang * clang again * hopefully OK now Reviewed By: fmassa Differential Revision: D27433913 fbshipit-source-id: c0b80c3b6817898682a78af705ff383855248a37 --- setup.py | 7 +- test/test_ops.py | 23 ++++ .../csrc/ops/quantized/cpu/qnms_kernel.cpp | 129 ++++++++++++++++++ 3 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 torchvision/csrc/ops/quantized/cpu/qnms_kernel.cpp diff --git a/setup.py b/setup.py index c998118335b..23bbdaab378 100644 --- a/setup.py +++ b/setup.py @@ -138,8 +138,11 @@ def get_extensions(): main_file = glob.glob(os.path.join(extensions_dir, '*.cpp')) + glob.glob(os.path.join(extensions_dir, 'ops', '*.cpp')) - source_cpu = glob.glob(os.path.join(extensions_dir, 'ops', 'autograd', '*.cpp')) + glob.glob( - os.path.join(extensions_dir, 'ops', 'cpu', '*.cpp')) + source_cpu = ( + glob.glob(os.path.join(extensions_dir, 'ops', 'autograd', '*.cpp')) + + glob.glob(os.path.join(extensions_dir, 'ops', 'cpu', '*.cpp')) + + glob.glob(os.path.join(extensions_dir, 'ops', 'quantized', 'cpu', '*.cpp')) + ) is_rocm_pytorch = False if torch.__version__ >= '1.5': diff --git a/test/test_ops.py b/test/test_ops.py index 8c938ae0e79..0031da45cce 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -418,6 +418,29 @@ def test_nms(self): self.assertRaises(RuntimeError, ops.nms, torch.rand(3, 4), torch.rand(3, 2), 0.5) self.assertRaises(RuntimeError, ops.nms, torch.rand(3, 4), torch.rand(4), 0.5) + def test_qnms(self): + # Note: we compare qnms vs nms instead of qnms vs reference implementation. + # This is because with the int convertion, the trick used in _create_tensors_with_iou + # doesn't really work (in fact, nms vs reference implem will also fail with ints) + err_msg = 'NMS and QNMS give different results for IoU={}' + for iou in [0.2, 0.5, 0.8]: + for scale, zero_point in ((1, 0), (2, 50), (3, 10)): + boxes, scores = self._create_tensors_with_iou(1000, iou) + scores *= 100 # otherwise most scores would be 0 or 1 after int convertion + + qboxes = torch.quantize_per_tensor(boxes, scale=scale, zero_point=zero_point, + dtype=torch.quint8) + qscores = torch.quantize_per_tensor(scores, scale=scale, zero_point=zero_point, + dtype=torch.quint8) + + boxes = qboxes.dequantize() + scores = qscores.dequantize() + + keep = ops.nms(boxes, scores, iou) + qkeep = ops.nms(qboxes, qscores, iou) + + self.assertTrue(torch.allclose(qkeep, keep), err_msg.format(iou)) + @unittest.skipIf(not torch.cuda.is_available(), "CUDA unavailable") def test_nms_cuda(self, dtype=torch.float64): tol = 1e-3 if dtype is torch.half else 1e-5 diff --git a/torchvision/csrc/ops/quantized/cpu/qnms_kernel.cpp b/torchvision/csrc/ops/quantized/cpu/qnms_kernel.cpp new file mode 100644 index 00000000000..fbbc062f3e9 --- /dev/null +++ b/torchvision/csrc/ops/quantized/cpu/qnms_kernel.cpp @@ -0,0 +1,129 @@ +#include +#include +#include + +namespace vision { +namespace ops { + +namespace { + +template +at::Tensor qnms_kernel_impl( + const at::Tensor& dets, + const at::Tensor& scores, + double iou_threshold) { + TORCH_CHECK(!dets.is_cuda(), "dets must be a CPU tensor"); + TORCH_CHECK(!scores.is_cuda(), "scores must be a CPU tensor"); + TORCH_CHECK( + dets.scalar_type() == scores.scalar_type(), + "dets should have the same type as scores"); + + if (dets.numel() == 0) + return at::empty({0}, dets.options().dtype(at::kLong)); + + const auto ndets = dets.size(0); + + auto x1_t = dets.select(1, 0).contiguous(); + auto y1_t = dets.select(1, 1).contiguous(); + auto x2_t = dets.select(1, 2).contiguous(); + auto y2_t = dets.select(1, 3).contiguous(); + auto order_t = std::get<1>(scores.sort(0, /* descending=*/true)); + at::Tensor suppressed_t = at::zeros({ndets}, dets.options().dtype(at::kByte)); + at::Tensor keep_t = at::zeros({ndets}, dets.options().dtype(at::kLong)); + at::Tensor areas_t = at::zeros({ndets}, dets.options().dtype(at::kFloat)); + + auto suppressed = suppressed_t.data_ptr(); + auto keep = keep_t.data_ptr(); + auto order = order_t.data_ptr(); + auto x1 = x1_t.data_ptr(); + auto y1 = y1_t.data_ptr(); + auto x2 = x2_t.data_ptr(); + auto y2 = y2_t.data_ptr(); + auto areas = areas_t.data_ptr(); + + for (int64_t i = 0; i < ndets; i++) { + // Note 1: To get the exact area we'd need to multiply by scale**2, but this + // would get canceled out in the computation of ovr below. So we leave that + // out. + // Note 2: degenerate boxes (x2 < x1 or y2 < y1) may underflow, although + // integral promotion rules will likely prevent it (see + // https://stackoverflow.com/questions/32959564/subtraction-of-two-unsigned-gives-signed + // for more details). + areas[i] = (x2[i].val_ - x1[i].val_) * (y2[i].val_ - y1[i].val_); + } + + int64_t num_to_keep = 0; + + for (int64_t _i = 0; _i < ndets; _i++) { + auto i = order[_i]; + if (suppressed[i] == 1) + continue; + keep[num_to_keep++] = i; + + // We explicitly cast coordinates to float so that the code can be + // vectorized. + float ix1val = x1[i].val_; + float iy1val = y1[i].val_; + float ix2val = x2[i].val_; + float iy2val = y2[i].val_; + float iarea = areas[i]; + + for (int64_t _j = _i + 1; _j < ndets; _j++) { + auto j = order[_j]; + if (suppressed[j] == 1) + continue; + float xx1 = std::max(ix1val, (float)x1[j].val_); + float yy1 = std::max(iy1val, (float)y1[j].val_); + float xx2 = std::min(ix2val, (float)x2[j].val_); + float yy2 = std::min(iy2val, (float)y2[j].val_); + + auto w = std::max(0.f, xx2 - xx1); // * scale (gets canceled below) + auto h = std::max(0.f, yy2 - yy1); // * scale (gets canceled below) + auto inter = w * h; + auto ovr = inter / (iarea + areas[j] - inter); + if (ovr > iou_threshold) + suppressed[j] = 1; + } + } + return keep_t.narrow(/*dim=*/0, /*start=*/0, /*length=*/num_to_keep); +} + +at::Tensor qnms_kernel( + const at::Tensor& dets, + const at::Tensor& scores, + double iou_threshold) { + TORCH_CHECK( + dets.dim() == 2, "boxes should be a 2d tensor, got ", dets.dim(), "D"); + TORCH_CHECK( + dets.size(1) == 4, + "boxes should have 4 elements in dimension 1, got ", + dets.size(1)); + TORCH_CHECK( + scores.dim() == 1, + "scores should be a 1d tensor, got ", + scores.dim(), + "D"); + TORCH_CHECK( + dets.size(0) == scores.size(0), + "boxes and scores should have same number of elements in ", + "dimension 0, got ", + dets.size(0), + " and ", + scores.size(0)); + + auto result = at::empty({0}); + + AT_DISPATCH_QINT_TYPES(dets.scalar_type(), "qnms_kernel", [&] { + result = qnms_kernel_impl(dets, scores, iou_threshold); + }); + return result; +} + +} // namespace + +TORCH_LIBRARY_IMPL(torchvision, QuantizedCPU, m) { + m.impl(TORCH_SELECTIVE_NAME("torchvision::nms"), TORCH_FN(qnms_kernel)); +} + +} // namespace ops +} // namespace vision From af4fded5a0ea4f6a27321582a6dceec4a1a8aa5e Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Fri, 2 Apr 2021 07:34:11 -0700 Subject: [PATCH 324/357] [fbsync] New tests for CityScapes dataset (#3595) Summary: Co-authored-by: Philip Meier Reviewed By: fmassa Differential Revision: D27433928 fbshipit-source-id: 950e7731b92f58a86a4d887e98e84170536beae4 --- test/datasets_utils.py | 10 +-- test/fakedata_generation.py | 72 --------------- test/test_datasets.py | 172 ++++++++++++++++++++++++++---------- 3 files changed, 130 insertions(+), 124 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 8ba55c21f60..658ef6640fe 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -734,7 +734,7 @@ def size(idx: int) -> Tuple[int, int, int]: return (num_channels, height, width) root = pathlib.Path(root) / name - os.makedirs(root) + os.makedirs(root, exist_ok=True) return [ create_image_file(root, file_name_fn(idx), size=size(idx) if callable(size) else size, **kwargs) @@ -797,10 +797,10 @@ def create_video_folder( """Create a folder of random videos. Args: - root (Union[str, pathlib.Path]): Root directory the image folder will be placed in. - name (Union[str, pathlib.Path]): Name of the image folder. + root (Union[str, pathlib.Path]): Root directory the video folder will be placed in. + name (Union[str, pathlib.Path]): Name of the video folder. file_name_fn (Callable[[int], str]): Should return a file name if called with the file index. - num_examples (int): Number of images to create. + num_examples (int): Number of videos to create. size (Optional[Union[Sequence[int], int, Callable[[int], Union[Sequence[int], int]]]]): Size of the videos. If callable, will be called with the index of the corresponding file. If omitted, a random even height and width between 4 and 10 pixels is selected on a per-video basis. @@ -828,7 +828,7 @@ def size(idx): return (num_frames, num_channels, height, width) root = pathlib.Path(root) / name - os.makedirs(root) + os.makedirs(root, exist_ok=True) return [ create_video_file(root, file_name_fn(idx), size=size(idx) if callable(size) else size, **kwargs) diff --git a/test/fakedata_generation.py b/test/fakedata_generation.py index 473c15d19c4..314222dc43f 100644 --- a/test/fakedata_generation.py +++ b/test/fakedata_generation.py @@ -210,78 +210,6 @@ def _make_annotations_archive(root): yield root -@contextlib.contextmanager -def cityscapes_root(): - - def _make_image(file): - PIL.Image.fromarray(np.zeros((1024, 2048, 3), dtype=np.uint8)).save(file) - - def _make_regular_target(file): - PIL.Image.fromarray(np.zeros((1024, 2048), dtype=np.uint8)).save(file) - - def _make_color_target(file): - PIL.Image.fromarray(np.zeros((1024, 2048, 4), dtype=np.uint8)).save(file) - - def _make_polygon_target(file): - polygon_example = { - 'imgHeight': 1024, - 'imgWidth': 2048, - 'objects': [{'label': 'sky', - 'polygon': [[1241, 0], [1234, 156], - [1478, 197], [1611, 172], - [1606, 0]]}, - {'label': 'road', - 'polygon': [[0, 448], [1331, 274], - [1473, 265], [2047, 605], - [2047, 1023], [0, 1023]]}]} - with open(file, 'w') as outfile: - json.dump(polygon_example, outfile) - - with get_tmp_dir() as tmp_dir: - - for mode in ['Coarse', 'Fine']: - gt_dir = os.path.join(tmp_dir, 'gt%s' % mode) - os.makedirs(gt_dir) - - if mode == 'Coarse': - splits = ['train', 'train_extra', 'val'] - else: - splits = ['train', 'test', 'val'] - - for split in splits: - split_dir = os.path.join(gt_dir, split) - os.makedirs(split_dir) - for city in ['bochum', 'bremen']: - city_dir = os.path.join(split_dir, city) - os.makedirs(city_dir) - _make_color_target(os.path.join(city_dir, - '{city}_000000_000000_gt{mode}_color.png'.format( - city=city, mode=mode))) - _make_regular_target(os.path.join(city_dir, - '{city}_000000_000000_gt{mode}_instanceIds.png'.format( - city=city, mode=mode))) - _make_regular_target(os.path.join(city_dir, - '{city}_000000_000000_gt{mode}_labelIds.png'.format( - city=city, mode=mode))) - _make_polygon_target(os.path.join(city_dir, - '{city}_000000_000000_gt{mode}_polygons.json'.format( - city=city, mode=mode))) - - # leftImg8bit dataset - leftimg_dir = os.path.join(tmp_dir, 'leftImg8bit') - os.makedirs(leftimg_dir) - for split in ['test', 'train_extra', 'train', 'val']: - split_dir = os.path.join(leftimg_dir, split) - os.makedirs(split_dir) - for city in ['bochum', 'bremen']: - city_dir = os.path.join(split_dir, city) - os.makedirs(city_dir) - _make_image(os.path.join(city_dir, - '{city}_000000_000000_leftImg8bit.png'.format(city=city))) - - yield tmp_dir - - @contextlib.contextmanager def svhn_root(): import scipy.io as sio diff --git a/test/test_datasets.py b/test/test_datasets.py index 77efc9c2504..2dde215e32b 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -10,8 +10,7 @@ import torchvision from torchvision.datasets import utils from common_utils import get_tmp_dir - -from fakedata_generation import cityscapes_root, svhn_root, places365_root, widerface_root, stl10_root +from fakedata_generation import svhn_root, places365_root, widerface_root, stl10_root import xml.etree.ElementTree as ET from urllib.request import Request, urlopen import itertools @@ -119,51 +118,6 @@ def test_imagefolder_empty(self): root, loader=lambda x: x, is_valid_file=lambda x: False ) - @unittest.skipIf(sys.platform in ('win32', 'cygwin'), 'temporarily disabled on Windows') - def test_cityscapes(self): - with cityscapes_root() as root: - - for mode in ['coarse', 'fine']: - - if mode == 'coarse': - splits = ['train', 'train_extra', 'val'] - else: - splits = ['train', 'val', 'test'] - - for split in splits: - for target_type in ['semantic', 'instance']: - dataset = torchvision.datasets.Cityscapes( - root, split=split, target_type=target_type, mode=mode) - self.generic_segmentation_dataset_test(dataset, num_images=2) - - color_dataset = torchvision.datasets.Cityscapes( - root, split=split, target_type='color', mode=mode) - color_img, color_target = color_dataset[0] - self.assertTrue(isinstance(color_img, PIL.Image.Image)) - self.assertTrue(np.array(color_target).shape[2] == 4) - - polygon_dataset = torchvision.datasets.Cityscapes( - root, split=split, target_type='polygon', mode=mode) - polygon_img, polygon_target = polygon_dataset[0] - self.assertTrue(isinstance(polygon_img, PIL.Image.Image)) - self.assertTrue(isinstance(polygon_target, dict)) - self.assertTrue(isinstance(polygon_target['imgHeight'], int)) - self.assertTrue(isinstance(polygon_target['objects'], list)) - - # Test multiple target types - targets_combo = ['semantic', 'polygon', 'color'] - multiple_types_dataset = torchvision.datasets.Cityscapes( - root, split=split, target_type=targets_combo, mode=mode) - output = multiple_types_dataset[0] - self.assertTrue(isinstance(output, tuple)) - self.assertTrue(len(output) == 2) - self.assertTrue(isinstance(output[0], PIL.Image.Image)) - self.assertTrue(isinstance(output[1], tuple)) - self.assertTrue(len(output[1]) == 3) - self.assertTrue(isinstance(output[1][0], PIL.Image.Image)) # semantic - self.assertTrue(isinstance(output[1][1], dict)) # polygon - self.assertTrue(isinstance(output[1][2], PIL.Image.Image)) # color - @mock.patch('torchvision.datasets.SVHN._check_integrity') @unittest.skipIf(not HAS_SCIPY, "scipy unavailable") def test_svhn(self, mock_check): @@ -490,6 +444,130 @@ def inject_fake_data(self, tmpdir, config): return split_to_num_examples[config["split"]] +class CityScapesTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.Cityscapes + TARGET_TYPES = ( + "instance", + "semantic", + "polygon", + "color", + ) + ADDITIONAL_CONFIGS = ( + *datasets_utils.combinations_grid( + mode=("fine",), split=("train", "test", "val"), target_type=TARGET_TYPES + ), + *datasets_utils.combinations_grid( + mode=("coarse",), + split=("train", "train_extra", "val"), + target_type=TARGET_TYPES, + ), + ) + FEATURE_TYPES = (PIL.Image.Image, (dict, PIL.Image.Image)) + + def inject_fake_data(self, tmpdir, config): + + tmpdir = pathlib.Path(tmpdir) + + mode_to_splits = { + "Coarse": ["train", "train_extra", "val"], + "Fine": ["train", "test", "val"], + } + + if config["split"] == "train": # just for coverage of the number of samples + cities = ["bochum", "bremen"] + else: + cities = ["bochum"] + + polygon_target = { + "imgHeight": 1024, + "imgWidth": 2048, + "objects": [ + { + "label": "sky", + "polygon": [ + [1241, 0], + [1234, 156], + [1478, 197], + [1611, 172], + [1606, 0], + ], + }, + { + "label": "road", + "polygon": [ + [0, 448], + [1331, 274], + [1473, 265], + [2047, 605], + [2047, 1023], + [0, 1023], + ], + }, + ], + } + + for mode in ["Coarse", "Fine"]: + gt_dir = tmpdir / f"gt{mode}" + for split in mode_to_splits[mode]: + for city in cities: + def make_image(name, size=10): + datasets_utils.create_image_folder( + root=gt_dir / split, + name=city, + file_name_fn=lambda _: name, + size=size, + num_examples=1, + ) + make_image(f"{city}_000000_000000_gt{mode}_instanceIds.png") + make_image(f"{city}_000000_000000_gt{mode}_labelIds.png") + make_image(f"{city}_000000_000000_gt{mode}_color.png", size=(4, 10, 10)) + + polygon_target_name = gt_dir / split / city / f"{city}_000000_000000_gt{mode}_polygons.json" + with open(polygon_target_name, "w") as outfile: + json.dump(polygon_target, outfile) + + # Create leftImg8bit folder + for split in ['test', 'train_extra', 'train', 'val']: + for city in cities: + datasets_utils.create_image_folder( + root=tmpdir / "leftImg8bit" / split, + name=city, + file_name_fn=lambda _: f"{city}_000000_000000_leftImg8bit.png", + num_examples=1, + ) + + info = {'num_examples': len(cities)} + if config['target_type'] == 'polygon': + info['expected_polygon_target'] = polygon_target + return info + + def test_combined_targets(self): + target_types = ['semantic', 'polygon', 'color'] + + with self.create_dataset(target_type=target_types) as (dataset, _): + output = dataset[0] + self.assertTrue(isinstance(output, tuple)) + self.assertTrue(len(output) == 2) + self.assertTrue(isinstance(output[0], PIL.Image.Image)) + self.assertTrue(isinstance(output[1], tuple)) + self.assertTrue(len(output[1]) == 3) + self.assertTrue(isinstance(output[1][0], PIL.Image.Image)) # semantic + self.assertTrue(isinstance(output[1][1], dict)) # polygon + self.assertTrue(isinstance(output[1][2], PIL.Image.Image)) # color + + def test_feature_types_target_color(self): + with self.create_dataset(target_type='color') as (dataset, _): + color_img, color_target = dataset[0] + self.assertTrue(isinstance(color_img, PIL.Image.Image)) + self.assertTrue(np.array(color_target).shape[2] == 4) + + def test_feature_types_target_polygon(self): + with self.create_dataset(target_type='polygon') as (dataset, info): + polygon_img, polygon_target = dataset[0] + self.assertTrue(isinstance(polygon_img, PIL.Image.Image)) + self.assertEqual(polygon_target, info['expected_polygon_target']) + + class ImageNetTestCase(datasets_utils.ImageDatasetTestCase): DATASET_CLASS = datasets.ImageNet REQUIRED_PACKAGES = ('scipy',) From 268ca6570a8f460187231675ae17231a512a6e50 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Fri, 2 Apr 2021 07:34:11 -0700 Subject: [PATCH 325/357] [fbsync] [iOS] added workflows for libtorchvision_ops.a binary build (#3582) Summary: * [iOS] added workflows for libtorchvision_ops.a binary build [ghstack-poisoned] * Update on "[iOS] added workflows for libtorchvision_ops.a binary build" [ghstack-poisoned] * Update on "[iOS] added workflows for libtorchvision_ops.a binary build" [ghstack-poisoned] * Update on "[iOS] added workflows for libtorchvision_ops.a binary build" [ghstack-poisoned] * Update on "[iOS] added workflows for libtorchvision_ops.a binary build" [ghstack-poisoned] * Update on "[iOS] added workflows for libtorchvision_ops.a binary build" [ghstack-poisoned] * Update on "[iOS] added workflows for libtorchvision_ops.a binary build" [ghstack-poisoned] Reviewed By: fmassa Differential Revision: D27433924 fbshipit-source-id: 2f7b07ae21d6f57a022a4748b8ae15cd71968818 Co-authored-by: Francisco Massa --- .circleci/config.yml | 150 ++++++++++++- .circleci/config.yml.in | 110 +++++++++- .circleci/regenerate.py | 31 +++ .../unittest/ios/scripts/binary_ios_build.sh | 47 ++++ .../unittest/ios/scripts/binary_ios_upload.sh | 42 ++++ cmake/iOS.cmake | 207 ++++++++++++++++++ ios/CMakeLists.txt | 23 ++ ios/build_ios.sh | 30 +++ 8 files changed, 638 insertions(+), 2 deletions(-) create mode 100755 .circleci/unittest/ios/scripts/binary_ios_build.sh create mode 100644 .circleci/unittest/ios/scripts/binary_ios_upload.sh create mode 100644 cmake/iOS.cmake create mode 100644 ios/CMakeLists.txt create mode 100755 ios/build_ios.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index 0f7e2394236..e7c15dbb8cb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -54,6 +54,59 @@ commands: command: | powershell .circleci/scripts/vs_install_cmath.ps1 + brew_update: + description: "Update Homebrew and install base formulae" + steps: + - run: + name: Update Homebrew + no_output_timeout: "10m" + command: | + set -ex + + # Update repositories manually. + # Running `brew update` produces a comparison between the + # current checkout and the updated checkout, which takes a + # very long time because the existing checkout is 2y old. + for path in $(find /usr/local/Homebrew -type d -name .git) + do + cd $path/.. + git fetch --depth=1 origin + git reset --hard origin/master + done + + export HOMEBREW_NO_AUTO_UPDATE=1 + + # Install expect and moreutils so that we can call `unbuffer` and `ts`. + # moreutils installs a `parallel` executable by default, which conflicts + # with the executable from the GNU `parallel`, so we must unlink GNU + # `parallel` first, and relink it afterwards. + brew install coreutils + brew unlink parallel + brew install moreutils + brew link parallel --overwrite + brew install expect + + brew_install: + description: "Install Homebrew formulae" + parameters: + formulae: + type: string + default: "" + steps: + - run: + name: Install << parameters.formulae >> + no_output_timeout: "10m" + command: | + set -ex + export HOMEBREW_NO_AUTO_UPDATE=1 + brew install << parameters.formulae >> + + run_brew_for_ios_build: + steps: + - brew_update + - brew_install: + formulae: libtool + binary_common: &binary_common parameters: # Edit these defaults to do a release @@ -91,6 +144,22 @@ binary_common: &binary_common UNICODE_ABI: << parameters.unicode_abi >> CU_VERSION: << parameters.cu_version >> +torchvision_ios_params: &torchvision_ios_params + parameters: + build_environment: + type: string + default: "" + ios_arch: + type: string + default: "" + ios_platform: + type: string + default: "" + environment: + BUILD_ENVIRONMENT: << parameters.build_environment >> + IOS_ARCH: << parameters.ios_arch >> + IOS_PLATFORM: << parameters.ios_platform >> + smoke_test_common: &smoke_test_common <<: *binary_common docker: @@ -288,6 +357,43 @@ jobs: paths: - "*" + binary_ios_build: + <<: *torchvision_ios_params + macos: + xcode: "12.0" + steps: + - attach_workspace: + at: ~/workspace + - checkout + - run_brew_for_ios_build + - run: + name: Build + no_output_timeout: "1h" + command: | + script="/Users/distiller/project/.circleci/unittest/ios/scripts/binary_ios_build.sh" + cat "$script" + source "$script" + - persist_to_workspace: + root: /Users/distiller/workspace/ + paths: ios + + binary_ios_upload: + <<: *torchvision_ios_params + macos: + xcode: "12.0" + steps: + - attach_workspace: + at: ~/workspace + - checkout + - run_brew_for_ios_build + - run: + name: Upload + no_output_timeout: "1h" + command: | + script="/Users/distiller/project/.circleci/unittest/ios/scripts/binary_ios_upload.sh" + cat "$script" + source "$script" + binary_macos_conda: <<: *binary_common macos: @@ -607,7 +713,7 @@ jobs: keys: - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} - + - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh @@ -1370,6 +1476,18 @@ workflows: - clang_format - torchhub_test - torch_onnx_test + - binary_ios_build: + build_environment: binary-libtorchvision_ops-ios-12.0.0-x86_64 + context: org-member + ios_arch: x86_64 + ios_platform: SIMULATOR + name: binary_libtorchvision_ops_ios_12.0.0_x86_64 + - binary_ios_build: + build_environment: binary-libtorchvision_ops-ios-12.0.0-arm64 + context: org-member + ios_arch: arm64 + ios_platform: OS + name: binary_libtorchvision_ops_ios_12.0.0_arm64 unittest: jobs: @@ -1517,6 +1635,36 @@ workflows: - clang_format - torchhub_test - torch_onnx_test + - binary_ios_build: + build_environment: nightly-binary-libtorchvision_ops-ios-12.0.0-x86_64 + context: org-member + filters: + branches: + only: + - nightly + ios_arch: x86_64 + ios_platform: SIMULATOR + name: nightly_binary_libtorchvision_ops_ios_12.0.0_x86_64 + - binary_ios_build: + build_environment: nightly-binary-libtorchvision_ops-ios-12.0.0-arm64 + context: org-member + filters: + branches: + only: + - nightly + ios_arch: arm64 + ios_platform: OS + name: nightly_binary_libtorchvision_ops_ios_12.0.0_arm64 + - binary_ios_upload: + build_environment: nightly-binary-libtorchvision_ops-ios-12.0.0-upload + context: org-member + filters: + branches: + only: + - nightly + requires: + - nightly_binary_libtorchvision_ops_ios_12.0.0_x86_64 + - nightly_binary_libtorchvision_ops_ios_12.0.0_arm64 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu diff --git a/.circleci/config.yml.in b/.circleci/config.yml.in index bddc7d4312d..fe811d75dbe 100644 --- a/.circleci/config.yml.in +++ b/.circleci/config.yml.in @@ -54,6 +54,59 @@ commands: command: | powershell .circleci/scripts/vs_install_cmath.ps1 + brew_update: + description: "Update Homebrew and install base formulae" + steps: + - run: + name: Update Homebrew + no_output_timeout: "10m" + command: | + set -ex + + # Update repositories manually. + # Running `brew update` produces a comparison between the + # current checkout and the updated checkout, which takes a + # very long time because the existing checkout is 2y old. + for path in $(find /usr/local/Homebrew -type d -name .git) + do + cd $path/.. + git fetch --depth=1 origin + git reset --hard origin/master + done + + export HOMEBREW_NO_AUTO_UPDATE=1 + + # Install expect and moreutils so that we can call `unbuffer` and `ts`. + # moreutils installs a `parallel` executable by default, which conflicts + # with the executable from the GNU `parallel`, so we must unlink GNU + # `parallel` first, and relink it afterwards. + brew install coreutils + brew unlink parallel + brew install moreutils + brew link parallel --overwrite + brew install expect + + brew_install: + description: "Install Homebrew formulae" + parameters: + formulae: + type: string + default: "" + steps: + - run: + name: Install << parameters.formulae >> + no_output_timeout: "10m" + command: | + set -ex + export HOMEBREW_NO_AUTO_UPDATE=1 + brew install << parameters.formulae >> + + run_brew_for_ios_build: + steps: + - brew_update + - brew_install: + formulae: libtool + binary_common: &binary_common parameters: # Edit these defaults to do a release @@ -91,6 +144,22 @@ binary_common: &binary_common UNICODE_ABI: << parameters.unicode_abi >> CU_VERSION: << parameters.cu_version >> +torchvision_ios_params: &torchvision_ios_params + parameters: + build_environment: + type: string + default: "" + ios_arch: + type: string + default: "" + ios_platform: + type: string + default: "" + environment: + BUILD_ENVIRONMENT: << parameters.build_environment >> + IOS_ARCH: << parameters.ios_arch >> + IOS_PLATFORM: << parameters.ios_platform >> + smoke_test_common: &smoke_test_common <<: *binary_common docker: @@ -288,6 +357,43 @@ jobs: paths: - "*" + binary_ios_build: + <<: *torchvision_ios_params + macos: + xcode: "12.0" + steps: + - attach_workspace: + at: ~/workspace + - checkout + - run_brew_for_ios_build + - run: + name: Build + no_output_timeout: "1h" + command: | + script="/Users/distiller/project/.circleci/unittest/ios/scripts/binary_ios_build.sh" + cat "$script" + source "$script" + - persist_to_workspace: + root: /Users/distiller/workspace/ + paths: ios + + binary_ios_upload: + <<: *torchvision_ios_params + macos: + xcode: "12.0" + steps: + - attach_workspace: + at: ~/workspace + - checkout + - run_brew_for_ios_build + - run: + name: Upload + no_output_timeout: "1h" + command: | + script="/Users/distiller/project/.circleci/unittest/ios/scripts/binary_ios_upload.sh" + cat "$script" + source "$script" + binary_macos_conda: <<: *binary_common macos: @@ -607,7 +713,7 @@ jobs: {% raw %} keys: - env-v1-windows-{{ arch }}-py<< parameters.python_version >>-{{ checksum ".circleci/unittest/windows/scripts/environment.yml" }}-{{ checksum ".circleci-weekly" }} - {% endraw %} + {% endraw %} - run: name: Setup command: .circleci/unittest/windows/scripts/setup_env.sh @@ -827,6 +933,7 @@ workflows: - clang_format - torchhub_test - torch_onnx_test + {{ ios_workflows() }} unittest: jobs: @@ -846,6 +953,7 @@ workflows: - clang_format - torchhub_test - torch_onnx_test + {{ ios_workflows(nightly=True) }} {{ build_workflows(prefix="nightly_", filter_branch="nightly", upload=True) }} docker_build: triggers: diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 24f663db9cb..4206a202814 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -261,6 +261,36 @@ def cmake_workflows(indentation=6): return indent(indentation, jobs) +def ios_workflows(indentation=6, nightly=False): + jobs = [] + build_job_names = [] + name_prefix = "nightly_" if nightly else "" + env_prefix = "nightly-" if nightly else "" + for arch, platform in [('x86_64', 'SIMULATOR'), ('arm64', 'OS')]: + name = f'{name_prefix}binary_libtorchvision_ops_ios_12.0.0_{arch}' + build_job_names.append(name) + build_job = { + 'build_environment': f'{env_prefix}binary-libtorchvision_ops-ios-12.0.0-{arch}', + 'context': 'org-member', + 'ios_arch': arch, + 'ios_platform': platform, + 'name': name, + } + if nightly: + build_job['filters'] = gen_filter_branch_tree('nightly') + jobs.append({'binary_ios_build': build_job}) + + if nightly: + upload_job = { + 'build_environment': f'{env_prefix}binary-libtorchvision_ops-ios-12.0.0-upload', + 'context': 'org-member', + 'filters': gen_filter_branch_tree('nightly'), + 'requires': build_job_names, + } + jobs.append({'binary_ios_upload': upload_job}) + return indent(indentation, jobs) + + if __name__ == "__main__": d = os.path.dirname(__file__) env = jinja2.Environment( @@ -275,4 +305,5 @@ def cmake_workflows(indentation=6): build_workflows=build_workflows, unittest_workflows=unittest_workflows, cmake_workflows=cmake_workflows, + ios_workflows=ios_workflows, )) diff --git a/.circleci/unittest/ios/scripts/binary_ios_build.sh b/.circleci/unittest/ios/scripts/binary_ios_build.sh new file mode 100755 index 00000000000..e2ad7b0c55f --- /dev/null +++ b/.circleci/unittest/ios/scripts/binary_ios_build.sh @@ -0,0 +1,47 @@ +#!/bin/bash +set -ex -o pipefail + +echo "" +echo "DIR: $(pwd)" +WORKSPACE=/Users/distiller/workspace +PROJ_ROOT_IOS=/Users/distiller/project/ios +PYTORCH_IOS_NIGHTLY_NAME=libtorch_ios_nightly_build.zip +export TCLLIBPATH="/usr/local/lib" + +# install conda +curl --retry 3 -o ~/conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh +chmod +x ~/conda.sh +/bin/bash ~/conda.sh -b -p ~/anaconda +export PATH="~/anaconda/bin:${PATH}" +source ~/anaconda/bin/activate + +# install dependencies +conda install numpy ninja pyyaml mkl mkl-include setuptools cmake cffi requests typing_extensions wget --yes +conda install -c conda-forge valgrind --yes +export CMAKE_PREFIX_PATH=${CONDA_PREFIX:-"$(dirname $(which conda))/../"} + +# sync submodules +cd ${PROJ_ROOT_IOS} +git submodule sync +git submodule update --init --recursive + +# download pytorch-iOS nightly build and unzip it +mkdir -p ${PROJ_ROOT_IOS}/lib +mkdir -p ${PROJ_ROOT_IOS}/build +mkdir -p ${PROJ_ROOT_IOS}/pytorch +TORCH_ROOT="${PROJ_ROOT_IOS}/pytorch" + +cd ${TORCH_ROOT} +wget https://ossci-ios-build.s3.amazonaws.com/${PYTORCH_IOS_NIGHTLY_NAME} +mkdir -p ./build_ios +unzip -d ./build_ios ./${PYTORCH_IOS_NIGHTLY_NAME} + +LIBTORCH_HEADER_ROOT="${TORCH_ROOT}/build_ios/install/include" +cd ${PROJ_ROOT_IOS} +IOS_ARCH=${IOS_ARCH} LIBTORCH_HEADER_ROOT=${LIBTORCH_HEADER_ROOT} ./build_ios.sh +rm -rf ${TORCH_ROOT} + +# store the binary +DEST_DIR=${WORKSPACE}/ios/${IOS_ARCH} +mkdir -p ${DEST_DIR} +cp ${PROJ_ROOT_IOS}/lib/*.a ${DEST_DIR} diff --git a/.circleci/unittest/ios/scripts/binary_ios_upload.sh b/.circleci/unittest/ios/scripts/binary_ios_upload.sh new file mode 100644 index 00000000000..ce56388e5da --- /dev/null +++ b/.circleci/unittest/ios/scripts/binary_ios_upload.sh @@ -0,0 +1,42 @@ +#!/bin/bash +set -ex -o pipefail + +echo "" +echo "DIR: $(pwd)" + +WORKSPACE=/Users/distiller/workspace +PROJ_ROOT=/Users/distiller/project +ARTIFACTS_DIR=${WORKSPACE}/ios +ls ${ARTIFACTS_DIR} +ZIP_DIR=${WORKSPACE}/zip +mkdir -p ${ZIP_DIR}/install/lib + +# build a FAT bianry +cd ${ZIP_DIR}/install/lib +libs=("${ARTIFACTS_DIR}/x86_64/libtorchvision_ops.a" "${ARTIFACTS_DIR}/arm64/libtorchvision_ops.a") +lipo -create "${libs[@]}" -o ${ZIP_DIR}/install/lib/libtorchvision_ops.a +lipo -i ${ZIP_DIR}/install/lib/*.a + +# copy the license +cp ${PROJ_ROOT}/LICENSE ${ZIP_DIR}/ +# zip the library +ZIPFILE=libtorchvision_ops_ios_nightly_build.zip +cd ${ZIP_DIR} +#for testing +touch version.txt +echo $(date +%s) > version.txt +zip -r ${ZIPFILE} install version.txt LICENSE + +# upload to aws +# Install conda then 'conda install' awscli +curl --retry 3 -o ~/conda.sh https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh +chmod +x ~/conda.sh +/bin/bash ~/conda.sh -b -p ~/anaconda +export PATH="~/anaconda/bin:${PATH}" +source ~/anaconda/bin/activate +conda install -c conda-forge awscli --yes +set +x +export AWS_ACCESS_KEY_ID=${AWS_S3_ACCESS_KEY_FOR_PYTORCH_BINARY_UPLOAD} +export AWS_SECRET_ACCESS_KEY=${AWS_S3_ACCESS_SECRET_FOR_PYTORCH_BINARY_UPLOAD} +set -x +aws s3 cp ${ZIPFILE} s3://ossci-ios-build/ --acl public-read diff --git a/cmake/iOS.cmake b/cmake/iOS.cmake new file mode 100644 index 00000000000..d42ea4c9232 --- /dev/null +++ b/cmake/iOS.cmake @@ -0,0 +1,207 @@ +# This file is based off of the Platform/Darwin.cmake and Platform/UnixPaths.cmake +# files which are included with CMake 2.8.4 +# It has been altered for iOS development + +# Options: +# +# IOS_PLATFORM = OS (default) or SIMULATOR +# This decides if SDKS will be selected from the iPhoneOS.platform or iPhoneSimulator.platform folders +# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch. +# SIMULATOR - used to build for the Simulator platforms, which have an x86 arch. +# +# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder +# By default this location is automatcially chosen based on the IOS_PLATFORM value above. +# If set manually, it will override the default location and force the user of a particular Developer Platform +# +# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder +# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value. +# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path. +# If set manually, this will force the use of a specific SDK version + +# Macros: +# +# set_xcode_property (TARGET XCODE_PROPERTY XCODE_VALUE) +# A convenience macro for setting xcode specific properties on targets +# example: set_xcode_property (myioslib IPHONEOS_DEPLOYMENT_TARGET "3.1") +# +# find_host_package (PROGRAM ARGS) +# A macro used to find executable programs on the host system, not within the iOS environment. +# Thanks to the android-cmake project for providing the command + +# Standard settings +set(CMAKE_SYSTEM_NAME Darwin) +set(CMAKE_SYSTEM_VERSION 1) +set(UNIX True) +set(APPLE True) +set(IOS True) + +# Required as of cmake 2.8.10 +set(CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE) + +# Determine the cmake host system version so we know where to find the iOS SDKs +find_program(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin) +if(CMAKE_UNAME) + exec_program(uname ARGS -r OUTPUT_VARIABLE CMAKE_HOST_SYSTEM_VERSION) + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}") +endif(CMAKE_UNAME) + +# Force the compilers to gcc for iOS +set(CMAKE_C_COMPILER /usr/bin/gcc CACHE STRING "") +set(CMAKE_CXX_COMPILER /usr/bin/g++ CACHE STRING "") +set(CMAKE_AR ar CACHE FILEPATH "" FORCE) +set(CMAKE_RANLIB ranlib CACHE FILEPATH "" FORCE) +set(PKG_CONFIG_EXECUTABLE pkg-config CACHE FILEPATH "" FORCE) + +# Setup iOS platform unless specified manually with IOS_PLATFORM +if(NOT DEFINED IOS_PLATFORM) + set(IOS_PLATFORM "OS") +endif(NOT DEFINED IOS_PLATFORM) +set(IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform") + +# Check the platform selection and setup for developer root +if(${IOS_PLATFORM} STREQUAL "OS") + set(IOS_PLATFORM_LOCATION "iPhoneOS.platform") + set(XCODE_IOS_PLATFORM iphoneos) + + # This causes the installers to properly locate the output libraries + set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos") +elseif(${IOS_PLATFORM} STREQUAL "SIMULATOR") + set(IOS_PLATFORM_LOCATION "iPhoneSimulator.platform") + set(XCODE_IOS_PLATFORM iphonesimulator) + + # This causes the installers to properly locate the output libraries + set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator") +elseif(${IOS_PLATFORM} STREQUAL "WATCHOS") + set(IOS_PLATFORM_LOCATION "WatchOS.platform") + set(XCODE_IOS_PLATFORM watchos) + + # This causes the installers to properly locate the output libraries + set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-watchos") +else(${IOS_PLATFORM} STREQUAL "OS") + message(FATAL_ERROR + "Unsupported IOS_PLATFORM value selected. " + "Please choose OS, SIMULATOR, or WATCHOS.") +endif() + +# All iOS/Darwin specific settings - some may be redundant +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") +set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib") +set(CMAKE_SHARED_MODULE_PREFIX "lib") +set(CMAKE_SHARED_MODULE_SUFFIX ".so") +set(CMAKE_MODULE_EXISTS 1) +set(CMAKE_DL_LIBS "") + +set(CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG "-compatibility_version ") +set(CMAKE_C_OSX_CURRENT_VERSION_FLAG "-current_version ") +set(CMAKE_CXX_OSX_COMPATIBILITY_VERSION_FLAG "${CMAKE_C_OSX_COMPATIBILITY_VERSION_FLAG}") +set(CMAKE_CXX_OSX_CURRENT_VERSION_FLAG "${CMAKE_C_OSX_CURRENT_VERSION_FLAG}") + +if(IOS_DEPLOYMENT_TARGET) + set(XCODE_IOS_PLATFORM_VERSION_FLAGS "-m${XCODE_IOS_PLATFORM}-version-min=${IOS_DEPLOYMENT_TARGET}") +endif() + +# Hidden visibilty is required for cxx on iOS +set(CMAKE_C_FLAGS_INIT "${XCODE_IOS_PLATFORM_VERSION_FLAGS}") +set(CMAKE_CXX_FLAGS_INIT "${XCODE_IOS_PLATFORM_VERSION_FLAGS} -fvisibility-inlines-hidden") + +set(CMAKE_C_LINK_FLAGS "${XCODE_IOS_PLATFORM_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_C_LINK_FLAGS}") +set(CMAKE_CXX_LINK_FLAGS "${XCODE_IOS_PLATFORM_VERSION_FLAGS} -Wl,-search_paths_first ${CMAKE_CXX_LINK_FLAGS}") + +set(CMAKE_PLATFORM_HAS_INSTALLNAME 1) +set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names") +set(CMAKE_SHARED_MODULE_LOADER_C_FLAG "-Wl,-bundle_loader,") +set(CMAKE_SHARED_MODULE_LOADER_CXX_FLAG "-Wl,-bundle_loader,") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a") + +# hack: if a new cmake (which uses CMAKE_INSTALL_NAME_TOOL) runs on an old build tree +# (where install_name_tool was hardcoded) and where CMAKE_INSTALL_NAME_TOOL isn't in the cache +# and still cmake didn't fail in CMakeFindBinUtils.cmake (because it isn't rerun) +# hardcode CMAKE_INSTALL_NAME_TOOL here to install_name_tool, so it behaves as it did before, Alex +if(NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + find_program(CMAKE_INSTALL_NAME_TOOL install_name_tool) +endif(NOT DEFINED CMAKE_INSTALL_NAME_TOOL) + +# Setup iOS deployment target +set(IOS_DEPLOYMENT_TARGET ${IOS_DEPLOYMENT_TARGET} CACHE STRING "Minimum iOS version") + +# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT +# Note Xcode 4.3 changed the installation location, choose the most recent one available +exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR) +set(XCODE_POST_43_ROOT "${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/${IOS_PLATFORM_LOCATION}/Developer") +set(XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer") +if(NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) + if(EXISTS ${XCODE_POST_43_ROOT}) + set(CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT}) + elseif(EXISTS ${XCODE_PRE_43_ROOT}) + set(CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT}) + endif(EXISTS ${XCODE_POST_43_ROOT}) +endif(NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT) +set(CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform") + +# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT +if(NOT DEFINED CMAKE_IOS_SDK_ROOT) + file(GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*") + if(_CMAKE_IOS_SDKS) + list(SORT _CMAKE_IOS_SDKS) + list(REVERSE _CMAKE_IOS_SDKS) + list(GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT) + else(_CMAKE_IOS_SDKS) + message(FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.") + endif(_CMAKE_IOS_SDKS) + message(STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}") +endif(NOT DEFINED CMAKE_IOS_SDK_ROOT) +set(CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK") + +# Set the sysroot default to the most recent SDK +set(CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support") + +# set the architecture for iOS +if(IOS_PLATFORM STREQUAL "OS") + set(DEFAULT_IOS_ARCH "arm64") +elseif(IOS_PLATFORM STREQUAL "SIMULATOR") + set(DEFAULT_IOS_ARCH "x86_64") +elseif(IOS_PLATFORM STREQUAL "WATCHOS") + set(DEFAULT_IOS_ARCH "armv7k;arm64_32") +endif() + +set(IOS_ARCH ${DEFAULT_IOS_ARCH} CACHE STRING "Build architecture for iOS") +set(CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE STRING "Build architecture for iOS") + +# Set the find root to the iOS developer roots and to user defined paths +set(CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE STRING "iOS find search path root") + +# default to searching for frameworks first +set(CMAKE_FIND_FRAMEWORK FIRST) + +# set up the default search directories for frameworks +set(CMAKE_SYSTEM_FRAMEWORK_PATH + ${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks + ${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks + ${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks +) + +# only search the iOS sdks, not the remainder of the host filesystem +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# This little macro lets you set any XCode specific property +macro(set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE) + set_property(TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE}) +endmacro(set_xcode_property) + +# This macro lets you find executable programs on the host system +macro(find_host_package) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER) + set(IOS FALSE) + + find_package(${ARGN}) + + set(IOS TRUE) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endmacro(find_host_package) diff --git a/ios/CMakeLists.txt b/ios/CMakeLists.txt new file mode 100644 index 00000000000..6b9fd3925b2 --- /dev/null +++ b/ios/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.4.1) +set(TARGET torchvision_ops) +project(${TARGET} CXX) +set(CMAKE_CXX_STANDARD 14) +set(LIBTORCH_HEADER_ROOT ${LIBTORCH_HEADER_ROOT}) +set(LIBRARY_OUTPUT_PATH ../lib) + +file(GLOB VISION_SRCS + ../torchvision/csrc/ops/cpu/*.h + ../torchvision/csrc/ops/cpu/*.cpp + ../torchvision/csrc/ops/*.h + ../torchvision/csrc/ops/*.cpp) + +add_library(${TARGET} STATIC + ${VISION_SRCS} +) + +file(GLOB PYTORCH_HEADERS "${LIBTORCH_HEADER_ROOT}") +file(GLOB PYTORCH_HEADERS_CSRC "${LIBTORCH_HEADER_ROOT}/torch/csrc/api/include") +target_include_directories(${TARGET} PRIVATE + ${PYTORCH_HEADERS} + ${PYTORCH_HEADERS_CSRC} +) diff --git a/ios/build_ios.sh b/ios/build_ios.sh new file mode 100755 index 00000000000..81ac2f2a218 --- /dev/null +++ b/ios/build_ios.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -ex -o pipefail +echo "" +echo "DIR: $(pwd)" +VISION_IOS_ROOT=$(dirname $(realpath $0)) + +if ! [ -n "${LIBTORCH_HEADER_ROOT:-}" ]; then + echo "Missing parameter: LIBTORCH_HEADER_ROOT" + exit 1 +fi + +if [ -n "${IOS_ARCH:-}" ]; then + if [ "${IOS_ARCH:-}" == "arm64" ]; then + IOS_PLATFORM="OS" + elif [ "${IOS_ARCH:-}" == "x86_64" ]; then + IOS_PLATFORM="SIMULATOR" + fi +fi + +mkdir -p ${VISION_IOS_ROOT}/lib +mkdir -p ${VISION_IOS_ROOT}/build +cd ${VISION_IOS_ROOT}/build +cmake -DLIBTORCH_HEADER_ROOT=${LIBTORCH_HEADER_ROOT} \ + -DCMAKE_TOOLCHAIN_FILE=${VISION_IOS_ROOT}/../cmake/iOS.cmake \ + -DIOS_ARCH=${IOS_ARCH} \ + -DIOS_PLATFORM=${IOS_PLATFORM} \ + .. +make +rm -rf ${VISION_IOS_ROOT}/build From 3635da27bd1ad5bbd89e2e948906d741b436c4eb Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Fri, 2 Apr 2021 07:34:11 -0700 Subject: [PATCH 326/357] [fbsync] and ROCm 4.1 nightly wheels (#3604) Summary: Co-authored-by: Francisco Massa Reviewed By: fmassa Differential Revision: D27433911 fbshipit-source-id: 429f6d4408e92bb1ce358d941cda5315be77ad52 --- .circleci/config.yml | 140 ++++++++++++++++++++++++++++++++++++++++ .circleci/regenerate.py | 2 +- 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e7c15dbb8cb..437d613d9ab 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -954,6 +954,11 @@ workflows: name: binary_linux_wheel_py3.6_rocm4.0.1 python_version: '3.6' wheel_docker_image: pytorch/manylinux-rocm:4.0.1 + - binary_linux_wheel: + cu_version: rocm4.1 + name: binary_linux_wheel_py3.6_rocm4.1 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-rocm:4.1 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -983,6 +988,11 @@ workflows: name: binary_linux_wheel_py3.7_rocm4.0.1 python_version: '3.7' wheel_docker_image: pytorch/manylinux-rocm:4.0.1 + - binary_linux_wheel: + cu_version: rocm4.1 + name: binary_linux_wheel_py3.7_rocm4.1 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-rocm:4.1 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1012,6 +1022,11 @@ workflows: name: binary_linux_wheel_py3.8_rocm4.0.1 python_version: '3.8' wheel_docker_image: pytorch/manylinux-rocm:4.0.1 + - binary_linux_wheel: + cu_version: rocm4.1 + name: binary_linux_wheel_py3.8_rocm4.1 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-rocm:4.1 - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1041,6 +1056,11 @@ workflows: name: binary_linux_wheel_py3.9_rocm4.0.1 python_version: '3.9' wheel_docker_image: pytorch/manylinux-rocm:4.0.1 + - binary_linux_wheel: + cu_version: rocm4.1 + name: binary_linux_wheel_py3.9_rocm4.1 + python_version: '3.9' + wheel_docker_image: pytorch/manylinux-rocm:4.1 - binary_macos_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1819,6 +1839,36 @@ workflows: python_version: '3.6' requires: - nightly_binary_linux_wheel_py3.6_rocm4.0.1_upload + - binary_linux_wheel: + cu_version: rocm4.1 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_rocm4.1 + python_version: '3.6' + wheel_docker_image: pytorch/manylinux-rocm:4.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.6_rocm4.1_upload + requires: + - nightly_binary_linux_wheel_py3.6_rocm4.1 + subfolder: rocm4.1/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.6_rocm4.1_smoke_test_pip + python_version: '3.6' + requires: + - nightly_binary_linux_wheel_py3.6_rocm4.1_upload - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -1973,6 +2023,36 @@ workflows: python_version: '3.7' requires: - nightly_binary_linux_wheel_py3.7_rocm4.0.1_upload + - binary_linux_wheel: + cu_version: rocm4.1 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_rocm4.1 + python_version: '3.7' + wheel_docker_image: pytorch/manylinux-rocm:4.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.7_rocm4.1_upload + requires: + - nightly_binary_linux_wheel_py3.7_rocm4.1 + subfolder: rocm4.1/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.7_rocm4.1_smoke_test_pip + python_version: '3.7' + requires: + - nightly_binary_linux_wheel_py3.7_rocm4.1_upload - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -2127,6 +2207,36 @@ workflows: python_version: '3.8' requires: - nightly_binary_linux_wheel_py3.8_rocm4.0.1_upload + - binary_linux_wheel: + cu_version: rocm4.1 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_rocm4.1 + python_version: '3.8' + wheel_docker_image: pytorch/manylinux-rocm:4.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.8_rocm4.1_upload + requires: + - nightly_binary_linux_wheel_py3.8_rocm4.1 + subfolder: rocm4.1/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.8_rocm4.1_smoke_test_pip + python_version: '3.8' + requires: + - nightly_binary_linux_wheel_py3.8_rocm4.1_upload - binary_linux_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu @@ -2281,6 +2391,36 @@ workflows: python_version: '3.9' requires: - nightly_binary_linux_wheel_py3.9_rocm4.0.1_upload + - binary_linux_wheel: + cu_version: rocm4.1 + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9_rocm4.1 + python_version: '3.9' + wheel_docker_image: pytorch/manylinux-rocm:4.1 + - binary_wheel_upload: + context: org-member + filters: + branches: + only: nightly + tags: + only: /v[0-9]+(\.[0-9]+)*-rc[0-9]+/ + name: nightly_binary_linux_wheel_py3.9_rocm4.1_upload + requires: + - nightly_binary_linux_wheel_py3.9_rocm4.1 + subfolder: rocm4.1/ + - smoke_test_linux_pip: + filters: + branches: + only: + - nightly + name: nightly_binary_linux_wheel_py3.9_rocm4.1_smoke_test_pip + python_version: '3.9' + requires: + - nightly_binary_linux_wheel_py3.9_rocm4.1_upload - binary_macos_wheel: conda_docker_image: pytorch/conda-builder:cpu cu_version: cpu diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index 4206a202814..d7d822db013 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -29,7 +29,7 @@ def build_workflows(prefix='', filter_branch=None, upload=False, indentation=6, for btype in ["wheel", "conda"]: for os_type in ["linux", "macos", "win"]: python_versions = PYTHON_VERSIONS - cu_versions_dict = {"linux": ["cpu", "cu101", "cu102", "cu111", "rocm4.0.1"], + cu_versions_dict = {"linux": ["cpu", "cu101", "cu102", "cu111", "rocm4.0.1", "rocm4.1"], "win": ["cpu", "cu101", "cu102", "cu111"], "macos": ["cpu"]} cu_versions = cu_versions_dict[os_type] From cb6cce385c82c98df9ae6e42fe6764d2f445bb46 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Fri, 2 Apr 2021 07:34:11 -0700 Subject: [PATCH 327/357] [fbsync] add tests for (Dataset|Image)Folder (#3477) Summary: * add tests for (Dataset|Image)Folder * lint * remove old tests * cleanup * more cleanup * adapt tests * fix make_dataset * remove powerset * readd import Reviewed By: fmassa Differential Revision: D27433923 fbshipit-source-id: 6ea3fb79f41e255045a642dcadedd8fa813e9dcc --- test/test_datasets.py | 151 ++++++++++++++++++++------------- torchvision/datasets/folder.py | 2 +- 2 files changed, 91 insertions(+), 62 deletions(-) diff --git a/test/test_datasets.py b/test/test_datasets.py index 2dde215e32b..db80b55a90f 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -57,67 +57,6 @@ def generic_segmentation_dataset_test(self, dataset, num_images=1): class Tester(DatasetTestcase): - def test_imagefolder(self): - # TODO: create the fake data on-the-fly - FAKEDATA_DIR = get_file_path_2( - os.path.dirname(os.path.abspath(__file__)), 'assets', 'fakedata') - - with get_tmp_dir(src=os.path.join(FAKEDATA_DIR, 'imagefolder')) as root: - classes = sorted(['a', 'b']) - class_a_image_files = [ - os.path.join(root, 'a', file) for file in ('a1.png', 'a2.png', 'a3.png') - ] - class_b_image_files = [ - os.path.join(root, 'b', file) for file in ('b1.png', 'b2.png', 'b3.png', 'b4.png') - ] - dataset = torchvision.datasets.ImageFolder(root, loader=lambda x: x) - - # test if all classes are present - self.assertEqual(classes, sorted(dataset.classes)) - - # test if combination of classes and class_to_index functions correctly - for cls in classes: - self.assertEqual(cls, dataset.classes[dataset.class_to_idx[cls]]) - - # test if all images were detected correctly - class_a_idx = dataset.class_to_idx['a'] - class_b_idx = dataset.class_to_idx['b'] - imgs_a = [(img_file, class_a_idx) for img_file in class_a_image_files] - imgs_b = [(img_file, class_b_idx) for img_file in class_b_image_files] - imgs = sorted(imgs_a + imgs_b) - self.assertEqual(imgs, dataset.imgs) - - # test if the datasets outputs all images correctly - outputs = sorted([dataset[i] for i in range(len(dataset))]) - self.assertEqual(imgs, outputs) - - # redo all tests with specified valid image files - dataset = torchvision.datasets.ImageFolder( - root, loader=lambda x: x, is_valid_file=lambda x: '3' in x) - self.assertEqual(classes, sorted(dataset.classes)) - - class_a_idx = dataset.class_to_idx['a'] - class_b_idx = dataset.class_to_idx['b'] - imgs_a = [(img_file, class_a_idx) for img_file in class_a_image_files - if '3' in img_file] - imgs_b = [(img_file, class_b_idx) for img_file in class_b_image_files - if '3' in img_file] - imgs = sorted(imgs_a + imgs_b) - self.assertEqual(imgs, dataset.imgs) - - outputs = sorted([dataset[i] for i in range(len(dataset))]) - self.assertEqual(imgs, outputs) - - def test_imagefolder_empty(self): - with get_tmp_dir() as root: - with self.assertRaises(FileNotFoundError): - torchvision.datasets.ImageFolder(root, loader=lambda x: x) - - with self.assertRaises(FileNotFoundError): - torchvision.datasets.ImageFolder( - root, loader=lambda x: x, is_valid_file=lambda x: False - ) - @mock.patch('torchvision.datasets.SVHN._check_integrity') @unittest.skipIf(not HAS_SCIPY, "scipy unavailable") def test_svhn(self, mock_check): @@ -1673,5 +1612,95 @@ def test_num_examples_test50k(self): self.assertEqual(len(dataset), info["num_examples"] - 10000) +class DatasetFolderTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.DatasetFolder + + # The dataset has no fixed return type since it is defined by the loader parameter. For testing, we use a loader + # that simply returns the path as type 'str' instead of loading anything. See the 'dataset_args()' method. + FEATURE_TYPES = (str, int) + + _IMAGE_EXTENSIONS = ("jpg", "png") + _VIDEO_EXTENSIONS = ("avi", "mp4") + _EXTENSIONS = (*_IMAGE_EXTENSIONS, *_VIDEO_EXTENSIONS) + + # DatasetFolder has two mutually exclusive parameters: 'extensions' and 'is_valid_file'. One of both is required. + # We only iterate over different 'extensions' here and handle the tests for 'is_valid_file' in the + # 'test_is_valid_file()' method. + DEFAULT_CONFIG = dict(extensions=_EXTENSIONS) + ADDITIONAL_CONFIGS = ( + *datasets_utils.combinations_grid(extensions=[(ext,) for ext in _IMAGE_EXTENSIONS]), + dict(extensions=_IMAGE_EXTENSIONS), + *datasets_utils.combinations_grid(extensions=[(ext,) for ext in _VIDEO_EXTENSIONS]), + dict(extensions=_VIDEO_EXTENSIONS), + ) + + def dataset_args(self, tmpdir, config): + return tmpdir, lambda x: x + + def inject_fake_data(self, tmpdir, config): + extensions = config["extensions"] or self._is_valid_file_to_extensions(config["is_valid_file"]) + + num_examples_total = 0 + classes = [] + for ext, cls in zip(self._EXTENSIONS, string.ascii_letters): + if ext not in extensions: + continue + + create_example_folder = ( + datasets_utils.create_image_folder + if ext in self._IMAGE_EXTENSIONS + else datasets_utils.create_video_folder + ) + + num_examples = torch.randint(1, 3, size=()).item() + create_example_folder(tmpdir, cls, lambda idx: self._file_name_fn(cls, ext, idx), num_examples) + + num_examples_total += num_examples + classes.append(cls) + + return dict(num_examples=num_examples_total, classes=classes) + + def _file_name_fn(self, cls, ext, idx): + return f"{cls}_{idx}.{ext}" + + def _is_valid_file_to_extensions(self, is_valid_file): + return {ext for ext in self._EXTENSIONS if is_valid_file(f"foo.{ext}")} + + @datasets_utils.test_all_configs + def test_is_valid_file(self, config): + extensions = config.pop("extensions") + # We need to explicitly pass extensions=None here or otherwise it would be filled by the value from the + # DEFAULT_CONFIG. + with self.create_dataset( + config, extensions=None, is_valid_file=lambda file: pathlib.Path(file).suffix[1:] in extensions + ) as (dataset, info): + self.assertEqual(len(dataset), info["num_examples"]) + + @datasets_utils.test_all_configs + def test_classes(self, config): + with self.create_dataset(config) as (dataset, info): + self.assertSequenceEqual(dataset.classes, info["classes"]) + + +class ImageFolderTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.ImageFolder + + def inject_fake_data(self, tmpdir, config): + num_examples_total = 0 + classes = ("a", "b") + for cls in classes: + num_examples = torch.randint(1, 3, size=()).item() + num_examples_total += num_examples + + datasets_utils.create_image_folder(tmpdir, cls, lambda idx: f"{cls}_{idx}.png", num_examples) + + return dict(num_examples=num_examples_total, classes=classes) + + @datasets_utils.test_all_configs + def test_classes(self, config): + with self.create_dataset(config) as (dataset, info): + self.assertSequenceEqual(dataset.classes, info["classes"]) + + if __name__ == "__main__": unittest.main() diff --git a/torchvision/datasets/folder.py b/torchvision/datasets/folder.py index fb4861e637a..d121bad7a19 100644 --- a/torchvision/datasets/folder.py +++ b/torchvision/datasets/folder.py @@ -129,7 +129,7 @@ def is_valid_file(x: str) -> bool: if target_class not in available_classes: available_classes.add(target_class) - empty_classes = available_classes - set(class_to_idx.keys()) + empty_classes = set(class_to_idx.keys()) - available_classes if empty_classes: msg = f"Found no valid file for the classes {', '.join(sorted(empty_classes))}. " if extensions is not None: From d2436061f0bc2774c6df321dd8cda24bdc47b977 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Fri, 2 Apr 2021 07:34:11 -0700 Subject: [PATCH 328/357] [fbsync] Improved utilites, adds examples, tests (#3594) Summary: * start adding tests * add return type and doc * adds tests * add no fill tests * add rgb test * check inplace * bug fix * bug fix * rewrite make grid * add plotting demos * rename file * remove * updt * Add viz * updt * update readme, add links * complte bounding boxes * Complete the examples! * link fix * link fixed Reviewed By: fmassa Differential Revision: D27433916 fbshipit-source-id: 144ca18f9d444b8c78141f2f7ae2f8077ab45076 Co-authored-by: Francisco Massa --- examples/python/README.md | 4 + examples/python/visualization_utils.ipynb | 683 ++++++++++++++++++++ test/assets/fakedata/draw_boxes_vanilla.png | Bin 0 -> 360 bytes test/test_utils.py | 58 +- torchvision/utils.py | 31 +- 5 files changed, 768 insertions(+), 8 deletions(-) create mode 100644 examples/python/visualization_utils.ipynb create mode 100644 test/assets/fakedata/draw_boxes_vanilla.png diff --git a/examples/python/README.md b/examples/python/README.md index 9cd02bcb326..1e6c66b5219 100644 --- a/examples/python/README.md +++ b/examples/python/README.md @@ -4,6 +4,8 @@ [Examples of Tensor Images transformations](https://github.com/pytorch/vision/blob/master/examples/python/tensor_transforms.ipynb) - [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pytorch/vision/blob/master/examples/python/video_api.ipynb) [Example of VideoAPI](https://github.com/pytorch/vision/blob/master/examples/python/video_api.ipynb) +- [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/pytorch/vision/blob/master/examples/python/visualization_utils.ipynb) +[Example of Visualization Utils](https://github.com/pytorch/vision/blob/master/examples/python/visualization_utils.ipynb) Prior to v0.8.0, transforms in torchvision have traditionally been PIL-centric and presented multiple limitations due to @@ -16,3 +18,5 @@ features: - read and decode data directly as torch tensor with torchscript support (for PNG and JPEG image formats) Furthermore, previously we used to provide a very high-level API for video decoding which left little control to the user. We're now expanding that API (and replacing it in the future) with a lower-level API that allows the user a frame-based access to a video. + +Torchvision also provides utilities to visualize results. You can make grid of images, plot bounding boxes as well as segmentation masks. Thse utilities work standalone as well as with torchvision models for detection and segmentation. diff --git a/examples/python/visualization_utils.ipynb b/examples/python/visualization_utils.ipynb new file mode 100644 index 00000000000..2f042cf02c8 --- /dev/null +++ b/examples/python/visualization_utils.ipynb @@ -0,0 +1,683 @@ +{ + "metadata": { + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.6-final" + }, + "orig_nbformat": 2, + "kernelspec": { + "name": "python3", + "display_name": "Python 3.7.6 64-bit", + "metadata": { + "interpreter": { + "hash": "b59c5859fdaa326f162dbe4b890c245edf044b3a52376874fe660daf6e3b88fe" + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 2, + "cells": [ + { + "source": [ + "# Torchvision Utilites for Visualization" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "source": [ + "`torchvision` provides utilites for visualizing images, bounding boxes and segmentation masks.\n", + "\n", + "All the utilities do not perform inplace modification of inputs.\n" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import torchvision.transforms as transforms\n", + "import torchvision.datasets as datasets\n", + "import numpy as np\n", + "import random\n", + "import scipy.misc" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "%matplotlib inline\n", + "def show(img):\n", + " npimg = img.numpy()\n", + " plt.imshow(np.transpose(npimg, (1,2,0)), interpolation='nearest')" + ] + }, + { + "source": [ + "## Visualize Grid of Images" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "source": [ + "Use `torchvision.utils.make_grid()` to create a grid of images.\n", + "\n", + "You can also pad, mormalize and scale the images on the fly.\n", + "\n", + "This utility can take 4D mini-batch Tensor of shape (B x C x H x W) or a list of images all of the same size." + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "from torchvision.utils import make_grid" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([3, 768, 1024])\n", + "/home/oke/Aditya/PyTorch/vision/torchvision/transforms/functional.py:114: UserWarning: The given NumPy array is not writeable, and PyTorch does not support non-writeable tensors. This means you can write to the underlying (supposedly non-writeable) NumPy array using the tensor. You may want to copy the array to protect its data or make it writeable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at /opt/conda/conda-bld/pytorch_1614931498178/work/torch/csrc/utils/tensor_numpy.cpp:179.)\n", + " img = torch.from_numpy(pic.transpose((2, 0, 1))).contiguous()\n" + ] + } + ], + "source": [ + "lena = scipy.misc.face()\n", + "img = transforms.ToTensor()(lena)\n", + "print(img.size())" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "imglist = [img, img, img, img.clone().fill_(-10)]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stderr", + "text": [ + "Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-24T23:32:48.421838\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "show(make_grid(imglist, padding=100))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-24T23:32:49.291422\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "show(make_grid(imglist, padding=100, normalize=True))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-24T23:32:50.133283\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "show(make_grid(imglist, padding=100, normalize=True, value_range=(0, 1)))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-24T23:32:51.060394\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXcAAABpCAYAAADBa2OhAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAACHI0lEQVR4nOy9e3gT1fb//+owhBBCCDGEUEoIpdRSSimlYIFaCpaLHEBARETEC6h4Q0TFOyoiKioi3hGRo4DIQURERERErLXWUksppZQSSikhhBBCCCGEIfv3x1QuQquec/ycc76/vp8nT5vZM3vveWdm7bXXWnvtKCEE9ahHPepRj/+3IP2nO1CPetSjHvX496NeuNejHvWox/+DqBfu9ahHPerx/yDqhXs96lGPevw/iHrhXo961KMe/w+iXrjXox71qMf/g/hLhHtUVNSgqKionVFRURVRUVEP/xVt1KMe9ahHPWpH1L87zj0qKqoBUA70B6qBn4HrhBCl/9aG6lGPetSjHrXir9DcewAVQgiHECIMLAOu+gvaqUc96lGPetQC+S+oszWw75zv1cBlvz0pKirqNuC2mq/d/oJ+1KMe9ajH/+vwCCFaXKzgrxDufwhCiPnAfICoqKj6HAj1qEc96vHnsbe2gr/CLLMfaHPO95iaY/WoRz3qUY//I/wVwv1noENUVFS7qKgoDTAGWP0XtFOPetSjHvWoBf92s4wQQomKirob+ApoACwUQmz/d7dTj3rUox71qB3/9lDIf6oT9Tb3etSjHvX4Z7BFCJF2sYL6Far1qEc96vH/IP5j0TJ/FM4yhVaxDdiVs5cOfdsCcGQ/rN7wFaMSEmhyWVvee/UTJky+GqJqLjoJPxeDXneSjp0awSmgIRw7ChWF2wkrQfI253HvM/dw9MAxKsqrkMIhXB4fvVLTcAfcVFZWEh2TSNBbTfcrz0ZyHt2+nWadOp3fySPHoHlT9f9Tp6FhA/X/07DfcZCg04NXAr0/TEx8DGs3FuILSQQjCi53BdXV1RgMBnQW0MeVktQjgmQ3M6hhOkNuH4evPJqt3+7nxmcuA2MEKRDC65aRLVoGjcpmSIce+A8Xk2B+vFYeg05BYz3sLT5A296t1O4dgzLHIeKlCA07t+StFz/ijgevO++6jz/czcjR7WnYCPZuO0bbzk05eQwWzHuXtB4pFOQWcNeTd3DyyCkKC0qItcewetVaMtJ6ECRIt6xuHHScpKWpETQ/p+JTp6Bhw7PfD52EFo1qymBXyS906Nr1zPfjvhNUFZcT1GmJVHswRhspLndT5Q4QIoLb48DpdGI2m1Ue40uITQxi7GQni2SG3H5TDY+l3PB0NhqLTMQXIODTobHqyBqcxa2XDmPL3mWk2WfXymPEKwiFwO88RctuDUHA6SA4XcewBoM07NySz//xI0Ov6Xn2oqPwfcExLr9CfUa2fLuHbn3bcXDfcZbNX0j24Gw2rd/EXU/eAcD2n3YjSxGWLV1BvM2OPdFOz4E9OXEIGl8k6O3g9h207NTxwoL9x9haUk6XzG7QGBBABHblbMcnS+gUhWDAj9svUe0J4vb7cHscuFwujPZoLPoI2oQiou1BYrrF0YskRt5zJxUlseR9+ygPPDkXbbQWxeslHDRijDOQ3Cue2zs8ztb9c0iJmVUrj/X46/Ffr7kvW7qAn1dsUwX7STi+G/x+gclkwm0yAlCWl4sIn3NRI0i0QsdOjfj5m91QI0Py13xDeZWLy/p357aJ97B760FKSyrRmEx07d+NK6+7grnzZlFZWUlycjLPP/4A3a+8jH1bd7Dlm2388MknFwj2w7v2nxHsJw6ehIYNOL77KN9+/jPCeRqNbKAiGKaqwknIaEKv1ZCdmYbX60QJVqPValG0MrJRj9fhx1kSwVVsx9bQyMi7xuHelMrWb0u49ene6Mxaqkq9VDpcZI9M5ZYpw4nvYGXZjuVUhOrm8fXX3+Fw6XEq3V44DYd3QYOm4PF4qKg5pywvlz07T5133bVj2tMwDNt+2I+kU++zZPMWomMTuKx/d4YMHsXhA6dZu2YTZdXVtOzQglsfvJGS0nxiYmLYX7aftcs/ACOc2H+II7sOs+3bb84K9lOnEUdhT5WDozsOAXCo6jAdunbl+O6jfPTu5xyrPEYwoFAdkSguKEVrj6VDXCxJcXYikeB5PEZ0GrwOP1XFCp6yGKzouOXBqbg2JqsD5EOZGKx6Kks8VFV6GTK2F8PGZZB4qZVXd7yOI6Krk8cpk5+ksQIFTpW1XQXHadAEvF4v1VotR3YLynML+OWnQ2cvagaXX9GUXT8dA0CjjwaguriMHv0G0alnR3ql9wPgsyXfsDE/n0u7d+DuybeRmpZAz4E9ObrrAGHvYTgKHFd/o4M7VVeWUaOD4yc4vOcIn73/MXu+3622a2pKl4HdOOw4yIdvfcrWjdvYV3oQt6ylsrwafWxnkuPtWI16QiHf+TyG3XirgzhLIeSJwYyGOx96iqoN8ez5djGPPjQLXYwOR4GD6ko/wydmkpIRhy4myKvbHqbAd+4LWY//BP7rbe7n9u+zT37EU+UiITGe3pmdIAjfrfuWPtf35ePXPuXaiSPYWriXLr3bXlDP1q93k5hkp9rvp92lzdny7RZCQYllyxcxesgYZsx6lPFjxzNo+GgclaWYzWbaR7djW+lWEhNshIMKgVCQFp3Oqfs47Cnegy2+Ha6qQ7Tu2oLTR6FBM7X41GFoaIJf1m/H5/fg9vqJS4invLQMs1FPqdOJQQmi0ckUlnlwKn6MspOgWUaneKhwOvj6/YWAgauezUaWDNw2aRzF5YVYTHGEZB+eUICCFS4qCkspWVVdK8fn8rhn13F8Tg/BUIBYWwxSJMzKpcu549m7OLjtCBFNGJO5JY0uUc/fvQ/a1wS3ioMQZYEDVSdo1bYxP371I44KF3n5m0iwJVJWUcTIYSNx+0OEFT9JSUmEfSEikkLPfr0hdIq9jgqirWYaRrdQXe7At//4jr7D+qgzi+6tzuv7z9/spvsV7Tm88whFJWWEg36sMXbKy8uxmo2UedxIbjdoFErLfVSEPMQY/SgxGuSAm0pnNV++Px2wcf0r4wkEwky8bSwV1WWYjbEE8OANB8ldWkVJXgFVGwJ183gaaAAH9p3Gom9AXv52NBJYzUZmTZ/BozMfoE2XDnz50XcMGtKHqJpJ3ftLvufm6y8/U9dPX23DHhdLy/ZN+ObTbyguLiEYDOKu9NCjVzJJCSmsWrcevUFm+KBscjYXkpSSSLeB3UHAkfL9aGRootVBa3Va9Nl7n3PVLUPZW3CA6KRWNGxc0+8jUFZ+kI6XtQTghy+2UVXpIj4hBmdlFXqDlspQmGB5OX7FT6U3hMPjItYShDgdklflcc7bY+jYaBQ3vzEKnzfM2PFDcHqrMBns+CNu5LCGZYsKKcrJxZdXK431+PehVpv7/4ZwPwnPTnuRac8/yNuz3gENjBzSj9ZdO7Dju9107NOee2++Dyns55XF70EUvPXap2SnplJQXs51N/dXp6RR8OEbHzJg0DACAQWb7RKemvUiY4YPJm9zDslpKVyWcRmHqo8TCXhoGdcWNECji/ft0LYDtOh8viA6fQACEjRrCZ++/w0jbr7iTNmen7ZTXFSGzmKjqqwASdYQmxBPeUkp7lCI8vJSnJ4qDBYzyb00rNm4mpjoRBJSdJRVOfA4NYycmAEaCcIRIoqeohW5lFf40ckaNq0qrJVjIQT7dwtWLHybjGHDyFm9mh7pqZhNMh16d+PHz7bQ86puvPjEywS8lTz9xmsg4NkZ75GRmEylu4ob77q6pjJ456V3GD5yDEZjM8rK9uL0OJHCAbSSjNag47L+qinru4++IrVHGk1NRmje4KJ9O7HnGI3bNf1NhzljZtv2/V46X352UN378w6qKl1EdCYKc9cTDitkDsqmMCcPr6JQ4SjF5XFiscWQkiGzeOVS7LZkElP1FJaVIBNN5rAkZJ2GSEghFNRQurqACkfgD/G45YcDeP0eCgsL0StBkpMTkaUQPa8ayHf/+JE+1/Tkwzc+pLQoh+fefQeAjz/8gX7paZQXF9D76t4AHD8KC19/jYm33EnjVg1Y8v4nxMelUl6Sh9VkRmfU03Ogat7Z8d1PdExKA00DaHrxvh3efpBLolueb/76FSfhuAeatIY92w7QrnMr9vywA6/XS1hroDh/M16vj4zBAyjYuBmfrKGirBBfwEt0rJ3EjAjLV67AaonFlqSltLwMuzWN+AwzslZLJKTgdimUr6vG6XSi12jZuLKgVh7r8W9DrcL9v97mfvQAzJ/zKuPHj6do9Rd4XA5ibHbmvT6fuyeP5/nnp5OxeRgb161n/qIFvDzjDSKEGTN2EtGWxnTo3ZbH7niNsTcNptNl7RmQPZyW7Zsy945neOqpJxiWkYzJaCHaFoujtITLel1GWVkJiXZrrS/Rr1i/fj2aPCPW2FhcTg8mfQSX04/WZMBsjGXEWFWw79lxknYdG9Husk4U5BdTVVJIwOdF0oXQOmT00Ra8VVVoCGLUG/A6vWxaI2OzZqKLdlJYUk2P9EyixxrQ6oxoNDJVBaVsWJFP0B1EqzOSPsBWp1A6tBeWvj2P8ePH46suweNykLvZj8vjYmwoyLJlCzHoH6aitIxRY0fzyjNvUVpWzIyZ86iuLOPGa67mhYf+zoAhPeh6eUduf/B2AO647n7eWvgyJW+uIS6pFyazgYqSEjgO7739IROm3KBq53XoEMuXL0dnMpOQmkpxUSlxNiNVlR6M0Ra0WismbYTjB0DSQuPm0LZ7R9at20AYDbKsIaB4qC4rR2M2gstFJOjDoNPjrnSxphribVlool3kF5UybPgYdPYIkqxD1kQo2VBA/noXYW8Ync7I8HEpdfK485cTrF+xlCl330KKIczri5ZSrISpdldSWV2Fo7wCo0kVdqmpWTz7yMtUOsp59+N3WPLOJ1w/5mq2fXcIl7eM/iMu557H7uHwoRM8PmEWD0y5m/Vrl6ExxJCa3oOivDw4eJq/L/6AG++/mRO7j9I4tlmtfVu3bh1aowV7YjzVjmqsFi2VLh+xsbFIkglvdRnBsMJV1/cBoF3vjuS/8neCioKiRAgobpylZYS1MmY5hCMcQCPJOEoqcDg02G09kKwuygpcjL1tIpI1DJIWWQqRuzqP4k1uwsEQWq2F8VOy6oX7fxj/9Zr7mGHT+OizF9j+9R469W/Hkpf/jsddjc5gpFdGBj6/i95DBnKodDcr1mzgjodu5+QxaNQUdv9yjPZdm/LDZz8SCAeoLK/g9sdqnFY/7MIeF8v8OW+SkdWD5MQkGrVtctE+7PphKw5XJQOvPj//2efvLSGvqIxhY8ZTXlROfFIyRUVF9EjrRUVFJXFxdqod1ST16oLDsYtwOEilo4L4ODtx0dHojSYuaduI3TuPkbNhLT6/h3KHA6fbiVYno7F68fk8pI3ugTFRh9kUjSyFWDl/BZWbQkiRCBaLiQdemoK2uY60qMG1cjx10lxefutexH6Iag3vPfsOfp8bW2wcNrudsOKnV7+BFOR8S1DR0edvl3H8GDQ5Z4Db+s02yhxlmA1Grri2PwBf/+M70tJ7sGn1JkxWLcmJSUjmFjS7iOPvjSdfxBpr4+obrz3v+E+ff83aDfmkDxqAs6ya7MFDWLVqFYMGDEGWtYTDQSKhCJa4ppSV7SUcDuJyVqPXaRic1YeIpAr+ouK9FOfnEFaCOKqqqKh0oJHDaG1BfH4XaaN6YU7UYzRZ0WsUlr25DMemECgKMTFmHnjpATRNtaRGDaqVx+kPLODp2RPOzCpefeRlDHoNNns8Gp0GpBBag5GK0hJS0wdwabe2iNMQFQKanOWxvLKcHimptE1oBzp4Z9a7JCXGYY9JZmPOGrIyMglodXTs3PKCPrzyyLMYrGYm3Hv7+QWHT/LY9OfJHDaEqpJKevXKpKCohMzMTNp1asCW7w8Ra22B3gaFhQdw+7z4ndVodTKZaWm0sDdjb/UhykqrKSvOxWq1UlhcjKOqkojiRx8bxutzkja+B9HxFvQGM1opwOr5aynb7IUwJGbbuHPSZDSNtSRHZdfKYz3+bfjfDYV8aeYMADr1b8fJXXD9/TdiMRnolZqCVW8kf0M+REFllQ+DwcaxPccJe47zyD3P0r6rKpl6X9WTDetzuOW2Ozh1RK3X66ymsqSE0beMpcTlplHbJpzYd/yifeiQbKO4uJhnH3mCI/vO5kQbOuF6os1mFr39Jrm5+VzWpw1JiSloNDqiY2zoTZcQbYtjw/of8bmChIIarHo7GsmKxxvCZG7Ey8/+HZ2pKXFp6dhMduLt8aTFp2LQmzBobCQMSMAWY8EkRWOQJPLmF1Ox1o836Gfq65OY8d7jJDVPx0p8nTzOmn4vx/eBT4FDW08y4bHbsUVbGNwvi1hLNIWbCnGW78FitpPZ7zKO7TlOxHOcZx95lWMHTwAQn9gZR4WTK67tf4ZHs17HpjVrGHHXlcT36EXzji3QhC7O4+gxgygtLeaFJ57m4O7dZ47H2Kxo5Qhrly+noqISo7EhEUUiNzefyqpqQhGJiKQnL3cPPlcQIgbsxngCPg0rVn6Dyy2Y//bHGCzRRCcmEx+dgFFnZFBGFmaLDV3EROKAZGLt0RjlaAyShjkTF1K8xosn4OHRBVOY+c4MEpv2wEJcnTw+PXsCS17/gn0/7odjMP6mScjAFaMHYjNZKNhYSHW5n+sm3sql3dpyaMdhKvJ38/GyL/jm8+8ACEckMnpl0zaxHceDJyEK+mVmUB0I0rr7Jdxw34206d6OjjEXCnaAYcP7UVXl4JVnnmPPtm1njn+1fg2RcID1K1eS3W8IiqTgdnvZtCmHPTtAicg4nCfZvOkg7iofkYCeFHsaXrf6/ny/cS/5OSWYY+yYrXZijDYkRWJQRhbW6Fg0YQNJg1JIjkvGKEejR+bxka+Tv9pJAIUZix9m2n2ziG+cigl7nTzW46/Hf73m/tv+ffnRd1w5vA//mPce14wfz+fL1jB04gi1sCm8/9pH2Mx6ou2JdOzZns8//QmLWY/ZYKV9l0t498UlLFr8AT9s/epMnUf3nqBZ28YXbf+HT7+m94j+fPnh+xTklZCYkszVt954pvy5+x/EaEgiNSmRNZtzeObV+wA4tgfyivcQikBFaQmJCckoeLEaY0hMa0FjA/y48SBKyEeQEG5PJfboeJbNn8+kyXfj9FUTZ7fTvvP5zuFnX3wPbVIZRhskJqZji0pFQwgIYYlKrZVjIQRbvj5Ot/6q+rhv22EIhNi4biW9+mVRkl/GiFuu4bDrIJd0aslbz71HvN3CFdcNBWDHjiPYrM1xVBykc/eWbPlmB5OnTiFnw1dEXTQn3fnY8uX3dLvycj555w0c5U5MVgsTHrz3TPnT99xLYsIgUhLjKXO6GHp9b3btAWMIcou2I2t0OCrKSEpMQdYGMWhMdOnRnBNhcFWD13WAClc5obAXg9ZM4aZN3DblbiqqyjDodHS7vMt5/bn+5vtJHSdhjpFJurQXVpLQEEJCwRyVXCePrz75Ffc+PZDvvtpBn4Ed+fytz6h2lBGXkoTfGWT4qH5UOj20730pLz/yInGxMVx16/khpkcOQPNWcGDXMaZOncbUO286E3J7bN9Jmra5uKNHHDxOVMsmLHntBbyuMEElzEMvPHOm/Ln7HiExMZvUpAS0FitKSMKpAFUuAhpwu90QiWAxR6MzGNESonOvZuyrVF05zsrDFJfnE5EiaLVaQh4P6f0yKSsrIj0tjVbtz/+xb733IZJGKViijSS3T0ePGS0aNIApKun3H4x6/Kv439Xcf8UnL37KkR3HyM7uA40hPTMbWjUkOT2Jd+e+CE3hi/e+4OY7r6O4wsOyhW9y4OfDJMfEctnlndi8Zj0HftmH1ag7I9iPHjrNt5//QrO2jbnr+gcv2m7vEar5wWxMIiMjA1d18XnlmZmZJKfEc1l2d2JiYvj+i+1wHJq2g+zsdvh8PoYPH8rAq9vSI70rXq+X4uLDfLx4C6mpLdFIZtJ6JOJwlFFeXk5sbCwVJaUMHNrnAsEO8NiDE9CZjcTHpWKNikeHQsXxfB5/7fc3vOrWvwn7vtvPru/30KbzJbTp2ZqY2ARkjZHEtAT+sfRdLrFYOL3/NMNHDiE6Lo3n7nmSAz8fxlVcTpPmoLhc7PlxF0Gvix+2fkWUGY4fgY/f+woEfPXhtxdv+8rLz/AYHx9PrE1/puzovh1kZWVhMmvp0Lc9breb3b8coUM70JpgyJBOBINBBgwYQHKPVmRkticUCvHpyq3MnPk+odBJ7PZWXDu2D05nJWVlZZjNZiqKSug7sOcFgh1gyfsvozcbiYtNwUwsWsIUHljHtFem/C6PcUl2dv1wgJSYGACGjrkKW1wy4YBEQqKNdStXIysRAKY+/CBX3Xodz93zNN9//DNvvfUpp09DcxMc3XkYxefho8/fIi31Mn7+ej8/fbOzVsEOEKVXB2erKQ2LxcLdk0afKdu/42fS09MxGnW06dmaqqoqLLYounWJIjqxFb3SWxGJREhN7YrOpKP75Y3w+Xx8/MHPbNz4A5s3b6Fr5iXceNuVhMNhysvL8Xq9bFi+iiFDrrxAsAO8++oL6K0W7PYEDMSgw0ju7lU88Mrk3+WxHn8t/usdqr/8eJAEqwnFYGX16s0Y9FZSUqJpF6sKvrY9O3Br+oN88fE3WMxGaAD9MhIpyA3j9FbQbeBlbP1+G+MnXUdZ2S7KqysB+PqLnyGskJ2tRiO8seTFWvvw/WdfcvlVV3JiXzR22/nTdptZ5qV5czHHRpM9eAgV+RVnbKtRGhjQoyue4EnefyWXYUP6kp5yKS7fSS67oRuff7iNoTd05uAh0IcldJKMO+hhxB33nKn/1Ekorz6Op7qSVRtyeOWZ20lJTSW6gREdMHPJ4wQ9ASIRTZ087tt+EoOssKnYQWaaqlEd23GcjMz+NIoGGrXh0r6dee25dxkzeDCturSm4pMvyMjMxhyjo2/3yzi88xBdh3bh+IETvLloAZdf05fPl31LmaOCBx+7FYCBN/SttQ9fLvmUK68fwaEdVqoqXGeON2vTEV1+HgWlJcRsi8cen0DYq+odTVsCJ2F4difcAcjbsJ30Hp2IMZswGo3ExyVh1DXgkvZqXdpghPi4OMpL8+h73eXntb9151G8zipWbcjh1WfvIKlLGjaMyISZ/fEsAm4/EoY6eTx1GFLiTEiKmWZ21fB+xHWE9F5ZXGJpDC2h098u471XlzChV0eU4Ak2rFrN1Acep1HbBlxOd47tOUJTS3M0Rj2zZkznrSVvsGDpR1SVl/D47GfrbJ8m8M3HX3HF9QPZ/ZOBvNxyrmjXGYDWHbvjqVhCebWL0yd6UlXlpFvfdgC0quFnSFZXmrQFzbamHN4DOgkS4+JRwhJdrzjrYKkuLCUtvQcBXxXXPzjhvC5s336YqioHRRXVPHLPCBI6JBGDmQh+Hn1rCnJYhoieevyHIYT4j39QYyku+nl95gdC+IVwlwshhBBet/pXhIXYsGizEH4hhEeI1fPXCiGEWDZngRBCiAUz3hQlm0rFudi8sUTMnblAzJo6UwghREWZXy0IilqxYcFCceeom8SMh2cJoQgh3G6xYOZLQgghqnJzhQiFhRBCeCpDYu3yzUIJn399aUFYOEqEKCsQorxQiLK8oHBVXtiOx+ERBWs3XnB89NiHxaABI8Vtt9wtNqwrFEIIUSI2idvmZYub5g4Xt8wbKRZXzRUukV8rh4BYvzxPhKqEWPpmrhBCiIDnbBubFueKQLHKRVW+UwghxMKZ84QQQjw/ZabIXZkrREQIZ6VKVEF+uZgx9aUzPBbmVwshhPBe5L5+xco5c8Wch2eKFR+sEkIIEXQ4xPJ589VCf83vEBaiosglSvOdYtXKwvOuD7iFKMkPiZI8RfiqhagsiqgFESFESIhwoOY8Z0B4yy7syNjxj4u01Exx2y13i1UrNgshhCgVm8Utc/qd4XGlZ77wiMI6eXQUe4W3LCTmzVglvBXn8xh2CFG1qaZtlUbx5uNzanh8XhSsyRNepxBrV6nte9xh8fjds0RFnvpwv/nmciGEEBUFblEbls9+Scx7/HmRt7FAbaawUJSuXXfeOe4yh1i7fLMoL/aK1YvyL6gjEhAid71XRDxCeCrUYy6HEJV5PrFubakQESGKNxQIEb7gUnHTxBliUL9RYtLEyWLRgtVCCCHKf+Vxzihx0+sDxNrAB7/LY/3n3/YpELXI1f96zf2ux24AoEVT2LPlCO261QTxBuCKG1XNbM/3uxk65Eo4Dpkpvfjs1SVUVVUyoc/5S7JjY8y8tGYxmZkD+O69b0juoZqqXp31Gvc+cw8Xgz8SwRodh1WvU0P6WrRgwi3qVFhvtHLaBw0scEnbRlzZ9nL27IB2HYGTQCOIj2uoLmqqSYEAjTlx5Gz9P3+9E50mRGVlJV5vBd2uPKv57t/xM7ExBtyKFZPJhtWSyHufvUtO2VokWUNqZiIp3dNIZxAyF/cZ/Ir+16j23OvuUGcqTbQ1BQL6XK8e+/r9r+g/ciAcgWFZg/nslQ/xetz0HKGWt2rbmF2/7KNb9w7Mn1VAfHwyWz7+iWBEge6tWfbBO9zxxO0XtA3gDgYJhWWGZGUC0LhdO665R9X2adqUX778mdi4VOy2ljRoDh1/Xch0FHZVCjokR5GgbUSDGuWyWeuacJUoOOgESTlJwFfFmjVrsFo1XHPpXWfa3v7Dt9isOjTBRCxmOwOyL+eJtx6k2l8Bkob0ASkkdUkhncE04JyUCBeBr8pNu79dyj1PXAXA1m/306VvawCCoZO06dOWHd8eoGOvVnAckuMSee8x1e7eLfsyaARXDrqcj977B9dNuAaTPkx5WSk6RUfhxhy44xpCAQ9wcUdGtd8PYTOX9VU3L2vVtSutDp04U77v5z2UV3qxxsRTWeVj6I3dAThxAFav28K1N3ejqgp6ZjaHRnBJzUK1lu3gi0IHPZIT2ZGzjUDAw4GyrbTqfNak9f1XnxFj0RJyGbGY7dw4YShPvnMfVb5KkDRkDkkltaONZMYQxcXXNNTj/w7/MzZ3gHb25nyy5Ef1S3M4vvU0AGVlHmgFyNCqb0es9jj6ZQ1CHIET52z4t3njJj778VscDgeFZfms37QRAE0dFg0tEWxWI7c+du/Zg63U5ZrNO7ajQcuG3DzuCfX4UVWwH97HGYNXg2aw88fD7Cw7zenjcHQPeNzw9ce/8PJzn6A3GghptBhNem647/4zTez9ZSvDhk0i4HGTkT2Y6dMfpFPXRpQ7CohJMpExNoNe3dNJJ4uGyITY+Yc43LcT9vxwkO9za6JVouDgz2p0Syikh2Yqt7IhBrMtlsl3P3Dm3gA6dG3D91/8wDuffoTD4SC3aDOr1q6BE6DT1a4rGGQtcTYLjdpcbIUNdL2yOxsKCmjQHLZ+c3b0+7HwKB26REEUuCpP8t3X6r4vO344xeljKo/ewGkWL1tKUNaQkZnONXeogn3/tp3s+ulnpj7wPD6Xk+whI5n+1P00bgahsBdrsonsW7JJ65JKGhk0QOJU7RvbqP3826UA7Nx2HA5CTHxr9m09weFtJ/B7w3AMJEmnLnxrAgZrHKkZ2Vw99vqzi+EUuG7CNfz9tQ+577knyc3NZf3mNaQlx8EhWLtmea3t6yIS0daaFAnH1HQGtKgZ2E9Am+7tuOKabphNLdGEUH+3k1BRfZprb1YHBIMGvly3C3ECdv+sXvr1J1v529Vdefyp6eijYwhEIrTqrEZgff3xp/zyzbfMnbsYV6WDkWPH8fQsNXAgGPISnWJm0G2DSOmYTBIjiUJC1O/P859HbSr9/+WHOqYdc+duEkIIEapUxNyHF5+dH3qFEL+ZvforhRCVQgifEL7SkKgucJ0pm3X3U0IIIV6aPkd4StTjVcUesXTOBxfOPf8AHPnlZ/4PB4R4/uGlFz0vZ41DFGysEoUbXeKlR1eJ6be9KbwVQriLQuLRqXNF3kanmDVjgZg9fZbwVjtEzppVorIgX8yZ9ZR4avIDYv2a3DN15VduEnNy7hTL3HNFvlgvXKJQOEWZGDm9hxh8Z1qd07fHH14mhBCiYE2Ryl0NKvM9IlSLOcVVJC7g+Fe+nn909hkeCzaUijnTZv9JBmvaKKk+7/vDk94UQggROrePxao5aNPqUlGwwSlWzC8SC2aoZrg1C3LE4w/MEyWFAfHmvBVi4pibhLe6QpTn54oNy5aKybdNFE9NfkBsWl9wpr41hUvF3PypYpn7dZEn1gm3KBJuUSEGTEsWg29LrZPH6dOWibJNZaJk4/mkrfsgR4jAxe8xUCGECJ1/zFPiEn6HT7w0fY4IV6n3V1XqF68/Pvf3SVMuPOSr8JzXxp1jnxdCCOE+xzJZsLFKCCHE2mUFIm9dlVi3KE9sXqbaZZbPWy+mTX5JrF1VLBYvWi/mzJghXI5iUVVWLBbOfklMve028dTkB0R+ztkKl+W8KeYVPCCWu1QePaJYVIoS0W9q4u/yWP/5680y//Wae1aKhY+f/YJGbRtw73PXc3JPTUFzzsxcTx1U/zZtCyhAM2jWsRGK72w9tz3wMId+OciAYaPw+SO89fTfmf7wdLRaLSf2nODLj7f8qX61697hzP/uUkCr5ZM3fuCTd7dyaAds//kYf3/2c3r/rR16vRaTTk/2kExGTxxH8/bw/NsLuXvivazfvBFfKEhcYhqLFyym96CrWL0un2WLNuHxhbHFqdrTe1+9S75rPZJOj4QecHHThDHcdONoXOUhFFfdP+W0O4fzj+e+pNvfuqjc1Sh9bbtfQqO26v97fzk/Pr1llxqOz1FmB48ey8Gth8/weMPA25k7ey4JCQns+Ho73372B/dlETVtdGp99thJMFqt7PnxBAU5B9n5w3G2/HiYxW8uAkCv1xIb3Yqrb+3ChIevBKCgvJLhw8ahRCQqKh3cdvc03p47n2hbPFUeBXdVBAk98QmqE/ndL9+hSilF0mmRkFFOuRg/YTTjbhxJoAo0wbodqk+/cC2FeQ461WQo/RUDb+h9xpF+7ND51zRpj6q1n7WecEmnlihhmcEjx6BEGtPxkm5MmzwJu93Oz5/+xKHd1I5zLR41v2Oz9peclyZj6qMPcWAbaKXTnD4I4iS4HVUAaLUyVqOJgTdeRvog1dMa0ugZM/omrryqMyVlpYwbfRNzZr2Os9qLNySjhExYTXYSElVT5xufvYJHrlZ5lCT8RyoYN2EUk26dTMipRaPUzWM9/g9Qm9T/v/xQx8h0MZRsPKs1C/9FTxFCCBGsFsJXrnqFwjUK4ozJqgbvdQrxQY0T9k+jDges2y2Ep1wRb89R6163tlhsWKFqO0GPEIU5HrFyqaot5WzwitFDHhalhW4xZtB4IYQQilcRC1//4Dzt7O6HHxCTPxgjZq67U8zedKdIHxstUrJiRY8hSSJrVD+RMjxGeMXaOkd4IYQIn6MNCyHEhqWbRaBSCMUthOI8v6zScf7JruLziX7+gVlCCCEKc6vE6uW5IlQHJ7UiVHtRuUMId1lYPPXoojPHfnX+lReFRN5GtyjMVUlavbxCzH5qmVj+wUYxbsgtIuALipA7JObOmHdeG+MmTRR3Lx4lnt8wWcxYd4voMTpGpGXFiR5DUkTWqH4ibZRNVIrlv8vjb7H89TWidHPoohp1zubiOilY8fZy4apUxKZ1JWLBrHmirLSOB/qfgL9UiHVL88TE8TPPHAu5hBCKEKUFIbFqabHw10xw335pkygt9ImXZi4SkydNE4X5RaK6tFpMn/LUec/8xEfHizs/GClmb5wiZqy7RaSPihU9+sWL9GGpInNshkgfYxOlYuF/WqP9/8unVs39Py7Yxe8I94J1haJyvVMItxCrl5UIIYQozHUJV4kQi+Yuv+Bhdhf9/ssxZ8ZCUVniE8L3u6f+YWxaVnbBsVWLCkXOuhKxcOZS4XWoJpozfZi5SkyevFDkr68WPr8QAa8QORvV+ztveu/xiMkPTxG3PTpIpAyyi8RedpGSmSJSBicIp1gpPOJtUSXeFKViTp0PwZpFa4UrR624JMcrQn4h5j6/XPgcQqxeUBNtUROAEnIKUbT2N/fzG+EvhMqjo9h7YcE/i6AQpRsu/FE2r64UqxZvEPlrSkTRJvcZflYsyBWb1laLhQsLRcApRF5+zf3l1ZhMzolk8ZaXiamPTxE3PZApkrNjRWKPWJGSmSKSB8UJl1glvGK+qBZv/y6PrhK3KF6p/o4RrxBrVxaIDWvUwbtsk8pZWQ3P3gohNi7Oq/V2CwtVUmdMmyfK8i5C8D+LgBD+Cx9HIfxCFG4uF8ItxKZV5cJZY2G5c5yq8JTVmI+WLVefQ2d5zbvkOjtqlW7OEZNnTBXjpvQSKQPiz/CYOChauMUqUSXmCJeY/7s81n/+euH+X2+WKczbRNv+rcAIZUW5fPziV3RNa0nLTnDjvdecd+6JPdCiy+9k+zoBUkRh3aaNqvOwBsf2H+fowX++n32uvZR9NVPpgztOAmA1Roh4A9z82HXMmfMivf/W7sz59z12FXOfv5mqQIBmTSF30wHiEmtyxZ+T4mZfUEfQ5ad4k4tAlYIxGh5dkcGsZcOoohCFIBG0aDHW2b+Swlxa9lYrtlmN+MtPMXrYNehMMHTCQPWkXzc7CUOXKy89e7FAdVifi5Mqj8XlZecd3rd9P6cvnn3g99EYOl7RTG0P1dx2+hgU569DDkTo/rdObN68VuXnEFw9oSdWq5Wbb+5Khec0l3Vvwodv/YIpzqZGK11ytmqvZMVd4aYs10+gOoQtSebxlb2YuXw4VRQTIUAICZm647OXL15A5xHq7xjVHK4c0Y1EewIAl/a5FARcWsNz8/bQ9/qzG70c2HZ+XV27tuL4fsGYUSMJETnv+du9ZR//NJpA00svPLxk/sfkrtvMAfcpKitLaFUTTPbGh0/y6ZJtXFpjPhp1TSeeffYLJHNTju4/DS3P2oG0Mcm4SiuoyA8SqA6Smm1h+qoMZq8Yh4tyFDT4iaD7HR7r8dfjv164V1aqtrt7xz7EpFtu5doHB3LcefFzG7e7+PHzT4J7n7wVWYnw6n3Pse27AwCsXLEeb+W/IN2BNu3h8B5o2VE1fl52VTfKStTMeM889SAn1Kb4/sMdAEQ1hqtHXMr+XVBSmktV2YXttzE2ZkBmFtlj0xg9O4lhU5KIaMMYmsrIgB8FBQ++A64Lrj0XGjld7ccdL1Je5qBFt4a06ggNm6kboJyLX23wZxDFhWik8hhvs/PKvWcX3ljMrSkvqDvi5HcRBXu3naBhS3VDkbueuZ1g0AvAPU/cqIaVtoBX71tCdIwqeLp0bsCurSdB8uMs9VyQptluMjC4Xzb9xqUybm4y2ZOSUfRgaapBIowXBYkgZkx1dq3fgEc4dRwevP4Z3nnyIwBadYrixN7TamTKxbiqQavOFx5r0jqKDt1bkxDXmlULPjpzvH23Nuz47l/k8Te4/v5riU+yY4xpyI23jDhz/OMXviXGZuJUTURU5bZTxMfaCLpO0qz1+SGNRinCkMGjGHBLKqNnx5E60kbEEMHaREMYP0FCaImgx/xv7Xs9/jz+64X7w7PV1XEvvfkCTWt8mE1+K3yAQ7vO+XKy7jpPn4AJ916NJT4Rm90KwI33jqDdZRdP1PRncMlvBpiK6mJefuItuAQa12i/aYPPj79v3QGSk5OJjb1I+03hmptvwB5tR5b0aLRakBR8aIlg5s5bX6JfxzeZNHZenf2yJFoAeOKtBzHYrOeVac/xff389TnewKN13+vpE9AxoRUGWyw7f1JHrkYtoWOfi/xAfxJtE86P2y8ozuH9Vz5Rv9SEosemJtH0nHDwDl0aYTKZMFkujBFv0DyKMeNvxqQ1EUGLRguSEsGHBgUTg/tPo1+neQy+ou5l85XeXTRsAi8ueQKDPfqMkzQYbsD+qrPnHTtX8T7y+/cb9J/EGw7yy7dnR9p/B4+/jezMyV3PplXfnZfO2h320/3y1jSsmcm279yQ+LhYkC5Mg9C8bTMGp2dCWEbWmNBogTB40RBGz+Cu08noOJvhA6f8632vx7+E/3rh3rQFPPvQWzRsAfff+AqchC0/XqjhtuhwzpfaU3MA4HedhpOwZtMGmrWtQ9X6Z3Di/K+BkIbUhNjzjjW+hAtwxdAOXNIGjh6GfbuPXVA+YcRjhH0RKqvKqFgfZMbQWbz54EqemvYUBTvmMWx8Sp3dun5Cd56871UAZjw66zzB3eAcWdi9/zlfzjFbXQx+12lE4BTFDgexCb+12/xr+Gr1d+e3FZKwGc6Pox96Q5cLrvvbNZ1pdxGTBEBUI7j/5hcJeMJUV1eSu7SC6UOfZ9ET61g8fz552+cweHRinf3629UdeOXpJezdAbKiZUuuamu5pAO0Pkczb9rmnIsuHtp/HvRyBIvNhiL9e80ZW/LO59HtCxNjPv+1/3VB1rno0r1JrTxe0qEtT9/xDl63n6oqB6vn5fHUiNmseCGHFevfJmfHLPoNi734xfX4P8P/QFbITWz5rojNBXYCZeuxRSeQOXwsa9dsICu7H516qsJo/7bzX6668Nl7n1KQn8OA7FHM/2Axj06+E7O90/kDxB/AK4+8i8tbhTMQweMoQTLHkp5q5YmnH1JPOHSEex+dztynZhPVuu4VpAA/fLUdnaxjc84G7n3y1jPHjx47xbJVi8jLz8cddtFrsAV3aR5uq4+7x95E70ZpgExU1LBa6xZiPft3+imtTGHu1FEMGTwGa2IazmoXdz1x/Z+78Rp89t6nFBXmkZU5jJVr1/Ho5DtxBbR06fMHpFkNvv9iO7kbN1HlqiSgRHBVOrDGp6DTennrXXUw2vf1t8xZsYpX3nn1D9X549c7CAfCuNwOrr39rPnh+AnBmg0rqHY6yS3dRK8hFpzFhfhtfsYPGs7lTTOACFFRw2utW4g1HNqrwWToz91jryI5OYOYxHTcHhcT7r+m1uvqwufvf4qzupLE+AyKS0u4686b+TZ3D31H/BE7IxzeIygpKSFn3SbKXRXodBrKSkpJzcjGXe3gw09fA+CTZ18gt9rFy2+9UnMh5/klfov9O4/jrHQSCLrpO6L3meN79uyjrLoMk8nE7PlPkTk8muqiYqRkGJ4+ip5NEoFwnTzW49+G/+WskLF065PFffdnIWvCRPDTLukS7nriWjQGPSdrlNw/KtgBrpowguzBkyh3Ovnw8zdYtTGHFh3g809/qvvC0/Dyc5+wdzfcc8ezSDo9EdlCijmWL3/8DJvRTs66nDOnvzx7NrGW6DOCfUTPEbXVDEDvgZ3oekU7VbDXTOX37NuLy13J7TfcSmq/JKLjDThKyvFKRhIZzdiUWdz+6kscIPg7dx1P60tt9B9oJHtAL+6YMokBA65g0p2qYN+97c8P8ldNGIE5Op2iijJe/fszLF+3kS59mvPhu1/+7rWvvPApACvWrsYcY0NriiXZGMNXP31KRWkllSWVZ87dXFqE3XzWlDThbxMQF05uzqBn/470GdGFa8eOUO3zwL4D+yktK+Taodfgw4nJpqE0vxRPREtsaBijkmfz7GcfsAff7/TcTou2eho0P05Kajx3vPAgOp2OzEw1rcI3n+/53Xv/LYbePAKXV0+VHOKup29myfIv6DuiHd98Wfvai9NH4MQxeO7pD5ENUazdtIHY5ERCigk7Jr795QtyNhfi8XjOXOOXIlj1xjPfH5nyJD9/Xfu6hNaXNqH7wA5kZJwV7AcOHSSAwpWX9+eD1W9jidVTnFuKW5HRV6UzKmMGS7ZuZDu1OMbq8X+G/3rNfd7D87nnuSyOHZhL01ZvADvY85OTdped3ZuUo/yuCeFieOfJ17j96Xv4x7tfcM0tf+P30mH8+MUOeg3JYFD2MJJTk7GZ4/ArWjQRhfL8t/ERg8Vq4rV3avJr7z0Gbc8aN++47iGclVWEZD9mUwzp6Rnc88AN1JXO5LvvvqNPnz688eEzlJQVsmrFWnSSEUnREfB70ev1BMMhUtPtrFlR+/Zwi2ev4PoHkzm053latHuPbQc/oXPLq/8MXRfFsT1HeerRx3n5o9f48cut9LzyQlPJb/HhG18wa+4sRo4cg8FkwGqy46j2Iwe8OB2rqPTpiU+I5dW3nlYvOHQadA3ORBFd038CIX+AoOTDYrbRr98Abr2vbq153759tGnTho8+fZmV61aRn1uEFgNKUCYU9KPVagmGQ/TIjmP1B7VvD7d5WQGXX2tj964ptO+whAefvJoXn/4Eju0FnYkzyW/+JHb+sINRN01h266v/jCPT973KqWVpZiNFpJ7pGIxxpJXWEbIWYYSLKLMoyUuPpp333tZvWDvMY76/DTroi4c+1v/a8EXOfM8Dh48jBvvutBEczF88c27zFvwOuWllegkI0FfhIgSQtLIBINB0gfEsvqDon+Ki3r8Kfzvau5+TZj7r59ZI9gPAx3PF+w7d3CoYhvffPbnc1k4XBE4Ddfc+hvBXotDtme/jkx/+HmWLn6f8sJiwlIYe4yZCDKZIx9n0KDJ6HS6M+efCgXhgFpZn659KXeUMX7SSySZ41ny2TtoDFrunfwin/7jh1r72KdPH/Yc3Mu8uQtYvTwPA0aCEQmMYbRGHREN2O3RaK26WusAiElO4Ilb59DC8h5w6ALBfnrLT+z86ltOHLr49bWhabtmGKzJcAp6XtmFPVvqUKlrMHLk3xg7ZiI90nrhq3YRUoIkJ8YS0RrJGP4oo0Y9ikZz9tE85fWcEex9uvbF6/dw5wNvk2qN5+4p81HkCHfc/hxffPYzJ09fvM02bdrwy86tPDVzHnmbHOgjBvzhCJJJQdZrkHQycXE2NMa6UydbEuy8/OA8/FWTgP2qYOekujy6QVNO/vQTP3/0/R9k7ywu7d2RFQs+gCMQE5fEFx/+ziwSGDduHGmpmZQ5PVSXlOMN+ujVIxlDdCJZo6Yzftx07Cb72QsiyhnB3rfbFQS8PjIG3EmKxU6v9FsIKEHuuetFvvlq28UbrME3P37NlAdmUFroQafo8YUUJJMCWgmNBhISYpEN2jrrqMdfj/96zd0nltKMbKAFrz55A/c+/SGwE7ACPiDCzi/XcWl8ArSvPZd4bfjp+8NsWL+Sx565lev6P8RH616oU4N/8bF3iEtJYsQ1vbn6ygfJGpRFOKiglSWMWonU1FQ6JrY6u8S/KbDvBC8sWojRYGXD2uWEJD1pSQPQWDVUlm2GiBar1cott02kbc0+rkePnKRZ80bsP7af8TeNIqIJoDUYsVj1RCQZnU6HrAmjMUkYtAomk50p2bVHzChiNQ3IAMLcdd0w3vjopxoeLwX2AC5ObPNBRKFxl6F/msdXn/scR2Upr77zEM/dv4RHXq7Djn8ann7gFcZNmkj7S5vy4F1voTPpMBrMyBEFk04mISGBbv1rkpAfB5rAlk++Z2VeDnZbAuvXLAO9lVhrClqrhLu6GCJazGYzg4cNoWfP8x0oW3Zt4YFpdxLRBNCbzJgtOiKSjF6vR6NVQK9gMcrodFamDni91q77xQqaMgTw8/S9t/Dkq58Dh1DzNOwEnLDLAoYQtOz2p3lc8u6PVJQV8eTLd7B/K7SuQ4E/ehimT32C4eNG0bd/F557+h+EIyHMJiuEQxg0kJgQQ7eBXQEQO44Q1bE5n7z6DzaWFEAwgttThT4mhYToRPxKNV6vA1nSExMdTXxSIiNGnJ8T/9NvPmXW3KnodLoLeNTpQaMLYTLrAAPTBr/9p++/Hn8atWru//XCXYjVQDoffzucjaVeMESw6yz0i8nmMmsGtM3i+x9vI1Ki0OfWv//ptg/sg+zMK9m+5+J24i0/7KVbeltoAN9/uxOd3sSalcuprHRyy52Ps3HdSix66JXWA4PBSLu0FhcMDk/c/gxBrQZrbDwhT4i09FQ2b8zB46/E7XZis0bj8zvRyFoyMnsx/qbr8Ssn2Zy3lhlzHiU6xoTZbCA6xkJQ9iPp/Rj0VoxmA3q9hrA2QjgYYEryolrvU+UxiYdeTsQv2/BrAqRFJ3BT+kT01RINuw1hz77ZKEUScQOeJOp3Io5+i1074O15r/LyW/detPyHr7bTe6C6SOvzT38iEFQgHCQSkbl+Ql+efORDLHpIT00jObkjDaO5IGb8lUfeoDoYwBobT9AdZNCQAeRuzqO4LBe320mczY7XV42EzOAhg7j2etXH8cX3n/PwzCnYY83ExERjNOnxSh50hhBmkw2j2YBWK6FoIoRCv8fjSiCRF94ZS1U4iF/y08uWzB1DZ3Doq1xaDBzPtu2TiQ1mU6W/kY4da63q4jgFP+cepHufi4flHjsATVuBOAWrV/9IhaMarSQzaNAg2ndqzDOP/B2jTiE9NZ3uf+t00Tref+Vjih0O4uLSCPj9DBicTV5OPgXFG6isrCQ5IRGv10kkEmHibbfQ5wo15fM/vvqYp156mLh4K3a7DZ1eg1/jQ9b6sVpiMVmMaHQRwkQIBv1MTfngT958Pf4J/GvCPSoqqhJVDz0NKEKItKioKBPwMWAHKoHRQogjUVFRUcCrwGAgCNwkhKjdGMzvCfd1wEC++uFpEnpp2eDMQ5L1REI+dGG4LjwZOpkAHdCRU8eg4T9h9nzlofeRjTL3PHLDecd/+fk4XbufXTJ67Ag0rQkGeeGe99EkpoKzlPueOX+PzN/imyXfkVNUQEVFBSkZ6RTl5+DxBpE0oDcZcVU7SErswZS7x+P2uujduzfPPPsgy9d+QNgXRgnLRDRarGYzkXAIl8uLoihEIhH0BhM6m0Lx+qpa21d/ghD7jzrwhEspCBajM5kJuL2YkRihfRhaS4AZaMdrL37FPQ8O/NM8Du19M6PHjeSGO4ae0bh/y9tvvz93/4f0G38DhWs+5Y7H6nY6f/3ht1R53RQU5JGQlkZ5SSEVDieyRiEuPpGiskKS49OYOvkm3F4XyakpzHlpOktXL0TxK0QUDWFJRq+VMRmMVFaqQgzAYDSijYlQtK6yDh5L+WnHfHp0TCBvVxklcjlas4WQ04NVq2Wo/AC0TgBK+eFLMyUVVdx+zxW11vdbfPGPnfztmku59epHGHfTWPoM7czun6F9d/j+x6Nc3lN1Lp08Dn7fCYymxjSsCcS67+ZXeOX9+3jvxS+Y8ODf6mzn07c+RWeOYd36lUTHx1PpKKWstBKdXiIzK5uS0kKMhmjunjQWhQh6vczipfNZvGoBIY+MJEUIIaHTSERbrJSX13AWCWG22sASorgOHuvxb8O/RbinCSE85xybDXiFEM9HRUU9DDQXQjwUFRU1GLgHVbhfBrwqhLjsYvWeU9fvaO5Due/mG7Ak2HnkoWf4gbvQ4CNMhJJfPNze9XEu/1sW33/xJnAHJ4+DywVt25+t5/uvd3J5/4sH7t5/zysMHpTNFX/rzMG90PJ31o7sOwi3TbydtSvfwROAFn808u8Y3DPxIZyKj1BEIdZiwuPz4/EGmTXjATYXbWTM2LEosoLcxMuib55H0gbQaDTk5pXTIyaeBbNXEHEbCCoRwpgwasJY7EYUSaFgfUWtTQuRB1zGPTdch2TW8+ork/mB19EQIEyYop9d3NV9Oq+9N417JtzGsV13gFnNdR8MgB5o2BIO7DlNq3YXt1t9+dk2zAYt3ft24KP3t3DdzRc3S+zeJWjfIYoduwVTp0ziy8/f+YMEqtsONpTgibufwxnyUlblQI+CwWRGiWiYNnUipdXFZGZl0aFVO7Yd+YbVhQuJyD50Oh25eeUkm20semkNku8sjwY5hDXW9Ad4dADtGHrNtQR9DmZ+PYAQTgwohPBTtNXPXdYsDuo0BHUBNEUzUCwNMOkhZ/M2Ygw2Ovf9jff/BJy718qp41BSuIfomHbk5O7g6usvrv7/suUoXbs145cf97Ny/VqeOSd89vfw3ddbiDbYWL1yBc6Ql/zCAjzOShKSkjGZY7jlpiwCQEJiMrZLWrJp94fkONaiSF4kjYGS4gpitSaWztuI7DcSJoISMaHXBDDFGJG0Evnryv9wf+rxT+MvEe47gSwhxIGoqKhWwCYhxKVRUVHv1Pz/0W/Pq6P+WjsxbVEyL9w4Hbia1z7uwD3XzgU8/MBGopHQYGPVtjyqczfx3O3TeOIOBV84hMliY0B2EqsWLyM+LZtbb7mOA67aBdMLD77IQzMfZG8ltD1nDOjQvC8lVd9SUfALnfp2/V2uLo6jnMZJA6yIQy4kSzo33XYnis9DWnoa1lgLPmMFQZx4/T6MJjN6KUh10Isie9FoNEiKnpAsY9FJ6HURIuEQIUcQvzPCmpVFRNDXKZQeXdiLmTdPJoqRvLIklvuuf5PPvpyP5UojMeiRsLBmRwEal5Ob+47kiVvDuBU/JlM0A7ISWbdqNelZI8kekEVxSRW9r7j4QPnkXU/z9BtPAnBgD7SqCdW+ecSTvP/p02z75ic6X1HnWF8HDgAhwMIn78zltocX8PjMWZTk5ZDaIxVrrAWvoQy/Uk1ICRMMhYk2yrjCfiIaH7IsIyl6wpJMjFmHVo7g97nQeGSqSr1sWl9BWNFSuMFRaw9mLxvJ5GuH0IjRvPj3OB68cQEffjSH+OuiicFAhGgKDxYSb7TRsVEMT9wawBXxo5V1pCZZKMhzMHrsGMxmM76AQow5lrZdzg+XOn0CHp/8GM+9q6Z12Lvz7DP5+cfbGXptJ3745At6X123dl479qHGUhi5pncaHimRW26bSGlRPvY4u8qjpgS3UgmyhM/vJ9ok4w4HQetHgxbQElEkLDF69DK4nA6isbJmfgGVrgBhRa6Tx3r82/AvC/c9qJHXAnhHCDE/KirKJ4Qw1pRHAUeEEMaoqKg1wPNCiJyasm+Ah4QQBb+p8zbgtpqvtXqe1uZOhGCESsXFHQMf5aufl5HYPY02GNnBJgJ4iCWLlTtWMrJjBnk/5ePOsTFoyABc1U6KCqqwxRjplZqCwxekkyWWg349kjGaFtEN61zN+vmSzxl6vepc3HcI2pyzePP4CVi27Huysy+nbZtaKrgIjhyD9bnvYtDEImlklq2Yj6QLoNHr8EbKsNjNWMzReBU/er0Ok15BlrXodBoikQhajRHFGMFoMOB2BQiFQuj0CmbZwEjzS7W2u2bTROQI+AwBru02mq9+3kx690wMBCmhgCBuYsli094NZLaNY/UnOSRJY4hLjmft6lVo5Wgiio+MtFSqfCF62OLxRqLxo6ND1xYcPwpNmsGxo9D0N4rp1u+30uVy1TN44CC0OsecfOIkrF2/ndTkTrT7E6vtf/7lIJWeNRi1Cbi9LjblrFYFj16Hh3Is0WasMdF4gl70eh1GXRiNRneGR41sIGKRMGoNuFw+wuEwOr2CIaJlTHTtjul1GyeBBnr0NtMcG99urSC9SyYy1ZRSSggPcQym8OhmbM0k1v29mAG2uzHFmJn51HSGjxyL1+nCYtBjtCVi0+hont6frXl76dL7LAGf/uNHhl/T8zy3w77t+zCa2tD0IouBT54ClwdMBmja5MLyi+HoCSgs2I1PycFiSKawOI9yRwEhvPjCVchmGZPFiCXaii/sP4dHDXq9HkVR0Gh0RMwa9LIOt9tPWPFhMOjQBmGcvd6h+n+AWoX7H91DNUMIsT8qKsoCfB0VFXVeKkAhhKhL+74YhBDzgflQt+buqXLjUKoYMGQ4EGFg93ge+3IWejmNtEQzxcVuVlQvx5SgMO+zD8jokUS5XEr+nE3oEmzclDKABa+voLqqDL8/QCA1jvjYDDavX8eQIaMIRzQ0buMDLpTQQ68fyuU9r2HwoJHExSfS5rqzoQtNGsOEmy+/4Jq/v/M1BMPceN/FtarmTSEpeTRxrTS8/t5LWGKCyCaZSCRERDHTw5pBcVku1pg4CtcWYzSFwGTFZNaCXiHGosGgRPAFwWzUEQqBIulAG6mTb3e1G4/OQ7/0IUAMA7vbeO6b54kocaQk6KiqDLKmcjVYnJQVFRKfYGfZyqWE13mRoi1MH57OnOdzCAVduN0+Ij2SSErIpKrMg0WXQbMYVTA1bYaqApwjlRJTuvDcM++zds1GZr80l1Ytzy6LbNwI+qV3ovlv0sEsee9bdMiMmHAhxwDdu7bEfHgcWq2HxUvXgaYCS6wVCCFhYUDiAFatX0psfArFm0vP8Gi26ECvYNIqWCIa/HqwmvUEg0HQGNBqlDp5dLlcBIwhjKfTuKxBEn27RHj5uzmEQlaS4jR43AprqufjU6qJjzZhTjby+vLXUXw+sBlJi9OzYLMbTUIQR64Dvz0ak7eaQNjAqV1GGlqbQVMYcU1POHYamp6dabq8EjoTdOowkJzcr87jrFFDsJhUPn/Fgd2Ql/stFmM0YSVA3xHn61DNGkPfy9tzgvY49m0jFKnGHyomJtGGQbER0YUZljKYVRtXojfH4Mh1YjD6CepkYmJikAxhjBoFC1oCegmLxUAwrEGW9BiM4Tp5rMdfjz8dLRMVFfUUEABu5f/ALPPonGzG3DeAzsQBBt74cQFJqXr6NBrFAYrYtC+X9atX4y+XSemVRmWFn2hzApXF5WROsTK8w0gMGGmEHdVZ6OW5+9/mkZfnAXpO764kjJdVKzcQjBgxxiRy9fWX8/WS7+h/fR9+2bmFrpd2A74Hzgqao0egWXPYsmU/3bqpscMvP/0FGCS0RJA1Orw+J488dmFI4Dv/eBaXtxqjxUpCkolIWMbvqqTMlY+kh9j4OEJIRCJhFCR8VR70OgtvzlqMv1KDrOhAHyKi9fP8m0+h4CIUIzHJWnsI3/MLhzHk5kw6EQdoeH/LcuJSDVweNYQ95FJwsIiFr69C9kJSeiqe6jBWUzzOskqypkYzvM1ImpKO6iPXAQrP3T+HR15+HzgKB2VOBCpYtXIdks6GbIzh6usv59juk+itjQg0OUxTLgF+QnXFnI+tWw/SpYuq0r/7yvf4In41aaxGi9NVxTPP3nwRHp/GFh9DmcNBXLwJq9lGdXkxZa5CNHoFrcWERqsHFIJhhbAniEYyMHfGYnW3oIiRiM6PpA8yZ8EsfIEKFLumTh7fXj2OzKGpdCQJCPL3X1aS0NXCZWSznU2UHipn2ayVmExGTDY7PheY9LG4K11kT7UwptXdRJEIeGtq1PPgzXfz4vufAz/Asd4I/04WzF+M1Z5GAD1ZWVm0sjbgtHLuGqltgLos+9RJaFgj1A8cELRqpY6sH737Cz4lhBz2E5QkXNWVPPfC+Xb5g6cPsXrV20h6CW8wiN2mI6tbNht+WEqVy4HOCIpei05nQJbB7fWhk40ovjBznlpM2KVHL5uI6PxojEHmffAS1c5iiNNxm6XuZHb1+LfgnzfLREVFNQEkIcSxmv+/BmYAVwCHz3GomoQQ06Kiov4G3M1Zh+o8IUSP32mj1k5Uipdoix7I5iumk8loGmNhLysxYGDWkqUYZLAYrJQ7PBjNBp64di7f7nmbh2cvJOetOeScqqRvw4c5eWQNjZqnA05gIE/cczsaSSYjOY607GzWrF/BdbdOQw3x2AO0Y8eWH+nYTQ0FO3lK1ZDOhTgOK9d8y9XX9uXVV79jwPA+KD7YtPFbiktymP/eE+dNrd/75n4mXPEyT/59KNrYCBpZjxIJEgpG8LjDaOQI6RmpSCEfeo2eHm2yKKAADRoSSaESB/7DLqSwnonDZ6CXrWjQENGFKdxQe7RMtXiJ1hiBAfzILNIZhoKWatagw8BLf1+MxaiHkAaPO4gtwc5d/R/lva+nM2v+Bor+MZtNR8oY2vxxtn3/Jp0vvwWogkMannl+FTKQZDMzdPx4vtywnCuvebCm5f1Aa15++mnuf1K1xW/bLujcSWXl5HFo1ASOHTzOxpxirrq6J2+88QPZw3rjqYTcTV+QW7CeTz87P6/MO9/cx5grprP46yn4ZA96vZFQ2E8oGEGrMRMKBUhItBP2uTAbzPRqm00hhWiRiSOVgtO56IMSPmeEKePmYNBakCMyijZE0cbqWnl0i7m0wASksJ0VdKIXp5CpYg0Seua8s4hqfzXJpmT8PoXsYf34W4eRPPne3cxdXMrRb9fy/q7XubnDLL5cMosrr38UcPLCfXPwBa1YLTEY5DA3T53KlxuXcuVVD6LmUFAfvDdeeJm7HlI3Uj9xDBrXCPtTJ6BhYzh+6BhrNxUR9mtBq6NXj06UlB6hKH89K9cs55etn5xzN6d4//vH8ZQZ0MaV4VXcmM1W/AEPRDQkJvSgqrocs9lM0FON2WQhs10/yigGJOJIJe/YRqxaA2WFbmZMXoRGNqNDJqwJUrypPgXB/wH+JeEeC3xa81UGlgohno2KiroEWA7YUBOLjhZCeGvs768Dg1DVvJt/a2+/SBt1RMvMBTIALe9umUKvbsnoDvpo13IqsI6TmFn443L8lU5MsSHy8kK8d+8HbKeE9U8WY50Y5ro2t6AK9HRU88uHQIS33l3BHbc+DGiA7sB+Xn7sJUoqHGRkjUWj0ZGZ0Y+2cU1qXdh07MAhmrYy8f3X5eQWlOD3+7FarbicDpxV1bz/0QscO36a3Op5hGSJsM7Lhtk5DJmciSk6muLyDei1BkKhECECSOjQynZMpgjalgpWrHgJcAWxQDIncdAIG6qbYjc/ihUkRsWRce04SpaHauVYiNdreJRYsms6sbEmTE6FS9vcCZRwCg0vfbmAiMtHfKaeSofMg/1nsIsSNjxXRvYjCXQgA9WhaQI61PBo5sOPFnHDdZNQZ0adgS289vRyisrKycq+BbvdTlpqZxr/JqroxAE1DfIvP+3CYpSwxEajBBqzYfN2ioqKMJvNVFeV4ap28d6S5zh+4hRF3kW4An4wBlgxYw13z7oJt9+Hy1eIXmsiFAoRlIPIig6NFIPJFMHQSsKMGTc+srHRgB41z4MB6A3s5mdWE0cMyf1HU72hVhoRYkENjxE+3jODaLOEXbHSpvkAwMUpYOl3G6mqKCR7QhJ20mhFBnspYvNbVdxwRyKQWtN2CGgPfAKksGf3Mtq17wXEAB0QR77j7TfXU1RWQWa/8eoCuS4XMbifBhrAFx9/Q3Z2CkEUml/Sku+/209paSkAFeUFVDmcfPzZaxw5dhRHeDUl/lz0Oiurn1/LbTNuorzSQTBSgUFnJhwJEJQjSAEDEnqsZg3G1hqMGPEfriTzkhSiSAXcqO9PL8DBLjZhwkRinzG4N9fOYz3+bfhfXsS0GUgG8vjVRXCMNfRqP5dtux3ARvaddLFwxUskp8QyotNqwMMeSpj9ymo8BQ7+seRtVGG4DfVhvALYAsRzw3XDqHL4CPtCGK1G4uIT8Xld6AwJJNsSyB45Eh0a2vzeDk/Aj1/9yPTp0wlrAkiynrKSct7eMB1LvB9XmYbXZ85l7Jh+2JLTqNbnYzRYCPsC+MJquKNBq0Nj1COHQdaEUWQdMVFmYtAQQMKKAZkAUZiBC2366rhaG485QBywBohHHXdz6dt9Bt/+nMN+VmLEzpwPZ5CWlciVbd4EQuyjlLnvbKR8fQGffzIH6A/sQF0d3LOGx1iuvWoYVVVe5BAYrRaSUpJxVjswmFJItsUxfPx4CCq0uLSORDo12PnzTqZMmUJYEyAQDJOanM6wh3ugM1fjdeh5febrjB2TiTbGSiimEqPehl6WqHRXI8u/rpY0oYmE0TaGEBqiMRGDhhAazOhq9GAJuDCuvm4ec4EYTrKKRvRCNa8UMGLg68z/ah6FBxbSq1Uac//+NpnD0ujTfDbgZT8OZr+xgdAGF+98Ogm4GlUncqM+3yWAnqH9x1Ll8mGKGDFYjSSlJFNVWUG0IYWUlBTG3HI1fh80+wNO/L3b9jJy/BCMRiM+f5Dpjz6FsVcASe+isijM+qXLSEmLxZiUANHVGHR2LAYtZVUV6GUNsl6HTm9BKwXQNNShIGHFiBW5hkeZRsApJBpy7W9aP01U1B916dXjX8D/snAvBaJ5Zm866VVx9L/8TsCIum4qhq8PzsemNbJgzWJmXj+ORjzAEXJojpWTaLG1HoK9l4Wf/vEBkIg6QDhR0xeE2MdM2jAGMHKCchoTB+g5Sg7LvlqHSTJxTX81RerxI9Dkd2Lat/9ylE5dm/HMc08zbHgKYa2LiClIld+LoY2WzS/nkzQkhspCDfkbNzJq2gAMBg0+JYTOqMGk1aOVzChRXiIomNCjRYeMlnZkAcWABVW4lgEDgI6/8lhrv4QoBuJ5+WAGvZxx9Ox6E2r0uhMw8s2hxSSaY1i2fg33DRwE3MRWVtOFVPae9JNmv4UFm+Zx1aXpqBpnfM21FiDIURbQjEwEGsJ4anwcRo6wgRVfb8IimbnqihfrJu8c7Np+AkkvsWzZbPpl2/FJ1ZhiZVyhELqWMpteLsCWYcDrMOIoLib7th6YTDrcQT86o4RJa0QfFUOQKiJE0KPBiAkZLW0ZxGk20YA4VOFcAmQDnf4gj3F8eXwq0dVhulw6GnWQ8AJWvjvyAcnNY1jx3UZu7dMPGMU3LOUKBvHWJ8uYftsiDh0+gbrCqxhVsLtreHQCOUASgggKXhpiA4zsPLmanJwCLJKVoX2fPb9TJ6k16mvv/tPk5eXh8RRisQYIGtzEJpkJyDI0D7Lp6RKsvTSU5PgxGzSkjo4n2mKmyu9Bp6eGRxsBKpGJICGhx4IRHW0YxAnW0JgU1OexEBiHmoqhbh7r8W/Dvxwt8x+EAQgjlyZy97QczJo1ZMYN4rmPbwOCWPRwaZM4YhONeFBojURzogEFn3BjjtHhLg2iCiQdqn3FCFQBHWnDK3yy9yqubjua7MsWoDco2Mx2tDqocruwyhKm4BYsdiNxVnVV1PGdJ2hy6cXzs3fq2oz+V07A4y/Aq5RhirNh8lSScEsG1XvKUSQzIUnGmqowcchICjeWUbiuks25eazd+DZKkxAyYXRY8OMhiIIWGYkIh8nnEuAEBTRmEKpFrCMXrIK5KKIBF6ECO5OeykcbXEasPp6Pfnqc/eRi0iq0ijLjC5VziH60IEIXsgAfy5Z+gMWmZ+rYx7lqy0JU81bjGh6LgMtpxmOc4B0ao2NIn5VoNV4sphjMFj0V1S7MQL9EkPSCiD+Kpq3hxK7TNO5wcXtXh06NuWLgzbh9+QS0vbDERmMpcWIdmUjlTgc6YzQmmwmLPULykExy15ZQstHJ2vW5FJZ+gC/KSwg3BqwE8BJBghoej7KJZsAxNtOUQaiCtRPnLamtFTGAi8I8Bw8/XIk2tJBEQxLv/zCVj7c9T0KsleZE4wuVcZwsmgBXMApwMv/ttzHGWujQvS27fp6POqA0QB1kc1AH6g7Ap0QBI/suB9mN2WhBZ4ng9YSwSBp62E5isjbC54IWNfue1oa2rRtw5weLqXbnMHx8JtHaaAL5fqRMI97tXmKSE4lN1RGd4EFn0LNpVSGlm1zkFxeQW7AYV5SLME4MWAjhR4OERASJMMfYSFO0HGEDzRlQ0/8WnE2qVI//JP4HNPcgUMEnP61k9lPzMEZr+eq9yRygEhOpNCIJVYM1oWoPSYAC+GneZgB2WyrhoI/tv+xGDdX/VfU+/wF85vvOPHH5bPr2fRSDHINWq0Vv0BL0hzCZDAweMprBgwYS8J2kqanR78qAI0dAq4NePTqRmZ1KfGIsZm0C115/HW+9+hH563N4f8UbfFn+HvYuTvK2luMoDOOuVNiwdh3xGTFMf2UiBkCDjA4zJrQ0xoyqKaZz9q0WQDVRUbZa+6PyWMALS+azdsVaguEAP38xjYN4MZNOAwKAloOU05IxqFqkGfDQot0wYqITCQX87Ni6h/MHkwOcu3v299zL5WRyWfenMOtjMBqNhJUgUkTGbo9h3PhJWC0x6DRamugb/m6q5oMHoWVL6Na1M4OGZRCXYCfakEyvtCw+WLoSr8PNE8/fxxeOV4np7CHnx1KcpRoCbg3r16wme1w6N90xCC1hZCQMWDGioTE21AG/z7ksAVG/o7kHAQfPfvgweeuKKC2vZvfPsziCh+aksZultGcwHx1ZzHXNF6E+m2bAT6sOozAbrITDYXZuK6g5/mtbO/h1BganOcx8LsHIlX0XQETGbDHi8Xgw6IzY42xMnfI4oaCCTqOlRUyzi4/tZ/2wHDgErVpA757dyR6cTlJKAkkxGciSnnUbcqkqreKp2Y+RF3gDQ1sn3gNWctblEfLqWL16JeMmD2L41elIKEhoMGPGgEwjrKjvW58Lmq/X3P9P8L9slvECPoZem05arxQmj8+geXMrkICqNarOLfCgCvgAqpYapG2nbEIe0Gq1uCJOTu5bg2qr3of6YoX5Vbr8dOweEpum0hQ7V/R/HGskBkUnYTVbcHu99EjrhTXazHUTruHgvqO0bPPHE8h//80enK4KSgtK0ZujCYUCZGT2YMHSR9HHSmhMYaxWK1arFb1Ji1arxefxk5aWRVippGvDCWznXcyYaUkq4OfXMLjf8FhrH4QoAVwMHDGKrOwspt6VSiNiUM0rBahapAI4ULXTAKpGW0rbTpMIuiV0Og2mVIlfPv0A6FvDoxHQ8qsUOcIbNCcF8NJ/4GxMIQsRvYzFZCYYDpOa0osYm5kR1w9l3+5DtGl/4X6nteGzf2zF43VQVVaF0WrD7/fSIz2FuYsmY0+zIuuD2Gw2LBYLlhgTkUgEr9tHr+6D8Z8soVujW9nFR9iw0ohE1GfmwuRadfO4icNsoF+3lxgyOpNnH0oHYlFTLOXX8KgFKuCM2cfISVYT3+klAi4ZvV7m0UWTuL1vFmp47QFU7R1+VThO8Hca14RMDhw4GzmsQ6vVYjIYUYiQ3qMf9vgYBg7tw9YfdtKldy174l0ES97/AbenAkeFC5stlnA4SFqPRN5c+gCWRBOyPojVYsdmtxBtV/fe9Xn8ZHceRdWpHLo2HMZeNtMWO+q75v3TPNbj34b/ZeHu5P6vBiM7bEwclkiH1ncDmzmCg+aYUF+scM2nF6r9NBrw06HjGILBIOEg+L0+Aqc30RA9qjlDCzTmtTf6c89dX9e09j6QBTjYtauYDh3Gct3QxzHqdYQjPkKShtFDxhAdE8JkSWPd+o3cded1dW62AfDFRz/i8VTgDSoYg2Fufvp2Pv76VRStD51eg8UcTal7IyEkXK5KNFortugY7LZEwuEgkiThC/uRlQiSpKCENYTCfiQpgl6vRwJMJgO95No3dxZC4br3o8mKHsu4ATaaRN0JLGUXxXQgq4YTD6ovYxCc2ZGohPaXTiMcDhP0K2g0EgUH5tOaDFSrnroU/dCRRbRorsain+YdGpAGePjl51y6dn+aG6++F4NGIYyCP6Lw6JTHKSpZTmbWRBYvXc7UKXfQ+HfGy68++wVXVQkubxhLRGHATaNYW/gmkiGIVqvFFmunqHItYUnG46lGks3E2uzEx6UQDPoB8IX9SGEFRQmikdXwSVAwGAzISgRLKwtpUZPq4FFw/bttmDZgGl3aaoBbgJVsZz2dmIY68GpQAwDOXReQQ7sOswgFg4RDEjqDTN6e+bRmMOoDdKrmWiNnQ7Perfldgmz/JZdO5uFMmLKMiOJB1hrwKUE+ePtDHph+M1Mnz2ThomXMnHH/72b0/P7rnVSU5uEPhNAGwhgSo/HqitAbI0SAxOQkipx5BENe3O4qZMmM3W4nIT6VQMBHkBDBYBAprAARNBotoVCQUCiANcZCxB8koU0S8VFj6+5IPf4d+F8W7oJ7378Mi9fMY/fPRNUS4oFNwA3AElStZzDgQtWYUoE8OnS5EyUQJBgMovg0HD5RgMBPFJ1RvVAyUMqvWvD34hmSo6w0w4Y6G+jF1V2t6GJHE6OzY4rVsnbFCkbdOZWS0iIS7HGEQx58QZnJtz1Ey3O3vDwOR4OneXzaUxRVlNAraxgpZhNhOURZ/CLstiTc/nwS7T0IGiuIKBImrQYlSkKLFokIEEGPCR8+tMjkbyshvXMcEjHoMKJFpvpENVXuarRSDDfZ5tbKsRCCu97tRoo2mVtveABVQ08ENgM3o0a7SkA/oLrm0wMooH3niRAKEwgECHtljpzcyEFctGQgqlCSECwmihsB+PbEE/RqHFfjVHWzDzPTB07CYBuALmyh1LmBoDvEmMnTKCzKx2IwoZUjaI1Wxo++meatz+n4SdhZvp+XZs2ltKqcAUPGkqjT4Ze8VCYsxmZPxRsqIs6aRNDoUPOdNNYRRkaDhAxEUNBhJEAAPTI524rp1TmeCFZMmJGQqDpeRbXbhUaycou99sU3QgS5991+JBHh1lsXozoRY1F9OFcD36EOkhk1fyP8mji1fedhKIEg4XCYkEfiyMm1/EIpXbkZNZ4xxG6epz3qTl7beJnOxKAKfCfvfF5B0Qe5eIM6ku3ZrFw/G5slmeE33UJBSREmjRadViY6LonRw66i0bnO/1OwvWQvs2fOocrrZMiw8aRaoilzFVKdtIzUlH5U+jYTG52KX1OKNiyj0UpIDfXn8ajFgB8FE1B+yIO9hY4IFqKxogClRxz4fD40krlOHuvxb8P/7k5McJhwuYnxd/dCFcQK6ov0a2reTFShHkDVkiyoWnwGALIso9Vq0ZglvtqxDs8ZjdSHqiEFUG2tcHnUEzQjGZWWEId5k09+8dErzYTeVE044GVj8RbKy0qwm+KIscWTkNqL1WvnM2rsFdxz+8vs2HoCgO/Xf8eK5WvIGjCEJKuZmaOHUKLPxRG7jMEZN4FfS7J9CP1ajMPeMBOLNgZCcYxgMjJxaLAjY0OHnWhSiCGLMZ3HoceEBQtGZEKEiG0cy7C2w8luk/g7PO7GnS8x6oYUVHu6OrtRBTuoAkip4SWEKvjDQA8kSUKWZTQaDRqzxGm06Pl1T9Mw0KBm1eUuAPo2fqZGsAeBIBIbef+rnehlL3FJQUYNn8jC1bkUFxVg1USTlNyD2MQkFn4wi+GjBnLfXa+yc9tJOAnfrPqavNwiBg0bRZo9hifHj6LMXEBV3Cru7D+bsAdS44ZwdYtZxDTshUUbQ+BINFcxEROpaIjFQAI67FhJJpp+jO08Fj0mzJjRIREmRHyTeIa3G86Atkm/w2MFFeu9jLx1DKrwTkCNvPp1Z6sgv/oqzpq2gqjaPEiShCRJaIwy0IMketVcJwE62jOMI7wBQGfuB/TsqQmTzBzq561/fItODjJolJEHpr7N1OdfJ7+sEotsJTYhFbM9hrmvP0xWdl8euf8dfvjpAByCL5Z+TnFROcNGjSXVFsP9tw2lOjYXV9Jqnhq4iJLCSlLswxjR9Dmscg8M+hjCfjtXMRodiWiIJZo0DMQRTRJmMshukYUOI2bMyERQCJPcPJ6R7QaT3fb3nsd6/NX4H4iWqcblrsbUSI8qcHyomvpBVOHUAVVQ/bqYQoMaYePD5/NhNBoJhoJEwhE2blyPuaOGFsSjalSgakU+fmQpPbnrzPU/sJTeDAccxMVLOOQYqtx6cjZtY/jwiQSDTrRaH2tXrMFZ7cOjKyEgO8ifOh9txIbNGk1YgbunTMYYr2dG3mRiTGZ81TLhyiBypY6khCSaY8Cz30NYq0EOhvjRVIYS1hIIhUlulUGICIFTAQK4keQgSlQSBjR4cKvmGKxosVD3JnsAYXR6CR0yqm8CVKGzDVWwd605Hqz5q6AKptX4/X4MBgOhYAQicNuzE5n42Dh6YkUdKLrWnG/l112JDlJNS+L56tQHDGx4E/A5z741m7eeW0h+UTEp6VmMGjUJr9fNVSO6c8/Nt9bwWIxfLidv6tsqjyYLWqOJwcOGoLVJPLZmLDFmC55KifJdJcTLiaQ0jmPb4XV4g14UnQZNCH7SOvCGFWRJS3TTJEIoBE8FqY64kDUh/FF2YjHgxo0WGRNWNJjRUHduGVCIS7ZiwFDzDMUCa1Ht692AK2vO21fznCpAa7btn04wGESWZZSIBJEIIx5L5tFnp9AdPSeppBHqRtTNGXmmtd04aU86H+6Zww3tJrJ39yu8/9m3vPrks+SWbmZ2dhbDhowj6Pcx4qpOjOh/Jc5qdQONdfnPs754BoZIEnazFY3BSEZWJrI1yEOLrkZn0aH16Vj/0yp6mTNIb5TIZz+/RtjiR6eNRqN4+emEh6AiodMY0DSKQyFM8KSXAH40jUIEicOADjcuDOgwE4sGPTrqc8v8p/E/INzL6DVKh09U0yTKjSrc84FJqI7ADnzHPPrwJurLZgYiHGI6OlmHElTQaWTCEQW/HCGVND4+uIBrW45GjZ7pCOzHfagYWpxEFVTQmzD3fTqcV0YU0v/q2zi2v5i8fJkeWZ3J7nUl3//0Jc889yxLV60AOUJMtIXpU+9kxqxZhOUKCpx+pKCfSVPGgixjkGSCigaNRkfumjW4fJUsXbCecDhMmBBarRZJrwXy0WgjyBEZjbIGg8GGLMs4qvIgEmDAqAE8MmEmoHAYJxpCBAji+52f8hvmkTpEgx8nLfCgatwBIK2Gx778wCR6s6DmuBoF8dmOl9BKWkL+EFpZQolE0FosJJFcw+Nk1MijnsB2Pjv0Jle1mEtL1Jw6AxveyYQl2bx3/TrAyKiRMRg3y3Tu1oa+vYfy7Q+f8+QzT7Nu83qQI9ht0UybcgszZs1C0laQ5/QjObzkFq8HSYsOhZBUiV5rIH/dKly+SgxaA4qiECakzjCMeiKRPCQ5jFbSolOWozPEIEkSFZW5aDVw0+RxXNl/DJfi4ih+JAIE8COfcWxeHK9sfYDEQToanpkprkFVECKoJpk+HOItWjCSs+G3x8mtyEeOyKCE1XhxjYzBaCGWWH5iA5dxI2oUUndgK58fms3QFjNpj5oL5oZ28Nr2qWR3GgecYMwYK9H5ibTt0Iwx40by40/f8OTTz1LiKCUiKcTa7UyeNI6nZr6EYnSQU+VDCqk8SrIObSSMImuxWuzkrN6IJ1CNXqMnEokQJgQ6DTqdDkU5y6M+EkKrjyaCj6rqcgx6DTdNHscVlz8MFHOcCAoRQvjQ/AF1ox5/Lf7rhfuLP72Ozm6idVQKe9hAO+yoU2ENquYOfbgJ1fHkQhVUV7DwswXEZadTurocg1FHUBPEpA0SRSzDWg5DfSElVJuxBUsLPWfpOAjE88qI54EAH//8PNd2fx2TdR1vv7SENau/5I47niA/dw0GoxmFMF5fiKnT5qDVGolIEPF7QZJQwkGUiAZ/2KdqvwFwV5cBEXwaCUnSEN/DjsGooI3WIesieN0uzBYbq1/Px2gKYI/XMOqBYax8czObNrnIz7kTWWtEbwCTyYSs1RCorntjhLJfqtDajLQgk+9YSB/SUGdCCqqQglgyULV1GcgF0gkG/UT3MlO+1oHJbMAbCRB0VdCUBIa11KP6QPSoPox4zEYNZz3MPwAW3rt+JqDh79+O48a+nxJY/xgfvvslSxev5K67nmHN6rcJK2A0GnG5/Ux7dB4ajYlwRCISciPJMsFAAEUJ4Y8E0Ov1eHxunKEQGo2ML1INyCRnxiHJAUxxetCE8Xqc6PVGNiwsQG/wkZCsZ+LM8Sx+aQNLlxayYul4NDrTGR4jEjhL68yUgeTToYmVABs/spieJNU8i2ezcgapruEkF3UWaaVHejLGxM24C9X++yJ+3OXlXEIy1XiBragzKA2QhNmo5dd424N8SEtk7uk0Hkhmy4Gn6NbxBQoX3oDx81h+/OkbrrnuITauexOtzoDBYKCq2suj098kIunw+jUQ9oAkEQyqPEoEkWQNfo8bJRxGo5HxRsJIkobUfgm4Ay5ik82gkfF5Xcho2bysDK3eyeCxCWTeNJpVr+eydGkhixcOR6s3YjBq0Oi06HQ6yvM31cljPf56/Nfb3IN+HYqsAbS0YwyqCaYaVSiZa86KBRqxk5WoztQf0YZj+GDmbBbOm0YwGODutwew/PUiolrqKSIHMHACF6oG66En49h+6gPgMNCSQ2xCDQks59ru8/ns20fp1vNaDPoQjqKfmDP7GXqkZ6HVRIhEJCJhhVAogNfrJxgM4nZ7CYUCKDLodBLBAKrZweVF1ugACY87TMAdIuiMgE+PZNKiKEFSB8Rhijdyy7zBPP7mOEpK3Xzw5kYsKQamzczA4S2kuqqQovwNhCJl3HlvKrGjYurksbTUiSLJgEIfJvProiZVCBkAaEUa0JB/7H8YVaOvINacysq5b7Lo9YcJhwNMmT+IDcurGThhQA2Peo6dcRyW0rvhTLafqskUSW9O4wSSOUoxN/adzVffPcSt90wjFHKgeKqZPesJMjIGYzJqURSIhBWCQT8ejw+/34/X7SMUCiBpZTSaCAF/BGe1D7fTA5IGvz+A2xXC7wnjq1TwVylEDDIRAiRnxRKdaOaWeYOZMns4BUVO3py9GnOyllmvD8HhLT7DY0Kqjqn398I2xHoBd+eisMKBpGiBMD2ZiLrCNFzDoxaAtqQATfj04JoaHuNIbNSDdYsWM2feo0CYyW8OoCQ3wpKfl6KteZZPQ81znUfPhrexQ7wHHKclN6AOxLFsZwPRreJ55+/X8/iLN/HBosfZuwvenvsCvdIHYNDL5/EY8PgIBAL4PH5CoQCyTkMkEsbnDeP3qsclWYvXE8DlDOJ1BfFUhMBrImyU0WhDJGTFYUuNZuLr2dzyQD82Li9l/py1aOJCTH0qg0pfKVWVRRTlrydjpJ7J9/bAmGGok8d6/PX4rxfuJZXVJLtjUKe3LlQN3VJT6kfNOqgu3gkQQF2klAoWHVNmTmPy3DnMXDyJxdM2E/ZqGDYoBSuxHKGYxjhRQ//MQBxyQw9HWQ8coQVJ/Bo/f4jVhGwBAG6+awIFrs0sfnsJep0Fvd5OwOcn6A8RDkI4GCISCaKRFWSdBkkLfn+QSKRmhaSkIeALotFoMFq09OiVic8bYtJNN1E4z4mzNIgs64mLNWC3WShzVzBtwShKS0spXe/ipVkb6JGZzNsrphGTaqekMsCkG2Yxe9KCOnn0BhWG6Xuhmgr8NZz9upDHgDqoqU6wwa1/XWnYHSla4raHJ/Pogvk8tWgSy54qIOLXYDFKWInlBE6aEuBsjpRSAhEHqkPxCErNDKtZTXqHolA+0Ixb7xnFstxFVJXuJTomHlm24PN4z/CIEgFCaLQRJK0Mmsh5PMqyusDMYDBgtGjJyMjC5w0xZdKd5M+tRPEaCIcjJCZZiYk24Qy5mTZ/JA5HKWUbq3nq0VWkZyWx8fMFWJKiWbYql4k3zGDhU6vr5FHW6hnbbghnU0B4UZ33QVS7+wnUhXQwouVY1HUUjVDwMX7Kbby+ZiG3zBjMqjllhLwhNqxdSgiJU/hpQFVNfb0ADw5nAerAcZz9VCDw0IlBtCIRh6aMJlzBh5/MZOmalwn7T5DZbwiKYsDr9pzhMRKJIEmqv0XWaUATUXPXI5/5BHxBTGYDJquOrKxsvJ4wg+MTKHy+Am3YRiQUJjU1GqvZQtgkMWneODzuSqrzfcx5fj09MhP44fMV6GNNLJq7kcm3v8T6RTl18liPvx7/9cJdFzaT3NvGPgIcpwg1DPIaoCm/kI9qfw8B++nGEFSNMYjREseo4YOQJT+P3rIQn9tF2B8mPt2GHhsBqtmOD9W23BCQqDrl5s0vF3AKN6rgiwesGNCT2l4VfEPv6M6tNw7i1gevxx8MYdZpkGUIR0KEw2EURUGWFGRZNfHIshpjjxJBRkJRFBRFwe8JYbPYKa3MQyLI7Dmv4w+5ceYHWPjASoIhPSF9mB4DEwjrNby+9nFWfjeToDdMZZmH+fM3kpYey4w5NxFth8xhGXXzGLFgaClzmhhOUYIqyPujOqRdqCF9CrCPJmTVXHWKSpeP4cP6EQ65ePSWD/C7XCgBBWtiDHpsFLCBE8ioZq4ooDtKIw33vzME8NOIZE4TD2gJEmTYwH4AXHFzJg/eO42OPc34/X6MGhmtVgY5ooYKhkLIkoJOp0OrUzdkDvj8SBHQSPIZrr2uADHWGEocuRAJYLLEEFL85C0rY+XsXNw+ibBBIXVgHCGdzOwVj/LBN9Pxu4NUlrl4+K0FZGQl8uZrU7DGaOg3sl+dPEpBAxH8Nc9GNapAb4NqK9ehRnQZUU17v2a6Pkn+6Qqy+/XAXezk9cc3EPYF0CBhtdvQY2HtkaWowlZXw2MS1tZx3PxMPKDQmsGESABcHMDBuOuGA9B/wigeue8mDB3KKCstxqxTd+2StZLKEWEkwmrEmFaN1AkFgsio5b/y6HH6sZqtFFfkQMRP1pgs0EVYPW8zq17KocwZJGJWSMyKQdF6eHzRVB5eOQqnw01VhZOH3pvHgMHpLH3rJcxWDRmDBtTJYz3+evz3C3fCXIIVHz6aMIhfp74AWmTUrH7RqELeVFPeHJ1Zy5w5cwA1HNJutyNrFMwJEpWsx00ILWFO8Ou2sEH6NxyNzRJHQ7RsYxlHcHIYPzN/mEkHRnGcL7DojFx5/2DgCO+8czehUM3enDUhbpGIanvVarWEQuen4I1EImdCMyVJwuPxoAQkfCEPVe5Koq1xuFwukPW8OWwlc0avJnRUIr19LFod/1975x9dRXnn/9c8TIZxGMfherler+E2xpjGFNOUUkpTyiqySvkiy3r4etRlKdoeVv2yrWtdi+jRld26SNWlbutXKbqWgqtU+SqliorRRuRHpDSmMYYYQgwhXi7xerlcx2EYZr5/zCSmPQpnzxFD47zOybnPfJ7LZZ73vfOZZ57n83weNu9rZe4jUylafexobKWtpcArm1qYePFV/PrOZcfU0fAcTqOCNlopoQL4aDekt9lC4Oh1Xj5wD8G471GgBKPUZMWKFciyjCzLlJeX41EkPU6lixfQSdFJE4fJEISUHqKSUsbVTAIM/sgqumjjIA5LX7qL85gDfECmM8P/vmMC4PHQQ7NRFA8hgpvfn+voOM7A9+h5gfNXFAVVDVfz5vPYeY+Ck6OhcRMxs4xcLodrwaNznuXRhQ3wgcYFX6xG0wVN73Yzb+UUisUi27bspK2lwOO/2czk2XN44o77jqljzHMZSQW7uYfgye6jEONDrCaImLF4eOu1YX2wnkIeAevWrQv2wxWCeDyOUBzStQqCDIZWyqu71/IB2VBHQf69DOOnTAN09vI0ebo4jMe2D7dwPrMB6Gnr4x+emskoksy+NklVdemA0+7/zfXr6HnegL6u6w58p4oSTJ5alhXq2IduCBQ5uPE6BZl1czfzwtIWDJFk0vm16IbAsUy+/+QsHFuwuaGRtpYsq57bRO2MaTxx54pj6hhx4jnpnfv4imoggfd+Iz7bGLwc9Dz6x5lP4an9DQQ9Tw84gCND584idlFF1QRKTGHBA1PJ99ps2d5K76EMBgadtBFcTEGCspxm8+quVSSpBmJ4xKhWgnHVUdTx8L0vIrJpfvTMNYDD86+9FlxArge4yDII2UAoAl1WEMIDVITw8Dxn4L2yAp6wsFwHXUkytWYmmVwbshZckFrcJE0py6euYufWAvGYIH1WDOFq3LjmZraveYFCX47mxna6Wpv46avrjqnj1ImTeJd2sm9tIFjA9BE9tISlMYh4ko9Wp76B5Th0NVkU8zKaJmPLReYtr6OnJcOW7a10vtdFBeX00EXQ41QYwwQKqstBGkgxngTVOGjMn/w9gmGGNt783UGKXXH+8w+LgApe3Lo1uEF6DOgoKyae8FA9QfAgpAJuqKWH8MDDAdnG9lwMNUVd5XRyhUBHxwPV0NEyGssmr6RzD6TiguSZOgKTG9bcwNZfPUtfb4bmxlZ62lr5z1fXHlPHWVOn8dSBFWTfLSW4CX60xP7xdx4JS+dQ840LQh1HAvW4uPS0eDg2GIZKrtjLVUsn0L6liw2vN1B0bGrOGY+HFX6m4KLTr8dVAdqBCnSqKKJQIddwlAIfsoYdr20i0wC/2vczLv36Av7riVXouo6MCK4HV0PIBo7noLigKN6Ajv2OXhEyrmcP6JjQK3BzDgWrI9ARD0U36NtW5Pbx92N9oFE2RiU2RsFzdRY8PJ+1v7yHTHeGbY0t5Lq6+b9bHyFiaDnpnfvcS2byH7tv4sujf4FEf2Ks98PXScBuAMrO6F8scgqwAXN0irrLq7B6HKZeVoHldGErFunyFJ5sUH1qBQIDQZ7D5AicTi2mEqM5U0AhS5EedJJc+bU5bOcF/nvPbcC7XHvD5fRscvjBmssB2LevE6G6CKEgRLBYBVUBQ8YMe56OB56Q0VWN0nQczws2uZ46fhJlyRTJcRpuETShoFgKqgqGnsJVVB64YSVLp20mTTXjRicQR4u8xCoWLpsOciddHZ207mg6po41Xy2nmzYuPO8pGNDxMAAXMh14EwBN8kItXOBx9JGlJGoUir020+dVkO3rRJgeWlwLdDy9im7yqFgEWRUVII6uxHjkuU3o9OGQRSVO5Uid16nnN/vXAXswYjY7Hu/hjt9eAcDevb0gewM6ui64sgBD/RMdXQS6qpFMmXiAoRpcPHEyCcNEJIoIV8VQNBRLRdMFhpHAVVSWXLGMJVM3U8UEqkbFkH2Ll1nH95ZcQF++kfbWNtqadh5TR71UkB6T4BtnXs7RgVjuIwBUfaGcIOoFZPozkR5lP6twiWObRbJdMGN+JUUri5yUsT0LVxjETzXJkkdQ4KPV03l0LclPfrucsRRx6UNgoDp99NJNBy6jSPDK2m1sWdnJf+1aDKi8884+XBxkWUWWwXMVPEXG0xVMVcPzPGw3uDlqiooZUxGyjK5pzKi7AE1RcGUNVdYwNTXU0cM047iK4Nopi/iXC+sZx0QqTjFQcemknbmLJ5HvbaR1ZzMtTceOOoo48Zz0zr2LLP90zl3Aa/zuaP+jXv/+3CbBTjYPUYpKMFG4l2f8dajIzLh+GtcuncX6R9txPY2+YoYHlq6mzIzjILjt17dxHpPwyBEkbBpFwWqn1W5m29v1WBhkyAAaGjpaWYzXWM3OnjZ6rSZ623R+/tZ1wCgO7M9imAJXBSHbQQIBx8ZxXBQho8oKqqyQLkuQt4okk0mMeIzefB87W5qZMqkORXjIcZOUolPM9dCdDXrYttvLVYtnsO3tRhp3d2GIODpxVCXFnJlXsegnd3HzP918TB0VTJJUAb9jq/9YaO0IX2uBKo5wN+OIE8S5F/jBb1fiYVF72TgWLJnJugfbsFzwZI8V92ygzIyjYbB261rOojqcq5CAJI7XQ0bvoeVQExlkMvSx7b1WNHQ4Q/AqjzF+5lRkI0dbI/xi13cBiQMHujBMgacJhFxEE0FsuG15KEJGU1Q0RaU0HcdyHVKJUrSEQWemh9b2Tuo3voDnWIiYQblhks320NnbhRCCotPDtUvn8MquBlr2Z9GJoWOiqaUs/N6NLLp7KTf+443H1LHqlHFkD7hAG70Dv8NgO7lvcTFBhNXP+QpVYZ3HNfc+hkWWeC3MXlDHqmVN5B0PgcL61TsxhCBNmo5DfTjIHCFH/7i7UPLk1QxvsoVeZPJYWIpCniw9dPI8D3L7o9ejxYvUP9nDy0eD4bn33juIboAr2yDnkBEIz6ZYsBEe6KqGLMskUyZCVQIdYyYtne20dXSwcMFCisU8jmFQYcbI9PXQ0dONImvkKLBw+Vw2vlVP874M8hEFDQNdS7PonmXcdvd93HTdsXWMOPGc9HHuCjK7jnTyxZIsZSPKQutOgkUzZniscwazCJzSWB59sIH7r5uGXmazdMZa3HwBS3apLS2lPtOObQkUdObOmQfE6aGBc4kBHv/n/Lncka0nUVbLkn9fwOJb7uEwfSy87nauv38a3SUKdXVpjNh0dm7pZPP6Lqoq7+CiEXeye89OvvS1qeQLFqWpoLeZz1kYpkIxLyivKKVYcFBE0KPqy+Sw8h6eIfP406u5ZsVchF6kLFZKQXbQFEEslUQboZAnT4I0KhppyoJ+W4nFhK/VYuNiD4qz/jhaaGUKtXxAMzVSTWjtIMjmVwOMoIRKSqgl+FmMobcn+L9mThEsmrEOJ18gMV6jUo9heCa2JRDIpBMVQIw2NnI+OuBxxflTWP5SC/FTx1H/2lomfnMm3zp9GpfeupD5P55MBoXKMh1FlNPUmKGpwWbPFx/mbL7L7j3tnP2lWizPJh5XkRWFTG8ORfVwbUEiEcO2gqX8iiLIZ/PYWQ9Hd2ntbGb+g1ehxV0qEmVk3QK6oRKLx1EkgYVFKZXESZAkQQvNGHqS9JdrcFCOq+OKvav4x7E3s58GxlJGMDeRAb4AzCIY8tAJYtZ1oITacdNIUs7cWTNYcVMDsiMzc8EEUkJgyjF0JUjsvOmVBr596Tz+yAbOZybgUVWu05uVcTAxyGKh8eWSOn78m/upuTSOiyBVGSddrrNxfRvPru1m/JW/5jRmseedbs48L4EjFFJJHQ+Znu5cEABggxnTwFNx3DyapgU69rnYms3k+ZehV5iYKY+yWKCjGdMxR8fQkCliMY5q4iRIk2Lb0W2kTq9AJ42FHebPjxhKTvpvoO39Zr5YUsN2WjDC1YN7B2o7CFZHCoKLygQgVToNg2o2tzYhJxXMRJzFDyxk1c+24ckKxUIfO/Y2EJNMdvEKHgrvhwuiPkCgxmVWPbmSm265AYMCDkksO0tVyUTEEY/aMTOonFDHZfOnI7sWDas72c69wJm8+fpmLLUXt+CR6ytSyPRRtDwS1S7E+kCzUBIuSlJQkY6hyDYTKivoanTY8G9P88C8B7jt8sVcfc58qsaWwwgXGYUESUDgotNBFxaCWmqRkVGQ+dLA/MPHY6AwkhiNNDMKA/iQwxTD2hxBCF8x1DDQOV0+jTiVOLpATmoYqRQ3Lfs+dy1ejytkioU+dh7cwQXnTOQATaRIczh0jqOpw9Udvn/nfNBkNAocQqe3t5Mk5XhHHP72nBsor5vCkh/dhFso8ORTOzjAGuBU9ry5E1excfIu+ZxFIZNHyDqpGlCSBRTTRY2DknCoLkshZJukDF074IVl61k6+z5unn0TV5+zgMoxaVzJRkHFJIaCHO5j1YWHTrVUg4ZBDP24Os4eOwOwaKct1KmIP9CDFwTDgjEC564Ch5H1alJUkq6pwCxLYJYmmTr7YpYu3oiDhye7tPttXHPpXA7RzPnU8SEW4PLNkhspCosVP1/N/Q89gEIfB7DJW0UUTJzDDtPOnoxcWsXDP3yMfE+GR55rIFhAJXj3rQ5kQ6aYLVDIFylmCxgxk7IJCkLzkA0HPSVQEg41FWlQbOJ4PLtiG/X3PcvtF9/H7Vct5upzrqd6dDl26Lg1dBRkcng004EyIk45lcTQKSXOlwZSXEQMFSd9z33y6ClAgRh6uMMSaANx7gpBil+TYCJVBvaSTAg0YvT25NCFQ90NF6DTQ67TRVMU7FwBkbIQFLGQKUVFDkZvGUUppaZAr52EIE/jgXZSY/LMuWYWBRRiJeNoowOnq0jFeTX86tYf8ff3fpv6/9dG8W9v5SJ+zPtvHOH5/WtYMu8ucl0eummTSJeCp+IpeQziGMKgNFlGR3MnDy5bRm3dbBzHQtNjOLbg7LMngecRT5o4bgHVjPH4Y7djnGHTQ4GvciUfsgcVmyCbYOaYOlYzDp8eqqmg3wmNDPUM0jU8zRj6F54IYC9GzMYkhVX08Ip9zLpxNobXC7aJqsnYuQK5vE3mNIFMjASxMAZH5Qh9VKcMUlfNp+7ccloOtpI+zeGK+bNQSJEsMdnKNkzLIzfS5qEf/oa/+8klrH5RZuZfFzmX+ex/4z3+/bkfsXH5BjKOiRmTiaXieK4CtkWKFMWiSyxVhWu3MnVqHWs3NOJ0WpixUqw8jB1bgywE8aSJ7eRRzRj1m5ajjdBppJtvMI8P6ETFoUietwdueB9PiiSHaGciUwjmJU5Dov9JyGM7/8rXmRYeq0AvZtwlRSWxWCe5bot5/zYFvZhBuAaqKiOKRXp6W0mdVUU7RUyKpKkFNA7TSGXCIHX5ZVSN0SkCvfQyfVodKSrRRxboJk9Kga1s5Bf//AxX//RSHo5tYt7XHUoYz56te7joh1/FabbodWMYKQU9rmOYfTiWS9JLkenNo8XLKNpNFDN5hC7o7naJJ9L09bicdVYVmqpixnWyjouhevxx6zo+oEAjHVzIPA7Rg4dFjj4KJ3+/cdhz0n8DvYd1drOZXgq8E0Z55MiGtR6/YyNBT0kM2HQtiY2HbReDRS9qhhVLGnHsIF46lwXXjiGT5MlnnmYMOh20EVysMomUIJ8vkD0aLIkHwbRvzcZDJo6BTYHVP1uLSp4/8DK/+uHT5Ap5et40OchvAbjkjKvY8Pxa0hUy8YRGMWvR1dqF3SeT67NQPcGG+vUI4XHB5MtxHAvP8ygUCgMhawBWEWwLZAsWXL6U6y9dysor1/H1r47hFBKciU4nXcSPk8tDpoJOmthBG0dDrY6EaQegj3Y6CMaL1VBLl7ieogSdrq4ONFXHkXtYcv1GRDislMuCY5kYVLLxtUbOwuAdugGVEhIIJUc+Z9ERTjy6eEz/q9m4yOGjfY4H73qMGPA6z7Hmn1fR25uhcbdN/3zALd++m03Pr6e8SkU3BMWsRWdLJ8WMSz5vkzbibKhfj0KBjRt24jhWELfd14fjOAgh/kRHxRZcNvUm5ly0kMeu3MCXv2IwihhnYpKnQPI4OgrK6KWDLUd30r/oi4FkY24QvUOcYDGdB+TRFYMRJGhtayZZqWCJbhbPfxJQUBSFQl7GdQxs4jS/kyU9MNcjM5IyhJKjqbuZNmxa97Xi4FF6egV5ioBDFpv7Fq+iFJPf8zz3/eBf6OzsYv2+LoKnMp+X7v09y1cupaJKQ5ZdrD6b3laFQq+DbUNFKs2G+vVMqDCIm2kcJ4jsymQyOI4TJDxzXWxLIFsWptC55ML5zLtoEeuu3MQ3/yrNqWiMIRFupB3llhlqTvp87hERERERn8hfcj73iIiIiIj/KZFzj4iIiBiGRM49IiIiYhgSOfeIiIiIYUjk3CMiIiKGIZFzj4iIiBiGnCyLmIrArqE+iZOcOAzkJ474eCKNjk+k0bH5S9PnC59UcbI4912fFKsZESBJ0o5Io2MTaXR8Io2OzXDSJxqWiYiIiBiGRM49IiIiYhhysjj3aE+u4xNpdHwijY5PpNGxGTb6nBS5ZSIiIiIiPl1Olp57RERERMSnSOTcIyIiIoYhQ+7cJUmaLknSLkmSOiRJWjTU5/NZIknSI5IkZSVJahlki0mS9KIkSW+Hr6NDuyRJ0v2hTs2SJI0f9G++E77/bUmSvjMUbTkRSJI0VpKklyVJapUk6U1Jkn4Q2iONQiRJUiVJapQk6Y1QoztD+9mSJG0PtXhCkiQltI8MjzvC+rJBn3VLaN8lSdIlQ9SkE4IkSSMkSfqDJEkbwuPhr4/v+0P2B4wAdgPlBNsqvQFUD+U5fcbtnwKMB1oG2ZYBi8LyIuDusDwDeI5g5+RJwPbQHgM6w9fRYXn0ULftU9LnTGB8WD4VaCfYISPS6CONJEAPyyXA9rDta4ErQvuDwHVh+XrgwbB8BfBEWK4Or7+RwNnhdTliqNv3Kep0I/AYsCE8Hvb6DHXPfSLQ4ft+p+/7DvA48DdDfE6fGb7vNxBslTOYvwF+GZZ/CcweZF/lB2wDTEmSzgQuAV70fT/n+/77wIvA9BN+8p8Bvu+/6/v+zrB8CHgLOItIowHCtvbvDVgS/vnAVODJ0P7nGvVr9yRwkSRJUmh/3Pf9w77v7yHYCmviiW/BiUeSpFLgfwErw2OJz4E+Q+3cz2LwftfQE9o+z5zh+/67YTkDnBGWP0mrz4WG4ePxVwh6ppFGgwiHHJqALMGNazeQ932/f/+/we0d0CKsPwiczvDWaDlwM4S7twftHfb6DLVzjzgGfvA8+LmPVZUkSQeeAm7wfb8wuC7SCHzfP+r7fi3BJrgTgaqhPaOTB0mSZgJZ3/d/P9Tn8lkz1M59HzB20HFpaPs8sz8cSiB87d8N/JO0GtYaSpJUQuDY1/i+vy40Rxp9DL7v54GXgW8QDEn1544a3N4BLcL604D3GL4afROYJUlSF8Gw71Tgp3wO9Blq5/46cG44c60QTGCsH+JzGmrWA/3RHN8BnhlknxdGhEwCDoZDE88DF0uSNDqMGrk4tP3FE451Pgy85fv+fYOqIo1CJEkaI0mSGZZPAf6aYG7iZWBO+LY/16hfuzlAffj0sx64IowWORs4F2j8TBpxAvF9/xbf90t93y8j8C/1vu//HZ8HfYZ6RpcgwqGdYJzw1qE+n8+47f8NvAscIRjD+y7B+N5LwNvAJiAWvlcCfh7q9EdgwqDPuYZggqcDuHqo2/Up6jOZYMilGWgK/2ZEGv2JRjXAH0KNWoDbQ3s5gfPpAH4NjAztanjcEdaXD/qsW0PtdgHfHuq2nQCtLuCjaJlhr0+UfiAiIiJiGDLUwzIRERERESeAyLlHREREDEMi5x4RERExDImce0RERMQwJHLuEREREcOQyLlHREREDEMi5x4RERExDPn/GUtqY+FycHAAAAAASUVORK5CYII=\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "show(make_grid(imglist, padding=100, normalize=True, value_range=(0, 0.5)))" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-24T23:32:51.844460\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "show(make_grid(imglist, padding=100, normalize=True, scale_each=True))" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-24T23:32:52.624197\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "show(make_grid(imglist, padding=100, normalize=True, value_range=(0, 0.5), scale_each=True))" + ] + }, + { + "source": [ + "## Visualize Bounding Boxes" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "source": [ + "You can use `torchvision.utils.draw_bounding_boxes` to draw boxes on image.\n", + "\n", + "You can set the colors, labels, width as well as font and font size !\n", + "\n", + "Note that this util requires a single image of dtype `uint8`.\n" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "from torchvision.utils import draw_bounding_boxes" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([3, 768, 1024])\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-24T23:32:53.654506\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "lena = scipy.misc.face()\n", + "img = transforms.ToTensor()(lena)\n", + "img = transforms.ConvertImageDtype(dtype=torch.uint8) (img)\n", + "\n", + "print(img.size())\n", + "\n", + "show(img)" + ] + }, + { + "source": [ + "We will draw a few boxes on lena!\n", + "\n", + "Note that the boxes are in `(xmin, ymin, xmax, ymax)` format\n" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-24T23:32:54.157276\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "boxes = torch.tensor([[100, 400, 500, 740], [500, 200, 800, 580]], dtype=torch.float)\n", + "labels = [\"grass\", \"lena\"]\n", + "colors = [\"blue\", \"yellow\"]\n", + "result = draw_bounding_boxes(img, boxes, labels=labels, colors=colors, width=10)\n", + "show(result)" + ] + }, + { + "source": [ + "You can also `fill` the box with the color.\n", + "\n", + "Note that after filling with color, one needs to save the resultant tensor in PNG i.e. 4 channel color format.\n" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-24T23:32:54.542848\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "result = draw_bounding_boxes(img, boxes, labels=labels, colors=colors, width=10, fill=True)\n", + "show(result)" + ] + }, + { + "source": [ + "You can also plot bounding boxes produced from torchvision detection models.\n", + "\n", + "Here is demo with torchvision's FasterRCNN. You can also try using RetinaNet" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "from torchvision.models.detection import fasterrcnn_resnet50_fpn\n", + "\n", + "model = fasterrcnn_resnet50_fpn(pretrained=True)\n", + "model = model.eval()" + ] + }, + { + "source": [ + "Let's load an image and get predictions from model." + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-26T09:33:29.242197\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAVAAAAD8CAYAAAAhQfz4AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8QVMy6AAAACXBIWXMAAAsTAAALEwEAmpwYAAEAAElEQVR4nOz9d3Rk+XXfi35OPpUzcs6NzrknJw45MwxDckhJpEVRyZL9pGtLtmzZV37X9rtetuUkK9BWoGzFK1JikihyAsnJ0zk3GqkbOaNyrpPfHweE5XeXg3itJ3Gt2bN60Ch0AQWgzq79298keJ7Hu/VuvVvv1rv15y/xL/sBvFvv1rv1bn231rsN9N16t96td+s7rHcb6Lv1br1b79Z3WO820Hfr3Xq33q3vsN5toO/Wu/VuvVvfYb3bQN+td+vdere+w/oLaaCCIDwjCMKcIAj3BUH4B38RX+PderferXfrL7uE/9U8UEEQJGAeeBpYB64An/A8b/p/6Rd6t96td+vd+kuuv4gJ9Axw3/O8Rc/zTOBzwPN/AV/n3Xq33q136y+15L+Az9kNrP2Z99eBs/+9OwT0oJfJdCBLIoZpYJkGpmVjmSZ4IAAIInpAR1VVLNtCUVVkSSEYDFCt1mi1WuB5KKqCKIpYtoVlWTiug6aoCIBlmWiygmVb6IEAICArMq1WC1lWUVWVWr2GqqpIoojrebiOiyiJ2JYNgKqpuK5LIBDAdV1UVaVSrSIKIvVaFVmSicXjyJJCy7Jo1OtEoxFs20IURCRFolFvEAwE/O8PD1lVKFcqhMMRatUa4UgYz/MQBIFyqYQAJFNJypUKpmGgKgqRSJRSqYgoisiyjICA4znIkozjulSrFVRZRRAEgsEgpmWDICLgISsSkiTieWAZJoZlIssyiqJQKpXRVRVJlhAlCdu2qVarRCNRLNtCEkUEQUAQBCzLQlVUBFHAdV0EQcDDw7ZtVFWl0WiiqiqyrCBJErZlAuz/3AzDQNM0HMdGVRVMy/a/jmVjOzaWZWEYBrquEtB0TNPAtCxkSULVNBzbxnVddF2n3mgQi8ep1WpEIhGq1SqqouI6Doqi0Gw1wBMIhcO0Wi00VcV2HEzDRNdVWkYLTdOxbRtd02m1DDxAFCVcx8ZxHf937rkYTf9jiqKgyDKGaWJZNqIoouoarutimSaKLCP4T14s28F1XRRFwvM8REHAdVwc10UURSRJwnFdHMfB8zwkQfSfd7b/eQVBwPM8XNcBQcC2HUBAFEUcxz9FCgJ4gOu4CKIAgOM4iKIIuLiex7dPnJ737f8BAv7zDQFRlvA8F/Cff+A/7wVx748Aouy/dR0P1/NAEBAlAUkWkUUZSZLwBA8PF891ERFp1AzMlokoytiWjeuCh4gIuJ5NT18nxVIJwzAR9v4D8AT/awkC4In7j83/IHiesH+tiJLkP788B1EUUDX/gXquAIKHLEmIgojoiYT1AB4uDi6G0UISRTbWiznP8zL/863uL6aB/k+VIAg/BvwYQCyW4J//s19iY2OLV197iYWFeZ59+hlEUWTq9h0kSSIcSpDJpHj08ceoVstIqkLLNNhZ3+TU2XN4osT07DzNehXPNrg3c5eDh8aZOH6a5fsLzN6+TW53m0atiuu6TB45ytDIKA2jRXZ7i1s3p3nhez6OqirUGnV2dnaIxeKYhs3CwgK5zW0mJg9w6OgR8oUCA/39BINB5ubmaG9vZ2tri63VdSrVIu1tXbSaNs999KPkcrvMzc7wwLlTLCzcYzNboK+nCxwXz7Y4/8Y7PP3M06zubFIo5MlubTI2eYhUKkWj0QAgHY2xvrlG02yyvbbByEA/qc5ugnqAL33pS7z3qfcwMzNDsi2O4ziEw2Hu3r1LvVIhk0wwMzOHK2nIepBzZ06zuHifeCJMvV4jKGl+E1YVREXGdV3uXLuOoqmIokgoHCabL/HII49wd/oOoigQj8fZWt3giSeeYGNjg93dXU4/eJZCoYCiKNy9e5darYYsK1imQz6fZ2xsAhEbWZb50Ic+xPz8PPV6naWFRcYnRjCsFvcXVzlz+gHq9Tr3799HlmW6urrY2ljjufe9j0uXLtHT101nW5yFhQVs27+4+/r6WF/doH9ggGwhT3t7O6ZtsTK/xO5ujhde+AgXL72FJwYQRZFMJkM4HObrX/86sViMkdEBZmbu8uSTTzI1NUtbpoNqrcnm9g6KrKHKDl1dXURiYRaXF5ibXqK7u5tAIEAqlWJnZ4ed3QLtPV1IqsL2zg66LBHWNXRNBUEmW64jCaBqMDE2xp2bU4gI1Bp1BgcHyRUKtFot1ra3Scbi6JJCLBqlbvjPAUUSEAWoVysIgQCNegvPk3BsF8MB0zQpFotomub/ezVAo9HAcRyi0Sil8g4OHo7nv9AZloXRbKIoCrIso+v+iweygudaaDrIokujVUQUXdSwgKDZBEMB1JCI1apRbzSQ9QCxNoVoIkgsHSGk6UiuiKN5tOo2MTXBH/zGH9ETbMOyXDZXCzi2iiwoiJpEIm7xd3/mJ/l3v/QrRAaiSJKCIslYLQtZljFED1WWEHFxLMD2cD3/RcYyXWzbRVMDaMEAtmshiiL9o70Ewwq1VhHXdZHkEKFQEEG0cJoGB4fGOTQwxPz9e7x1+TyDw4O4jsVn/s9vrfx5+9hfxBF+A+j9M+/37N32X5Xneb/ued4pz/NOybLMF7/8Jfr6+zl95hwnTp3m6pVr4Al86gc+zXPv/wBPve+9jB+Y4Ld/+7fRNI3s9g7Td28Ti0e5df0aszN36O3vAVzefvst2tszdLd18NJLL3Ht2jXGxsY4deoUj7znCTqHBrkzN8f84gKlao31rW1M16BcKXDj5jXWVlbp7u6mvaODWDrJ6QfP8cxzz1KqVpiemaG7u5vp6WnW1tY4duwY6XSaoaEh+vr6iMVibG1tIEpgtOrEohF0XcUDGk2DQ4cOYRgGC8tLCKrMgw8+yvrGDq7nUSyXiKeSLNy7T6vRpFapoqsar731Jru7uxydPMTHPvYx+gb62c7ugihw6NAhcsUCnueRz+fZ2tpCkiT6+vrwPA9N0zh77iQPPHiag4fGGB0dJplMkssWEEWJI0cPE0/E+OY3v8Hk5AG/qYZDeJ5HrVaj2WiQTqd55/xbyLLE+vo6sXiEfD7P0tISBw4c4Omnn+bGjRtMTU3xzW9+k4mJCXp6eujIZOjp6mBkaIjO9gwPP/wwtm1z9+5dFEUhEAgwMjJCV1cXfX19JBIJrl6/QankN+ze7k5eefFP2dxYp1SuEAyFuX9vCVVV2d7eRlVVxsbGuH79OkP9A7imRVdbO/Mzs2D5k2c63cbU1DTHjp0k3ZZhYGiQUCTMa2+8zsTkAUqlEosLqySTbczN3SMYDJLP5xEEgXA4TKFQoL2zi2q9hm3b1KsNUqkUpmmSTCa5f/8+juPQPzS4P63LksT66gZGs4XRMtECIQRJJKAHUVUVx3GJRCKYgBYKU643MG2Her2J6IGqqii6RtMy8SQVw4FoPEm5XEYURQKahq4pyKKAIkvIskxbW5t/cpIkNE1DkkTAQ1UV6vUajuNgWRaKouyfHjxBQJAkDMvC8TwQRdy9SVkWRMrFEoKrYBqgykEkT8No2RhVqBVcdDWMruvoAYlAUEVRBTwsXM/EbFkops4rX3yTuNaD01TZXCoguAqiJ+AKoGkuP/2zf5PPfen30JUIri0gCaI/OEjgfbt5eiKuLeA4FoIIju1iWx6O4yFJEnpIB8FG0yXau9OIsketXkUQJGRVQdFlbM8GCfSoynpunSv3bnJnZYbRQxPE29I0he+s2f1FgEgyPoj0FH7jvAJ80vO8u/+t+ySTae8nfvzvc+f2DB//+At0drXz9S9+hVq9jivAgYOTLKyt0ahVeeDcOW5eu4osywwMD4LlYpo2kq4iKSId7V10dXayurKOY1pUnRrffOllGqUS6WScJg7NhsF73vMeNje32d7eQbBdXLdBd3cXc9PzxKIpQtEINqAFQ/QO9JOJJYhEoywtLXHn7hR/7fs+Qblc3j9yBQIB1ldWCUcC/OZv/gYHJg4RDCQ4eeY0ByYnabSazMzMEA5oyIrI1atXuXDhHf73v/ez3J6Z4fjZ06ysrFArlqmXS5imydGjR4nFYsyvLCDhEQ8EkCSJSDIKUoBGrY7RbPL6q69x9OhR7i/4ON2xY8eYm5tj+vYsnmPwxBOPUm62GD0wSa1cYXZ2FsOwcF0X2zb58Ic/zLWbNzh16hTFcolrV67T3dHJ6vIKqiQztzBDo1FHkiT6B3pZXl7kA+/7IH/8x39MIOBPdQcOH6Krq4vbt28TDAZpNptsrK0Q0EOAwPHjJ4lEQqTTaZaWlhBFkXA4TKNWp2XUae9sI1eoYJj+C8HRgxNsrC5TLuYxzRbtvb2MjIyxsrDC2GgP2WwWXdepVCqkUimMpoll22iaRiAcAmBweIjpu/cpFctEokEy7W1MTU0BcPjwYebm5jCbDdbXthkdHSWb22JoaIhqpU42V8RFoLOjm1Q6RqlYIKhrTN2+TSLdTrPZ5KmnnuKtt95ibW2NAydOktvZxbZtHMdB9WQ0VSSZinNjep5wIoUuimTa4mxvbhGPxKk4Bq1GEzwPTVbIZrM0Gi2GhoYwTZNILIaoaNRqNXJba/R2pEnGYxQqJbK7eXp6+snniliSSj6fx7IsAGRZxsPZb5qWZWGYJrbnEggFqdVqBEIh6vU6jUYDRVGIRCIAGM0aoihiGk2Cmo4oeciaiC01cGgSCOmYLYtAQCXVFcBRWoRTEvFUGBQHVZRwWjZOU+WPf/cb9LaPs7NTpZa3sD0LQbEIhBW6ezr4kR95gZ//hX9LPJZCtEW0UIhCqQCSiBbwVwGSJNGsmwiI4Bp4OJgGuI6ALIsEgioWLolEhN7BHgyrhel6/kpJAlGREQQPWXPRgxq6GgADsrkdArJKo9zg4oWbxDIp5r6Rv+Z53qk/T7/7Xz6Bep5nAz8JvAzMAH/432ueALZp8ea3XuP7v/cTXD5/gV/+d/+eVDROZ1s7VsvAtR2SySTPPvsshmHQ2dlJd2cXuZ0sm2ubFAolXvz6y0QDIRzD5J23L6EHoly+PsWNGzdIJpM88sgjHD9+nPHxcQ4cOMDVy9e4ce06x48eo6+nl7ZUmkalTKVQIrezS0jV+cgHPsSRg4dYmL/HxYsXWV5eZmhkmGPHjvHGG29Qr9fRNI10Os3s7CzxVJJoPM6DjzxMrphndnaWnY0dpqamKeQrpDKdXL98BcmFRDRGLBxhbX0Vw2gwPz9PLJpgZXmTXC5HMplkY2ODSqWCKIoYhsE3X/kGX//Tr7Gzs8P9+/f5whe+QKPR4KMfe4H5+XnGxsZoa2vjm9/8JocPH2Z0dJye7j7On7/IxvoWd+/O8I1vfIP29nZ2d3epVqt09/Xzsz/3j4jGEvzqb3yW3/vc53nugx9C1gOcfehhrt66RU9PD3/zb/5NDh2epFar8cQTT/Anf/IVHnzwHLZt4ro22WyWXC7HvXv3iMViZDIZJsbGOXzoEOfOnOXWjevEYjE0TaOtrQ1RFCmXyzSbTTzPo1Kp0N3dTS6X4+DBg0iSxOnTp8mkk8QTESy7ycr6CltbG7RaLdrb21FVlXA4TCaT8dcqw0MIsoRhmZSqFbayuwiKTMux2NjZpdFoIEkSlUqFhYUF+vr66Orqor29g46OTpoNg1wux8TEBACCIFAsFtna3cEwDEzTZnh4GE3TSKVSZLNZRFGkra2NUqmEruvUarX9CbZardJqmvT399NotGi1TBqNhr+zrdcplqvYrkcsnsS0XVRVJxwOAxAIhajVatgubG1tAf7O1WjWqdfrhMPh/b1zqVRCkiRM099l27aNbRvYtoEguEiSf99QKITjOAC0Wi0sx/YnNE1FkERcPBzXwLINQMS2/R2wbbuYTRM8EdtyaTVNJEHyP4fdQhRljJaJZTlYpkOt1uDrX36FtkQnzapJrlDGMSX/2I5AOBLgx37803z2N/8D8Vg7liljGP7PXpFVFMXfmQuyQKvVwnU8yoUiW1vblMp5Go0KlmWgBzQCAY10JkamM02rVUNWPIJBHcuxkSQFVVWJxiO0jDrLa0ssrSyysrZGvdGgUq2DK/Hkk09y5PDx76jf/S+fQL+T6u8b9n7uZ/+5f1xqbycej5PfzrGT3SXZnmF2bo5SvkC9XsU0TdKZJB/4wAd45RvfIpVKMTExgSiKtFotisUiuq5z8+ZNenp6GOzpY2ltiUIpTyAQwDEMdnZ29i/kkydP8vpbFzl76jArC/OsLq/RNzJGvdYikUjwf/3B73JgcpiJ0QPYnsWtOzM8897nWd9YJZ1OoygKPZ1dyLKMqMh7F2Y3V69e5fyr5xkaGiCWitI7MMrQ0CiL92dYXl7m05/+NL/wC7/A7sYKn/rUp0gk07z48iucOHWSixcvMz4+zptvvo4e0Eimwqyvr/NDP/LXyWbz7OzmuH3rBqlUiqPHjrG1s008lSS/tsrM7BR37txCkQM89OCTbG1tMTk5QSgUIJffpdVq0dHRwfnz57l//z5PPP0M4O/QUqkUly9fRg9qhMJhHnv4EWTLZX13meXlVTRR5e7du3zw/R/k9uw0jz32GNVqlenpaVKpFJlMhlu3bjE+Pk4mk2F1YYVsdof2jjbApdE0UVWVQ4cOUSwWyefzSIqGHlCJxaLs7u4SjwZxHIdGrc6Z06eZmbpLpVLCEwUymRSOaxONpLhz5w7PPvssnudhGAa7+RyarFAuFOkbGqRQLRPRg2Sz/mRWrdbxPI/x8XFefOklurq66OjooFSo+Dv2YIi1tTW0ZJRUPEF2a5toOML66hrprg5uz9zlwbPnaJar9PUN0Gq1uHbtGkeOHGF9fR1B1jAtg0KhgCQJpNLt1Ot1gsEg2WwWSZJoS8YxnCa1Rh3bFbFdiUw6hoTNyv1louEYFjJKQMfzPBzDRJag3qwRiAZJxKLICGxubxEOh1FlBatlkKsZCB4ENJVms4lltHDcFobpoao6pmOiKjq1eoVSKUcqlaJaMTBNC1SJYDiEJIg063XUveYuyhItyyQeDtAy6phmg0BQBsFFCYsEQjpa1MOmQaIzjKa6KKKHYEtcvXAHTUhSq9Ux6g7NuoTTMommAkweHuKDH3qOf/xP/yntvX04poGu6xitJuVmAVkWCEdUhka6GRwcoK1zAFmW0TQFTdOwZBfLMP1VCR6yLNNoNqlWq9i2S7PZZHM7j+d5KIpCLBYjmU4RTwSIamFyuRJrW1vktgt4rosuabQsk5Zl8upvTf25J9C/Eg20t2fA+9Ef/Cn/KGYY3LhxA10PMjI2ypGjR5mem2Vt/h7nzp0jkYxx6dIFdF3HEyXW1tZYXV31EUpH5NChQ3s7IIlCoUBHpo10OklbVxuVapVoSCcYDPLOO++gqir37t1jfXubJx5/iFqlRCKa5Mq1q0xOHmF+7h5b25tIssPI4Ci5/C4TBw7SNKC/v5dsNkswHKK9uwsXj5geIZFIUCzlyWQy/Oov/BJtbRmaZpMzpx9gYGAEW3B4/fXXOXXqFJ1t7cxMXePO7bs8/vjjLK6sMjY6zvrmFpcvX2ZgoI9qrcLa5hKGYdAyLXp6+zl79gEyyQgzMzOsbaxj2zY9PT1cevMCybS/n0yn2ojHE8iyjOs6xGIxqtXqPtLc3t6OIAiYlsfg4CBzc3NIksTbb7/N8sp9BoeHiUejpMIxDhwa5/z586iKztDAEFevXuf4mRMUCv7utauri52dHeLxOB0dHczPz3PhwgWef+4D5PN5VE3hzp07DI+MAlAoFAgEAiSTSaamphgZGSYcDu/tHfcuFMuir6eX+fl5trM5hgb7wXXQFAVZ9VcES0tLRKNRJicn0XSdSrlMpVJhY3OTUCjEwMAAluWws7NDLlegajRJxhN0tbVz5dJlHnnkEVZXNtACOum2DFevX2dk7ACbm5scGBnDsWx0XWc9u02xWKS7s4taucLE+CgzMzO0tbURjUapVqt4rsj8/ByVSoVwJEg0ldlnGuRyORRFIRkNY5h11jY3kJUAnuMSjuhIgku9XCUWS7JbNxBVDQEJx2iRioapNxvo4QCyJIDl0Gg1GRwcpF6tUatUyFX8Y7iItweS2jhWC8uTCIajWLZBs1bHsvzpMhqNUi5VadkOSiiAqGlgOdimv9YxTRPHcxEVmaAkUK4UUDURQbTRNAU9GcDxTJSwTTSlIIoyqgyeA6uLG7imilE1aDQNXAQsWwTTJJkO8TM/+5P8/L/51yQSCXbKOSRJQJbg9Mnj9I+10d3djaIotJoGnudRLNdZWlrh5o07bGzsUm5Ce4dCIhZmYKAHTVfBEzBNG9Pw96KGIOA6DrIgYhkmiihhenV0UWd4cAxB1jhy6DSteoOZOze5M32Lm9NLNOf47mygY6MHvH/787/Gzs4Ouq6zu7tLR1c3lmWxurrK8vIyJ44c5ObNm2QyKaq1CidPnkSUFYLBIEtLS/T399NsGpimP+XMzMyQz+fRRJlYLMbE5DjTczN85Qt/RF9fH319fdy8eZMjR47wwAMP8Cuf+QVM0+TwoWOcPXeKN994h0ceeYJGo0GhsMv25jqzszPEUyl+8id/hpX1VRYWFujo6mR1fY0jR44w0D9MsVgkEokhSRKbGyu8+uq3+OQnvpfz71zi1LFzvHn1bR596GFyO7u0pzMEAh53p2YIBsNEgiH+zb/5dzz19DOcO3eOV1/9Jql0kqm71ylVynR09TAxMUm90UJTwTAMVpeXGRoaIpFIMDd9nxs3LxMKhXBdD033UfXurl7i8QSbm5u0Wi0ikQi1Wg1d15m547MIHn30UTY3N7l79y6jo/3o4ZCPhLvQ2d2Fpmmsb2yys5Pl/R/8IJZlYZomg4ODhEIhQuEA9+7do1KpIMsyMzMzxMNhHMehWChx9OhR0m3+hKooCqZpEg6HeejB09y/v4imaczN3SMW1Wlvb6e3v49wOEwun0cLRrBaTbo621EkmW996zUefvhh3njjDTKZjD/9iyJ9/f2IssTtm7dYWV5GkmXGxw/Q0dHBxsYWlUaDyxcucvb0GSqVCpFwGNcTSKSSzN+/j2maiIJGd3c3uqrS19dHPp9nZvE+0UCI3u5uTNsmnYhSLBYpFouEw2FEUaTZsiiVisRiMdbXVxk/eJj19fV9oGtxcRFdEtAC/s9GkDTMRpNgSCGRiJDPF6nVGlQMD1WPEQiHqBR3iKgB6s0GYwcnqNcqWI0WLh7pdJqNtXU820He242XCnkkwcM0W3iugxyOUW8ZBDWVam4HRVFRFI1Go+Ef73WNqmEQjSVoNQxcy6HWrGPbNoIk+sh2rYJltRBEh3BEQ9MUGoJFKBLEkRuIqkVCi+N5HtmdAq4LjbqB1WzgIeLgoOgSmmzxIz/6A/yrf/fvOXp8hOPHThLpChHUAyiKTL1apVxsMTU1w8z0Peo1E10P4okergPpdBvj4xPoYYdKrUy5XKRcL+G6NoIjoygakXACRdZxfCICIgKe4+A5Lp5jkIq2c+n8VSQ1gCAI7Gxv0R6P8vSz7+HY2WP88NM/993ZQIeHxrz/9z/8eaLRKHfv+utSQZBIRGPcvn2bM2fOIAckpmemWF1dBXzQppIvEY/H9/c+tb0jfiKRwHVdbt++zeGJSdLtaW5P3WJwcJCutnbK5fL+lFoqlbj0zgWSqRiiLHH0yClMp8ZX/+TrPPH4+1hfX+cTn/w4lXKBRqtOy3RYXdnmPc89wx9/+SvEIhE62tppa2vDlkS6u3vxPAFNDTC7fI+Ojjb+5Etf5OSx03R29PClr36B48eOEQ+GCWo6yXSA9fV1bl67xfufeT8b6+t87nNf4kd/9Ed5863XGR4ewjSqTE1NceTYcV59/U2i0TgNu8Wxo0cxmy2+9tU/Jajp/Mt//a948aWvcvv2LVxH4NDhA3tNQaHZNLBtm0LRBzq6urpYXl4mFowjCAIjIyNcu3aNp59+msX5aW7cvcOBAwcYGRxiYWGBSrXGsRMnWd/c5tVXX+XHf/zHuXTpEplMxgfRggq6rhMIBCgWiwSDQaxmnWbToFqpkUikKFdLHD9+nGazyc7ODtFolFhMIxZNYBgWq6vrZBJx2traqDTqTB46yNTUFIoks7u7S1dPJ6MTo0zfnPK5lpbF4OAgOzs7rK+scvaRh3DwKGzvkk4kefP8O8iyyuDgILFYgt2tHKZtcX9xAXtvf5jKpMmk0hjNpr97TqSp1+sk0inOnDnDq6++ih4NI7QsJicnOX/lEgeGR6nVavT391MulxEEgZX1LcqVEiMjIyws3OOhhx/jjTfeIJlMMjk5iW3bbC0vISmQLxZo1E26u3vJ5rbQdYWt3R1aTQtFCSDIIcqVKvVKlqAeQtUV4pkktUqVgCLTNFoIgkCjVkcRJeSAhoiAa5t4nke9WiEY0Mm3TJRAEFot7GYRVQ1iWwLgIoh+k6y0TBQ9QKtmYhsWZXOP+hSPUanXUBwLxzEJBBVEycHzHISwjieAHBCRdVAaFi3DwnEcHNeiXC7jSSKCJxLQRDKZEO9//gk2d9cYOzCE4zjYDtQ9l4vvXGZxcRXRU4jEFIqFKp4r4Xki4VCcgcFOIpEI9UaVnZ0tFE1GEARkVQFRRFJkFC+wx1nFB9JUnx/s4GHaFoIoElci3Lx0C1WJgBRAQqOYy+NaTVygaRtU7xvfnQ20Ld3uffR938OJUyfRYxEaRotqueEv+NvSTN26SbVaZWlpiWazyenTp3nttdcIh4KkUik822J25i5Wq0xHTz/ZQhlJDvDMBz7IV774Oc6eOU53RxcCCrvVKm7L4NaVS9RbVULxMF2Zfjo7O9E0bW9y3aIt00kqleHNN18nmYoRS0eJx9JIkoxlOgSTKY4fPMzqwhLLy8v0DQ6QyqRJt7XT3zdMqVwjEW/n+o3LXLv2Dg+eeZC5ufs89vRTTM/fwjBrlHYLdKTaSWXSlEolEqkU71w4z0BPLx0dHYii6IMyaR/9D+ohXAeS8TiG6NAsG3S1tVOvZLGtBsFQhHKhxNsXLnLo2FFKpRrb29t89KMfJZfL0d/fz6/+h1/Gw+HA5Biu67K2uoksy8iyTDAYZGdnh4fOnWNxcZFQKIwsqzQqNQ4fP8rlq1fp7+3lla+/xHMfeo7Ozk7u3LlDoVDgxNFjxOMxBEkkV84TjYbJbuZIJBKkUxnGxw9w/fp5Go0GjXqLcDhKuVzmzLmTvPTSSzz88KMEgmGazRbhcBhN08jn84yMjDA/Nc1OLosW1BmZGAHDIxgOksvlkBSR7e1N8rldotEoK8tr9Pb2k0ql0HSJe/MLuI5EJBIjkQ5Rrxmsb+5gmj6VaDuXY2xsFE2CWqVCud7gwQcf5PXXX+fZZ5/1+aZNi67eHlqmwfLqKodGR7l48TKPPPEEuVwBxxPQVZn5+Xn6+/txHAfTqCHLKlN3Zjhz+kE6OjoplHexTYPrV69w9MghFu+t41AnmQ6wsLiKIoVJt3dQLlXI5/PsZjd8ylIwjI2ILAoEFBHTNGmZLp4LakAmFg8i4IJj06hXwXUwPJ8+12w22d3dJiSpIAoIIRnHsQgHdYxaA9MGy3RpGjaOB81WBUGQQJKp1hsIok08HsVxTQyzCoCgCvvPGcuyEKQGkqRhGja208D1DHJWlaBsc/zQGO9/+jFS7VGWljf48ldfJV9oYLq+OCCViCJLHrFIkGq1SjgWRA9qGJbH2voO+a0youTRM9BOe2faJ867Aq4LkiSDJyIqLo7j4Tqe38QlBxwB0ROQJQmjZZFf38F1BDxPwragWWrtMWgEpD3y//Ls1p+7gf6lEen/bAUCQR559EkajQZXLt/gfc8+w+3cTW7euMLtmzcwzRaSqBKNRolEIszOzu6j34qicPnaVYaHBpClXuoNn2D8Az/wA/wf//T/wz/8e3+bN996jTdfe52AFmJo8jCpWIxytUIyGScQCpHfzTIyOMTm5iaFbI5IPEogFKS9o4OJyQNks9vMTc9x5IhGtVLnoYce5sKNWwx2dzMyMkStVkHVFbLZLVJtKe4vzNLTO8jS8hzpTILJyQmuXb+E43jEIxHu3LhJf38P8VCE5eVFNjbWOHr8GHpAZWR4kPxunnq9TjQapdVqMRTuJTwxyebOLqNjE4iyxM2b15kYP0CzVicQCHBj9i5DQ8OMT0xQrFTxRImJiQnC4TAvv/wyL7zwAi+//DJ//+f+IVevXmZ1bYXh0TG2t7Ikk0mSySSu62IYBoriU2ocxyUUitA/0IuqygwM9pGKJzhx8hhjE5O8/vrrnDhxglKpRLlUxLQsXvnGy3zP932cu3dn6O3oQhRFNjY2mJ6e5fjxAyiKwsT45D6NanZ2ng9/+KPYjoeoKLRMj5bp0taRodYwWVrZwPEE4okEoUiIUrFCPJ7ABizbJpvN49ouHR0dNBsGTzzxBF/96tfo7OwknU5jWR6ObbOxsYUU7GNnZ4eJsTHmZmbZWlumo6efrbV1RocGScYTBKMJdndznDhxio2NLX9K3Nwmk8nw0isvMzE5SanWIByPI3hgm4Z/HMxuIXkOkucQ0FWuTC9w/PhJuru78XAoFPLUW1V2trc4cOAAs7Oz6KE4mXQ30YhCo27T2dbLbi6L5PkX5kBPL8urSyRSGeqGRTAYoJjdJhSJUK6WCIYjRENBWs06qVSKYi6L53kEAyES4QzFYhHPsfFcG1fW0YNBmlaLnq4eNpdWESRf2WOaJpZlIMgSiqLgIWLaDrqqIMgirufQbDZxPRdZFmnVW2iahivtqaiEKJbt0DCaIItkiwXOPjrJ8889iy7IFLa3+Le/8llaTZu2tk4UUQPbRosFkDUR13VwZOjq62dzc52FxXVsS0CVggSiIdLpJLFkmKZlIgr+Dl+SJFzPAcHCbXh7iisZQZBwAcu10FEw6wa5zV080/+YZTg0Gi1f4SgICML/MyLSX4kJNBHPeL/x73+XoaEhLl27ysb2FuceOM6Xv/hF6vUqsUiYzt5BEokEwWCQ+fl5jh07xoW33qJarSK4DrZlUK8Z9Pb3USiX6Ozs5Ct/8sekUxEUCTrbu7BNm97+YTo7O8kWshiGweL9eRbmlkgmk9RqNYaGhnj/R5/j0sWrjIyM8Vu/9Z84dfo4GyvLqKoK4NNTkPj+7/0E+WyWQCiEKwnEwhGu3rjJmdPnkFWFubl5EokEiiSRSSVYXFykv3OQSDLOzTs3ySQS3L55lYGBAUqVCidOnfR3WxtbvPjii/T19WHbNgNdXfzW7/w2Dz7xBJbrEU0mUG2LnZ0dUokkB8bHEZB48503sU2TnWweLRLh5NFjtFot2tra2Nzc5OLFixw4Msbubo6HH36Yz372s3zihReYm5tja2uLzs5OLly4wAefe47bt28TjydQFI2QrtE0DTxRQBZEeru6KTeMfaXL0aNHGRsZotVqEY2G+fVf/zV6ursZGOhDkiSSyTSu49HZ6aPn8ViScDhKNpslEo6TaW8jns4QisUJBkNsb2/T19dHsVj0aSxmi7W1FQJBjc21dXrHRomGI1QKeYKqyu1rN0Dx6O7uJpvNUy5XMQwDAZlarYaq6qysrGBIIg+eOY0iQK1UoVzM0zc0SrVaJZfLEY/HsQWFsbExdnd3KZfLPPzww9y7P8v46BgLCwvs7u6iqmHC4TChoEqzVaOzrZ1yqeDTqfJ5HzUORanVaty/t8Dp02eZn59ndHgAcLl+6ybJZBxRD9LVmeH+7AyDXf1srG4hqQIgc/nyRVRNJBgKYbse2WIFRRLpzCRZWFtDkjQSqTSqLhPAIhAIcPP2LeLxONFoFFyNQFDj/v15wCMQSYAkkkwmqRZKmLUGoiJTb9URJbBdBwcXx/WpQ/W6z1qQFIFKpYLjWMiKLxv29o7LmqYRCARoNfOYtGjrTXHo9EEiiTAdSZ3zr1/i2sVrdKQ6yTdcZFlCwEbXJFRVQYspeJJApVal5RhgypgtC6tlI9oKwWCIrvEMkiqB6OK4FrgKouRLOx3X8GXBBLFtFwHJp485TSJ6mNJ2DqNcQ3IEcENUq3VaTQNRFPH2JKqiKCPgS2kX7q5/dx7hJyYOehE5TWemja6+XgaHh7hz5w7ZbBaz1aSvp5vesRH6+vpwXZdXX32Ve/fu0Z5IYlkWttHCc21+6K//DW7dusH25iqC6OuOmw2baETn/vwCu7t5PvaRj5Foz/DGxfP09/Rz4vBRyrUqqqrS1tbGwsICi0tzPHDuYQRB4hd/8Rfo7ukgGY2wtrZCvVGlp6eHk+ce5c1vvUZQD3DqoXMsrq5wcPQ4uWKOM2fOcG/hPr29vfzGr/8mTz7+FDtbaywsznLwwBGee/4j/NKvfIahwV5mrl2iWCxy/OQJ0u1tTB46iOtT9fa5nYVCgaXVFa5cuYamBugfHCCiSORyO5RKJQ4fPUUsmuTK9QuISDz86GN09fVy5cJFarUanuf5LxrZLLLiIokKr7/+Jq2WSVsmRq1W48CBA+i67nMLXZdsNktHRyfXrt2gr7uTZCZNoVzCsx3qlSpSMEJbWxvpdJpQKEStUqWnp4uNtTWOHTmM5zosrdxH0zTi8STFYpmALlMoFDBaFoFAiK6uLg5OnsB0HMKpFJKq4ArOPnodCASoVqtIjgeuTamQp1ous53L7yu+MukkpVKRaDDApUuXGB8/QDKRwrZtZmdnsR0LTdNYXFykYdh0dfUw2DdIPl8gGAxSKO7Q3dXLdj6PY7vEEzEikQjZbJZ43JfGDgwNYbZadLS1886bb3H04BFu3blN92A/61ubHD91kq3lFcbG/Cbb29vrcyQtiz/90z/lkUceoVwuMzLQTzaXo9asUW1USMRTlMtlTNPm0ORhNFVnaXGWUDDiYwGCRVDTqVRrFCp1XNskpKvsZguEQ/7pSQ9pCE6NRr1FpVZHDwRRAzqKqLC2toLr+hxqURCIp1NUm008T6CaLWE7TRRdJxqJY9oOuWIBB49GvYrZauJ6DvVmbd/7wNfUgyfJqKpKJBLx+adGFiUgEo6peKJALl+kVqsTCgTRFIV6qQyaiih5ROK63wwFC6Pli1AE16Ner+O4Ko2mhabppDMJ2jsSCIqLaRsgsucZIADivqZfFH2/AM8F1/X5rs2aQzFfwDNdJE+kWW/QakkYhrGvm1eEb9/fb6CKojB/e+W7s4EODY14/8ff+2dEgyGK5RKBUAjHlYnHIlx4+y06OzsptCpcunQJz/N4+OGHiUQiBCQZz/NQJZGArnLp2nVmZ6cpl3bRdRnLbvHQuae4dOkdIuEwIS1CT08/c0sLHDp5nHKhTCmb5/gDZygWi/zBH/wBzzzzDKvL9xCQSaUyJBIx7t2fJShKZHM7ZDIpVFXmwtUp2lJpcD1GDx2gd3iQ9XtZ2jo76OjoYHZ+hscef4Ryqc7aygahgMz5C29w6NAhTj3wCFvZHK5joBkNqtUqs/NzdPf1Uq/XOXnqDM1mc6/5xBFUmcuXL9PZ3kV2N8+dW7foSEY5f+ltPM/j6LFzbG3m6Opt49GHH+HO3Wnml5aQXJfDhw9z4cIFDMPgwx/+MKsr97g3v0BnZy+Dg4M0miVarRbb29v7yPJD5875u8pGk0AgRKNapK2rg77BAe7PzbOysISe6KC3txdN0zh37hxvvPYtnn7qPVy/eplkLEqz2eTsg8e5f2+RUqnC8PAomxsrXL58mUcfeZy2tg4KhQJ9PWOEYhHkUAhXENnOrxONRpEkiXK5TCaTwW6YBHSVZqWCpiisb24DUCjlqTeqqLqO6jpUq3Vu3brF8NAIvb29fOWPv0gymUSSJIrFPMlkG909/dSbFo26gSgpVCrbnHvwIaZn51lcXub44QOIokihUMC2baLRKEMjExRyOSr5ItFolO2VFUKxKKYgYngCHT3dhEWJQCDA9evXOXr0KDN3p6hUyySTSdrbMxQKBQ6OT7C5vUG+WKR3oIegHuDNN97myfe8j2ajRSKd4sbVdxjoH2F2dpp8YZdYIEAuXyIYTVDMZ3HMFgE1iGF5iJKMqkkYRpFyqUpbRyeW51Gp1vEMA8dxiMWjbG1tMDo4QMM0qDkujWYLyRWxjQrhaJJoJMHmdhbHA0d2qZaKeI6J0ajjiO6eoYm/7bMtF0XTCIVC6LpOq9XCo4UoeSCYOLZHo2ESSMQxzRqaIiJLHoJoEgjptLwmtmBhOhaqEMRstnAMGwkBwxFpNE3au7vo7m/DFVrI+AYonijgCR6S7OztQSUEQUSWVFpWbc9sRcC2HHZWSggeuJaL60K5WMIw/Cb5bR19QNozdRFlJNHf587dWv7ubKDd3X3e+x7/IKlEkprVpFqv8eyT76VWqwFQLBZZ316hVCpRK1fY3d4hGAwSjccYGBiiu7ubd86/geq6BAIhtnd2cTyX9vZOJFUkt7uNrmo0GjUSyRgtw+HMuYdY21jhlW98nZAaZmRkAFGUGRs9iGG0mJ6e3teXu67LUP8gT733aVZWVsjvZmlr7ySUiBGJJ5AFGdeweeP8WwwO9qKqKru5EuMHDxCPxvjsr3+Wn/gbP8Err7zCwvwtzjz4GNl8gWOHDpHb2cVxfKefRqPB5uYmPUOddLR3+TQOT0AJBAC4+PabbK0tEwoGkNQQL3z4I3z9a1+jv7ePiYkJNitlSoUC6xurzE3P0NPTQ19fH6Io8tZbb/G+970Px3F4+803wLWo1so4lk2pXOWjH/84c3NzjI5NsLO1S2dnO5cuX+DgwUlK2QKDg4M4jkOhmGd7e5tIPIWmaRiG4evee/q5c+sGXR3tNGtlBvv7WFvbYGL8IAsLCxhmgw9/9HnOnz/PzZs3+ZEf+RFM0ySU6kALBmiaBoWdLNV6zUe4e/t8RYooEtAkGi2TcDjqu+tYLo4ApuuwtLBAPBwlv7NNd3c3+Xye+fl5enp6WF9eYnNzE8fx9d2uApoaIBgMYhgWoihjWU1C0RjBUARN09jY2iQRiVHM5nBFgVR7BtFz8TyPZsMABETPn3zUgI9GlysVBnuHcTzfpWt1fQ23VkFVVYaGhtjZ2WFjY4MPfegDrK+vs7mzjarqGI7H6Oiob9oSCvlGIEaDQrnEjRs3fIRdU4nFIri2zfWrVwgGdBqNJuFIjFq9ieUZ2I0mHV2d7Oz6QJqoyOTy28TjcVZWVkgmkwi2r2YTBGFPwmtjSTKZdCcgUCrnsSyDgOShqjLZrK++an7bFWnPV6FarRLWQqgBnWqjjid62E4DzxOQJRVdD/oOUW4DWZPwRBslYOFIlt8IPW/PQcrBthw80wXPo1ivEoqHGBoZBHzZJXt6fkmSAAFJUvb08C6C4PO+XU9EVW0kFLLbZXLZIpoTxHNcquUarZaJa9l4gi8L/TZa7/uXiXsubDKIBlNX1747QSTDMOgbHGJm6g6Hjh6hp6+H3/2d30aSJLLZrI/KKi6SKJKMx0gM9PguMrpGJhbh9W+8iCB4CJKMrnuMjIywsrbq71SvXGFsZISrV98hGNTZ2Wnx8CNP8J8/+1kSyRiD/QNYDZNmo8HW5g61ssnQyDCLiys8/fTT9PYayLLM6tICM/OzXL16ldzmNnosziOPPMIf/9qvE1A1vud7voexyQPIkkc8HGL53hK2ae3v1hw8Hn3icRYXp7h58yo9PX3kcrsYLZ+sPT42SbFYpL9vCEtosry8jCzLlMtV2jq6OHz4MMeOHaOjLcPN61dJhRPcunWLoeHhPfMFkZXV+9imRSIRIRzRCIfDRKNR8vm87xi0s0NXW4ZkLEwhv0NHJkmj6ZAvlJidnWV7a5dsrsDhg0dwHIdjx46xvLxEJKAzNz+NroUIh6M8/6GPMXdvmnA4TL1eZ2drA8txOXhggkatwmaxyMjQIE888QSO49Ld08nt27d48Wsvce7cORzL5c3X3+Khhx6i2WxiWha1Wg0Bf68mIjA1NcVAfz/hQJCtjSw9fQO+7BOIBiMEAzqm63Do0CHWl1cxDIN6vU4sFqOrq4tSqUQyGWd1dXkfGDNNB1lSKZVKuK5PlVMUgWazie14vgWervmKJElG0lQ2NzcJyT7goCo6kqRQrjd8KWWrSaVSQVJkBNejVCyyWlulVClz6vAY09PTOIu+JV+9VeW185fo7e6glC8wPDSALuncunWL48ePs7CwQDAYpC0ZJRmL093RyW4+R3d3N1tbG/R0dZFKpXBsi1qziYvnE94F3+HKcRx6enooFosYtuWvr5p1wAd+KmUfbHQcB9M0sW2beEeCSqWCaZrE4iFUNYJj1imXy7iCiO25iILPJZYlCceyUSQZV7BpNuuEwxGy+SKSrOy5QIkIgj8ZiqKC51mIko2Hb9sI3j5o5SutZKw974DO7i6SHSFkxUMPBrE9G0FwESVl7+gu47kCqhzBcZvgmUiyf/qUPY1CoUwhV0JBxTIdmo0GjUbL3+OKMrZnIoiij9qLMi7+79SRLBpOncH+Tqaurv23m9R/o/5KZCJJosTv/O7v88L3fh9/+Idf4FsvfYPTx4/wyANneN9Tj9PX1Y4myMSCYerlCp7Vol4u4BgmF956m3MnTzMxMoyu6+TzeW7d8pfp6XQaUfK1xKlkhkymHdu1ePPN12lvS9Pd0Y7kOMRjEerVCieOHyegBfE8m4cffoBbt64zMzNFs1nj7vQMV69f5/0f/CCPP/EkQ0MjbG9uMTk8zOBAD1/+yh8hODatWpUX//RPuXT5ApIH2a1thoaGuHDxIi3DoLtngFQiSVDRKFfqDI6McvPOFDfvTKGHwuzmC9TrTRzHY319Hc9zWF9d5uL5t9lYW0UURZ77wIcIB4LYnktnTzfxTIqbd+8QCoUoFHLcmbrNqVOnsAyT5cUlOtraOXr4CK7tcPvWFIcOH0NRg1QrTQJ6kImJA4RDUTxP4OMf/15u3PBlosFgkNOnTzMxMcHzz3+EwcFBDKPJ/fvzTIyP4dgWoyPDPPH4Yxw7OM7q0n2ikTAPPPAAN27dplyu8OKLX0cUBR566GFq9RYLiyscPnKcEyfP0GxZxGIRZqfucP3yJS5fvsjmxhqNepVkIsbu1ibbmxu4rkuj0SAej+/5i/q0k1gshiiK9Pb2cuTIEd8tqV4nFArR2dmJ7Vik0kk8XOqNGkazRTFfoJgvgOvhOf7FrCgK+Xzed0gyTRzHR51N06ReryPLMhvrW9i2S6FQQA8GOHBwEtd1fSqVByvLy4QDQVqNJookEwhFqTdNFC3Ibq6IIKlsbW0xOzPH2Ycf5ubUjO9Lqmmsr69Tr9fJ5XJk2tsoFYu88uJLdHd3Uy6X2dnZwTRN7t27h23bRJJxWraFIEsIrkerZbC7k2VpaZlms4Uk+YhzpVKju7sXw7CIxWK0t7fjOA6CIKDrOqVykXAkiKZpmGaLltGkVCnieC6qrmGYLolEYp9WJkmSLxrY85AtF4sEVQUQaTYNAgENsLHtFqLoISsOHqY/8VoeAjKO7RuBtJoWrmNhuCYdA50Mjw0RjYdQNBnLtZBkFUXVkfZsFj1R8O0WBRdJldE0jaAWJKyFWF/YILueR3UVvBaUSiWaDQPPFXxgCRFJUvYmYH96dSQPMSDQ3pfkxIOHyfSkv6Pe9VeigbaaLf7Fv/h5PvMff5VPfepTdHV0c/nSBS5fusDiwj3yuV1qDRNF0QkEQlTrTdrbO9nY2iGRyjB3bxEXed90trOzk9OnT/PSSy8xPDKAIHoIgkQhX6G/vw9NUzh88BDlQh6z1QRc+vr6WFvdwPME+vq7MMw6lt0kHNGx7CY/+b/9XZ568lnWVnfY2S35VmXVOiFJpl4s0d/VzZ984Qss3rtHIByiq6eHmbvTRKNRXNdlc3MTRVNZXt0it1MAJKoVg3xxlwceOsOBg2Ncu3GZvoFuXBfa29sZHh5mZHSIro52drY2cV2Xmbl53nrnPO3t7bRaLS5duUwgHOLu7AzBQJihoTGOHjlBNpsjpAc4/9bbWC0DCYHerm4iiRSCohOOJXng4Ufp7+9nbGyC7u5eotEoW1s7jI+Pc/fuXba3t5mbm2NtdZvZmTl6ersZHRvh8JEJXnzxRTKZDDdv3vQNKlyHE8eOYraa3L59m6GhIcKhKM899wzT01OEQ1G+/4d/mM7+fjxFYfr+fWxRZG1thWajRjwcwrEMNtfX2NnZopDbpdmosbW9QaPRYHZ2luXlZXK53L4BcavV2r+og8Eg9XqdgYGBPSWWS7VaJZ1O09HRQTqdRnA9HMvCcxxa9QaOaZFMJmm1Wti2TavV2jfbMAyDSqVCMBik2jSxkSjXm7RsF1ULsnB/GVnWUEQVx/R8mo/rkk4k6WzvYGlxFQEZ03BQlQABPUxvZzuSJPGFL/0xx8+cY2tri0aj8V98ASSJ2Xvz3L55i77uHiTJBz5ardaep+rYnsGIr/luNpv+BeSJGIble2NqAaqVOvWaSSScZHBgDNsS9j0/I5HIPue3q6uLXG6XSDS0Z1yt+5JQEWLRBJlMO4roN+mgpiPttaNQMOpLTV2Laq2EbZuoqojttHBcA0UF1zNxPQsEF1FQkKUgzYaDY0tYpoDryBitBpOHD9DV144nGjiOhyApaGoASVRRtOB/BWAJgoAgO4CLpMhois78zCJm00QVZFo1k2K+hOf59/GP7Hv3Q0ZA3tuDWqQ6EwxPDNLRl0YOSAQi0e+od/2VOMK3d7TTqJd56PRpdrc2KRdLHDpyiPOXL5OIJjh95BQNs8bCwn3i8TjIAnPLi7z/wx9DESXWVleoV2sMD00SCoW4e/cOv/Wb/4nJyUliss5606K3b5hbd6eQpAR9A2lm782iBnUqlRJSpU6pVKOnt5+pqWmOiyfZ2MoS0kL+E0cSqFWyqFqAc2dOY546TTgQpFjIsru7zZVL5zl+7BD5UolkZxfhSAxNkpmZmeNI7CiSJBHQVK5eeIdYLEJbWwc10+PRxx/Ho0mtUuFPv/oVnnnmGWambpBqS7G6uoosy9y/N4fkebRlMmiyQE97isXFRV6/+A6HJw/y1BNP8jM//Xf44R/+YV772p/SaDTo6eljZyfLsePH+fjHPsbrr72GIXpENte4evUKh49MUqlVyZYKOA2DgwcPUq/XGe7vIaJJtB0a94+Le2a8awsbnDx3hlfffIPh/gHCapTnnnuOYDCI6/qE9GbNYGnpPh//+MdYXF6iXC7ymV/7DD/wAz/A4MgY33jtG4wfPEJbMsHM3Wn6uzuIRHXypSKtVpNauYKNiyS6rC7NE43GfQ7s4AjxUAyjkUWVZFRV58KlSxw8eNB3hFf846OoerRn4iwtTlPIZUklk7R3dFBplMj0ZFhd2SQUDZPPF/BcgZbVIhgJs5PLE4xE0fUAkivhGH6DdV0X2zSRAyFcJGRLICiolAyD3HZuf2rt7u5meHiYSq1OyzSJpdPouk5u27fA3dzYJhZLEAgEkANRjHydRCTF3btzgEc8ESYejzMze5eoEaZSVpEiMXozaVIdbdy4M0U8k2FpbZV6tYYky+iKTsEuEAj5nMhEJkxHRwdTU1NkMimsTYNoIk0ykaFYqnHoyGFqhSLJVIpSucLA8BhNo0W6o5t6/RqtVotENEE5X8EwXWRZ25soA9RaLRxBQlA0WnYVSdFwbX8v6QDBsIaqRxFcB0wLT7Cptwx03UaSVNjja9plExmJqlnD9AwSbUn6u4dxVIGm3UKTBFxNRpJEXBEEwcF0GkiyimuLiJ6AInvInoUoyVSyZWaXNpEFGbspUKs1aDUdPFfCwUASFTwkHNcB2cOVFBAc4pkgXT1pAuE4gUAAPaAiSQKKonxHveuvBIg00D/sPfX4B+lq72BtZZkHHngAwTVQAjp3785w5Z1L9PX10D84wMbWOtFElOMnT7C1sckbr76GKit4rksqlaKtrY3FxQVisQhra2u4rksq00ZvTx9bWztM35thZHAQ2zJoGTUKuSyhcJxILM7ExATTs/NMHj3MzI3bFLK7HDl6iLXNDTzL4+KVa5w4dYbjZ85w6/otnnricfL5LPOzd6lWSvQPj5IvV/jBH/oR3nnjTTo7u6nVavuyQ0EQGB2Z8GkUskZXVw/L6/dwLIu1lWWKxSKF3C4b2xucOHGC3d1dBgYGuHPz1v7y/bHHHkMURfRYDNsweeO112Ev1uLM6RNcuXwVTQuQz+fJFgtMjo2zvb3N4Pgof/ynX+XM0ePMzs7y9Hvex4kTJ7h85TwXLlygs7MTy7I4cOAA9+bmOXr0KK7rEg6H0fUwa1ubTB49TLVQQpcVPEx290CLyclJ7s0v+kqglSWeefZ9bGxsoOm+TLW9vR1RFLkzM8/EyDCSIGK7FuFElIWFBRZm54nFYki6im01946rC3ieR6PeIhVPcuzEKRRNR9d1Ojs7KZVKdHd3s7Gx4bvFhzUcy2Bra4v783PYlkU4FMWwGyyvrJHLlkikU8zMzOI6PiiSSmWQdJW+wSFqlRrbaxs+cdy2UWXFR589CMUS7K5vkkylMFybnr4Bdnd3/ccsSYyMjPDOhYsMDflc2HK5TCSgsru7i6YG6O7uRRRFku0ZvvXSK4TDYZLtGRRForu7m5WVJWRF9PmJ7p6zr+CytrZKKp2hUa9hmia1apmOjC81be65yUuSRF9PL4IgsLy8zLFjx1hcXERSBQr5KgcPHmR2borO9nYeeewxvvXaa5RKFTo6uxFFmVu3bhEK6riWiWmaNJo1FMWX5VqWheX5gFOpVPKBM1Wl2ajjer67fTgcpmkaOKaBiI2oiIiajKy0EGUB07FoGQaqoNIwGrT2mmdXTyeC5IEuIEqgSCDI2j5VShR91Nx2bXBBkyRcp4koiuS28lTyFZyGh23a1CreHkC2h6x7gCchCIovPRVdvCB0dLTT3dOJqsroYd//1LINgkEdTdP4zM/91ncnCh8OxbwDw8f5ib/5/wLXZmpqissXL5Lu6iQWS3BgfJJaKc/o+Bif++If8ukf/jS/+3u/R0wWqTcbhEMRHnzwYabu3mJ7extwMc0WsViMYqlOLBLlzu3bTE4e4IGHH+LihQuIIriOhWc7xNvasF04ePgQ2WyOxflZmtU6jVqNRCqFIwuY1QaeKCHIMqn2Lh44c5Yv/OHncRyHT37f9zA3O0OqvZ1gNEYuX+TowUNMTU3tO4UXCgVmZmZ44tGnWVpa8l2KVJUHHn0AyzD4lV/6RY4ePUoiFmE7u42iKNTrdTY2Nnju2Q+wsrLCwMAAnZ2dzM3NoUcCXL96lXq1xrPvfR9f+9rX0DXVBx02t7Ftl1A8zNjgMAJw7eYNFF0jk4hRrTTY2spimQ4TR0aRJInx8XFmZmY4efIkNy5fJ51O09nZya1bt3jyqafJ9HaxvLJCsVCgr62Ter24D/ClUikS6U7i8SgBTSOf3SUei1JvtWjsOdpvbGwQiiWZnbpDIhZH0WTaezp5+603wHK4f/8+tuBhWf6R9dtZNwE9RDqRJJFOMzA4DECrWUOWZRKJBIODg3vgkkNI11AUhRvXr6KrGlvrWxi2wY3rd+jrH6Gzr5P//J9/i0jY350mEinSnRlyxRKd7V1UiyUaLQPPdohFfBUYrsuJM2d5+7U3kFQFRIFUph1N01BVPx8rHo9TrzfJ5/OYpklvby/NVpVIJEK5VMXzBEZHR7k7M43oeL5LWG83eiDgA3GNKrVaxf++RZ/I/u0sq+xuHk3T8Bx/Z2jbNq1mjVgstn8s1yWFkZER1tbWSKfT5HI5tnbX6esd2gN1HEr1Mh0dXdTqdXLFEo7tUS9X0HWdaCSE0ahjmibZbBZBEAgEfLZCoVzYB3NlWaZer4NgIYgqpgXBYJhqM4eEQKteQ1AEtFAQXXept+pYroXj2YQ0lbrRZOTAMCgCnuQh6RKBgIakSXj4oJ60l2sEfhNFdHEdC03wEF2H+YVtmpUGki1SLzRxWjamo+F5NqLk4nkOjunTk4KBEKIkMDjUjd6uEwqFCAbCgIjr+Ud8n5Tvc0P/wz/67b98Q+XvpDRN41/9y5/n0vkLXLt2jYvnL/D008+QTnXwoQ9/jL7+IVq2xZtvvsEnP/5xfu83/hN2pYpjGYwOj5BOt3Hnzl3W1jeIRGMcOXqcnr5+drI5HMOhXq9z/ORxOrraefON19jYWGOgrx+zaVKrNVhbWeWlr32dZqVOKV/Gsy0kwSMZT+C68L73PsvIyDjd3X089eSzPP2eZ+gf6OaTf+37+NDzH+DGjVusrW4yPu5Pe7dv3+bmzZvEYhE2NtaYm5thauo2fX093Lt3j1AoxPr6KtncNrVajVKpxE/8xE/sOxwdPnyYt99+G9d1eeqpp7hy5QqyLPOtb32LL33pS6ysrNBoNDh27Bjd3d28/vrrhMNhhoYGKJeL1Bs1OjraaOto58KFC0RDYXRFZXVhCdcTWFxeQgvIHD0xyYkTJxBFkQsXLtBqtfazippNH2F+/vnn2dzYYG5qmum7d2mUq1y9coVq1W8QhUKBgYEBssUShVIZw/IBCxD2/TBVVSWdTnPv3j0OHjy4Hz0hiiLNZh3Pc4iEg6iSiOu6gI+Q1mo1dnd3uXfvHvPzc9y4ec1fUfR20NvXSTQWZHZuilBYw7KMPYmf7xva1pZmO7tNyzSQNIX+Ad+xStd1gH239rW1NTo62iiVfIu9ZtOfZFotk0qlRjQSp1KvgeRPRFowQKFQIJlMUq/7zkWWZVGvVBkbHkGTFRRRQg8EUFSVerNBuVrBtH1GxrcBqnq9juk4mI7NxtYO9xeXKVbKKIgItotRa6Gg4tkg2AJmy8GzRVQ09ECInt5+nL1gNk+A+fv3qDXqLCwtEgyHOH3qLCsra0iiTDabx7Fcdra2KeZLuJaLCL4vaNU34FlZWfGRccfZ3/16nkc4GMRzHOLRKLZp4tr2vg49FArtT4oAsqwS0CNEo0nYA4w8V0RTQ9iew+DgILbr4An+iUlVJMJ6AMn10XvHsRBFkGURfxB18UQBVZVRJZWVe1tYZRPZ1qiXLZotB8OV9xqguLf7VNAjGo5oo0dVRg4MkGgP+Ws1PYisaiiaSiAQQNO0fSevb0++f976KzGBJuNp72f+t3/E1voGeA5nzpwhneqiZrb4xc98hjOnzjI52cPMndvcuzuDZxj+EUuyiCcyRGJJ4skUPb39XLp0Acv2AQBwEQyXWDpONBFjYXUR0bbp6+3Fallsbm4iiwqyonDg0CEOHz7M62+8RXZ7iWg4hmnaeJKMiceDJx/k3/3iL3P2gYf49I/8GJXKGr/2H3+VkZERejp7iIYjZEs5QrE41VoDo97g8uWL/O2//beZmpqi2WwSi8WIaAl/ughpXLp0gVAySXsmQ63ix4Mk41ECYZ/3eePGDQYGBggEowwPD3PhwgXC4TAvvvgiWkjm8Uce5fjRY9yfmyeXy/F7v/uf6enp41Of+rQfMtfRxvjgMFfeucDJU6dY29zg97/wRR57/BEURWT+3iynTz1IKpUilUrx5ptvomkaR8aP0NbWhmmalMtlP+AsnWRzd4f8zi6paJyaWSGdTtPX10ez2aR/4jCNWp2ZO7c5ffwYtUqVSCKyzz2sVCq0bI/8zjaKJKPqCigitVKe+ZlZKpUK61ubIPmZOKa5F42h6Ii4VGoNtECAUCjEuVP+4+vo6PAv8nAYPRTGaNR95LpUIJ/NcfvuNC27xfZ2ES0Qp1bK0Wg0mZ2ZR5Ik4vEkruSAJBMNx9BlhVKliSJK2Kb/Ynb21Gly9QrZjS26errZzmXRFJ1jx47x5ptvkslk0DQNTdYQBIFQKESj0UALq7RaLUzTplKp7QcPDnT3cvv2bZLtGXYLBVKpFLZt0Wj4q57x/l4WF5cJh+IYholpQ0gPYBhNPNcmoKl4AXcfTY9EIkTD/s+5VvMJ5aZpEg6qbKzv0t/fz/rGCpFQkGrdp7sF9BDReJyVFd8KMRYNs7a8RC6Xw7bdfZWRYRgoqu/Kbxi+dNd1XSRFwRNEFFX110XlTWzDJqBqiIqKI0CzmQfJQ1R8OWosoeAJLq7qoQQU1IBGQBNIR+OUqjVcRcIWfUd94L8kkUoiZqPO7LVpQmISz3BY39hClFS6egaxHY/y7s5+wCAIpHvCtLd3EovF0AMikmLjiSlUVUFR/KkTT9yfQG3bRBAEfvFnP/vdOYGGw2FuXL5OKp5ibPIwl2/c5vKty3z2Vz/DuWOHOXJsnK2VFSqFEuFQlPauAYZGJ/nED/0tzj76NMmOLgZHx/jc53+HZrOI2SoimE28msnREwep12vIooxRadGe7GBsaGKPnxlFVgUkSebCW5e4N7/E8PAgpqNjeho9g6N4AqwtLRGOBvjrf+NHCYR09KDGlbfOkwxHKexk8V82JZaX1gmpQcxajdHBAQ4eOcrG9g79Q8Ps5guEY3F2ihvYokm2VOCZD36Q3rZOhodGiGUyNC2bpZU1atUWN67fYfLAEfBkuju7mJ2e4dSpU8RTSf7W3/lpHjn3FC+9+A1+7h/9Y5qWwNz9dc48+Ci5UoVbd+/SME1uX73OlStX+JOXvs75K5fItLcRi0e4dvEys3dm+em/8w94/bXzXLx0k6X1LR546BF0JcDNm1eZnr7NrVvXuHz5PJbi8Aef/z0atRKi6LKysUQmnqTVaHLr1i0Wl5b4ype/iGMZHDg4iRYKI2s6tYaJLOlUSnVEV0YSRMYmJkm2ZfYuIB3btFB1iVgiRH9fz/4EKorgujYto4aky3R0pomFNBTBYW1zg2whj+nY1JoN1jY3MBt1QkGdSrmArAj0D/VyeGIEyXGRPJdGaRdMG8FxiIR0XM/CtOrUq1Wa5Sq1UplisUhnMkG9WqOvf5jJQwcpNErEYxHSne3ooSDJeApBkKjVGrS1dRCJxPyIXsskqAf8uGFRQVSiVBsOeiBMNBLz7dUsG1kNYTkihVweTdZo1VvEYykEUUOUdJZXdwhHU9iAoCkouka+UUYMq3iy6HM5TYlEtJ1oKE2l2CKbzeF5IAoakhhkd6fC2nqJoZFJqnUDUdboHx6j0TLR9CCS5u8WR0Yn6B8Y5p0Ll5ECIcYPH92nh7m2gybKuD7Bgky6nVAwQigYQRNVNFEmHNAxWlWclgeugKKpOLaJJnrEYjFiwSC6KiHqLk3JxFL86RPPRUYgk+kkW61Tt23fAlKIINoysif5U6klUVnLsnxzie7YEOtreZp1gRPHH6S3e5D1lVXW19ZomjaeKIIGnUPt9Az3kOiIoUZkBE1BUMIomoSiyciqgqppaIEgWiCI44oIoo4oBb6j3vVXYgIdHR73/t7f+jk+/wd/wP/xT/4J5y9ewKo3ePVb3+Lv/szP8OLLL9HT1kky3UZXbx+Lq2u8973v5af//s9w6thhZGwUUWDm5m0i0RDFSom29naf5Cy6JNMZ+geHfX39tq+wSKUTBAK+ea6qhPAEhQMHJ7l79xZ35xYZHh6m0agxPDzMN7/5TVq1MgePniKd6WB4fJLP/davkUon6OrqwvE8mq06zUqNar3ByMgI29vbVMo1pqameOGFF/b3Y6guoVCI7e0dTp44zWDfKJValRvTt4mGIzjNph8TfPo0d+7c8Unytn+sisZiRKNRbM+l1miyublKtVbmicef5tixE1RbFZaXl30DDtelmSvQ2dnJ8vIynucxPDzMw08+yfTUXS5cuMCBg5OEQjEkRWF6fpo3X3uVf/y//yOyW5ssLi4yPj7Ozs4OC6vLBDU/ZsJotjh8yA+QuzM1RUeX73rUqBmomsboxDjrO1tsbW2hAQMDA5gtg46ODhwBrl+/7iu8ClkmJyeRcVlYnKNQyJHdLbKxu+3vHvFze5rNJo1Wk3QyBY7PBx0cGWZ0dJS2tjZisRiJRALJc+nsbEdVFSrVEuFwGMdyWVhcYmNji9u3pnBtj8XlJRAF8qUigUAASdZwbI9IxM9xcjyBfL7Eg6ceIp/dorenk2KrQatl0mw2OXrkOAsLS77zfDhMJBLxgQtFIZlMcu/ePZLpNvL5Io5lIAngui6rK8v09vfRqPuKHMtuIKGQTKdomQaGZREKhWhWyj4DwHH8THQUHBw0XcGqN+lMpkDz9+PfXrXUK1ne//73c/v2bRRZ9dcSPf37K5R0JolttFhaXfGd8dMpLNvGdP0jeyIZY3Nzw08XiCcolUrgelgtg53CLqFQCMuy/Mla09BFlVgiSqvVoFKpULV9jXm1WkGSBVRVJRhT0VURGwt0AVTbB09VPzU0HA6TiGcolEsoqn+k9jwBTZdwXT87qtk02FzcYXdzh1PHz3F/aZntZX/VIGsy1h7lTNZFevp7aOtoQ9Vk5ICwH9OsKH4ukodP3ZJldZ/uCOyrozzP49/89C99d06ghUKBP/j8H/ITf/un+NZrr1MqlFlYWOR7P/lJrly5ytNPvIdKrcVXv/4i+XKFYDzGD/7YX+dTn/prxONxXnvtDTzPJ9pubO1w+sxZPwTMbVEqFyjksjTrVWRZZnh4mMOHD9NoNFhfX+f8+fPcmb7LlWtXOX/+PAtLi+CaLC3MMTY8wluvv0FA9VUW3d3ddHd3E48l+L5Pfoq1jR0ESaEtncY2TJKJOGbTJ0SPHzhIV1cXjz32mL+8DgZptVqMj4+TTCYZGxvzo31DQRx87momk+Hy1Sv7cRunTp0il8vxwgsv8Pzzz++HnIVCIY4fP85T73mC7/u+7+XatSt+Y3IFTMNm+u4s0Uicnp4+Xn31dXp7+3n44Ue5desO3/rGqxw4eAjb9TBbvqPT9vY2Dz30EPV6nVdeeQXTNGlr8xMsOzo6eP755zlx4gTvec976O3t9U2UEfnY93wvkqQwf3+R/v7+fR5hd3c3o6OjlAp5rl25jIvD1s4mO7tbxOIR+vp7OH3q7D6YUyqVWF/3wwG/rUGv1Wr7qhlVVfE8b9/GLBwOc+PGDRYWFkjv0YYkSWJnZ4dWq4WqqpTLZQJBPwV0aGCQWDS8d5FX9xzZbRqNxr4ZRblc3s94Hxz0I4pPnjzpT46OH4nSaDQol8sMDg4CkEwmAVhdXaVpWKxtbLG9m6NW8U1XXNvxgaE9fqgf9uab/aqqitGsowiAY6OKAlbTd7f6tnLq28d0YP/7bjabpFIpJEkiFArR1tbG+NgEG+t+2oDtWASCOqom093T6VP5ognW19cJ6QG6uroI6gFSySSNeh08j5WlZXA9ZFHaZ4vEYjEMw0ASRGKRKAFNR0QgFAhiOx7Hjp5AECSS8RSmaZNIpLBtB0lU0LUgihrAtgFbQHRlQnIUxQkSU9uIyGmOjp1j/V6OIAl6M6MkQ93E5Axd0QHSgW68msrWvSKtksBHnvk+Zm7Psry4su+IZts2tmMSiQaYPDJKW2cSWQdRAVEScFwbPaAhKxKqpqAH1P1IZ/+Q4+I4Fo5jIUl+ZPJ3Uv/DCVQQhP8EfADY9Tzv0N5tSeDzwACwDHyP53lFwf9t/yLwHNAAftDzvOv/owcRDsa8l1+8xOr6Gr/1658lrAX4P//5P+P8lUtcunSJdCTG4NgAB48cZmV1ndffeIt0Os3Xvvx5wuEwH/3Ix1lYWOKRx89y5co1irs5jGYJERPR9TBsi3gsSb5Yor2tEwBNVyiVCn5Wth6ho6OHRrNJpjPFO996hUQiwebmNqdOnvUJ5QvL/I2f+Ft+lo2ksLW1wtmzp7l14zrl/C6rq8uY1RKKpjM4Ms795TV6e3tpb2/fX9RnMhnuLcxz7NgJ3njjLQqFAp/4vk+yW8xj45KMx5mZusPmyhqSJHHq1ClUVaVer9PT04Nh+dG0f/LVr6IIIk8+9QjVapVXv/UGi4vLPPLQw3z4wx9mbm6OL3/5ywz19XPo0CHm5+dRFIVHH32Ur7/yMoIq8+M//uN88fc/R900+cKXvsT3/+D3o8kSgz197G5u7KtV8vk8kq4ievDYY4+xu71DMpGgUmtRq9UYHhvFcmxu3rntMxricbo6OomGwgieSblaYW19neGxUXRdZ2tri2w2RzSS9F80khGWlu5x4cIF4vEktuCwurrKxsbGfs46okAiFsdq+QYZyUwb4XB4XyFz+PBh2pIxTLNFOp0iGgtTq9XQtAgCLuuraywvLnLx8nXW1tdpGi0aRgtFUYgn2lAVnaWlFX70R3+UF//k6zzx1HtxXJHOrgyvv/Uahw4dJh7385vOnnmAa9ducOjQIb7yla/wsY99jFqtxk6hxs7mBqoisbR4n2SqnXg8SiGfJZNMsbm5gRzU0bWI3+Q1AcXxp+z2zg6apg+CmaYva43GYhRKRRLxDA2jweBQP9mNLVQPXEUiHo+jKIqfLbSzSz6fI5GIoagSm5vfNmRR2Fjf4vHHn2Rt6b5vEzjQjxrQmZqa2t8z5vNZOjs70DSNerVMT08PO1vbmM0WCH6zbzab1Go1ent7GTtyDLNlsLayRHZnm4W1NUzTZPLgBHNzM7zvfe/l/NVrpCJhItEA0VSYYqFBX98AAT1IX98A6+ubDA4Oks5ksFwHx3OJamH+4HO/i2k1fRlyJMav/+pnOH70ICtrCwxMDnH//iKG1SIcDjBxcBQ1oCHr/g5TD4YRJHEPhBL3lWqu6yIrur9qcRXwBCTZ9zdwXdfntDoO/+anf+UvRAv/W8CvAL/zZ277B8C3PM/7l4Ig/IO9938WeBYY3ftzFviPe2//u9XV1c3ld65Q28s6Onv2LP/kn/5zuro6+MQnPsHS8j0mDx/h137zs0xPT/E3fuSHefWb3yIaCPPeZ57h0uXzfPqvfZL/6/d/m+2tXU6dOkOh6GtwA7JONpunWmkhCyr9/QNcuXmNto4MjZZJSJKoFGocOZbh4sXzDPd1Mz5+gO21DRJ6FMeymTxymPd95GOUSiXaYmE0TUEO97K6ucTS0j3MapXetna+OTNL/0APq2srHBiZpKMvg+dK7O7mqJbztGfijI4eYHNpnYgeZMfJsp3boNlsUigUqBbCDA8PcnhsDEnReOfCRRAV+gd7Wd3eZnh4mNu3b/ORj7zAt178GnduzpBIpRkenSSZ7uTajes89PBjyIrORz/2AlcunOflV1/k1OljDI+MMTA5yEPme5icPEStatI/dpydnUV+6NOf4v7cHJ2dnVzb2uLcqQdZ39okmszgajoBzyVXLLCwvMT2xibpRJJwJEZvTxezd6dp6+yip72TWCREKBSiWi4xO73A+IExHMciGNAQ9qasUi7L3Vs3CQaDbLW1MTIwSDwVZnikn0q5wb3pORrNGkENCrU6sqeAbWE3WmTSSWKxCMlMBzdu3MCMxzl8+DCrS4tsrQXo7ukkGoNG00TTQzhmi0KhgCC6jIwPsra5imHW2N7JYVs6iqhiNy3a4l1kki10PUh7OkWrWvS5uzUVsWVgNltsVFbIbm8heBai6/jNHNCjET7/1a/ykeeew6gV8Uyb7mQGRVdRRf84G4pFaa2vklB0FFmkYtRpz3STSCS5e/cuoqKQjkaZmZkhFk0Qj8eRJBFdkXBsm97OLlqVGjguifY26vU6qUyaRrOJ4ziEIiECocB/McRWw7SaLqrqkU77YODhYwfJvZqnkK/iOEV0RcYWPMKqhhsJ0WjWyJd2SUTTKJJKMplmO5fFNlvE9BClQhktEAJZIeQJzExPQ0Bl6PBB9JAvU7VNA88TWFlZ5+zhI35iZqOB7MikIjGOTJxgN5sjmehkcGCCtrY2XNfdP0KXy0U++YlPIwgS9VqTz3/+83zi+34QxxPwlAibK0vUm1UOHh9Hj0rIAQeRpu/spAXwJM8HiAQJPRDEtmVkWQVPwvSaiIKIILRA8M1OfJ28huuIqIr25+mb+/U/bKCe570pCMLA/8/NzwOP7/39t4HX8Rvo88DveP5Ye1EQhLggCJ2e5239976G68FOvsSJE8dIJGNcu3aNJ9/3FB0dbWgBlddef5215SU6UjHOfv8n+a1f/zVikRA/9MM/gOlaPPrYOT7/+d+nVq/z/Ec+yjvvvINlNXn8iUe4+OZ536U75O8/AuEQwUCIcrFCOBjEbho4roUiyRw/eozXX3+NJ9/7XmZn7hGLJTh25hxzC/dJxOJkd3ZZXlyi1Wpxd26Ohx9+iEAgwpEDh+nqbKfcahII6DSbLWqNKq+/fpehwRFyuRxms8HVq9d45sMfQ1c1bt25zeMPPITsCUwMj3KrdovdjS3y27sUcrtMHJzkgbOnCITCXLp6BYD1tRWi0SgL9+c5eOAAluMf/UuVKgfe/xxvvdHD/fuLrK+v0tPbyRNPPEEiHWdpaYk3Xr9MNtfk2IljXLr8Dp0d3cQTIfr7zzBz9w7TewYP4+Pj/NEf/RGf/uEfYnFlmXKjxtz1m3z8E99Ld28vbak2rl68zGNPjPkmMH192J7L2NhhSgWfptPW1kYiHsO0LTQtQGenH3IHcO7cOY4fP87Nmzd9Ew8R1EAQEQlFlmk0WnR0drCwcM83ybA9JFHZbw6NhoRcKTE6Osziov+9+pQolXAkiCQJDAz0YbQapBJRNjY2iERCgMvg4CBTU9MEg0EURURRVIrFMpLkr2csy2BswufDKopCqVKmXK1QLpdpb2/3lTl7q4XFxUV6urqp1+s8+573sru9s6fcimA0mpQbNfRggM7OTvL5PLgeoVCI3e2d/ZVOo+FfxLqu09HRwdzcHIFAgHAkSK3mxyc7rkR/fx+1ahnRYz9/PpvNUqvXCekBLMf2xRW67kdaOA6a4nNUs9ksfX19LNz3/U1bTXs/jiMcCWI3/H2zIHgkk0lS8TT5fJ5oNOoT6lWZcrnsy2Q7/dDEtZ0t2rs6cfG4+s5FFNUfgu7OzHHy5EmOHD5GreTnjh053O37FQwOIYoiDzz4EEi+pPLbO1XTNNE0jVQqQblcxnE8mo1NfuqnfopsbofPf/7zdHS0oYZsxiJtSEEBT3bwXBcEGUkPIGsaniTiqSq6rKGqGnjSnv+nh2dL2J6HLEgIgIeyR2ECV3ApFHf+Z/rl/62+0x1o+59pittA+97fu4E/a2myvnfb/60EQfgxQRCuCoJwNZvboX94GGSVX/2N/0y6o5Ph8TE2tjb4/Oc/T6GY49a1K3Slk1x44zX6utp5/MEHuH79KvVGlbm5WQJBnf5+33ItHksyODjM8vIytuMwNj7B2Qce9CMMELEsC9d28FwBTxRIpVKsLy9x+/p1BgYGeO21N/jYJz8JikokkWRweIRf/uVfZGCgj0OHJtE0hQ+851mMmkFADVA3TS7fvM21a9d49dXXKBQKbGyuMdjby+L9eR5/5FEK5RInz55ja2eb3sEBhoeHETwQPZGXv/4yzVqT0aFR0ok0Dz/8EI1Ggz/8o8/xh5//fWRBxGg0sVoGuqJSyhfo7e4ioCnMzMzgeQ4vv/gi4wcm6ertYWB4hJ1snj/8wz/kP/yH/8jE+GEOjB9ha7PA+toKS4v3yOe3WFtdIBAIcOTIEc6cOUN3t/+r+qm/89Nks1kGBgY4d/oM73nv0xiWRbVeY2VtjYOHD+1xIeMkkrH97KZGo8H169epVCpomkYsGse2HERBIqAHOX/+PKurvnNSf38/4XAYU/Bomg5tmS4EV2BiYgI8mUQ8gyBI6AF5n1xdqfjE71Ixz/bWBgcmxhgZHqSzo42xsRE6Otr2Il/mKRRKFEs+mBgIBckV/otZiGEYTE5OkkgkMAxfw/7+Dzznu2H19yMIApmM7+F5+vRpent7aTQaJBI+wBLY47YemJjgzvWbNGo1lhb9ZNFoNIogS7R3ddKy/Bclo9XCNAzS6TTxeJxQKEQikSCXy9HV1fVf7WPTbSnKlQqBYIhgKMzhw4f3+aa5XG7feenbGnk/D93e/9l82xG/Xq+jqirDw8NEo1E21rNEwgmKxTyxeIje3n7fa1bwUBRpXwM/PT2NpmkUCgXi8bhvzLFHwfM8Pw00m89hmiYzt6doT6Rob+9AURReeOEFDh30KWZPPPEUBw4cZHz8AMeOnSAWi5FKpfZ9C/L5PIFAYN8ZKpfLsbrqG0AHgzqDQ/3EE1FsS+DJp55maHSEZDKOrLl4mLSMBh6gyBoe+MR4VUNWFMDfc9q2vWfDp+DYIq4F7BmMiJ4MLrQaBoV8lp3t9e+oEf4/BpH2ps0/N5Tved6ve553yvO8U+FwjFgsSjwR4ad++ifJ57NkUgnuzc6xMDfLUw8+zIGJCebn79NoNAjoOq+++hqnT59lZnoOy7IRELEdj1q9ycOPPkpHZzeW7fL4U0/RNCyu3biFICkMj4wRi8RxDZuBgUFcUcJ1bXY3N8kk4mxtbyC6DvfmZnnm/c+Qze7wyte+xtnTJ7l75xZf/uIfkd3ZYml1iQOTY7z19ps0m3VeeeXrfO8n/hqPPfE0LiInTh/n4oW3KORzTE1N8ZEXPsaV6ze4duES09PTZLo6iMZjfPOtt5g4epRwKkXTdUHTePkbrzPUN8L3vPA99Hf10KiU0WWJhblZNldXODQxjqLKxCJhujvb6e/tQxYFqvUaff2DxOJJjhw7xoGJg6SSGT7zmV9mcWmes2dPsbq4RiqeYnVpmXIxz8svv8ytW7cYHR0lGPTz1ucW7vPQo4+gKypzU9PogRAXLl2mZdmMjk8QCkfp6GxHEGFh4R6bm+uYpokkSZw5c2bPLX5rT5ffQyQSwXEchoeHqVarvPbaa6yuruI4DjevXWdtdZOxAwc5ePQIExOTDA+PEgzEaG/r5MCBMUZHR4lEIui6zs7ODmfPnOTE8SNEI0G2NtcoFrIIgu9jqes64XCUeDyJ5diUKmUMyyQYDnHz5s292I8sExMTfjyF5xIM6pRKBRRF4u133uE9Tz9NpVqlr7+f3Wx23yrv26F7fX19/j6wqxtVlHCbJo1qjZ7OLvr7+5k8dJCu7m6Ghod9VZHrMbEXCfLthvFt1ydBEFhdXSWXy/HUU08RTyZIpjPogQjRWArDMCiVfHDN8zza2tr83PQ9A5RSqbQnS03tyy0TiQSyLO9LXXd2djANj2azxeTBsX2Zs2UZzM3NkMvvUqmUyOWyBAIBFEVhcXERYL8hu65LqVRCkiSmp+5itQw0VSUZT1CvNfnmN17lgQceQpZ9bmgkEuLIkUMkk3GCQX0/vdXzPHZ3dwH2Y7a3tvxZ7MbNa0zdvc3MzDT37s1x69YNJEWif2iQoeFxHnn0CUQphBaIEo7E/GROCVRZQ1N0VFFB8AQkUfsvPE8RTLOFrqgokogig6aBY7XI7eywcG+O2buzrC79/7eB7giC0Amw93Z37/YNoPfP/Luevdv++w9CgImxIRbuzfCvf/5fMDzYy2/86q9iNRs8/uCDvP3q61i2h2HZJFJpQuE4J06d4fKla9TrBrFoiuHhcWLJBOubWxTLZabnZukfGmJjfYtyuUw8HsfzBErVCuVylUMHDrG6ukowFEZRFFIJH5Ws16tokkB3Vzura0tEQhpWo4rnuEiCSCgQZGxklKu3r7K1s8nE5CgLc9Nsrq6wuf3/pe6/g+TKz/te+HNi5zjdPd2T8wxmkAY5LDZjA5fkisscJCZRtiRKFC1Zyb7X6Uq+vrZkWVayInOmuHmXm7AAFjljgMk5ds65+5zz/nGGsG69tiWx3nqLPlUodB3MYKYmPOf5Pc/3+/lusbi8QldPL8VyCb3RJJ/N8dJLL9HV2c2Bg4fJxpKsLi9jSCKVZp0mOqub63hafOTLRZxeNx53gLfeOs3ffvc5jh4+xvLiArVKmXAoiCwKrK+uMDczy61bt1hamOeP/+t/ob09AobI9es3mZiYQFEUAgFTbN7UTELOd7//NXaM7MJmdTI9Pcv6+iZ2u53Ozk5WVlYYGBigv7+fV199lS9+8YumSNvt5vbtOzz44MNUK3U0zSCZTFOvV7ly5QoWi4W947ux2WzMzMywsWHi5/r6+raTNwvboniDcDhMR0cHY2NjbGxsMDU1RdDnp1oqs7SyhsXh5O7du2ysb+LztTAyMkpTq1MoFEzpiixTr9e5ceMaVquK1aoyNDTAnj278Pk995JbQ6EQoiDfoza9/vrr9zbfVquVhx9+mFdfffUeP1RRzQ4sHAmxEd1CkCWcHjdDO0awOR0AtLe3I8tmJEk8lWRsbIwvfelLqKqKzWrl2LFjJJNJ0uk0oUgYu9OBoijY7XYTaGyAzWajVqtRq9VYWFi4xzcIBoP37ufzeVpaWkwfeNP0mvt8PoLB4L0iZgr061it1nvF7UeF1uUyPd7VavXe9295eZmOji4K+RK6rjM3P0uxWKS9I2IqQWw2mts20WKxaJonrFaWl5dxu933uuNSqUQ6nWaorx+Lqpr3ZZMY9cwzH2Bqcgafz8fw8Ah2h0qjWUGSDRrNyr1TyY/GAc1mk1QqxdKSORK7efOmmddUKDA1NUUsZorjdaGJw2FjcHAYnz/MzrH9KLKDenNbbC+J2BQVVZQQNB1VUBDF/+4ukiQJBB0BDZvdgiRDKhFlcWmapeU5Njc3t9F3P14p/HEL6PPAJ7dffxJ47u/c/xnBvI4Aub9v/gmgyBL/+rd+nTvXLvNPP/0J/vKP/5C+/g5sdpGz77xNb28fFqeNsC8IFRgY3k1TMTV4e4YHaRQK3JmYJBVPM75/H62drQT8XmLLa/QMdKOLkExl6ezqpV6v4/W7WNlaon+ozxy66xKSopApmPnlbV3dLC2tcP3iFWwWO7LNSSYRJ5dN0NvXwaUrFzm8dy+SJLF//0F83iAHxw/j8rSwb3w//b0DzM3Mki+WkRRweeALX/gnNMtVPv/rv2KGdFUq6PUSHquT2ckZaloTp9fD1NRdDu3fTaNR5fB9R5hdXuYXf+XXSecruHwhszNxexk9cIj23l6ef/EFIqEAF98+xWsvv8TVKxcYG9vBP/vir3PkweNcvnyVSLCDl19+le7ubm5dv8DM9F2+8Mu/AoaAr8XPD37wfQTR4Or1ayQKFT71s/+U3s4O/sPv/g4ul4cPf+JjvP3WKb75pS9x9eI5KuU8q5tRBoZHqTchupXEqqjsGz9AZ0c3FquTWgM0AULtrbT3tBNsCyJLBsVCBrfLxshwPyPD/WxtLnHl8gVOvXGKjfUovQPD9A0N4wl4iaXSFMsihUaVhq4hoKBgJ5kosLS4jsPh2EadqUhAKOCjXi1w6cLbRLcWKOdLlLN59o3uIhdLojcMwuEQlXKOvr52MJrs3buXqam7vP76D1lcWKYl4Lk3V93ajFOvGczMzLF3fA8+jxevowV/sJWxsR14PXay2SzOliB79x1CUiy4PD56e/oxmhpOh8N0U9msBCKt2F02JENjpK+f/fv309vbi6Io2645zJjgYo3U1hY97WEcioVLFy6i1zRUQUGRVPRak3LDlDnVqlUamgk5dtodpJMpGrU64+PjqJJIKZ/D63Li97gxpCrhjiD1epNMMkMw4CO+vEl7KIjY1GkWmhTTNfxeN0vzc1RLRSrVErVaA9lmoYmGIgkUUgkqzRLLKys8/tiTuFwOHn/wQWySwOhANw8c3odd0WkaGrKqkiuUKJQqlItlrly6QrVSwW5RKeayFDOmdTWxtUlia4PpqVnefOMUW1tRzp27wNLSCvl0htjmFrJoUKsWmZ+awW4xsXyizYZst5rcUAUsVhlVFpFkA1kSsKgyEgYWQcLqUMjn00zP3OHO1G3WNzLkczUEzQINEaEu/S9r1P/s+nuXSIIgfBNzYRQQBGEd+FfA/w18RxCEzwIrwIe23/xlTAnTPKaM6dP/kE+i1qjzS7/+K1w6f46vfvXLJGJbeC02Li0vcuS+40RjaZKxNLl0hg9/+MNsxRPEN7fIpxN0dXYQTWTxBoI89OBjtAS8/N7v/y5up4Xjxw8weWeS7s4e7tyZZc/efVy5cRGHw0WxWaPR0FBVK0MjQ1y8eB6700Ik0ko2X8Ki2ghH2qk3GwyP7kDSNDaia2xGY7T4Q1jsHpxuL6lsnJuT1+npaEer5NGbGhfO3KJSynL8vofY2NjAaNTwWArcfOctzl04z/uf+RC3b96i3qjgsosIgpXb1y5TLVewyVbOnTu37SeHjo4OZpfMPHlZEtAbpi5ycWURXRL44m/+Ov/uX/1r9u7di9/vodbUCIfDvOc97+FLf/FXfPzDHyEdSyDdJ3LzyjW++MtfYHJmmnwhx0c+8hHi6QyaJlAsVNEMUBUbqqry6BNPUcoXmJubYysZ54tf/CKvvfIygaCfSqm8PfRvoVw2Ox2n04nNZqPRaIAgUCqXkEUQ0SnmciSTSTwuM0unWCzes4nWqjoW1YzYcLta8LlbuH79Kvl8EUEXGeofJJNpYSu6gaBrGNYGyUzW9J+XSvekPGDOSPfu3Uu5XN7GzcXobG9nZWmRqek7hAIdONxWZqbu0qjreL1uJBE0vY4oGdy+dYMdQ8OIgISAKsso2/HQV65cwW6xY7fb6eobpKTBweOPYLE7aBiQSMXp7u1h5+5dLC+vUiqViEQiqKrKAw88wJkzZ9gxNMKdYpV4PMHi+hr3HT9u2jr9fqxWK7dv36a3s5dMNsnVq1fpaO+hp7cDWRBZW1nH6/GbsSKigcWqUqtUcTtd1BtNRnaMUq83qFarrC2umKetbB5NM1hb2+Dh0VGGhgb42+99H7fXh93hBEXG4/WTTqdRVAlJVWjUQbWaNk6b4gS5jt7UENHxuJzY7XbqRhNf0I+iCrjcdgRJ4IknH6e7pxfVZkUFhEadxcVlOjo6qFbrbKxv0dvfR6FYZHNri/WtTUqpJBsbW6SSaTY3o4gOMxH1R2OOeDyOLMsUSyV8wWESiQSBUAupcoqmoGGxWrAoFgRJQpAMDElGQ0TXRXRBxDBErBYr8XiczPIUCwtLiEiIhmBmJmk6mmY63/7xQ0jz+ods4T/6P/mnR/4Hb2sAv/iP/SQUVeW5537AyuIC1UKJj3zkw7z4wnP4Q35e+eFrDA3vYrCrD9cuFw63ByEax6qodIyO4rR7WF6NsWf/Ibp6uvmNX/9VOtsDBENezr7zDr2dJoT2Xe96F6VKbZvVWEGWVErb0Qxd23HKXq+HhYUFTjz4JKdOneL+Bx5genaWUqlAJBjGUTCPcy6HG6fDjtWmYquoOB02ZqYm6e3uI5tL06yX8bk9rKysMTg4SC6VpFYtU6mWwKbwg+9/j3e9+z1Uq2We+9ubfOZnf5ZL168i6AZ6tY4oygSCQbK5HBMTExw+cZz5+VlKxTzx6CYAgiQRCoXo6enj3/6732FpaYmlxXXu3LnDyI4d7Nu3j1xyk5mZGbwOF+FwmJbWEN/81tcZ3jHGV77yJbxeP4MjY3zmM5+hVilz49ZtUqkUuVQal9eD0+Vh794gxVqFs2fPsm/fPhxOG0sLi3iDPkqlEgMDAzQaDSRFRscAUaBQLBJui5Da2iKdTFGulMx0UM16b/mhKMr2BtrO4uIy9fomhiDywWeexuf1IgoGhl5naWERm92Kz+NF02tk0ykCLSHKZVN25HC4yOcKlCsl/H4/KysrhMNhEokEPp+HTCaDLMv09PRQLTZo1k3YSbFcZ2srhtvlwGZRyWVS+P2m2H1+fp77jt9PpVLH4XAwPz9POBIk6A+ya9curKrC8uoa69EE+/d3YWg6TqcNr9dLPJ7EYTe1nt3d3WxsbJjOHLuddDJDV4eZzNnd3nbviA/mg7JYLLKyuoQoGtjtTiRJMNmldfPz2MhuICFtH++b2O12JElCUq1k8wWGh3awtryCw+YkGAxRLJbo7OzkzTffwuf3Uy5X6e7tYWlhEVlWyeQLSAKoVhVJN6g3dUqFIkMjw8zNzZlf82aRWCyGzaJSLORxu5yIstWUJ8kix44dwev3mTwAu41kKoPFYmEzFsXn87G4uGzaP21WLl26hG4YVOo1092kN2jrbGNoZARZtlClvq39LbJzl4lTvHzpEvv27zeVLPU6S6sruAJOFNmCKlmQDHnbSS2ZMiVkDMGUM9XrVeJbm9uz5yySIG4HzcmgNzEwMAzTpKAJ/9iqZV4/EUDleqVCi8OJd3QnPb3dxGIxxg+OUywW2e8OsLoSpeSNcPTECf74z/6EnYP99HZ1ks6mOP32O3zh134Dm9fGX3z5TxkZGcDvctDQ6nR0DVIr1Wht68LmdDE9O8NAfzflfI5UbJNms8nw8ChzC2uMju1levIuu3cdRBJVEGTGDxzkr7/0F/h8PvwtQW7dukZHezu7RneRyGxy/tQbDA4O4lTsLCUKrGxsIAk6qVye/OoWPq+HjY01RnbsoiYYLK8s8Ph9u6nUmnz7O9/g5BMnefoDnyJXhngyRz6b4Oi+cVKJnBnwNjJMqVTCabVRzmZJpeIcGt/P6bdPkUylkJo6V965yMc+8TOsr27w0Y9+lAOHj5DL5/ne975HT0+YeqlCI9DE5nYyOTNNi9NOIhHD6/Xi83kQRJ3XXnuZ/r4eRkeH8AXDOFQHFqeHfC5HZmsVXdfvyXi2trbugSbqtRIOh7kgyhcLbG5uEg6HsVqtbG5u3kuG/BHgolhskslk7m2d8/k81WoZf4uTcqWBQZP5hSl6etvZ3DSTHJt6iVIhT6FUpFSqYLM6sKgWVIvM1avX2bVrF3abCwSTujU6OsrZs2fp6elhemoBVZYItwbBkLBYROKJTWwWlVQyh9/rJh6PYlFF3F4vxVIJwarSPTRASaszt7zI3r372ErGWV5eRpVUFudWefKn3s2ta1c5cPgE+XSKgN9JMl2ir6+fybuzjI6aM+Hl5WUKhQKpVAq73Y7VYmdxdg6Xy0UskSDg85LP52lrayOTyZh4PEFAUSRqtQqxWAxRctHZHmF+doEDB/ewND8HsoVYLEYwGDSlVU2Ny5cvs3NklEKhQKVQpFA057sH9h8iuhVHUVSKpTKRSDurq6vYHC4CHR0sTd8mHIlsL3OixBMJhnYO4PBYEYw62WyWZr2G4jAXQ/VqGaw2Hn7gYY4dPUStXkCUFAxRoNaoYxgCtyamsFglQqEwNquD5eUV8qUiHq+XO1OTzC+a6o96tYpumO4yl8sBsgWLxUIqmSaRMhURPT09pFIpdtqHGR8fJ1ffIF/JU2mWscgWVNmGQB0RaNabWCwKNa1IdGuNjY0NCrk8qiTTaBqIhmFqJgUNaTssD1EAUcBud/xYtesnooBWKxVqzRoHD+7n5tUrFLN5M9jLZiWXayAJbg498S6u374BzRpun5tCqYzb7+PpT3yIzqEufvmX/ileh0JbOMxWYouerm7i0RjOgPl0nJueYWhsJ5l8lNmZeSIePx5HCw6Pl2AwyLe+/V2qdY3Rfcd446WXeOaZZ5BlGb/bxUhfLw6nhXBXF7vGx6nUK1ybuM3e8V3MzU+xe+8uFpeWqZZz2K02cpk8kiSjKCpdXR3ICoTCEWSrg/OXLmFXVZ48+QCZbI7wri5isSSPPvgYr7z0HO3tXfjbBBqTk3z929+hUavReeca67E1JEPmzVPnCAc7efrpD/K7v/u7jO7ayfLyMg6Hg//253/C8ePHGRkeINQaIL60yuT0FGvRKE8dfi97Dh4km9ikWCiTSqSZuH6TQu4NOru6UUUBrWl6oy/cvoavpRW3x8+x+x+iVMhQrVZZXlncFnlL5LJmVs/rr7/JscNHaIgiqUQCUTNw2qz09fQQrxTIF3I0alVq1SKqYsNqVVla2jCBz4kE9YZBrpDH7nITTayzng3Q1ttGZziIS5GQ9AZNdwuFahHD0EglEiytbyCg4Pe3YLF58YfcIElo9TobW+sMDQ2wvDhPd2cHKysrLCwumuDijUVKzRoNrUlruAVBECgV67QN70ZSVGLxNZIbSxx66mmef/UtunuHyBQrtLSGSM7EcLlcHD16lKXZRYItAdKpBB2RMMtLy1CvEva1c/7MJQb6BhkcHGRtfR3dMGgJBbF5XMQTGdpa21hdXqFcK5GKxnCoZlRGqVrHanGyGlvG6XSaIWpak7ZOD5laGnvIxeCePRR1jbWZZQ4c2MfdyQkeeeRR/va5Z/G6nPT2daPpDdxuN8WJOyDDRmydplhnc2Mdl9ttniycboQmrM7cwW61kEhmGR8fZ23zRbL5GNlkFL1WY2D3XtLn11AUA92o89DD7+Lll1/mmSce4sCRnWhyA4vNg6wJxONx5mdmEQSBnvYgG2vrfOMrf4MvGEZS7GiGxFe//m1afC7EpkZycwNJUhAEA5/fQyoWR9MaBAIhgm4Ha8sLiPUanX0DtPg9qBaJheUt8rUSmgEOqwtZltBpIEsyjaa5VCuUUsxM3yKXy6M1BWRFpGGUMQQHugCGoaOIEnXJoNFoYNvu1p0OL/D3mib/v66fEJjIkHFg3wmy6SSNQpEWjxdUGafTzcDATloCXRSbFa6eO8MH3/dTLC2tcPadc/z8F3+JllCIv/nrvyCXjnHsyFF+8L3v88wzz7A4v4AoCNicTsb37MPpC9AUBV547tvopSpdoTCBcCuqx8nNi+epNTRC4VYEJBbnl/m5X/g5bty+js2iMDlxm2A4wmY8xoEDB9DrDRaXl6mUs2xuruNyuHE7vSyvL+F2ulicX2JgYBBN09jY3OS++x/AkGTWN6PUixkwdEKhEO09Azz76qt88Zf/GQszC9gsEvVaka3tp28hl2d1eZmltWX6enuZmbxLb28v6WSKjkgHu3btoq6ZPu5isUgiEWN1fYPDR48DUM7kGNoxwoUrl+no6iSdzRBo8RAOh/G6fRhNg3wiTa6Qp1I3RfH+QAtWWadWa1IsV7l46SpHj+xn796995Bmfr+fQsnMsw8FgogGpAsFBEMnnYwjGjpoOitb63S0R3A57UxPT+N2m8fVhYUF7t69S61Wo6mZHUCpWjMjh31Oeju6GO7pMYuLIqLKFuKZFBsba+jNOqvRTXzeFiRJQZZF/AEXHe3dOGw2cvkMsijRrFeZmpwjFApRq5nJqna3mchp6AKTk9NEIhG8niCFfAVRVognt0C2EIm0kc0USaQytLW1kYgmibSFGN25h2Agwne+/k0sLjcDI2P093Rz/uwZvG4Hm7EsQyM7GBodZnbyLqlUip7+PkLhVhYWFmjxeVmdnqNWrrCeihNwu9CB7u5ukuksi8srdHd2sLCwQDgcNuOd+/qp1StsbW3w6KOPsry8RGorTm9vD+VyEUlSyZeKrK6u8sQTT1AqlfD5fFx8+yyVaplwe5hcPo/d46Gjs5PNWBRRN2gUKzS0PLreJJszsXq5XJbXXn6Fnp4eRoZ3UK83iW5tUCoVefqnnsLnc9E/0IfFasNitVPVNBBFlmaX2djYoL+//14Cg8vjJJUrUK1pbERTLC0ss3PXKGhNyqU8L7/y4r0HtqJK2O1W7HY7giDh8/nIZQuoqhXZ5sDlsjB+eBfzG7NkKxtIkpnxpKimTMkwDPL5PGtrK6TSSWRRACSaDbaJ9E0QbQhAs94wO16vx9Tj+j1YrSaR/k//xT8eqPwT0YFmczkkyZzt2JxOBN1gaGiM9c1Nbt6+wz/9+Yd58aUfsHfXDl5+6SXy+Tpf/JXfYCsfR5AlDL1Od1sb83NLeD0tWC0OHA43+WyOvX1jJFM5Ir0DPPvC8zitNiw2Jzt27URUZM5fvYzdaqFcTrFzZJi3z5xh3769rK6uMDIywo1rV5BEhe6uXvLlCqIoY7GqlItFBMH85ZYE2XQcZVK4XG7e9a6niEajeDweZufmzERDixW/38+d5Tk629pYX1/HH2zD7/ViaLoJsQ35sdptBEWZr3zlKxw7cpRQKMS+Awex223mL1oySjAS4MaV2/zg+ef47Kc+zebmJslEgt379lAoFFhbWcLh8rC5vk4g0mpCj/t68Xm8OL1uECQEUUa0CLz21hnS6STj4+O8cPNF3G43swvTPP74kzgdLt7//vejyAKrq6a/WpZVNja2sNptRKNRNtc3QNOxu5wUCjksioIqS4gCDI8MkkmlcTpD7N69k7OnTZOB3W6nxedjY2ODbL607eDxUq9UaY1EqFbrVGsa+VySeHSTcrFCppjF4XCQjEVRHSrZTBJVtbC+vobX6+XmlVscOXqYgYE+JiYmkCQTiLG+vm5yBGo11lZTdHV14XC6yReqNHWNpmbga/GjWi2k8zksDg+xRIZ8Jo3NYmVteRaL4qZWrVMslXD7avT29nLpxk3S+RKysJ0Rb7dTqqxjd9mxOpxkMjn6BocIhkJoGDhcHoItLRRb0qhhhXgug9fvQ1HMAqhY1Hs6yUqlYs6VJQnRgFKuYEq95hcQRQGnx02ko51Lly7h9fro7+9nbm4OSZJYX18nnU4T9PuJxmtUS2W8Hhdr6+vmyEYwsNotLM3OsnfvCHfu3EY3zESAw4cP4XV76OvpxWpRSSUTdHf1srm1xtjYDuqNAja7hGFIlMtVUtkMS8urbG3EOHLkCKqqks3mSKVS1Gjg9vippfMEg0EcNieNRo03X3+VUiHPoUOHyGXyrK+vUqmUyKTSiKJIKBQ2H8yhEJFIO6GOdlQF7G6R7GQc0cp27nwDBQEQiUU3SSQSxONxrFYrhi6h65guNklGFBQM0UAwQLUquN1ubA47Ho8Hh8OKJBtYbT9eI/kTUUAbtTqKJFEoFBjo6aa9NcLC8grlis7nf+lX+OM/+S90dXVSqzfZvWcP6XyZ0xfPs+/AGLH4BsHWEK3+EM//4CV+6Rd/kdnZWe7emeGhBx4k0tHBxNwU66sLhH1OLp+7xbFjx7h5Z4K+gX6siko6laWto4dKo4nFZsXhtKLr5pzu5o3bjA6P8Oqrr/He97+PWq1GIpbAaXcBTebTObJalpA/wr7xw+hagxdfeI5IJMz8/DxOp9PMKA+1ous6HpebSrFEKBBkc22dvTt3c+b0aUaGR3E4LczO3SXS1sV73vOe7XFAhm9886vcd999nD13htGxMaSGqVMMhIK8/vrr9HR3I4sSf/5nf8Iv/dIv8Rd/9TcEW8N8/le+yPe+9z0OHj7E22+/zejoKKdOvckjj5xkZWGVA+P7+NTPfo5arUIxn6ant5OOjjYa2uM06w2C/hZKuQxXb92io6MDQxBNp5fXS2trkNbWVmqVKtVSmUIxR0dbmGq1zPr6mgnMsMsEAn5mZ6cBnYG+fuZ1g6mpKaLR6D2NZCIWp5wv4nS60So616dusry8wr694+zdd4hsMgWygM1uoVausLiySKGQo96oMTQwwt07M3S2BVhdWCKdiNPZ041haNTKTex2B4uLi5TLZQ4dPMKV69fo6O7h5JPv5dnnnmOgNUIsEaWtuxOXO8D5i5dwuVw0bDZ0ARKZLI88fJgLF69hdXqw2WwkEgn6+vroGRjGYlFxu92UskWGBnvZWF2hp3eArfU1MDTsqsLK6irdfb1srK2yurnKI488ws3bN3B63MzOzuH2eNAM8Hi9rKysmLrMZpNKpYLdYsWqqAi6wcriEsFgAEMWSaUzGEh093YjizJ79uzh7NmzlMtljh49Srq2SVtHO5Mzk+wIjLC4MEdbVxuZUoGqzYbd4yAej9PR0UG+kKVcLhOLxfD4vOzas5MbN67RP9hDvdrgM5/9GVKpBE2tZsaVNEVqzSouuwuHaufRx04iyzJ37txBlmUcLie5XI5MOo+q2Mkk85y5cI5iMc/C3DR9vd1cvXqZaqGCzW4BQ8eiyFSrVROu0toKhsjW1hYdfV34/U5mV24iyU1ARxIldN1gfW2FeDxOuVAABBRRQqtr6Aj38t/ZnnVKgoa3xYfdZapFHA47siyjqjI224/HAoWfkAJqtVgY37mboR1DrK8sc2d2mmSiwMMPPc7s7Cwnn3iMufklegYGyWZSOHwuytUa9XKJjfVVgqEwc7MrHDlyFItq5dw75zl44CAjIzvIlYv09nfx3W98BbfVyujgsOnxtZu/CIFAAKtqZ/feXcwvLeANBGk2TXbh5cuX2blzN/lMlsceewxVVbl79y4Bj4/oVhy322J2Tw4Xzm202EsvvgjA0tISvb195AsFvF4vuVyOQCDA6sxdWlpMtiUSLMzN8dAjj3H+3EXe+/S72Ixuoah2XC4XggHvvPMOdrvE6uoic3NzjO87wLUbt3jq8ceolspmntDsHIJucOK+47zyyit87GMf48UXX+Qv/uovefTRR1lZWcHpdDI9Pc2OkRHeePWHHD9ynNOnzjB++DB2u5VobIuNtWXOnT+FKIoM9vVzt1ZHFgQOPfwYoVDI7JJVFUTxnsREFiXTvSKLTE3dZWrGzFWyO6wkk0lmpiexqorZURkQi8Xw+Xzous7a2hqarJobXMWKTbUQi5oplkMjo4RaI0iSiSAs12ssLs4zOz2JYrFhs7loNpssLCzx6CNPsjx3E7fbjWpVTPthrYzL4qNSqdLb04/FYuHOnUnGxnZRKFfQdBjbvYdr5y7S1d3G9PQ0tZpBKZOixeOko7uHmdlZ+oZHCXWG6UsMojV0bl27vi2zMR8k6yvLZFNJ8okUAzsGaA9HKGWL9HRE0HUNGQ2Xw0Jic41de3aRyabJZNK4XE527NjByuoauVwOQxCRJfWeTz2bzdLb20tbOMLiwhyhQJBAIEAwGEBxWnj+uVd48sknmZmZob+3n927dyNJEjdv3iSdTmNx2Mnm0tg9Dqpag2Iuz+baOoWmudizKxayiS0GBkwtdLPZJBAIkMplsTjt2D0uBkeHEBoNSqUcADark3rNQJAFmk2d9eV1bDYbOiKFUgVJsYAgsLW1QSy+bubA1w2WFtcJRQJUq2VGRkaolPM4HHb0uinedzodaFoDi8OJJEnk83m8Hj+iKHL9+nUGBjow0ND0OpImUK7lSaVSxGJb1OumBM0smAoCEoahYxZOAVEEl8uBzaHi9nqwOR0IoohiEbfD8+zbmfE/3hr+J4IHagjw5tunSGzGadR0QOaBE0/Q2tlNTdc5d/oioXAr+UoJQZH5/re/w87BUeLxKNO3prE0RfrCYVq72/nyN75KZ0c7x08cR3JYKNSLXLp4kc6OHnRBweHzY3c5cTgtlMtFtja26OnpZHF+CcmQ8bqdWO0e5ucXiW2sE/R7GB0dZXpqAUmxEgiFuH37Jjt6+8mnMiii2Q1GkzFSySRCs4pNgHZ/EIfTi6YJFPIlNtfX6G4P43A57jEdR0cHKJeLFHJJxveO8o2vfZWQL8jmyjr+QAvJbBJJEujvH0BrNPjkxz9GKZvi0J5R/q/f+dc4nBaiW2u0eJz0drWxurpMpVzg/Nm3qRTyOBQJrV4DHfYODeMRDHKpOD/7mU/S09vJ4SMHsEgiZ998k5tXrjC2YweKIOCyu2iNtNM1OMixRx9FkQSS8SilQo56tUw+m+bu3Sk2NraoNxvkKwU0SaGzf5D7H3yE9fUtMuk8HeEO7r/vBF6vH68nDLIFq9NDQxAoNZsIViuIKpJsJRAME2rroLM7QndnGFmv06jmCEb82J0Khl5iZLCLD73/vZw4fICj+/bS2drKzsF+Lp09xdiefVQrGqpgxSg3qKfKRDraqTbq3J2eYjMWpbuvl2AoTHdXL3cn7hBuCVHMFdhciyNoMjN3pjl4/AFyxQaq4sBqcWGTHdQKGj6vF4fThWJ1EepqJx7bZO7GFeqFLPlsiqYk4HI42VxdIxnbontwkGQ+z+07k3z/29+ntaWVRDxNX+8gTQ26+gaoN5rs272H1Zl5VMCiivjdThq1CkF/C4cOHSJfLGF3OOjoa2NqfopSvYbT7mbPnj00mjrVqo7scJAvlSnny/R09HD2/AXimQwOr4Ojxw4wc/cu6XwKUdDpCvgZbI9g1Itcv3WZWrOCrMrYHDYmp6dobw1RzOTo7egiHU9QrpbRDA1fi49wWxiLzcLi/BQidfqH+1EdNjbWFknFN5C0CrVCgs6Qm8HeHiKtAfbu3837Pvwejhwa54ETR/C4nVgUK6lEBl0TqTYMCuUGuqaYs/xClUQsTzRqhtt1dXQj2yzMrsxRqZdYXFvh5u07bG3G0BsCsqFgaGDoOoIg0DR0dENAR8PiBF/EQWu3H0+rA6tbxmJTcLoceN0+7FYnNsWHLDixyM4fq3b9RBRQTdP46Y99lNjmBrl0ivjWJnvHxwgHvPzVH/8hxw+M09kRQVUMXn/jFXw+N2vri/T2DZhMwUCAWxM3mbpxm0Imy2NPPM6VG9cxZJE716/SqJRYX1mkqz1Cb18fDoeDs6ffQVEsDAwOowMIAvVGlfXVNeLxOCMjI9TrdRYXF0kmk4yN7aBcyBPd2CIQCBGKhBAEgVAwCIZIa7iDUrlMcVtK097ZgdvpoFwsUC4V2DE8bM60LA5km4smMleuT7B7997tI0STnp4u/H4/Y7t3okgys9Mz+P1eE1AhCNRqNVRVZXp6mpGebuam7rJ3/27sPgeaaoaE1etNWkNhPvnJT9LicPNXf/znCE2dubk5hneMMdA/xOuvv06lUuH69avcvn2T3Xt23fOvW1QrbpeXmzdvMzFxl6tXrzM9PcvGxhYbG1umOyRfJBgMEg6HuX37NtlslqWFRbRGE6fdzv7xfbT4/GxublIsFk3ijVHH5/OgqjKxWOxeqFupVKZSqbO8vM7ly1dZXVmhs6ODQwcO4rDZ2drYZGNzzYyy0DSKxTyZbJzllTkkWaOtPcjo2ADXbtzi8H3HWI/GGNgxRm2bXGS32xkZGTEBxZLEuQvnKZdKLM7MU80XefiRk2xuJfC4W1BtdjraO+8Bk/P5IsPDw5w9e24b+ryOy+Whs62DXDJDpVZn9/59VNARRZGuri7W11dJpRJ885vf5PHHH6etrY1KpcLbb799D4KcyWTI5XKk02my2Sz7Dh4wafiaRmurKQNzuF043R5Uu4O2rl4OHThBa6gDSVSYmJjA5bRz6eJ5Dh48yNaG6SkvlEvs2DnG3t178HrdlMsV1tei+Lx+gsEgyWSS+fl51tfXSaVSDA8OkUmlMTSdcrFEs95A0zTS6SRujwmtbm1txePx0Gg08Pl8FAoFLBYz/ykej+Jw2Egmk1y8ePGe3bZQyNHUKiRTUV55+Vm+9c2vcf78eS5fvkw6nSYajVLKm4xcm8OOjoGqqrSG2gkFIxw6dIye7gEcdjdt7WHCwQB2i5Xo5iZb63EETQJDRtdFGppg2jAFmep2jpbNbiEQaqG1rZVAIIDN7sRqM4/qNqsTm9WNKFiwqC6aTQNdE+/Rwv6x109EAXXYHfzJH/0ZLb4gpUKFf/Fb/wf1Zo0ffPc7fOCZ99HZ3UG1UuCv//IvQG/wwP3H2NxYQ7XZCbW28s6Fd9iMbXLfgUM8+fgTWBx2ugf6eO7559lYWmHP6E4C/hZSqQSpfJpvfeObHN53iFQiQ//wGPFkFo/Xidtlx+Nys7a2ds+frOtmLrZqV5iauIMiiPT2D1GomHRym2xhoHeIjs4eNmNRas0GG5ubCLJEPpegXMwRCrbw6suvsLm2yZ7xA9SbBjPzS5RqDXp6epifn2d2bgq7Q8VqtaPYFGLRTR687zgut4NcLkc4HKZUKlEulymVSgR8XkQM5udnES0Ss0tzzM8v4nF7GRwcplZrYFWsnDh+gpaWIB3tXWxsbHHt2g0ymRzf+tY3iMW2aA0HGBrqIxD0c/36dQ4dOsSjjz7G2NguxsZ2IYrmEToUCrF7t0nakSQJWZbZ3Ny8R04PBALcuHqNd86c5e23TrGxvn6PHNTWHiESCaJaBHSjgcfjYmtrC8MQtt+/sQ1DDtAeaePGteucPX2GFr8fSRQpFguUyyUq1RKZTAqH04LVpqBpdS5eOke9UaG/v5/pmTkefuxJMoUqfcM7ARG73Yksq2iawcLiMl5/gCuXr3Jg30GuXL7G8somvT1DRNp7uP/+R8lm85TLVTY3ohw/foJcroDf10JrKIzd7mR+fpGhwRHcHh+1epMrV6+zc9cegsFWbt68yY7RIe7cvcnBg/tZXV0mFt/ioYcfoN6oUs4VeOO11ymWS/hDQXRNY3Zxge7Bflw+L426aaLAELE7XWQKRYKRMCM7d6GhsGPHGPF4nFI+TzGXI9Di4+aNa7QGzZ/tQDiA0+2gtcXP5OQkoqDyxuunyeVyhEIh/H4/nZ2d90AhXe2my6lSLCELItGNTXbsGCYa2ySdTuJw2KjWa8STCRSLyo1bN9EMHavFwfVrNzlz5m3OX3gHl9vBsWNHsNutfPVrXzbJSsuLTN69zeryEitLc0xPTZHLmmL2SKjVJHFpTZqGjsPtQlRk3G4vbW1tCIKAz9dCe3s7dqvMaz98hRvXrpPP5rApJpFe0zQ0XUeSZQRRRpAUvF43wdYAgZAPt9+By+XE5XEjW1RcDjcelxe71YVFtiPLVnQNc2yiiIji/8ZHeEGU2D1+BEF28O9+9/c4c+7qPSvaE+9+D9emJ3nrtbf5+Mc+gcflZXR4lFq5xvr6Bol0hp27x3jyXU9w7sIFCqUiyxtrWBSVtYUlLFY7BqZbY+eefTQNnWAwSKVUwW5zUqk1iLR1EovFyGaTRFpbKZfLJBIJXC4X5XIZz3YW0czdKRTBpIFn8xkcNhuGptPaGqahG/f4hoVyydTiFfPYHeo28cdOLBpFFkTG9+xBBIqZHDar3ewyPXaGhvpJJpNU6jWsVpVKucjOPbtYWVmhUqng9/sJBAKEw2EOHbkPu8PDgf1HcFndKKgc2H+Qjo4OXnrpJaLRODemp6jqTZqawcLCItVSmZ/+6U8yMjKC3+/n7uQEf/pn/5UPf+SD7Nu3l5MnT7K8vMrVq1dNoXy9zvT0NGdOn+XK5avMzy2AIdDZ0YXL5cJisTA4OIgsy3icLvbs3s2+ffsIh8M4bXZKpQqqKrO+vkosHqXZrFOtlmk06vT09CCKIvVGCZtdJdIWwu5Q7kEgpqenefbZZ1lcXNzu2lKIognJiEUTRCJm6mIk0kYmk6OUy1Mv1YhH46iKjbnZRaqVOqVihdNvn6VcqrK1soZNtmB3usgWikQ6Osnmy/QNjPBv/93vMDC8g1KxgqpYqdebyJLCC8+/SG9vL06nG0Wx8OEPf5hkPsuHPv5Rjh8/zuSdu1gkE7nX1d1BuVxEVgQcTjt7x/fQ399HR0c7Dz/8EPF4nKNHj1IqlQgGg2RTadPWamjYbDayqTRra2uIokxruA2rzYbDZ6Vp1MhkMpw9e5pyMYfX40KSJMLhMNVKCbfDwc2bN1jbXKepNSjm80QireRzJXRdIBJpv8cJ/ZGL6Uenmnw+T6lUuofYE8TtlFOrlfvvP0G+VGQjusX80iKZfI4bt2/x3HPPsb6+zs6dO9m/f5xyucjMzBQzs1M8+eQTaFqTG1dvMnHjDopiIRLqoFquUC6WyCRT1Ks12iNteLzee8R4UZKoN8pkcyksFglVFXG6bGTSCWRZxOW0m3g6rQZGA4QmuthEExrY3VZaAh7cPjv+oBu3z4XDYUO1KkiqhN3uxGn1oYo2VElGkSQEwUCSBQwaaFodgx8v0uMnooAaBnzkEz/N4eP38Zdf+jK37k5S1Op8+NM/ww9efJ72UBgJC7WygCg6SBYK2H0ussUUVrvCyy+/yne+/X0OP3KMIycOYxEM1pcXyCSifPCjH+A73/wGXR2dlDWd6csTyKIVT7CdI/c9SClfwCIZBAJ+1tejvPb6WUrlAlarjUAwQkuola34FpV8BdlipSGYXdOVa1cJtneQrlZIl1I4PTI0a7jcHmSbg3BnJ/lkGZ8jCJqAzWYjFtuiq7ONicmbRDrCRCLtGKINfyBCs9Lg21/7Ft1dfcxcvsHbr79JJpdlbmKKSDhIOBQiurlFLpOllC9z5tJVjtz3IMl0iUSiwK5dBwm1BimWcgwNd7O8MsXIyAhPvusJpucnue/xRxh/8H7u3r5FMpnmySfey6c+9QucfOTdPPLou/jBcy/RqGvYnQ5qlSoWi4VAIMCHPvIRnnzicd7z7qdQZInVlWXWVle4fnOCrVgcHZHpuXnmllZQHS7sbg8dPV34wyH8ET/lZpO2zm7cHi/JeJx8JksulSafSmIVRayiTLNax+WwUyrk2dhcQZINHn7wPu47chinVWErvsHKyjpnTp/H4XYQdHkpZwoM9A3x3qc/hN0V4Mz5m3R0DxEMhZmfn2Xf/j1cvX4NSVIY6h8mE88wsmMUTRAxBIGewX4sHifDA/2EIwHC4RC/+c//OVafD9liY3FuAa/Xi789zA9feAkaGof3HWBpYZF6qYDTZSNVyfLJz/w0WyvLSHYnwfZ+3L42OsOdNA2VcsNAUO00dYHF6TkcHgezc9Ncv3wVrVIjmtkAsUZyc4OFqWkO7BknVymg2GVuXL/MG6+8zNzENLN3p7h66TyH9h9iZHAnkiFTLVe48M4Z/H4Pp19/iZDLytLdO6iCQLlRIx3bYnllgfHDB9EllfGDB7h05TKCINHW1kF8K8nCwjKz07MU80XKhSKyAI88/gTBSBib28ZabJULZ8/gczlJxaKoosCZt94kn8vgdDhoVKp89+tfI7UVw2m1EfAHiW0lmJycQcNGuKOX9WiMzcQW6E1UScbuctIQBFKFEpKk0NPeTcDTQiTSjqg7WV3ZYmp+lmwlj9XnZqOYYH5tiUQ6Rx2VZrNJQ6+ji00sbhlXyIGlRUXxyaheC4pLQXBJqB4Ldpcbu+zEo7iRRQeSaONHJU/QVNBA08vbQXY/Xu36iSigqkXl1q1bFAoFdF3nAx/4AEF/C9NTU0xPT+Px+xgZGyQQ8nP/iWOcfvMNOsKtKJJ8LzHwvvtP4HA4eP3112ltbeXUqVP8xm/8BjPTszzzgffTGglTzGWRZRGHw3FPqCwIEkurK2xtbREIBGg0GjgdXnQNKuU6e/bsw+32kkqlCIfD98CwoWAb0WiSw4ePs74WRVFslEolLBYz6TOTyaA6bLj8XnNmOTDIxsrqvWykXM5MX4zFo6aHOpbk2LHjRKObrKyscPTo0XuoOYfDwcLCAoVCgWq1yujoKACRSITDhw9y9OhRDhw4wObmpuko2R5BxLbW+PbXv4JVFgn6fDSrVcKREEcO7WN+dopSLkMg6CObTiEYGtMzd1AkkZ3ju+joagcJypUiG1ubLK0sM7ZrJ8fuO47D5eT4kcO0hyOkEgmOHjrMwYP7UWSJyclJEzVnUalWyyiixPrq2jYo147b7Sa4PTduNBqIgikEWVlZ4ciRI3zsYx/jqaeewjAMkskk4rbDSdc19uzZw7UrV6g3a2RzGa5cuczG5grvfe+7+Df/9v8knUly6dIlBgeHWV/bYmxsF6urqyayTrGQyxVwu90cP36CbDZPPlfkh2+9QVPXuO+B+wlEWrHICm+dOoXVavr2D+8/wO7du5menmZ5bRWbzYZFtXP92i3a27qIbiVoi3QyNNjPzMwM0WiUPXv34rI7eOG55+91zflCgXKpSri1jfF9e6hUi0gIhEMR1ldWCbdFWNlcI5NN43Q6t8PxZCrVEj6vG4tFAXQWlxcoVsrY7Xb2HTxA27amOBAIUq/XefbZZ7cZmHUajQY7duwgkYyxsLDA3r17TeJTo0F3dzdNXWff4YNE2tvI5nNY7TbKZfP//pGnXxAE5ufnOXXqFKlUih07drAVi4IgEYvHUSwq8W06/u2JCaZnZlhaXqZYLG4rNdR7GMFKpUIuZ5Lq7XY7VquVfD5PpVKhVqvR2dnO/fffz969uxkeHqJWqzA7eRerqmBRZEQBZJuC1WHFYrficDmx2G2oqgVFUVFVC6IoYVMtKJKMuD3WlGQVSbIgCBKCYFLqJRlTkC9CU6siy///xdn9//QSBAGXx823vvNtPvnpTzEwNMjG+jq9vb088a4nWV1fwx928X/8q18nEVvH73JgFwXsVge3btxmfP9B9h88TKVcY35ukeXlVXbv3kuhUGJjK8rpc+/gdDqZvH0bq03FTOTTEJBIpTIkEilkixVZsWCx2lFkK06nl50797K2ukWgpZWNzSgHjxwlEGylVm/SqENvzxAL86v09gzRrAvk80UKhRKBQIhMJofd7cLhcSPLMtMTd2lxe5mcnKSnp4dcLoff70dVRer1Op2dXbjdXrw+D4cPH6ZYLCLLMhMTEzSbTbxeL+9///vvAXNP3PcAHR0dTE9PUixl+fZ3vkq5XGZ2dpZAIMD169eR9CpdkRYa5TwrczOc+uErvPLSi9y5fQuXw8I7Z94Ao87nf+mfgNDgzsR1Ll46y3MvPM/c3BzhcJjOzk56B/voG+qnXK9Q1xuU6xXyuSw+r4cWn5fY1iZ379winY7THglSKRfQtAbhYAitWadUKpLNpIhEIthsNqrVGna7EwELsqzicDjo7OxkfmGWUChEo9Egn8/T0dFhLlZCEQ4fOkC9Wubg/kOsbqwjyBKHDh/A47Lz7A++Ry4fR1FhbGyMSrmB32cGz8XiCZxeH8FIG62hdvy+VtyuFqJbCXLZMi6fl9/8l/+CoyeOE2qL8NYbb/L5z38exWrBZrXiki1sbG0ytnsX1XqN5dUV7t6Zo1EXuHrlNstLm+SyFRqlEpVykabeIF3KkohuoQhQKhS4ees6siKxvLSOruuUSiVmZ6dpsfmgqpFOpVjbXMPmtrNrbCfBQAuKLDI3M8tLz72A2+li//79XLt5g7bODraSca7dvklnZyfT09NoTZPMHgwGyeUz3Ll7G01rkEol2NraZG1tjdOnT9+TK01MTFAoFGgJh2hpDTG/soTT66FuaExMTFAsFimXK0SjCdoiHSzML/HIwydZW93g0sUrRMLtZLNZCoUSQ0PDCILA2toaU1NTNBoNOjs7zUbE6UQUJLQmqKqK1+s1vyfbS0Sfz09vbx+dnV1EIm2oFpl6o0yotQWX28Ls/ASp+BqZXBSNCm6biOK24vR7cHjdWOw2nE4nDosLu+rErjqxKQ4EHTNXHhFFsaBpBgIyGBIYArpm0DSqGNQQxCZarUQm+fdSN/+H10+EDlTTdVbWVvkv//UP+da3vkVPTw+v//A1JEXmkUcewd/Swh/+/u/w6U9+CkmSWF5a4cETDxDLmxa2n3rmfaytrXH18hXuu+8+crkcly5dIhJqpcUfZHx8nD/4g//MgfG9yLLEYP8QhUKBQMiF1+NnfN8+lhZnmZ1fQJQlhoYHSafTNBo1ikUTeDEwPEQqbVreLHYbg4ODeF1uotEoxWJxm6ot0mho96JF1lZW8Xt9rGSy9PT3US6XaTQatLe302w2sVqtnL/wDrt37sSiOnj22Wfp6Oml1dfC6NAYl69d4uDBg5y/fI5sJk8mk8Xn85mJlF4LZ86cIZ/NsjA3zezsDH6fj/b2CG1tYfbs2cPa0iLNZpPFxUVqdYPjx0/w3CsvUJ2b5+D4Xj7xiU/w3IvPc/f2BJ/4+EeZnzOByP5QJ3Mz09y+fo2Bvn5ae7pN6HRLy71kRlUwlz8ulwNRNPWspVKBBx+4n0I+jSAYNPUGiiITCYdIJ5JcvnwRryeA2+2mWs7jcrnRBfB6PSyvzPP00++551Tav38/iXic9vZ2qrUSywvzpFMpchkHvX0jbEXXmLw7jWKxsHN0lDfeeIv3vve9XLt6nZWVNZ566ilqNSu7d+/F4XSTSKbJZYtMT8+TShbo7Rmit1/E7XHeO7Hs3bWbs6fPkkwmOXDgAOVcgaWZOSx2272UUkEUaVZ12traSOdzHDt0mGsXL1OqlBkY6OOtt95gfnYOvdpkam4Wp9NOS4uJjLN7zSTSc+fP4vP1sri4jN1pM0lRtQoWRUKQFLa2NkgmE4zv24vf46VSKlCrV5AUEa/fQ0PX2LVnN9evX2f//v3MTtxF16FYLG47bZxM3r5J3TATOiVJ4PDhw1hUlWKxSEtLi9lAaCLxaJRquULT4cCqysTjcTRNMxenqoygNenvH+D69RtEo1H8fj8Ot4uV9Q2eeuopVlcXqWw/WKwOO41Gg7XNDbw+N7ohohmmW8iiCDTqGg6Hg+6ePtxuLwIyqaRJb5KlKiICmtEgGl0nmYHNrWXK9RyG1ES1iqYLyqqiKCKiIKPIClbFiiKb+llJNP/Ioo6AhCSa/aEsy+iajq43UVQRWTLQkBBlkWI6TSqZZOLG3R+rdv1EeOGHh8eM//an32VtbQ1d16nX63zv29/kyJEj2F1O5pcWSS8vMDAwyK1bE3z0Yz9DW1sbX/761/jAhz/E5atXCEciBHx+GtUaX/3yV/j5n/95UokEb55+m56BLpIb69glge6ePupNA0lxMr7/KJNTs3T1h5ievI3f60NAYaCvi4uXzqMoCr29PczMTBEIdhNsDWF3OSlXK8jNKt//9nfp7u4mU8jxxLuf4oXv/y2GYfDe976XK1eu4FbN5cI7ly7Q3tlJpVbF4fHyxBOP8eKLL1OtaOw9PE441EpifRNdbxJNxRCbkCvl6ezpYH5qBk1osrG+xeDgkDlmqGukckUUSaBWLTI82MfZs6dRJCuSJHDkyCFUVSWfz5PPFxkcGkPTZXbsGOPa9G1WFxeJrq/R09HO5uYm5985x46RIZ5++r20tYZ5++xZ4ltRVFkhurnJ8P5926FrDcLhMCMjIzhtTkplc+RisSimuLxRR1VFKuUiFkWi0qghSxKJ6BYTt29SrVeIRVO0+MPomoIoqCwsL9DUaoRa/YyNDROJdGKz2fB73NhtNq5du0ImFaejs5X2SDtXLt4C0UoyFaWvt4tUKkWlXKcm2vB4XDicdtbWVsjns6iSE0mRGR7bicPlppCqoCMwMzOHbhisrG9w4tg4f/mXf8lnPvs5CuUK586dp6Ozk0gkglGu4ZBVDLeNTDZPR2c3p0+f5uihw0iKjKfFj4xAOVcgVc0z0NONhEAxk+XUG29x6PhRVrfW2Tm6g1deeJEdu0fRNRGb1U2jbuBySty5M8Fwfx+TdyewWy3URYFqpY7P18LS0hLDg0OUKmVki0pHVydvnz7Nu59+mujGBqsrS+SzOTpDbXi9bs5dPIevxUtPfy9rS/M0BJlEOo/HZeOJkyf52+99jwP79rO6ukounUFRBTo62kgnU2jNBrlchkiPGXmyb98B05FVMY/iKysr7N27l0gkQriri0K+wtzcDPML0wiCQKVSoVQq3YujdtjcuD1+FIuDZsNAVTTcLi+ZfA5ZsdDb289A/zB2u7kcymQyBFq8uH0OXjv1KhOT19CEBp6gREPWsLgkrKqALFtRJAVJVEzYuaxiyNZ7BgRBEFDEBqIsYbW4UBU7iApao44gaMgKNBp11jdNIf7i3CRCU0fSJSbPbf3v6YVvNBr8p//nP9De2srNycs43FZ+6TO/wCuvvLKdqifha2lhaWWZj33842xubhCJtPJT738/W5tJdu/cjWoVOfXaWwwPD3P/gycIt7Vya+ImY6MDxLa2KGYL7DxyhEKhRCKdIdjuxBPwUq0UGdnxMKmNGDeuXePhJx6lUC7hdbtJJhKkk1lEyY2BRLPZ5Nzptzi4fzeSaCUcbkOva9RKNSRNoAmEQ+04HAEU1YFiUyhWyhiiirclhFcSaW3xkklmaA21kU5n8bmDSKKVim7QbGrYnT60eoHlm7NM3rrJfQ/cz1YsQzpVYuhdo7S0+PjLv/pzarUqbW3tZNI5Mukc/pZOdg73s7KyQqOms7m+RrJQZHR0lFQuj6qqrKwv8I2//hvWVpb54PvfR6VUZOfoDnaP72ZhaZEXX/shu0ZGGRvfQ9/wCKqkcvPmTbp8ERrVJk6Pk2g0ytiOYa5cvmwuWVpaUCw2BAVU1UIyukV1G2jhsNqpVEq4HG4G+ke4c/MG4VAbG5tx3C0hDhzaTalRoF6tcf8xc4adz8epVsvIVpFUIUFHVxvdnW1Uq1VS6SI7do7hCHSauthKlXC1jNvlYnF5kZdffpl8Ps+hQwdoNp2Eg11UKhWWZhYY37uPYHs3E3fv8MnPfY7f+/3fZ//Rw0xO3eUXv/DPaBo6+XSKHUNDXLp0iccfeYQf/OAH7Nixg0a9zPTMXU6efJxkPEWjVmRpM8FDw4+jl6uoGlgsFm5cuYWnxUOhXKCh1tGEKivL8wz0dJJIJLjfG6CpabQEfLx99gxhbwuNigmBESUJp8dLIpM1uzNBxG53sLo8TygUol6osTQ5w0BbJ2+8/BIel4NCNsOxw4d568xZ9u7eQ29nF5lCHpvTjdXppZhMUsqmkHQ3U9MLNA2ZZK6A1+Nj4c40eaHB0K5dGLKIx2Ezj/3ZFD5fC4ODvVy5epELl87zU089jabVkawymVKB/PQMW2urDAwOkkmHKDfyWB1W5mfncKh2JIuMIGpIhkajUqQlEEaxSlSrVfoHhrA7HbS0BBEMGb1p4Ha7GRwewGWVuTs9RVd7B4V6lEIlQVXKYVUsKJIVUVIRZBFkFd0QMUQZQ5QRJBFEg6ZeQ5QEVFQssh1JsdAwdAyjTkWsoWo6sbUkmUyK6YkZtEYT0VAQDRG9qf1YtesnooCm0xne974PEltf58h9B7h95yYvPPd97DYnpVKF/fv38/a5S3z0oz/Nsz94HlW1sO/AYVQV1tdXcbqGKBbLDA4Ooqoqvb29vPbaa6ZlzWZGve7dN47b68FidaLYXfQPjyCKIl6vl0wqzdziAh1dnSiyTDQWo7KdTyOrGQTF3Ejn8mkqlcq2RKmIooKgNQlHWtD0KpFIhPb2LrKFPIYo0FREtLq58W0KBi6HnXBrJ9Mzc7S19VCtLGEYBsvLy8zMzPCe9zzFxsYG5TwoqpVCNIHVaqecX+RXv/B5crkMi3PTDPX1kcplWVtbI7oV5/Of/zw3b96mJdyBoNp59tlneeaZZ2gsLxLd3KJUKvH222+za9cunnz8MarVMm+/9ZbZcbR2EAi3su/AfvbvPYSMwMriErFYgv0HD7Nzz27sFjt3p+8y1NpCyN9CIZXB4/EQCATweL0kM2nyxRx2mwW/38dmyaTRW1QHxUIVi+pEFDO4fC1E2jroH9rJ7bszOCwunnnf+2k0GjQbDfRGA1GE/r4essU8ToebWrEAskyhVCEQCHLp0hUc7jVcLhe9vQO8/PJrdLR3MbSjlxP3P4B3m7BerW1gKAr9PT1MT81w9fZtVtYTHDhwgBs3rrFv/15OnTrF4cMHuXDxEstLS7S2tvLEE08wt7jI3elpnnjqKarVKl09HXS0d/N7v/cfefzxJ1ENkQ7FRm/fEKlEmgvTZ1Fl0DGoV2s4VSuKaMfQFQ4fOMjE7Rt0dpn57OsbG2zGojSaOu0DvcysLrGWNFF5hlWhoWsYtSpem41QJEx0fRWH20MuW2BtbZ3h4WHkpsyDJx5FlCUikTDLq+usra1x8uFHePmHr7K6vHIv+dLtdvPUU0/x8nOv0NttjmKOHj8CgM3tYHZ2lmIuiySbuU9+nx9RlInFEoiiyIkTJ7h16xaCAUvraxw7fgKH08nExASbW1sEWttwKQ5u3ZnA4/OiqlZqjQZirYmu6yiquUw0RAfpVJF8fpn+wSG6O1tw2W1k8xmkOjSaVaYWVnjr7OtMzd/FGVBw+azYFSeiJCEpKrJqRZRNDbJgsC2BaiJqIpphoKoKqqJit9gxDINqOYchGtTrdcrFPDMTU8TWYlgsDiq1BqqqUilWkAQRQfjfeIn0I4rM3ekpjKbGxsoqpXyBQi7HxuoGNtXOoYPHeefsBcLhdp5534cItITJF0r09HXzvW9/G6Np6td0Xeett94yn2qDgyzMLrDvwCFkqw2Lw0m1qaGJAuG2Vs6dO4vLYcFomii7jq4uJifuIAgCkqjQ1HR6enpwu7xmUJkoUqvVWF1dJZ2JI0o6jUaF7p52stkkTrv5jXN53IQ72nG4nIyM7iCVSVOtVtE0jWQyeQ9e0N7eyezsLF1dXZw8eZJoNEpXVxcNTcfucPHkU++mUmvw0z/907z++uukUimuXbtGV1cXe/fuRdM0PvaxjzE5OcnIyAh2p4tkOsO/+jf/lqZucGD8AIVcjkRsiw994H24HFbsVpl0Ms573/deTj7+JMVCmY2NLRKJFJOT05x++yzZdIbW1lbm5+fZjG7REOH4g/fT0dWJz+fDpqh0d3fj8XgolUwSfEd7hHAwiNZs0tPVgaE1yWbNzndxcZH1tU3S+RJn3rnMmbMXef8zH6ZYrDAzN0+xWMTr99LR3cXI0CCiKOB2uzF0HRmF1ZV1Go0m+XzRzKGvVtja2ODy5cs8eP8DHD16jIZm0DcwQltHD6Vyk6PHHqR/YJB6Q+e+Ew+xY3QnO4YHqVVKfPlLf83hgwc4fPAA5y5c4v4HH+K3f+tfkk1mKZeqvPc9P8XszDxejx+LauNrX/sGsizz4Q9/mEqlRLitnVNvvk18K87S0jJ9I8MMDA9RrdXobO/A63LjtLpw2R2sLq+gN5ocOXSAjc1NkEScbg+iYFLtw23t2BxOsvkC5aq55PnRjFLXdQYHBxkZHsXt9vDkk08yNDTCYP8Q8a0kxUKZO1NThFpCzE3Pce7SZQLBVpbnlkilMgSDrVQqNZLJNPEtU+3h9np459w58pUSt27dolqtIioy/kAriBKqamV9bRNFsRAKtVKpVOjs7GTXrl0cP34cSZJ444037qWvqqrK/OwClWIFXQcdsNptKIrlXqib02UnFArx8MMPc/DgYURBIZMuIkigWCV27x4llYuyHlvB7pXZf3QXDp+NutHYPpqrWC12BEFEa+romoEgmPpRQRCQBANVkpEQ0Bo1KvUSDb2GJEImEWf67i2unbtIdiuFVVShCWg6jWoDSZAwDBCMH68U/kR0oIoksW//LuwOiVdfeR6HVSFfkXB5gxRKAr39u6gtLjIe6ebKlSusrG6i6SK5Qp62SICTJx9hZmqa9zz9bl566SV6e3uJRCIsLy8jCBKrq+vsGB3l9t07DPTvoKPFx8zcLOFIiOmbEyhWC4Yo4G8NMjVxG2dLC4rVhs8fIJ3N4w+14d0m5YyMjLC5uUlPTw/5XBlRNwgF21hZWyWRSNASjCAqMsM7Rnjxue/hsNlREOkMRahUKgRDfhYuXcHl9eD2OAh37jUtlFYTuFGpVChWyvT39zM2NoZit/LSa29x4OgJzp1/B0G1I6h2KqUsX/ziF5mdmUdVVSRJ4oXnnmV8fJxTb76BoihU7HZ6e3vZ2FhlfsHkX775xg9pagaGKBCNJfi5f/IZmhg0tCbJeIK1Upbh4R7zOJnKIKkK6WSS9Y1VIpFWVEMg4HbjkUzRe1PTsLucSICuaVhVBaPZwO10ks5m2dzaIptLEgh68YXb2b17LxfOX0GWbHS196NJFYItPoqFLPliBrugkcqkyBZLREJharUGLcEgLqeHfL5IrZ6Dhohe01FtMvl8FpfPhcvlwenwEI8nGd2xF1lWWFuao1arceGdy/T09DLY3082n2N4YIBvffMb6LrOJz7yUTo7O/nyl7/MBz/2EQzDZFQ+9sTj3Lh1k9HRUSLhDqrVKpOTk0QiEQTZ4Ff/2S/z2vPP4W8J0tnZydzGKrqmoVotJNMJEBrcunmVcrlMpVTg1Btnsfl9nHzsXWQzOZ7+qf0kEhvU63X+/M//nLGxMfLZApIiE43H6OzoYnZ2lsNPPcWXvvRlnnjiCZwuDw6HC2H75CSgs7y8RCFT4Nix+zh04jiGYRBsCbEe2yCbydPXO0CjrtGzY4h8rUylkKKno525iUn2HdnH3bt3qdYaBMPtDI2McOXMm3R2dpFMJikWsyiKAmCmkWbSHL/v/nvqCL/fz8r6FulimUPHTjA/N0OpVEDGwGpzYLPbsdhtWGwqoqQRCHpRFBeyYseiOrA7DQaCXZTrBdK5GPOr0yyuzSDZDKwuK6IkIwoCsqyi6waGABgqmgYWRUESzeZLVWSazSYYoCgS2VyCcqnC2somWxsxjIaAKijYJDtNrUmlUUfHQERHb2ro+o8difT3d6CCIHQKgnBKEIRJQRDuCoLwhe37fkEQXhcEYW77b9/2fUEQhD8UBGFeEITbgiDs+/s+hiTB6twNkmuzZBMxUtE4om4nm6nw7vd9mGi2yOpmjGC4nd37D7L36FGsPh+dkU7O/vAd1peiHDv6ADOLs6Tzae47cYRobJ14bIN8IsGjx+8n4AlglezEoilsooJq6MQ3NgkEQmSzKZwWKzIGLr+bpeU1cvkiXm8A0ZCoV+qg2qloOla3l0hPP209ERTVisXiYSuawOZy4rBbCPjdSLpBLm52X7qu43E68LjtVBslqqUmLofJZawbVQqFEj5/kHBbN7FYAlmvszy3xPDoGJl8jomJWwwPtuGyCewb3cFTT76brUyWVK7A33z1GxiSSqSzl3S+yOEDh2nWmtTKNd56/S1+4zd+i9WVTZKJApcv3uW5H7zBwuIahVyJfCqDTZL41ne+zYvPP8+1C5c4d+o0Hpcb0eHnh2+cZXUtyjtvnefK5ev0dQ0iaDLr0QSaxY7T78XisKMbTTKJKJVqiWh8izuTEyytL7OZiuFw2ujo6GDXznGKhTodbZ3UqzWOHN6PxaLR1M24aUlU8HkDOOxe6g0dp9XDyMAYVrubRKFENJYlnszi9QcYGhlFddpR7TY6u3txe33cvTPFD199C0W1Mzy2k0BHhIs3rxIOhlFEhYceeIDV5SVu3pmk1tA5fPQ+bFYny0trXDl9hmvvXMDr9lEuV5mausvNm9fp6uogHA5x5colrKLAt77zbU4+/gRrK+v88Nlvc/Xcm6wtTOG1SZSyCXKpLUZ39HH3zg0KxSzNcp1jB48T34hhVW2kUhkCLSFCra1U61VymQTL81PcuHKeno5Wcqko5XwKVYNqPk8pl+GJRx/mztQke/fvIRD28NVv/TUbsVVeffN1FLuVpY01Qh3tRPN5nnjvT/Hss8/xyiuv8Mobr+Gxu/nQ+z9EMpkkkUkwNDbMD557jg+890PcvjHF4Mgg125PMLe4hKqqZJIxluem2TW2A0lokknGuHb5ChurCQxBpVBp0Bbp4rVXX2dseDebsSxnzl/F6nDzzNMf4uqlm2TTFcpFAxEXW6kkWkNDlRRE1UqlprO5tkl32E93mxOvt4nVKnLhyjv8zdf/kjffeYPlzDQWn4xqt6AqFlRBQpBE6s0aJa1CXWhgiJL54DbqNCjQ0FPIio5hNEgns0xPzHP2+fNcf+smsbk4clVBqApoTZVys0GpUUPTQWvYqBQEytkmKlZUq/3HKqD/kA60CfyqYRjXBUFwAdcEQXgd+BTwpmEY/7cgCL8J/CbwG8CTwOD2n8PAn27//T+9yuUykqRw9uw5gi2mDtDjtNMSDKFYLFRqVZ555hnm5uYYGBjAMEwcv47G8voKv/KFLzA1N0s6m6ene4D19U3m5uYoFvKM7dlNud6gphnY3SaFuqe3kzt3rlIslnE73Aiyh0Cg5Z7dzePxYLWqeNwe6jVtO4+8bNrP3F5kSWRpfpVqtcHwYD/pdBa7xxQGa5q2ja5rJRgMks/n70EtfD4fC4uzzC8scvj4EW5NTjI4EOHNt07xU8+8j/vvvx+9UuTQoUNYLBbi8YqZSliusrkxhdfbQjZvosVS8QQDvX08/+zf8tu//S85c/os8XicSqWCy+Xi3e9+N5/85CdZX1+np6cHTdMIBoMcPHLwXpCZzWbj9dffpFIsgU9mx+huVpaXWY6/xs/+7M9iNDUMTUeUJRYWFjh58hEGqv33sr0Fw1yeuJ0OStUCLpeLFt8olXKRUqlENpulo6ODWzcn6O3tJZFKolhU0llzhmpz2E1rZ62CIolIsojVagdJpFo1o4xHhoYxDDMyIhqNU6/XOXr0KLFkgs2tGOVyFY/Hw32dPUzcvslWLMqx++7n/uPH2FpeRxRFJicnaWtrQ7Ta6e7uplgscvLkSXp6eohvblCu13j/Bz9ALp9HEDRefvllcrncva/RjcsX6e/rJR6PsryyyLsfe5DNjSgtoSDJbAa73Yw3dmcyTE9Ps3P3LmKJOE3dHA099tij/NEf/RGyIPKlv/krxsZ2cfqtU6gWA4vFwvj4OLFYzISNqE60uMHIyAiXLl3ikccex2pVuXHzCv39/TQaDSwWC9/73vd4+un38Ad/8Afcd+wBzp07R3t7O+Pj44yMjLCyuIxhGPzCL/wCL7/6Cjabjd/7j/+RP/3TP6VSLrAVXQZZpK+vj907x/jmN77G4cOHaZYDlMtF4nETCO73+2lpacHtdpNOpzl27Bivv/46C8tLfPZzP0tD0/jGV76G3+83mwWPi7a2Nvr7e8kkklSrddra23A67QS8PlZWFhEtEsG2MBtLK5x6+3UMWaMh1pFUC4YhIAgyjYaBJEk0mw1ESUIRJQxEJEFDRADd/L0UBYGtjSi5bImF2UWMJkiCGVGsaRqNeh2bzYaoqFQqNQxDxNBlVMmKbjTRdQFBEPhx1Uh/bwdqGMaWYRjXt18XgCmgHXga+PL2m30Z+Knt108DXzHM6yLgFQQh8r/6GLphsLK8gcPRQlO38DOf/AU+/Mmf4YGTJ+nq66JuNFhbW0FVZWRFYnZ2Gr/fy9vvnOWf//Zv8uyLLzA8tgOHzc1g7xDLiys4bHZuXL1G344d3JiepFivEkvEuf+BYxSKGUrlPLIM5XKeZrNJJNLG/JyZVhgIBLBYLKTTadOnK4o0m2Xsdiub61tE12M47UF6+4aQVAtjO3ezML+M1jRo1E2/cbVaRkfA7fEiKxbS2Ry1hobVrlCqFFhcXCbgDZFNx7GoEi6Xi5XVdZoGIAosrSwjyzK5TBaXz8eduVkEu4XL16/g9XpYXJijWi7xTz73c9y5fQu3y4lqs9LT30d3Xy9f+frX+Oo3vs7C8hLVRp29+/dx/P4TDO4YpSXShs3j5bXT7/DpT/8Tfutf/ht+/pe+yGOPv5vf+K3/k7Gdu1laXCGWSOHxmpG7R48eZX19/d4MV5LMTkDTtHvQlR85TqxWK+FwGJ/fT61eZ3B4CJvDzuDg4L33d7vdFAoFVIuEpldB0KjVSmzGE6TSWeLxJNlUlts3bnNnYoYWf5hqRUOR7dy4NUG9oeHztZDLF7G73AT8fhQJ9u4c4/LZs0RXVlhd3yBfLOH2+hga2YHf778n8H7jjTe4c+cORx84wcOPn+TZF19AF6BUKvHAAw/cc/JcuHCB8f270bUa2UycXXvG2IqnyRZLeAMt9I8MkC2Zsc2JRIKuri5yudw9s4TH4+HMmTM89NBDLM/PMTc5jdtm48xbb9HW1oFhCESjcQKBEHa7k83NTVpaWlheXub48eMmuahU4syZMwwNDfHCCy8QjgS5//77ePvtM/zar/061XqNSq3Ort17EUSZyalphneMcWdqivPnLyIicOHMRb7zre9yd/I2Bw7tx+Xx0BoMEQoEmbx7l8///C9gNDUuXbnG0uoadpcbQVaQJIVMJmd62iPtTE5O8673vJvf/d3fJZNKk4zHeeKJJ8xwRafznsdeNGQ8LSHaunpxWN00G2V0rYo/5EYTapy/eJprd85hcYHq1EAuY+gSimyjUTfAkGnUTQG8KCoIugQNkI0GFtmAepP4WoLJm7NcOz/B9M1pjIoADYFqRaNW1Wk2BOx2N7omk8/n0TUJUXCgyE4M3dS6IjQRFdDE2o9VQP9RM1BBEHqAceAS0GoYxo/k+1Ggdft1O7D2d95tffve/0vqLwjCzwE/B2Cz2pmeXeLnf/ELRNo6+aM/+hP2HznAjVs3eeihh6hXymgeN+1tnczMzdASbCWVSrFn1xjf+PpX6ejoYH52hoDfhShpFAo5cpkMhw8foau3j/mlFfSmQX/PAJqmsTC/hKFDU9dxWB1kMjkEQWBxcQm/30etVqO7PcLFd84xMtxCPB5naKwft8tFOp7A6W+hVq4TbmtjI7pKXatiNDU6O7vMzaDRZGNjHZfb3EoqikowFCa7uECgJYCmGYiiiCKLFHIZQi0BisUiNruTTKFAvdnk8KFDnD39Nm3hMOfPnufhhx8lV8izY8cO6pWyCdttD/Mnf/JHiKLMpz71KV5/8y12797N1atX+dV//mssLy9z8+ZNZufn6OrpZmBokJmZKfLFMha7nfd94P2cuXCO3Tt3oUoyuVyOtc0NBoYGGR4cQhJELBYLIib82O12oqgyXq+XZDJOIhYn4PdiUfz3imkslqZRr6LrOm63m3ypiCQp2BwONMNgYGgIRTF1o30DA+hGE4vPTyGfRVVVXIPOe3k4k3enQYdiIcv3v/99rFYrPp8Pj88LiLS1t6HaHeRzBW5PTtLXN8C5M2dpbY1w8/oE7T19HDx4EKfTyd27d+ns7GRiYgJZlnnyySeJx+OkUikWFpZ412OPs7a2xr59+/jBD35wb4P98MMPU63m8ThdXL18jWyhyC985nMsLM0zMzPDSy8+z/i+fSiKQiwWY2xszIR1r8eItLfT0d3BhQvnOHXmNAN9PQyMDGB12HniicdYXV01M67SafL5PIZh3NNFLi0v4/P56OrtQ9fNxVIikeDjH/84yXQCTW9y8uRJrl+/id3hYmxsjPb2CJlsCn8gSLgtgsPl5Pq1K2RTGbo6ulhdXeHd734XpVKJffsPY7fJXLtylYcffIC7dyeIbm7hcDvNZM7hYZxuF4qikM/niUaj1Go1RkZGCLaG+NP/9md0dXQSCoW4fv068XjcTAgt5WkJ+LAoClZVRrWpqLKIKDkwDIPJyUmuT9xiamEGp0fF6bejS02aUh0BC6AjyzKgoygSiE10vXnva6NVy2zFEhTzZbbWYiiKhWYVDM2MM9Y0DVEycXuSLNJsGDQaGrKkIIoqGCKG0ASlhmirg6FR0pIceeA4i9ej/5hyCPwjCqggCE7g+8CvGIaRF4T/jn8yDMMQBOEf1QMbhvHnwJ8D9PcMGR98/yeIxTP81z/9b3zsEx/H5/FTKZUpZHK0eE2C+be+/Q0+9OGPIkgKN2/eZPL2JYqZHA8dO04ql2UrvUQulyMeXaNarvPpT3+WF597HllUcdtcOC0uErEcG+txhoZGmZ6aRVUc+Fu8NBravWAsu9tE2jkcDnp7e5mYmqVRhXAgTCmfp1LOU0jnCXT4kO2wFV+jt6+DSqVGpK2DpgFz8zMcPHGMeqWMrCpY7Q5TSO/yY7U76GgLk06nKJdL7N2zj+XlJdxuN9l8hVC4lY2tLVKpFAM9++ht72ZucpYdu0dZml8gurzG3t27ePXVH9Ld2c6JEw/wyksv8IGP/TSnT5/GarezGY2yur6Ow+XiZ3/u53jrrbfYisVYX5okEIqwc+9+5qancLptTM7eoaO9HVVRaGtvo1BqUCiWKRYKzM/O0d0ZYWxsjPX1VURJIBwOEwwGaY+0oTfraI06xUrRpINj4PebXWupVDKtdg4XVosdTbaYNsFqBYvFgo6BLFmp1xo47F5qtQqSDE6ngWB3MdDXJJNK0eF109EZpqenB1VVicZNt5Jqs+LVfVy+cp3ugWFQbEg2D5Ji591Pf4C16CY/fONNrFYrJ06coFjM09raSjKZZHl52Yx2sFixBaw4ZAthX4A7c3fo6+szo0YSCdbW1tgxMsxA1xCraxuoHidzUzM89NCDpOMJBHRee/FFHnv8Kd449RaXL1+mraOdXSM7WdtYJxDwYwjw2c/9LH/95b/i6WeeQbJI7DqwDwmBmZkZEvEUfX19ZpEIWUjnsuY4R9c5f/48TqedD37wg7z99hlOnTpFrpDl/e//IF//+tcZGhzlgQceYnNznStXrlEuFzl69Cjnz12kXCqYmVR2KxfOXkCxyXT2hFnf2GBgaCcbq4tYrVa+//3v06ybCoC27nbGdu/CbrciSRJXL1yho6MDm9VBuLUNh93FqdOn8fl83Lx23fTb7xzl0CHzQeVyuUxHlCBTEw38gRbqxTKiKJDPZMlkCkiyasoJrQKlWhVUHVHUkcU6CMY2fb6BIMqYq31jO9NqiVIyR62qgybTrIk0AL3ZRBYlkAQkZBroCIKEJEogyoiChE4TDBFJ1ihV0jgCKg8/dISRHb2UmgXS1cw/pnzdu/5BBVQQBAWzeH7dMIy/3b4dEwQhYhjG1vYRPb59fwPo/Dvv3rF973961ZsNTp17i3A4zG/+1q+j6zrPvvhdxgaHqVWy5BQDuWnjk5/7LFtbW1TyaTbX7qI3ijhdKpVmmVqzBpKNdGqD1mCYPQf2cXHiKipl8tkityeu8+73vIfT596iUEggi1V6enpYj8axOh0oTjedA0M09SalTBq7zU68GSdbyBNs8WNoDQqFAuFQmLnpHKpfxea0sXxpmZGBfiq1KihuKvUKmWIORINGsY6oCXicfry+ICgWUtkYO3fuJZnIEo2vUstXqBbzVKs5Bod6ice2cCLgtNpoD0dIplNYnTb6WlvIZDKICNy6dYtAMMJnf/6XeeOtN1lc3cDjC5JNp3n85En+8+/9PhcaGjv27UUSRNZWVmjWqxRrVY4/cD/nz18iHksSbmvjzu1rLM0v8OijjxIOtXJrc5VUMsee8QO43F4effQk65vLvP3OWXP7WtMoVRvITRM0Yuh1nA47Nl3F5/nviLRCMU0gEAZDoFSqo+s6DTGPzW5D0+R7sA7qTVT1R4xHg3zO7MSq1Qr5SpF0Kc/a3LQ5UskW6e7uxe5roVYpszJ5B4tsYf/O/RSLJVLrWzz1xJMsrqySr5S2oc8hlpYXuHrtIuH2NmwuByGrFbfHh8/nI7m1yVtvnqKruw27VaFcLtHe1UVHTzfXv3qT3cO7sTgVlhYmSWfzPHH4af7rn/wZfTvHaIgigWAroVCY9s4ATlmmxenn0K7d5MpFyqU6ACMjQ8zOTWCRZDwWN6+/8Cp7x8e4cvk6QyPDZvEUJcZ27eTVF16gv7+fqakprFYroYCPU6dO0RYO0dXewfUrzzLcN8R3v/YdClWNT3/mPl548bu0tXXQ09PDxO0kt27e5fqFd/id//QfuHX7NmJT5/D9B8hm80iGgtvqYfruddLFEpJg5rn7vT7C4RDu1hCnTp/hwP5x2traOLT/ALquk0qlWZxboj3cQXxlnVqtxu6du0ye7eo8C3NTOJ1OggE/ne1tOD1+7DYnTcOgqdox9CbFUpVYNkexXsXmUkGvIgoGWkVDxIJgtSCKBo1mBcUi0jRkyDUoFyvkM2Wy2SKaLtBsGmBoiKKAKGnYBBVdA12TkUUZCw500aApNjEEkCQNQShSMap097TzwM77CPd40DSNeGUdUZGxWpR/aM38f13/kC28APwVMGUYxu//nX96Hvjk9utPAs/9nfs/s72NPwLk/s5R/3941WtVHn/0YTbXVrDIIn/4n38PiyHyna99i/WlNfaN7aIj0sa1i5dRBYmXn3uBQ7vHia4nqNd12tu6KRcqLM+vEQl3cd+Jh7l86QZXLt5gz94DpLMZWgIBDFGg0TCfTs16g7uTN2gN+2lra2NjY4OxsTGcTierq6tYLBY6OzvvzewEwSAYaiEajSLJIqooEN+KoogSVosdVbWyubVFS0sLsc0oqUQar9eLxWanrcPkjdpVO5FIO7VaDa/Xi93mZDOaweH0Ua9BtdygNRihXq+bVJ89e7BYLAwP76C7u5dEIoXH50dHYHllnWKxQri1nUdOPsHBo8fZ2tri3LlzPPzww+YMr14hGlvj/IW36eoMc+DgHkqZAr/2hV8lsRVl+tYkPe3d/O7/9e/JJbOk4yncTg91rYnP78bptqDIDfaMjvDYQw/gUGVS0U3mJu9QqpbNbqNcYTO6RTyWoVJuIolWXE4/XZ39CIIZP2u3//eMp0qpjNPuAN0wF1QiNBo1YrEtNK2B1+ul0WiQSqXx+1sIBIJ0d3YxMrQDAVhZXiQfiyNpOnt27qElGMLuddKQYfzQATA0nIqCx2pl4upVZicm2FhYxm2xko0nCbjd7Nu5k3CLHwWDQCDAyZMnqVbrFItFLp2/wLN/+wP0eoMPfOADvHPpAsmtGK0tQdLxBDevXOPhBx9gaWmBcrlMS6iVtvZOvP5W9o4f5Mixw9S0KuVKjlI5g6Y1qJQbWC0ePvD0+9hcXUGv1wh4fPT19bC2skoun2FuboYb165z/Pjxe2OGgYEBzpw5w/3338/du3dxOBz4/X56d/TS0ubn3/8//5q/+vJ/Y3x8nLa2MMlkkqGhIfbu3c3v/Pt/z/VrNzh48BAvvvIKLocbQ4MbN65x/vJ5svkC4/sO8IEPfYie7n4zwjgaZ2l6gcMHDhPwtJBYj3H1+i2mZhYZ33+YRCrHzOwykUiEBx988N7Pp8vlwu839waFQoF4PInW0O8li1bKRYq5HPNzM8S2ouQyWYxtPWezbkJ9MAwaWs2cpzehkm4QX0gzO7nF4nycWDRLo9JEq4MiWrEoNkRk9Cbohg1BsiKqKrosYCgVUEo0pDQlbY2uYTtPfuQoP/drH+GRp4/jCtmo6FXqQgPBKlKnQUNo/mNrp1kf/77tkyAI9wFngQlMnSzAb2POQb8DdAErwIcMw0hvF9w/Ap4AysCnDcO4+r/6GN2dPYZLDfC5z32Oq1ev0tLSQilTIJ5I8cwzz5DPF7F53HT09HP27FnaAj5K+TRXrtzis7/4T5FliT/+gz+kv79/O2M7RSGXp6urC7tF4sr1CT752Z8jX8wxceMa1y6d5+iRg2TzefbsP4DD5mdxfROfz4NRL3P18hUeeuhh4vG4uUWMdNDW2Uo8HmdzfZ1KqYAv6CYRjVEul7FZrLT4/SwsbfLMh9/HK6+8xOStKX71n/82uq6zvrlGo1ZDN5rIqsDi/AqRUBBB1Dn1xnk+/PGPUWpWSSQS2GSVUiVNMV/A63KSSMawWR3kKyXcfh/xWIxSNo/d7kexWjh+/Dj/8ff+E3v3jbNrZID19XXGdoxy9u3TXL5xiZ27RpEEkUI2y+zcNCeOPUAqlWFgcJQXXvohv/CLn+Wb3/wmTz72OMFAgGw2S6nRoL+3j0iklR/+8BXK5Sq9vb3U63X8fr8pnO/qpJgv4HLYAJ1GzfwB/NHmXdd1VIuEgEilUkNRLHj9Jgi4Wq1Sq9WQJIlGzexOJUkyw+DKJaxWM76jVKyQTKbxtfhxu538aGyUTuZYXFpCsVgY27OXazdv0D8wRL3aIJ/KMDa8g7nZBTxec4a3srKMz+dBR8DrN2faBiLVRp3N6Bbjuw9goBGPruN2u5idnUO2qBw7foJoLMHF02/hd1k5d+Ein/ncz5Mu5LbnfgmOHz9Od3c3LcEWzr9xmh2jI1y9eYGevk4uXrhGZ0cvo6M7efPN17Er4r0xkSzLTE5PcffuXR565CSFognjHhgYIJlM4nA47i2QbDbbPSNHf38/0fQmuWyReCKDy+fAJttZWVmhv28Aq9WObRv0XW3WuXr9Ok+efIx4bJ3W1lauXruM3+9FlmXiqSxOp5Mv/fVfcfLRh/H5fIQCLUiSxMrSInar+v+h7r+j7LqvM034OfncnG/lBBSqUAAKgQRBgCABkBRJSSRFkZRkkcqWLVtt97Tb7dAz/nrs7uluf3Y7Z1mWoyxTmZJISqQYEUnkDBQKQOV06+Z88vxxSuU138zX09KanqU+a2GxCryoC1Tdu8/+7f2+z8vkrSlarRZ33XU3Pd29rKysUC0tUywWWVlZwTRN1JBONpVm08hGujqylEslIuEk0ViMUCSM5dp874VvkS/XKFTLOIKFHJAQRBdPtJE1AUkCQ3ZpNmpYzTa1fB3bAMcT/XkmHpIoYNkegiDguj5NXpIkPEEFwQbRRlIF6o1VLMHkgffcR/9gB92dCVZqs5iAHgyBA4bR8l1fnoeiqViuw+d++rv/z3vhPc87yg+yQf/P14P/F4/3gJ/7Yf4ShtHmf/2Vf4EoimTSURqNMqVSnSc+8BSiqlOeWyTR00UwGqFvaJDDr73Mffv28J73vhtZFXnrrdfBa7P7ju2kuzr43T/4fR564EHOnXqbe/YfJJ3pQgvoBDyD+fkbdHTEqNcqWG2Pxbk8O3b2Ar7sQZEkTNMkFAr53yBZ9vPqAwEqlTKyImJZBo1SiXajTq1aR4gKRGNJ0ln/TT82tpXpiVlmZ+bp7e9B1YNUSmU0QaRu2MRiEQrFVSRJYsv2bSytLNG0WuiaQmcmxkKuSTadIRIMMDDYx/zcMpKuE0kmeOGl7/Lv/udfw7Btzr59kn/8h7/hf/qFn+Pzf/vXXDp7km3btvHv/t2/Y8e2ce64Yw+55RV2bR/n1Ssv8xMfeIbnvv5V3vXgu7ljz90MbNqMHpJ5z+Pvo9Fo0B0K0RtPkO3uYml+kVMnzxMPd5ArTiJpATKpDN3d3SSTSRQVUloSs22AI2KadRRFIZGI4Th+2qIe8HFmyWQSSVJwXcsPDqvXEddIOZ7rO24cx0HTNLKZAVqtFo4NnqvQ2xNBlAQsw8Q020SiIepmnS07xrFMeO17r7LrjnFqhQLJZJruzZtxRBjfvYNzp04xMjJCspEAXC5dusSjj72PdFfH2sKjxeb2KC9/91W2j+9E18KcOHacZq2BFgzw3ep3efixx9h78F6uXTjDz/3rf8Wxd06zdWSEN197nc/+/M+zms+jh8Jcvnoey7BZXF4hHs9SKtZ5z7sf5ytf+Rqbx0boG+jEdQQW8otUjRpeS8YyDPbvv4dapUSl1qCnr5dr167x7LPPIggC3/3udwmFIgSDQUol3x2mKBp//4W/pyPbwzPPPMNffv7PePd7HyMU0Hnn7RP81E/9NF/76jeIRqNcvH6Vn/6Zz9CuN7h0/jLTkdvcc+BuLl+9wtTsHKFIkk2jY/yrX/glWs06iUSC7p4sX/rSl9AUBVVPc+D+/UxNTdHZncH2TKqNMjdu3GDv3r1s3LjRT2tIJXAtm66uTox2k6GBDXiuzNLyArdv3aRar7BxQz+tazdYLbsEI0FMp40jiAg22K5FrV2mUndotqrg+lt4wRURRA8cD8v2sF0BTxKRJNkvSJ6EY4u4ch3bbeKKTcZGh7l7735kVaJNC9drUKi2EEQBTZUxrRYSAoosILkinuA/v/w/cqSHqqpcunSBZrPOtWtX8DyHg4cOUa01OHP+PHv338PghiHOnj/HmXNnefLpp3j59VcZGRnm+NvHyK0ukUhECQZUypUC++/bx8lTJ4hEgriuy8GDB7Ftm0KhQCzu49fy+TwbNgxz5fIEsVjM74YsC0EQyGR8OK1pmrTbflbPysoymUyGW7duYZomqVTC7xh1nVwuRyQSIRTyvcXxaGw9UwlEVF0jl8uxYWAI23b9jfualGfrtjEEwaOrO0OjUaXRqK5FvYaRZZmLFy8SDof9qFpN49d+7de4cu0qpXIePaBw5+6d1FpVHnjofqamprh27Rp33HGHH6a2aTP51QJHjhzjQx/6ML/3e3/Ez//Lf8Xm8a1ImoqqBzhx6iTVZp0t27bS0dNNz0A/r3z/eziOx+jIVvr7NrJ9x5109wyweWycTLabSrW5zuxsNn0rYDgSIplKoAc0DLONosq0Wi1s26bdbpPP52k3W1iGSWe2g0QsTiaVJp1OksmkSKeTSJK/VCkWi0xPT6+DZGq1GrZt09nZSavVoqu/G0+AcDjMB556mqH+fnZuG0dwPTzBRdE1Ll27SiAUYjmXQ9E1tGCA+x94ANOxabQazC8t0mw3CIWDPPvss7zzzjvkcjk++tGPsml4mO6OTuLRGF/52tdwPY+55UVK1QrdPT3UqlUeeeQhQqEQiqIxNjaGYbVRVZVGo8Vbbx3l2tVJrl+/waFDhxBF8DyLnv4+WqaBrKm0TINYPEI4GFojGJkszM3TarWQJInbt2/T1dVFve4XtkcffZRGo8HRo0fZNraD3u5ejr5xmP/5l/4tExMT5HI5nnjiCb761a/ywQ89zc477uRTn/o0p0+f5TvffpF8rsClS5f44he/iOM4LC/nuHTxCm+88SaGYbC8vMyXvvQl/uKvPk93Tw+KpoIs0WjX2bR5BAcHSZUY3TLKnXfe6S8MRZFkMklnZyc9PT0IgkA4HMYwDJYWFhBFX2daLVc4cvQwruuSiscw2wahUATP83Bdl1qtRiGfx6iaBOQggiv4WWSei+f4N07XdXFssAwLo2XSbho06y1qlSqGWWfL9lE++Mz72bZrE6XKMm2riif60eFtywRXxGz7ceWiKKKpMqoioSoSguvwo01Af0ysnJ7nceXKZRKJOBI6IT0FikR/bz+KrlNtt8nNV8Bu8/T73stv/Nqvse+eu7k9c5PJC+fIpLJkh7cwN79EpV7j6uVL3LtnL9/+xtfZdech2pLH9LVLpCMROjtG8axb9PZ00jKa9Pb3MTu7SDAY9I8GDnR1+wVUklWG+nqZuHmJDSMbWJyZwTabBONhPFHCaBoQdOjKZGk0GnRlMuSKRZpNl77+IX+OuWsnS/llJEVGi4QorOaJhsNsGh7lrbeP09kzQC6XQ5I9eru7eeutN9h/925OnjxO/+AAG0ZGkcMRNihjVEoV6oUKg119nL54kZguMjTQz2/+5m+hBkM89sR7OXf6DJYVQhZd/u65L9Lf3UMmlebijRv8i1/6NxgW6JLMr/0v/wv9fYNkkiliapBL505jGBbtlsXDjzyEaTYJRARsT2LXyDihUIjp6WmazSaZTIZisbHmha8xszjNYG8fjiCgh8NYnocNBIIBPKDRbhAIBwgEAsiqjIuLsobAs9b0eJZl0Wi1cVyBqek5XxO5tIRl2RiYjI/vIJLJ0HL9TPJgVOf27Wm0oSCBQIy2ZxPvyvpwmFKB0c0bMBs2sizRqFcpF/I07Cqy1iYSiTDQ1Um+VCS/tEIqZfPoex8AoFIvsve+PZQLRW7cuEHh5jVezudIJhMcfeMtenp6yC3M0dc/wOm3j7J3334E16RZqyMFJOymyZatG9m5ZStff+FbvPexx8gXVlFQ+cJf/AU7duzAbtoEJQk7FGVk82ZuT0+Rz+fQdZ3RzeM8//x32LRpEwsLy8xM3+bpp97PF/7qb3j66af54he/yC/9yi+TW1im2mhy9uoE23ffxX337Ocr//QciWiMwsIyVaNFZa7MXePbqa+sUpcFHnns3dy6fZtKxeSZD3+UY8dOsHFokGvXr3L54gU6OzvZu+8AY9vH+N7L3/ZjXVJdfiMgSKSyXawWigRjETzTRlYVrk5OkK3m6ejoIKiptF2fcxuIBojG4qiqyrseeYwtO+4iGNRxBJszZ05x7doVJNOkVCpj2zaiFUEUBYyaiWMLmKaJ53mIgoYk+VEeguDgSTYuNq5osW1XP9t3jEJYpGmUaQnLKIJPrG87FqJjIYkemibgSvhifFHAEcB2BBAFPMlBCSiY1o8mpP+xKKCWZRIJ61SqJTq6skiKSE/vAJO3bzE8PIyuaoRDYXRFYXLiOplsiv7ePjzLpaerj0qpzIa+AZZXcySiMfp7e5m4NkFHpgtBEhnq6+XEkTfJ7r6LkU0bmJue4NLlq4xs2kpfbxeSJNHd2UWpUsZqGaQ6uplfXED2BKLhMJbVZnVplUAghGmaRKJRGs0akiqg6gqWazMxeY3xbbtpmwbxVJJ2q4VrOJhtA1EU2bJ9nJrVZmZmnl3bd4AnkYinAZFqtUpHZ4aFhQWCwSCVSo2R4WEWllZoNk2c5RzNZpNsOs2tyZvM3LqFoitU2xYXy0U+9PSTJBIJVqstBt4/gOC5hEIh7j54P45hkojFOX3+HKrqxyv8p//0mxw8cD/BYJB0IsmWrSMUSyucP3+Rgwce4POf/xwbNw753Xeqh+58L5blR9729/ezOL9ENKgTD0UIyDpqPL3esYuiuA7DqFTK/t1e0wiHw36Eh+J3psVi0d++O37qqaZpJKIxUtEMHR0NP/q3XPOF+aJDLpcjl8vR1dmNZRlUa2U8z2FpaYnZ2Vm6+7p9ETcukXBwLZL6Frqukk6l8DyBRCJGPJUEwHZMZEUkFApQqfjH43PnzhGLJXAUSCQyXLnyHT76kU+yUi9z6exZdo5v583XXmd8xzbK5Spbt25FVkRuXL9KfiXHzgfvoF6vs2lsH5FQkAeaD7CytERI1ZmbnmHr6CilQh7Hcdizby+Xz10mnUzh2i7bt26n3W6ysDDLwsICmUySeDzCM89+gMXFWfKFHIVCkUceeS9vHjtCV7qDdDJDn21TMxu89NJL/jKs0eTL//QcSijEhg0bOHfhPIIs0Ts4wMSNG4yNjdFoNSmXy3QPDRCMRdgwtJGIHqJerXJr6jaWY7B/7z5mZ/x0h/7+fjLZLIV8AXPN6ba6uMzbJ9/hAz/xIdLJGLZpYFptQoEguiIT6shgOC4tB1xZw1YlTAm+98JLFAurGEYbw7SwLAcQUBSNVtvAaPsUJ88VkWUZz/GjX1zPQlTADbXZuXMrI2MbEFWLSr2A1g6gqAqIvq/dcixQRCRRRFbA9QwcR0BABEEEwS+eriviOR62ZfGjHsZ/LAqof3eRaDVNbt6e4/4HxmiaDulMB5oa4Oy509xzYB+3bt6gsLKM0WrS1ZGh3TIZHBjmtn0Ly3UwHZtwMI7tSeihKEPRFHftvYuvfuXLBGWFqRuTDA120dPfy7XrEywsLzC6aYRrFy+z74GDVOs12p5LZ98wF85cZNvoJpbmZkl2drK6kiORjBEKRmibJq16E8N0iSVTNJotkpkO2qZJtVFHEARsx8HFQ5BEQpEwq6srAAQCGsGgjijCnrt3Uy4UyWQ6KOR9wG0oFOHaleuMjo4yOjzKwtKyjxrbuJFGo8HOO3ZhGAaO0WRqZo58YZULFy6gKRL5msF73/sY1XqDZsvm/JWLbBwY5Dvf+jbDm0fRdZ3f+70/4OmnPshjj72PVqtFrVTk/PnTaLrI+9/3BG+8fphwMISAi2WYlIsFook4i4uLRCIRCoUCPT09uJrGjRs3yWbTAAQFdT3r5gdxJKqqoigKnudRq9Xw7H/uNpOxOIIg0Gw0aFsWjXodwzAIBpO+JTSdprunB9ezkTSdZrO9ftyLRqMEgzpDQ0MYbYvBwX6Qfa6sbZt4nksgoDO0ocfHAdZ9opCiCpimf9Su1xtIqoIaDhAM6azmV+jsyhKPpTl6+Ah33XknP/uzP8uf/+mfsfvgflzXZWpqinvu3U+pXGXfPfcwMz/H4TffYP/+/dy7dx8bN27k8LGj9A8OUCmscvniBYxGk/7+fuKpOCElwMUrl1laWuLixYsoeoiFlRwIEqObx3jpxRcIxqN0d6epVPzk0WqpjCRJPPKuB4mGQ+RWVpEEkalbt/0NtigSCYYQ07CwsMBbb73FRz75ca5PTGJZFuM7trO0tITlWpw7d47phTlyS8s8/vjjePkcV69OEFBUEqkOVgsVSsVFioUckmTTdixURedbz3+Hu+7chSzLRCIhAokkkUiMxx57H8VCmXK5TCgUQlcU5mZv+aMwOYSi6Syt5qjW6kSiQSTJp2yVinlqtRoOJtFojEql4m/fPYdAUP9nd5vnYNFECQgMDmfZsn0DtuqAYNFwV3BNB08Gx5WwDVBFFUHy8LDRtCCC6NcWXdZwEBEECVGUcTyXdttAFGVikTQVs0RA/R+4gHqORzyapF5r09M7xOPv+xDPf/cFRM9lsH+AkZERblyfQFuLHOjv7aVYLBBNZHnr+2/yqU98nHPnTmF6Fp4ikcimyS2ssGFoEBcHo9li144dvP3OcVy7Ss/AILXmWVqNNvVahcJaeJksy3gCNA0bSVWYm50m25nxSfmmRTQc9C1ukkKl2iKd7kBARZYEVCWIKIoMDAxgWP4SqtJs0nIsJEXBNi1uzU7Q2dmBZZu02k0Cicha52bR1ZVlbn6G7eM7OLKSo1qpI8nL4Lp09A1g2zbLq0V6e3uR9CBzM9NsHB3j5vfnuDk1w8bBfoY39HP79k2OHjtJIBTjJ559EsFxWVlaZnx8nI6uTv7wD/6Ymzdv8vLLL/PGG2/S35Hlyacep3+gi+e/+W3uvfcgyytzXL58gYCmMDY6wvJqmXQ8vV4Yw3qY7oE+RFEkEPA9xYrgRzf/oAs1TRNBYP1zgHatTqvV8qlT9QaFQoHe/r51vqooitiuR6PVZiW3SE9PF8lkkly+gOcJ68RxBG89xkGJKNRrYFptBNdBFkTMdpu26xKNRTANi3Q6SSKaoFBcoVWvEwwG6e/vZ25xgWQiSbvd9gHNhoFlt7j3vr3EwhFOnTrFp3/qE/yX3/sjPvmpj2MYLZ5//nn233OQ6bl5BNelM5ulr6cb07RQFYXx8XFOnznDpt4uHrzvPhRJwhI8Ytk0x156jUajxratY5y7dJFQuotDDz3IXffdwxtHDnPX3r3Mz8+wdetWPM+jWiri2j5C8ZFHHqFYLDI6OsRSrsitQoV0JsOWXdspruY4c+YM09PTbN++HUmWuf/gIY4eP8b3vvc9guEwgiry7Ec+gtFuszA7x9e+8lXKjRqPPfo+rl2boNEqcee+fWwe2UClmOfPPveHdPV3MTY8xujoKI7j0NfTTbtZx7Zd8vkituPRO9DP4MgI0XAEXZXX2AYmoiJgtC0cyyWXy3P06GHeOnqYeCqKJ3pkOzuwnTaFQoFms4mu68TWbtA/eO2EQkGyQ9109ycJZQSa5gqYQVRNwLJtECUkSfHtmKKKgIIoOKiqiOc5uLaIIgVQ5QCqBoqqUqpWsF0HRZSxLIdQMEqr0aJR/e8opP/vfYl4BKQw77xzjj/667/nKy+8xJ7tIyzOzfH1f/o7to9v5Z++9BxPfvADzM3N8fFnPkKjXufVV9/g/e9/hnMXr7BcWGFgw0ZER2Dzhi1M3V5kx70HePPV11AUk5Xl22zeNEK55EdAmK02vYNDZDszJFI57HaLmenb/sxRclCDKiv5HI4kMNgzSLavm+NvH6Onb5BSvQyiSrorjYXAli1b1t+E186fI3SHiCMoCKKKaeNLS3SNxfkZ+gc3MjefZ2h4K1O3Z0kn0nR19iBJAoocxHVkKvUmW3f2kUqlkDUwWm1KpQp33Hk3tWqZUn4JWZbRZZF0NMK//9/+E7/+679OOJXl2Juv80u/8qscO3KYv/6bP+eDH/wQjz75BNeu3qBWN3juH/89yUSK9zz2OD/z2U/zX/7zf+QJ4TE+/ZM/w09+8lN898UXiScTXL82xYc//GGi0SjxjkESyTCZdBzJU2i3HKZmbrJx40YKhTLBoI5hm9iWzw1wXAtZlhBdb52DGgwGSQSDNKsVBM/Fsgx6+3sIanHq9Trthks0mgLVVz10dGbxPA9VVekb1LEsC9O0kSQFw/CQFIX55SUMw/BTNzWJYCiybhNttVo0DANd1wmnopiejZ6Ioiei/qzNNejt7yafK2AYBh0dHRiGQaPog1/y+RV237WLt99+m7vvupNms4kHPPnBD/HSN7/J7n13EYnHGdsxyul33mbn7rup1Mok41F6uuOcPXGCu+++m5bRwjTbLK34iyIHj6Zp0d/VTzga5MWvP0dvTw9BReLGtSscOHAvz3/vu3z42Y/SLanMTU1jmn5q5NHjR9B1nU2bh9k8vgFNE/i9//ybNBoNxrZuoaOjA9txOHbiOIlQhNPnztLZ0U1QD7F1xx6WFkuIYpuFxVksx6ZarXLs+GGGhzew+66d3Lhxg+9+61u0LYP9ew/QbDZZWZgjmcjQqLep1OqomoimwN37fGF+bnmR+YUpbNtmYGCAzs4uCoUC5VIVQRCo1WrU63UWl5fQAjqqKoPg4jgWjiAi6wE2bRnnxo0btKpN1HCQVCJJZ2+UcESjITewxSb1pocoSAiOjYmLLAtoegBBUJF0BUVwEYQGgiRASEWWBURRwHHaVK0WlqfgNlpIgoskSIhqEtHwyDhBEuEuJlbLP1Lt+rEooKoe5NTZq/zpn38eLRgglYjyuc99jk9+7COMbt7ElSuXMU3f1dHT00Or1WJiYoKtW7cST0SR5iVs2yUcijI7O09vj0Q0GsU0Tc6ePsM99+7kzdde5/4DjxAIBHBdF10PYtsu5XKVjRs3Uir5VB3P81AVHc/zCAQCDA0NUclXGN28GXAJaQqFlQZRLUB3toNarUYoFkXSVBzHIZ1OMzExwfY79tDX3U+pWkLVQhiG6YNhdZ1aYw5ZVcnn85TyJXp6uggEtXWCkSioyJJGMpFhduE2yUSUtORLqSQRauVVLl++TGdnJ8PDw7z44ot87GMfo9FqI6kh/u7v/oaPPvNhevszfPmfvsbUzd/irp27mZ6e5qmnnmLf/ns5e/4Cr778Cr/4K7/ML/7KL/PAoUO8eewIjmlhT9/mk5/6JDMzM2zYNMz167e5dWOFbCaN4EIwECWUjGPZBpLk5+Hosj+rCgaDyIqI4/i60HA4jCRJ5PN5VsrVtXGNgG0blPIlJLVAPp8HIJvNIqh+VHUwGERRFPL5PJIOouiDdcFClv0xQX9/P41GY21L71EsFtF1fU02JdFoNGi32zSbzfWRArD2xrLWX0+e5zE3N+f//NYC4JKZNIIocvc9+9heMzl87ChjW7YwefsW995/HygSfUMDTE5cp7t/wNe3mhbxeJRavcjGkU3ooQCGZTA3M8u5M6fIz5fQVJVarUa2I8v07BSrq6s+c7XiL1N8fmiTarkM4Qi1Rp3xHdvRAjqHDh1aew14TFyf5Ojrx5EFmaGNAywvL3DPpnvp6evl1Vdf5fDht1B0nWxHmpnZeVRNYG5hHk0VmJ6+zfbxLbx/4xO02g1M0+RL//AlGo0a0WCKer3G0tIC/f399A0Msby8QqPR4sr1ItlsEkSRpmOjqjqp7m6S0RCJRAJFUZAkiY6OjnXYTD6fp1QqcffddzMzO8WJE8cpV/K02gYEFAIBjWp9lc3jAzSMJoGwhqw4uHKTstFAdBwEWcaVBCRJQlFlZMVF0mQsHBQZPExESUIQQVT4Z1qb+wNfPXiOS0BRER3PjxJpN/AMi1BY4+gbp5mYuvUj1a4fiwJabxr8h8//ESgap04eoaczzqOPvpfllUV6u7r48nP/yK5du6lUKuzcuZOrV69y7epVHn/qg3zr+W+x5+7dXLp8nkgkxsmTz1MZrfLBZ57l9PlzhEIhyoUikigydfs2d+/bw4lTJwnoIVLJDjzXJyFVm74/W5ZlPM+jq6sHwbVJp7IE5TAXr1zCdgympybp7+nlwqVrbB3zO89KrYqsqczPzPse8Fqder2OVM4jyhKO43Di+DtsHx1FD4ToH+pHDynowQAiEsVKmbGeUWKNOvn8KiCytLRCPJ4kk+6gWFxG1oPIssxqrkK73ebJJ58kFArRaDQAmJqaYsPwJt773vcyPzfDb//n/8jW8W088sC7eMNx6e5Mogo2ly9eYnJikj137+PpJ5+iUCry0z/zGVZXctx5551IkoSuav5NYPt2vvKVr/j53aUyJ48f59CBg6iSRFf3KNVqee3vUEcPR/E8h1arhayISJJPIzcMY12AHw5FUFUVu21w/PARMpkMiVSSRCrpu7Y0Dct10HWddruNJElIkoTpGXieAJ5IMBgkEIyQTPrLoHA4DICu67iOr9sVkJAlmXQ6gGEYRCKRNW1vkOXlFQIBnUgkhKbJuI7Po+3pXQOGWQ6BgN9F+Wg1ARSBrVvHaDYbdKSSFGslQmtqA0nWiCcztJpt+gf6QPCwbZd0V5Z6q0k8HqWvq5OTrTbVYgFCAcrVOjemJvE8jwMHDvj58J2dHDt2jEqtTKNSJiDL5PM59t67n9HRUS5fvITZbjNx7To7d2xjx/btXDh3hX1795EZ6kBRFP7hH/6BYrFIIpHgQx/6AIbtUK/XKZUKOE6DvXfv5k/+6A/oyKSZn58lt7zCqVOnANYdYHfv2cqWLWNY7RZzc3PIukxWELh2/SobNgwSCAQo1+p4okQy00k0GicZDFEul6lUF+jo6CCXW8GybBzHT+EUBIFyoUitXKanswtdlTGiCUrtCq5sk+2OUGkVkGUTSzSwBRtZdgEHyfXAExFFFU9SsAUHURJBcBElFRQBUfWQFAHPE3y3oWn6qDtR9Df5oojuiTi1NiIyjuERDeucvzLBC1NVktFurpyd/ZFq149FAUUUCCfjuLaFpsjMz00z2D/AqXdOcOLIW3R2dvqauGaTW1O3Ka6s8uSTT3Ly5Nus5pcxTRNN9ZH/pmmua++isTCRYIhQMEi9WkPfoFOtlhkZGcFDJp/LI+BbDZumRTaVoFqvEwxFiIRjLM5PUwqUsVv+prBvYAPVagUtHkPWVVRd8xmilu1rHC0LRRKwbdsXGMfCWGsRsaVSCcty0ENhhtNxcrllECRESWJlZYlt8lbSmQx6UMes1Tjxzin27t2DIDs0Gg2Mah1JCXD58mX6e7IAHDlyBM/z2LdvH9/97nep1OocOXacjUODWLUiC1O3WJyd4uDB+5EUhQceeTe5pTyirGA5LquFPJnONEE9wPXLV8gtLhENhdHCQQ4cOMBbRw5TLJfYunUrg0PDjI1uQfRcYvEw1boPjDaMNp1dWTzTBkSfhN9u0Gw2iQT8LtK2bWZnZ1me81Ft4XCYQ+/yPRjVlu+F/wGT0WfDSjSbTZrN5noB6+joQNeCVCpVRMmgXq/T1eVT/gOBAIZhEY8n198wyWSQVttCFEWWl5d9ko/jkEqlsCyTctl34eiagihKhEKavxGWRH/hJbjIax2VpAWQJIF8bpVivsml8xd44JGHOHnsHe7bfwAFf2yh6yq2bRKLJZC8Fo7nIEkCyY4Unb1dnD11kYGuEZYKq4S1AKIsUS2VMdsG0VCYvu4e2u02Dxy4j4mrV3jo3e+hf2SYQrnEhuGN3Lh6jX379iGILm+//Q7ve+IJFEXn6Mm3qVQqPPLwe5iamsK1bF555RWSmTSGYfHMM89w+txJ/vxPjvPRZz/OK698D8tsEU/H+cSnP0GlUiMU9HXM9XabRrtFPBwiHo/z9a9/ne07trBldJhGo0Wyo4diZRVJkLl54xbJZJKptk1XdyfBQBhVVenv7ycWi/n8gzU7pyz4apObN28yNzfHqVOnCER12l6DfKmIJzkIsrC2C/et1pIk4Eiib/n1XCTXRlIEf4mOi7DGkRdEEdcTEJDwXGHtBi6taz5brRYqLiE1gGzJTEzcJBvvZXPfnTz//HeoV8/h2jrQ+KFL149FAe3s6mRqfgoZj2KpwOG3Xmf3L/4yjUaNWCzCzckJNm7cyD/805cYGBoksXEj3d3dfONzf0kmkwHg0KEH+Osv/C0PP/Rukskkb731Frbg0d3Vhab5z+PZDqurq6Q7u0ilO7l4/jJPvPf93Lg5gRLwdaCapmEYJp2dnSwtzDA5OcmWTVuZuTlP79AAs8vLDIZChFMJitUKkVgMs9kiHAwx22rR9vx0P1mWWV1dJbKWG5NMpunrG8DyRALBICfeOcHY5u006nUymQzLy8v+djqVYHTzRq7dmEBRRVbyS5w9e5bH3v8UkViK0dFRwgGZRs2HbkSjUb7whS/w8MMPY7se9WaL73zz6/zUJz5CNBZkJZdnZjFHqdFitdGiWSxhux7hSIzdu3dz8vgJbMNkfPMWujo6icdivHnyBN99+WXe//7389xzz3FtcpJHHn6cWLIDSXARJZt2pUw2m8HDod1uE1Q0JMmPcfZzbCQa9Qa6rqNpGt3d3Wzo9F1GaijAYi7nH9WjCT+KVlGQZZlAOESxWERRlPXuUgmqKLLvuRZFiXQmiGHEcV0wDP+mGYlEKZfLWJbvpy8Wm5QreRKJBH19vXge68J+SZLo6UnTarnIskiz6ZOIQqEQSBLBSNiPefE88vk8Aq6vENB1crZNpVCgWigR1HQunD5LKpZkx507Ad9N5Xk2YSVEpCPLSi5Ho92ibjVBlSitSbuCqgaChCpIJNMZJEHEtWyeeP/7OHnkBNu270APB5Bkmb6BfuqlCnfffTdm2yBXyvHwo+/h7JlLvPH6YT7xMz/F8ePH+eY3v01vVzdPP/kUtmNiu5BIyBw5ephoPEI228HxY6fZOLiZwYFOvJBHq2mgh0O89uab7Nt7D/1Dg9RKJY6++Qb9XT1sGRnFsyxaVZ/43ig1iGfjhLtCDPQNkkymaFWbCIKHh89QVVWFWr2yvpiVZJlmtYZtGWweHUVTVUzDoGwWuXrjCqbl0PZMJMFE1mQkxUUL6ICAKwuAgyh4KFhIYgDRc8AFUXKRPBfPUxBFv+O0PBfPba/XFsuyUBQFTVS5dWOSwdQQhaUSR56/iqz5IX6IAXCD/A9bQCvlEma1yOT0NPfuu4fBrj7+5m8/zx3bRpiZXqCja4RgKkLvUB/LuTyf/ezP8we//0d84MnHmVtYIhjUSGWTPPPUY+jBNKbbAqFBiCh9fR1cuHgGRQ2xUirRNbqFqfklwokOPEVirriMGtJotiy6e7OUKkXK+QIVDETRQ1Zl1LBOMCCgugYdkRCxgI4siCQSCaLhCFOTNwlFwkieS75YJpXpJBqJExA9CoVV+vt6UGWYnJ5gw+AGQsEsA30D2K06zUqNDRs2YDomtbave5ybLfHAIw/SarfR5SjP/sQznDx5ki3bthEPByhVK7RrTeqVOsePHGf71u2k4inytSq77thEKKCyWmpRMx3efuccq6urZLNZsvE4+w4cQtd1FhcXmZm4jmf5W/IvfumfePLpD3D2/Ivcs38vsqLz/VffIJZMsmlwG9l0lmvXLzM2NkqjYZBMJpFF0YdcSwKipOFYJs1mE9e28FxnTS5Ux3OhVKoQ0CUESSYiRFB1BUGRqdZLSKpGVI1jOf7cKpZJAQKW6VAul5GRqDUaCJJENBrh5s0ZIpEImUySRCLgF0URUsnIugIgEg4SjfRSrVZp1Or+/EyS8DwPSZRo1l0URURwQVdUBFUDDwqlGslkhHqtTTgcRlNDeJaNpUiUS3Vsw6BeqXLu/Fk++slPMHvzNtuGNlFyakiEsG2LZCaG59h4goznQEjSSSpR7FYd2wqhBURM28QTJRaWl+hIdhAJBOnv6CG3lKdhmHT39yGKsLK4SHzzJuSAixZScFWIy74CQguF2bd/H99/+VX279+P0TLp6+vDFkUcTwY8XnnlNe666y62bRn3QTGmD00pN6pU5ssEAv73T3Hg0ukz3J64xvSN68STKarVOk88/j7eOXkE14NEJk0228XMwjSTt6YJhOKEbIe2KJBOplAkkUa9iuJpPk2rUiAeiaAqCm2zRbXeRDUsIqkkm8a3c+vGBTrSGQJNGVe2qLUrOKILioCruHiyhy74XnhB8MXwntVG9kREJATZRRBNbDtAU5QQcfCwkG0Bx3FRPQnZUKmsFmkrHtMX67x08RVER0KSVFRX8cc0loAkmD9S7fqxKKCiIKLIMslkkj/73F/wwQ9+kL7uHo4dfQdNC3Lg0EPMTC8zOrKVoUGTl195AVE2ePvkSRYXF9kwvJGF83NMTUyQSPfx0OBBJicnaFdg20/9LIObW7xz6iSJSBhVEKgVi+iSQnGlgIKMpAeJxSPkiwUQHZZX5onFIiiKDjosLM4xODiILErrER2qrHDh3HnGxsaQVYV8sYAkScTjccbHx/0ZXtCn2qdTCQYHB4lEwkiKjIcf0jWyYSOFvE/sUVSJRCLB/NwCrquyvFQgEkqDJ3L0yHEWFha4Y/ce6s0Gc3MLbBoc5F0PP8LwyCipVIoTJ04wsm2Yr33lHxkZ3kS+UKRL7eHOXXcQi8X49re/zfmz57g1eZve3l5SqRRdvT288ubrtFptfusPfpe5+XlWKyUunTuFZTk8+fRTTEze5Ctf+QoXL17kZz/7Ga5fv0Gj0SCdTTC8cRDDsGi5NqrqgusQCASoVdrUazVUVSUQCGCZNtlsllBYp1qtgiAirXWcoUgYJH/ujMA6qV6SZGTZX5wpqh/RUC77i5ZEPIskSSwv+cfwWq2O43i0Wi0/SldRSCQS6LpCMBhco9AHaDT8zuQH0qp22yUY0v0xgedRrVbRtACtlk0gEGBhYYF0Ok21WFrvRpeWlshms1y+eIlbkzfRJJn53DJdG/v8Iq1IxGIxBMdhaWGOmdkpBNPmxRe/QzqdJl+tYgsetuWiqCHi6SCiKIDXZtv4RlxsBgb7QPRIdXYQ7/Rzteq1BgE9yspyHkkOrnf6p06dYveefSzMzfPU+59kcnKS2ekZ0um0b65YXWVhYQFNlOlIprlw4QK6rlPJF+np76FcLqNpCnfcsXOdU/ChjzzD/PwioXCcWCLOHbvvJBYLoygatWqTTeOjaJqOKMi4QL1a9QlTmSSFUpHJiQlSiQiNehXBdVEVBUQPRQugaTqpTJpisUg+X2Q1V0DUXFqtJp7sISEgShKe4CEAnuAiyRKIAo7rIWgekirhyRqiEsBxRTzHRHIFPEEABIyWiOeAZauUVmq8/upFNMIInkhAiOFJYIstRAUi4QCxWIRMMskrL/5XmUf/l9ePRQGVJJEvf/nL3HPPPTz08MMkkkm+8bWvM9DXhygHiMSjtFptLl68SDwR5vLli9x99x6stsm7Hn6Ib3z9axw8eJBsNstKPk8+v0qhUMBpKkzPzNHZ24kjQDKdJRjSkRURVVVJpVI0m21S2RS2I2C7FvnVZbq6OpibmyO3vEJ/bze67m+DM6k04XAYRVEQPI+grlMplch0dFAul31rou3nKtVqNWIBdX3zOzQ0xLVrV+nvH0DXdVpGm1K1QqvdoNGsoREgEAxz/vxFsh1dhCMJ4vE4N2/exHGc9UiNWCLuZy3Va7z55pts3boVy7EZ37Edx2sSCuqU8gUatTrnF88SiUSo1WrEI1FWV1d55D3vZnZ2lrvu3kO5XGb33ntwLZPvvPACzWaTmekpDuzdS29vPzcmJilXa3zsY5+gr6+PYCBMX18/iUQcT/JQZLAM0BQJQRDXZ4uNWhVNVWi1WrRaLfAEIpEYxZJf8AzLQQ8EaLXbGJaJHgojiQou3vooQ9N0YtEEuq6jajLRaIhWy7f34frkcdu2WVxcJJvNIkkKXV1JVlZ8GZLrupTLZXRdp1Qqkc/nSSRjfux0JIKmyRiGvbZ48kESuhb0TQqO3z13dPjJBwFNw/Fc+vr6aJQqVKtV0okkR956i/vuu4+OTZsIhULYtk0k4o8d2s06siiQTaW5cfkyY5tHaLYs8rMNDMNAllQCuoxlNOgZGQGzSb1WomZY3HvoIFow4OdGui6uZxOPJ5mbXSCd6qJQKpNMJpmfn+fRRx9l85Zx6vU63//+99m6dSuVSoVUKsWtW7cYGRkhk8lQKpXo6ekhlUrR2dlJrVajYdQoFArUajXC4bCvgkBi8vZ1to2PszC3zNmzZ5Fkh1othGFY3Ji4Rale4q679tDT00cwGESTpTXpmkwiEefAAwewm03wHIxmk2ajgaLJtE0b1/VvdMlkkl27djE0MsDl6xe5NTeJJIgoioyogOHZ2KYFGnguuK6/hcfzcD0FTQ4gCyqmaSG6Ni4SoqditS3MFkzfnOHalWlkQUWydWTZQw3KaLpALBZFj4RQVRlVFkkmIpjm/wuRHv+9rmajycMPvout28f5i899jlx+lcG+QRKxJFvHdzIzP0ezVmV+fpY9e54iEAjQbLYAlzfefJ2BgT7ePn6YTRs2k0qlUFWVbDZNvWhz7M3X+MTP/yTRbDfVloOgCiQ70swuLTE2vh01GELVAgiOS1JPUm0WyRdWSCbTLC+skkgkcNy2n28TiRKNRtFCIYyWDxmRJImevl7mFuZZXV1FVjV/UWH6y5/l5WU6sul1aYXtudyauk22qxMPcF2HQED3xc6izM6ddzAzN42qyrTMBuWKv5XPZDpYWF6iXmty+9Y0hw7cy7vf/V7q9TqxWIJ6vc75c1dZmF/m5sQNPvszP78eKNfZ2cnVq1eJxWKcXOvajx8/TqvV4lOf+RfUKmUmZq+hyhIP3ncflUaLr3zzO/T1DvKRj36SwdtPtgABAABJREFUbDKLZRvkcjmy2exaxKxLo2kS0FWarTqRYAhVVfE8n0ivqQr1uk+pD+hBP544laJlWESjIUzbwUVkbmYK24NsppNYIo6iKEQiEVzXW59fiaLoF7u1pUQ4pNJuG6TSUTpkfxtvGi6FQgXTbBEOB3DWdI6O44eP+RxXj66uLlRVptHwl1SN5j/bT13PRdd1P8ivXl9fenRlskTjMarVKrOzsyiKQqlcZtvoGPV6HVR5nX2qqirNZoN6pYRt+N+fmdkp2o0m12/cwtF8KZssqQxv7GJpPo9tNrlj23byq8vcfd8eAgENVVfRwkGMcg3wcX+uK3Dy5Bm2bNvC9LTP5dR1ne++8CKapjHY18+Fs+doNpv0DPSwf/9+qtWqD7axDN/51axTN1rIAQ2n6Xf0AMePH+f+++/n8FtHSXUkOPzWUaymzdDoJkTJpmU0CAbD3HnXblaXF1mYmkEXVeaaTXZtH0eQJS5fvsTGTRuot5pYtRquY5GKx4lFo8iqhO1CsVji+o0JguEomuxRqVQJh8Ps2LGDxeVblGtlGuU6QtB/jbm2jYeD56lIooImRvAMm7bRpO35xg7PFlhdzHH7+hzlQhtVEAkGQySCUWKhBIFAEFEDPaxhuy0E2cG2StRaNpqiY+Zq62qWH/b6sSigwWCYbG8Xv/Yf/i3Dg0PcvHYBJajjrBWnSrXArWvLhEQdqe1x5dw1RrdtYWnlFrdv3+bJ9z2OJHvM5ebYuGmMa9du0JPt5/rKWcqFMpV8mT177ubc22eIhpJ0bxC5cOIk9+zeT8MwECvl9Yzp/EKOwQ1DNJtN+vq7cB0w2vgiZddBlCXqhRK51XlGNo+ytJKnbVkYro0ry3QNbERUAkzPXKcnk0KXJf8Ya9u4skSz2iQcDdHRkeXmxA08x8PxRM5cvMbmzSO4romuKutEnu7ePpZcEVeUUDUN0zTZu2c3hm0RCIfQg2Hq9Trzi8ucOnmWe/c/wP2HHsIVPVrNKmBz+PgRLk1M0NXVxdNPfpBisUwikSAYCPPWkaPs2DFOMhohlYwRiYT49kuv8sCh+1EUnXqlTCgWx7ZN0p1pZAVEwcMwLWTJp+8IAliNJooiEVBUVFWmbbSANR2oKGOaNpVyyXcihcIEw1E60wmy6fR6x2612tTbvqde1lQyHVn0gEqraWHJ3rrOFEEiFteoVltoyFiWRbnkp4LG4xrnzpzx88xNkbyXI5lJc+bkWeYXZnj3u9+9Jkmqr4OeZVmmWCzieR6NWoNmu0W5XmPb5jFCehBJETl39iIbN26kc7CH3OIMdjhIMBJm05YRJNXFWdOAirgENJWm4NGq17h68RKTN2/T8FxsQcN2RWxT4N59d1NcXiQWjBLQJdSIwkjfTlId3QSCYRRdR3QdIqKK6Zos5PJM3rjF3jvv4dT5U3R3d1KtFdmwsZ+HN7yLRsPXcw6NDvjdueuny46GR3zCEwqKouB6/o290agRCoWoVuroWpj77n2ARt3gvnv2Mzs1yX17dzOydZSp+WUkBHIry3R3dnDm9GnSiSSxeBjLqKMLcOrcSbKpNMl4ggvvnCao6WzdNUYg4KtU9IBK2zQRBQHTM9kyvtWXqqExsutOPyV0bpruVCezyzOsVnMslGaxMZEFP6FVD7gILqh2AEWSsSyblYUCK0vLuAb+GMbxSMYD2JZEQJMJB2RcoY4ckgjGw0SiQRLJDLF42M/osizsto1t+BzZ028u/tC168eigCoK/Ntf+QV2bL+TzlSGdr2KacDGjcM8//w3eOYjH+BP/vhNnnrfE0iKwNT0TT7ysWf48z9/Hc0TWZye5Z579vJHf/Y5to/fSaXeQJNV8GRS2QSe65KMxX2ZRq2NFgxQq1VZnJ9l70MPYbbaWGZ7TTNXYrM+xuTkJJqisrCwQHd3N65rcfHCJR599FE8oY6mBZidnWV0bBuiIK+7bTZt2kSlUvFthppvN3Qc/0U7vGEjrVaLbE8Hs/OzFAoFBEFAVVW2bdtGUFNxNL/7KRaLGGabnp4eduzYQaPRQJZVv4B4Iq4D5VKVoaEhRFEkHA5jOj4geOfO7eTzOa5PTXFxYpJCqYJtO3RkuiiVSiiKyvXr1/FcgYG+XvK5VSauXcJ1TBRFYtPmbSTiCbZv30k0kqDS8rWUhfwyuqbSbjfp7u5ED6gUCgVUVfEH/ZIfLHfz9i2y2QyKqtI2DCzL7140NUgs7guuLcdjObeKadoEg0EWFhZQVZVQMOyT1zNpDMskn8/7wv1QaF2j69gwn8v73W0gQDgcJhAIrFH42wwPD7OwsMDrr75OsVjk0IMPUC6XyeVy3Lp1C89z6OrynUctq0A4HKbRaFCtVpEEid7+PgRF5urVq0zduElXZ4auji7yuRX6eno5XK2gBSIEAgFUVUUWJaKRKMC6dCYQCDBdKrFlyxby+Tyf+8JfEQwkEBQF13W5446dfPVL19m0sZ9sNksklqCvv59wOIqm69SaTRRbQ1dUZqZniCSTRENhfuM3foOf+OhPMDU1xSOPPEKz2SQaSwCsK1Iajcb66KJera3NS8U1Z1CDVsvANCwkyaGrq4tYLEGhUGRycpJQJISshWg0mxw7fhLT9E8OZ0+f4eUVf/67MjOPEtR5z2OPguMynIpSLhYplVexnTbFUpWJCRF5LTa5Ui2hr9l8+/v7sSyHUqlEy7GYub2A0apy8dJZarVlSo08hlBHCYOiCAiiiBzQESUQBRfDcjEsEwkJVxCJplJEghqBQGAdSxnQgkQCOgFVwkWgVG/RrFaYnZ1l9lbd5zGofkhdIhwnEgz59eJHuH4sCqjrNfnQkw9w/eoSnp2mVi/iuip7995NJhulVi+QTkToHejmyo3L/Ptf/zX+4R/+DsFxGRneRCoW58v/+CWqhSrppB8JOzK8CU0Pkens4PbNW4TCEbZv3cbxIye46/67qZbKTN2eZI99H4qi4NgmS0tL6LqOKIr+D0MQqZX9aFrLbNPT04thmCiK6oek2S7JhJ+yqWsBtm/fjqIoNBtNotEolusQSyYIhUI4S0uEgkEW84vYtk2r1SIcDlNZKSB6YJkWS8UCiuQRi4bIrSzTkenAajsUaiVc16XZbFGp+EVO0X2eaKPR4Oy50yQSMZ756DN+IQqo/M7v/w5Pf+BZ7r//fhbmFlBEhWazydLSElNTMxw4cIB0KsuZd44zMzPD4NAAMzNTNJs2t2/f4uMfP8Dy8iJf/OI/8pM//Rm+/fw3GBzsZ+fOnSwsLhKNhjFMiXq9TiQSRpNE2qaJJEkk0ilcARzXQdE1omvdrtluYjkehuVgux6RWALLsvDW0jo9zyO/UkBVdWRZxfUEgoEwpVJlbdmhrRHt/VloKpWi3W6zslLAMBpYlkVHNs3kjRsUCgXuf+AA586d4zd+4zf4N7/8Sxw7fphvfvOb2LbJwEAfyWSSYDi+LtpfWVlhdTXPXXfv4ZFH30s87uPYbMPk3JmT6zCV2YV5kqkOvve97/FU+Em6u3euJ0mapomq+nbSeDzOm6+9zvT09BoJS6HhWijKGv/WMBFECVnV8ASRUDiCHg6j6zqW5aJrQY4eOUJHR4bf/g//CdtVUFQV07a498B9NJrNNQOCTiAQWJ/91ut1jEadZNTXdjqOgyNatFoGghBGECSCAYlCcZFY3A+9y2SzDAwOksvnGBoYpFwtsbCyjNNukYon6El38NYbr7O4uIgmSywsLHD02DFkWWbjxj6ioTCBgI7nxRA9f1HX2zu4Hk8jrC29ms02tu0yOzuL5UAorGM7Jl3dWbZnh3ntrZcJqBImVQRJRpAkVE1AUUGWFZA8lDW5XPdgP7qiYiGvaYEN2u02uE1aXp2W5YCokm81sIQWWlbDrNlokoQWlNA138jS9gwqjeqPVLt+LAoookv/sMzlazPs2f9BSuUGL377CCsrfjLl/EKVp596AlkRGNjQx1/91efQVJVIJMKG4Y2cPX2KRqOB5Mq06w0M0/dfJ+IZxnft5BvfeJ6Pfezj3K5MYxpN4tEIoUCQzo4eJFTK1QqSCAMDA+u4sUqlwvZt47z0nRfYs2cP5UqRaDyGrCrrHYYoyniegCSJaFqA5eVlOrsHKBbK6JLGSq64FsjlF8mubAflvK8DzGQyTFy9RqNexzJNUHSCgQDl/Aq5ZplENOLPFWWFWsvEMFpkMhnK5TLlconAGund7zZUDh9+i/zyEg8//C6qxQK//K9/kbdef4u/uXadZCbLlq3bCAaDBCNxHn10GydPnuR9j4/i2QZ333UHLdPgnnvuoW+gn0AoQrGYx7Jstm8f58v/9CWefPJJJEXm0tUr7Nq1C9E1QfA33q7rIEsShuHLkHxpjP8x4Hf2xcq600uU/S7MaDZJZdLr4OpgMMim4VHq9TqW6aBq/s2sq6uLSqVCJBJZAysHaLfbayL9NrKsoKp+GuQ777zDti1jAHzjm1/BcwU6OjK89eYRDh06xPe//31EES5duoQgCBSLVQzDnw9ms1nGtm7Dtm3+9m//lsvnL6AgInkOn/rJjzEzM8M7b59C1TRq9Tr7NmwglUhiGQa2HPBvbIqP5nVd138zA0tLS4RCIUzDQlREVE1hampqLYCvTqaji66uLhotAy1sIZkKtuXiKq4PwCiVSERjHH/7HAcfeISdu3Zh2QYIYFgmjuNh2za2bWOaJtlsFlUTsW2bWq3m6zFFmXQ6yuLCMpFICFlWSWUjNBotioUywWCIcrVCsbCM5IFhGIQ0lWAiycTEBIV8jnA8TrjZpJzP0dHRgSgIeJZNrVonoOrIoky16lO3RE1menoa0zTp6u7Acnz0oGXNEwiEyGQyNBstVvILlMqrRGIhrly+ztYtu5i8fZVW09+sB5IhZMVD1wV0PYCi+VhFRRSQRAtRdAmE0jSbDVzPBdlDkGRUSUJwLTQ9SLIvgyD5NzjP83AcG891fbpXtb52ExeAmz906foxKaAQSbX46Kfu58r1U3z3eyd55P7HmbhxjeXlZeqNCt2pFJbbJhqPc2PyKt0dndz3wEO8+tprKKqEJ4mkkxlUWaNRq7O6WmDvvntpeybVapVKpeJ7jVtlHNckk8nS1dGNZfovdFHw1mVIqqr6UhRBIB6PAxCO+vi1pZVV+vr6CIej2A5Uq1WS2QxjY2NcuXDOx2fpOtlsBseLU61WmZycZPvWbQge6/ZLH1iR5/7992J5HpFwmFbTR7oFAhrNRpPBwY0sLuRIJBKoanrdOplKpVgt+F1ptiPN+Qs17rrrLl762lc5f/I0K7klZFnizrExovEElVYL12lz8dIEJ0+fo6urh1/91V/lL//yL9m9dZhyqcDZcxeIp5KcPnuOT376k1y/PkE+XyQUjBGPxThy5Aj3HriPsc1bWc0XaZRzDAz2rdvlDMtEC/gMAUWVENcoQh5guw7BcAjXdrAcF89uo+pBlLUQsh9YNldWViit3CAcDhOORanWa77eVPb98a1Wi2q1ymreWF8wmabJzMwMq7kijuOwdctmPve5z7Fjxw4WFuawLb+Yzc/Pg2gRCAQoFFaxbX8p5ccuh7AsP3X15MmTHD1+jExXJyFNx26bjG0e4eiRw9y+NUU2202rXSMZ90nsANFwBFlR8Dx3zedvoWkaoiiuz1ZlWcYwfISa4zjkVpdR5QiBUJDr16/TNzhI3+BGmu0WruzfeFZX8riuy5/88R+iSxrve9/72H3PAQzDoN6oMjDQR6FQYLB/gGQyiuNAvd7wl26OjWVbKAE//dQ1PPAMZFmm1W5QqxcxLRfLclAV/zFdXV0EVZcLp89SLJZwBJhbLbBt2zaUukZvfw/b79xFbnGek2dO09PZRToax9MVluYXfA9/tcqB/fdSaZUolYq+hTYcINPRwZYtWygUSkiS4mdKLS1Ta5VQdZnpt2/R0dGDrOk06x59PVv49gvfpmsoTSSqUa2tEovFEEWTYFAH18Ey25hmGzOgIooi3d3dSJKEIwlEIwF00cZ1PCTHI9CSUBQBPSDhSRYNDxRFQw1FcRyX/248UEEQdOAwoK09/mue5/26IAhDwHNACjgDfMzzPFMQBA34e+BOoAD8hOd50//VJ/FcZFklEFAYHxcZGznAl/7x2+zYcZCt2zZz9Ngprk8XOHjvTv7mC3/ML/z8T1IqFHnz6MvEQzEazRayrmMEoWH7cROTk7c4dPARXn39FSJhlXajQDYZ4LxTp1koE091oSQS1BsV5uan0GWdzo5u0h3d1Kolzpw+iSxKPPjwI8wtrJDtSuG5CpIMbdPAUVS0kIoSVqg0Sz48QdYQPSjm82Q6sniihixqJGNxWk0DwxSIpZM06w1kUSGkhfGAaDzC1NwkW7ZsYWbKwTNE2m2LZrNJ26ijKknOnH2H8Tt2sLqyjOuYdPVmmJtboFqv0NGVZfLmNd792Lu5eXOS1aIfmvX6icP09/ezsLBEMpGhUChw8L57uWvfXj7wwScZ37yF+cmr7N+/n+6uLlZyOX7h3/wiL77wGpcvXyWTyfK+x/fgeQLdvT50o96oMj8/TyYZo1ZvogcUBMHD9Twcy0DEo1ZvrcFwfcmQJEhIIijhIJqm0Wy2mZ9boFKpEI8k0DSNVqtFKBQik035x2HPQRUFFAHKlQrNZptgIEQ0kiJfLdJsu1ilJrIEnmGgCHD4rTf57ne+za/+6q/yu7/7uwR0iUI5j4SMYItU63VUWUKVNSp1h5137mPD8BAvf+frBFwTQRIwbQFZUqkulyGRQg9EeeXIcSK6yKbhfqYWb2MaApJYRXQtYpEQpm0h6zqOaSFLCpZhMnPzNlOTN3Esm0g8RsloguWA6KHJAoqoML80zU/82i+RX15BVWQc/CVZs9GkbTSRNYHvv/ASrXKLWFeKpdU8DbuF55p0ZNI06w16u3tYXV1dUw+oiKKMbfssWllUfTScK9EymlRqJrquE0+k6Ojspt2oUa83aLdNZqbnOHPyJPVKmYOH7qNSKWFaBqqqUs0tM9TTg2maXL90hf6BPqy2xbUrVwloCtt2jSOIDls2DzN9e4oL50+TGuige6BnTdFQpW25NI0mLdNieXkO07Hp7OtCKSlEYjF27dnL0vICFy5cWAtqjPOpZ3+W777xEg1LwjETLBbL1M0Kuq6iahKdnWk2bNpCVzQOosZSbo56O0fZaTE/WaNcqqKqEolYnFS0n2BAo1WvoWsKWkpDkkQisSixZALtR4w1/m/pQA3gAc/z6mv58EcFQfgu8IvA73ue95wgCH8BfBr487X/ljzPGxYE4cPAbwE/8V97AskDp1GnaZq4BHFdgZ/9uSe4dH6W0mqT8ZFeejaO8O3vfBNJkjhz5gx4Dvfu283xw+/gKSG6e/u5PTm97o02DW+NdO4fF69du87mkTF6eno4d/EC+/c/iKJozC8uYLTa2G6bVjjC0KYRjHadaq1BPJ1ECQQJAcWVFfr7hrEsi8XFRZKxOK7gx/R29/Zg2hbZbJZAQKNer651R/4RzrZtVlZW2DC8mbbTRFqjsseSCS5cvsSevXdz++Yttmweo2kabBkZ5ezZs+uRwNPTU9x55x3MryxgtNvcuHqFBx5+hFgkiqqqBAMK0UiEw6+9QbPt8PQHnuHN118jFItgOTZdPZ0sLa7QN9DLptFRXn/1NfbctYeNQ0M4TZtX3zpGpruTj33yE/zB57/A/fc+xLsffYJjR08QjsXRNYmVlQUQfGnJltFhysUCly/5ouyenm4CAX+Qb5gGC3NzJJNJouGIHxC3JiXCYy1R0WVwcBDHcZCQ1yUkp0+f5sEHH+TUqVPrkqXOzk60YIyVlWmy2U7q9Tq9PVmMehUJgTOnz/D6q98j3dNF3+AA5XKZ//T//U2GhoYo5lcAEVGQkVWJ5ZUi0WAARYlgGAY7duzj9u3rYEpkU/2EY3HMtkKpUsWyTTzbwmrVSaezFAoLXL0xSaPRZNvWO2iUy37yqOpTuAQXP6rZdqiVK8zPzXDr1i3OnL2IjYxhCciihKDIvostFmX79p04jsPQpmE/U8jz88HMtuGnX1ar2I4HosDi6hL73/Mu+nu7yOVyCIJAV1cX+XyeeCLqd/uer8fVddXn2jabiKKveRZF1iRWTWq1GpqmgeegB0LogRDhSISBoX6iEX8UUqyUmZ6dI9PdTbPZZNPWrdy4cQM5GMQy4OCBB1BliXwuR6tZQRIdbk9NYFom9VaN+XNLpFL+/D8aC1OpNlleXkbT/M18Mumf9AKRIMVyiTNnztAwGmzYNMzMzAy54gqLuQX0kMro6Bgn3j6MpEok9DSiCILo0ao7XL88xYTs0ai30QMKfUOd3Dk6gu25GKZJuVrBsC1aRYdCKUepUMDzPDZv2ka93uTG5UvUKk1CWvhHqZ//TamcHlBf+1RZ++UBDwDPrv3+3wG/gV9An1j7GOBrwJ8IgiB4/5X8ZA+PeqOMrGiEojrBYJhKZZ6ObgVZ9vBc+OM//W3GhjeTSnSztFDCsS1EER5//FG+9u2XSafTnDl5bk0zaNDV2c/i4iKKKtFs+RvWxYVlBjdu4OSpC77PWpQo16rkV1cIq0FKxTyRQpxgMEhHZ7cvQFcUbNdZj9QNh8NUa3m/G6vW6OjoAPCBELEwguihqjIePlW7Xqv5shLLB1sE1AAzMzOMb93G3NwcyY4MS0tLbB7eRKvZRNH8qNbeXj9C9gdunmvXrrBt1w5KxTwXzpykXCmiqkFqtTrdPRlf8+gKhIJRFhdyDG8aY2FljhdffJG+vj727NvLgQMHmF8pceDAAQBEWaK4XCaUStG/YRBRVvl3/+7XmZ9a5MaNGyRTUSZuXGH7+BZu3rrGwMAAM9O3efO1l4knEwwODtHT00MsmkBWhLVQPonRkTH/yNpurmMBXdfFXJMrSZKCJPpC+NoaiV6WZcbHx5mbm2NoaIgLFy4QCASYn5+nULnOoYP3E4sluHLlGidPvM2NG9dpG02i4Qi9/YPMLc9z/fp1FEVZx9ipqoqmB3Btj2AkjNFqYtounijS0dVLT/cgf/x7v8OWgS4EV6KjcwOBUCc9PX288er3qdRytNpFMp0ZavU8jYY/x83lciTWIkp+oKO0TV9IblsWzUaDRCTK6dOnEVQZTDBbbeSgiCz6qa/RcISgpjMzM8PA0CCu56HiA1V+EHCYz+eZnZ1FDwXpHhhgaGiAmduTjG/fiWmazM3NkUqlWF5eIhaL47gWRtuPpxBl6f8wh/XTAnQsyyEYDPvi+aC/YGq1WjiuRTgS5OrVy0QiMWzbZnx8B+War/Rot9u02216e3spLK4SCgfW56uuZVNczeMK+GxWy8SqVrEsa22xI6Mi09nZSTqdptlsYpomhm1x7sJ5Wq0WPf095GYKXLx0ieFNGykUVqnVKrTbLY4dO8zOXdu4PX0F1xGRpDVKliciCCK266AFQiB6zE0tM3PjJrbrEggF6R8apL9viGCfQqVaomUY1OoVCoslVhZy5HJ1UvEYoUAU+OEXSf9NM1BBECT8Y/ow8KfALaDsed4P0ujngZ61j3uAOQDP82xBECr4x/z8/8/X/AzwGYBsR4REd4r5uUWapkcylkaVBbSww6aBNHPLRT712Xs4d+IGnhXCcqok4nEWVvLMTL/AZ37qp3nz6DH6+vpot9ts27aNGxNTVKtVjh8/ypYtW2hUmkiSwtLKMk899RS1Rp1sZzeO41DIr+KEov62UoC79t/Hnj17eP37r/D0E+8jIIAXCPicyGQSVVVZmJphfHwcq21gmxaibzzD8zzK5TLNph/zOzk5yWBvF12daW7cuMHYzjFcQA8GcPHo7unhxsQE45u3ICEga36XkMvl2Lx5M5VKBUURGRwcRBTh9u2brOZz4LhkOtKcOnGacCBAZ7qbrp4BdEXFNFp4jkhHxxB/8Rd/zzef/xqTN2d44cX/D0Ojo2zsG6C3v5/B4Q1ksh2M7Rzj61/5Km8ffpODBw+iB+N897sv8tjj7+XcmXd4483vMTQ4wNtvH6ans4v3PPKwT9tvGqws5ejK9qIGJAyjTblYQvQAWkTCwfUYDlVV8cQ1PJ1pUinXaLfbJKLJdf6nD032Z5r1ep3R0VH+/u//ng2jG/nyV75IKpXhG9/4BkNDQ8RiEca3b+bChcs0GjaxRJyW4S+iBMnPvTHaDq4KkVDIX+QFFar1Jp4jsXfvARrtFlvGNiE1yzTrFo4r8dRHP4FniSznW3hunTcPv8jU7WkSHRkarTqmYftLsVxunTTUbrdRBQXB850yjmUjITM0vJEbt2/hmU1ksUlQT2E5Nprih6StLi2za/edeJK/8FFDYawfmAXCYU6dOuWzUlWZiNlEVRUmJ2bwEOns7GR11Xfcdfd0+BlDhuDHQ6sBLMv/OqLoU5CMtv81FVmjWqkiywqVahMEF01TMBptLMeit78P27ZJZ3x3XcIRSIV94EtyV9xPRsjM0Wg0mLiWw7ENPMMmEkyQ7elienaGRLKD0c1bcFyL1dVVLp2/gBoOr0e8bNiwgcXFReptg02bNpHp7CCRirNn790899yXmJ+fR5IdLLsNkkMynWBuYYb+wT6WZufxexm/H/NsD1dykXBxTYuAqqHog36UjOOydLXC2e9fY6VQRQ3Azj2b2b5jjG1jErazhUqthWW6XL56jcmLP3T9/G8roJ7nOcBOQRDiwDeBzT/8U/2fvuZfAn8JsGFjpxcIxhnZojE7u8Clm6fYNrgFXJmunhhdG2LkmxqhboVv/u23KK5CWNuCIIZwZZVjJ97h0Qfv51/+0i+wd88Yx49fxDBFurvzBHWfHSkIHhZtWnWXs++c4r5DBxFoUqiucObkKe69bw+d8QS22+DSuZNs2jSGJGpImo5rG1SaFgN9XUi6zMzsPIP9PUh4GK02giugBYKIkodl2aihAFpAZ25pmbmZaYYyaYqlPJ4qITgu42NbsE2L4eFhZqamWVpc4b4Dh6g16oieiByIMzg8iqoHuX3uLPfsvQfbtigtriLbElbTolQo0tHRQf+GHsSATCAao3d4AKvVJp0Y4rXvvUJnJsnMrQkefteDIAqcvXAeo+13BSsrK5w8eZJf/ZX/lWa9zFOPP0GjYfDKS69RqswxPLqZyxfOg+Oy984d/vbS6GTTpmFe/v4rbBgaY/PoFqqNJrV6i5tnLgMwONhPKORvy2uNGq77z1EfxfwqrgOeJ5Dp6CYSiSJ5vsC7WCjjOA6eKCDKKv1Dg5w6e4pH3vsIf/lXn+eJx9/H+PgO9u+7h7/50t+Q7e7i6sQcSEEcStQqTcrFCvnVIsGwv6jr7epGsF0EJDI9fSwXl5FEqJZrSHjklpdQRImWZ4HscuHMG9y+8m76ejfQ05GlbWi855F38/nP/TZ9/b0EtDBNs0C7WcPzJG7PLrC0mmP7jjEsw8Fybex2g6Do8s71SSRbwGm2QXARdJl0MonjWCwuzpPpHOWuffcwvmsr7VaDUChEzTIIyCpWq80b33uN3OwSelSmf2CAnv5evvDXn6PVavHhDw/w/PPPs2XLtjUXWoNEPIWiaBitFo7l0LAq6xzWeCqO4NhYVp1KtU4wHCUWi+FYxnqSgqIoWJaFHhDXgwA9wcaOxWnh0VqDUguyhB5JEIomED2RW5OTIJsUCgWWVpYY3bKZSCTCwuIilm2QyKR5z+OPEYmG/JhqUaRtmUiqQKtmkS/lmbl9i5MnV6k3a+y5+y4Mo8GFi2dRVRlJEHCcJoInkFtYRfN0H+Aqu3i2iei66C7E4ykcW8AyPVbmmpTLS1Sr1XXtcEiM4DZcLr0xx+U35zH0OgMDPXzo448SjAoksjJvf3Xmh65jP9QW3vO8siAIbwD7gLggCPJaF9oLLKw9bAHoA+YFQZCBGP4y6f/vVcxXKS1KdHR3sHkow1D3GOfOv4NpW0i6TDrbQbQ3xt37NrB5+Ke4emaek29foLkYwHPD9PSN8Fu/80f8+R/+IfNLOdpGna7eIZKdUbLFJPMz02zYOMjE9VtEk0l6hzfy5S9+iY99+ifZNjZOcWYB27aZn58nFIwSGUkyMzXN008/Tb1exXZaZLMd1BtVgnp6ffvaaDTI54skMllWy0VGR4ZYWcmtZ/yEtQDNZpN6s0GrZrPvwP3UqmVUVaVSqaynZD700EO+cN7yMXqruXl/FmYqdHcN4OIRSyTWZ4Vbt4wTCMZYWS0TCITBEWnWm+iaRlcmzauvvEgwKjM/P83xt48wsGGIV155hZ/6zE+TM3yO5/e//31+93d/lz/90z+lWS/z8//is/z+7/8HHn334wxvehhBUnj1tTe4d/8hDKvOxYsXCQQCvPrqm2zfvp279+zjyPFj3HPvfRw/fpx9e3YRCoV8q2Dd775dBwzDIhJW0DWZjRtSa7NNh3bbxGg10RR/9hQMBrFt23cuIeBYBqok89J3XuB9jz3OiRMnOH78bRbml3j2Yx9gcXGZwsoSKysrRKIBVNnXiIprxKV0Oo1l2yiCXxAs2yYcCuFICo263xmlMl0ImkKraIJRQ1V1/vxPfx3bEikWKjhum1BEJJmKUijlicdSOEYbz7ERRYXjx4/z6U9/guWlJSLhOJqmYhgGZ86cQQsp3LlnJ7lijrmlZWLRDK1Wi3g8yqFDD/DQQw+S7uxaU10EfSaqKGDYFqKqEE0nee3IW9xz7x7Onj3HlevX6esfRJIUfuM3foNkMsn169d9fzgivb29bNu2jVAogCzLtNu+CaNg+vi+SDS0/n3G9btoxzLQNM1PwfS8tXGErwCoVCoA6/PSjo4OLMtienqaRq1CPBpBkER6+vpYXJ5C1XW6u7tpNlq0DZNarcamkY00m00uXjyPpmls3LiR5dwKXT09WKZHOt2BoiuEYwEGhrs5ffodzpw5QqNRQ5Q8JEnAtT1kRDzXAzyctoWoKUiejOeqmA2D1VKJK5fmwJMREBFdH0X4g3m7IPidua+Q8BMRvHqA3EyTP/ut57CFFlpI+GFK4fr137KFzwDWWvEMAA/hL4beAD6Av4n/BPCttT/y7bXPT6z9/9f/a/NPANeR+KP/8g0GNiR5/ImDdHQm2X7HnRRWVzl57B0OHXgXtXaJ7r4OwjGVnQdH0DpEvvXFE1ieiBCQkTSNU++8zY47d7Pnru3kylVCEZHe3iyq5nHixDGeeOJJCsUiOE3yKwscffMtRrZup7Onm1a7wsS1q+zYtovV5UUadZPOjm7qzQY7d26n2jT43osvcejQAaKREJGAzkvf+g67d+8hEomwUszTbrfRNI2xsTGWVpYJKAEG+/oplktYjktuaZloPILneWSzWT+Dp9EgHo8ztzBPy2gzNDSEhEsymWJhfgkXkWgkTrVWJpVKIQgCR44cQYn4MppgUEdTVRqNBkO9g1y6fI5kMo7ZbiB7SW7evkkhl2PHtm28c/QYs8slPvvZz/Lgg+/ir/7qCwT0GP/6X/9rvv2tbxCLRfjqV7/Mvffey/ZdO9e89g3efO0YgiAwM7fIs88+y+LiIl/8p+f4yZ/6NKurq+y9Zx/teplKpYLr2qQzKVqtFpV6mXg8jmH788GbU9P+kbfhC8ADmi+izq36LhjbthnoG/RhK40mu++4k6OHj3D8yFG2bh+n3Tap1Zv84e/9Nh959hOENBUZD6PRoGyUcF2bnr5ecqurCIKHoijosoJhW0iiSLvVpN02CUWjXLp8ngMHDiAo6hrpp40ogm0uoyo6iZiDhwOYlAwHqyYQjydxkQiFNdptm3g8zsLCAh3ZONlMl49wq1bZtm0bL7z4TS5evILtCISDMRQ5wMjoELOzs4yNbaXZNLl1a4rtO3f4zhjbwDFdBE+iUCjx+3/0h+y7716mZ2/RbLfQg2GuXr4GooCi6ORXVyjkVwgGg0hikOXFJWZnbqFpKgODfey9Yy+rCwvcunWLO++8k8uXzvuSrUgERdV9v3x3J+WStS4TCwV1Wm0Ty7KJRuN4noceFCiVSpw4cYKdO3fS3d1NLLKJZr3GqiwS6A9QaxXQgwFs16XWqLNp0yYioTC4As16gy2bt7Jh4yYfzBKMUms20LQQ1Xodx7M5euwtLLtOrrjkmwCMFqIIrmeTjKSQJAnP8+e47VqdldwKtUYT1xJQBAkUHawAnguCKK+ncf6AsrVWx9Z5BY7jEJID2A0TGZlENI0oi6ys94D/DxZQoAv4u7U5qAh8xfO8FwRBuAo8JwjCfwTOAV9Ye/wXgH8QBOEmUAQ+/H//FCJ3734/5y+cIRrYRbVYR08KdHfE6XxXJ0ffOg6KSHvnVuKdKeI9Gbbv2s7W7Ts4fuQyc1ffZq40wVI+S+Odt9g6voMHBwY5duI4Zq3NwGAXiRi8+J1/5MF3HaBSXEUW2pRXl1C8ccZ3bOfm5BWSyST1SpVdu3axkitx69YtNo2NUm22CGo6kgiNepVmo4YqChw8eJBcLr8WAdLF0tISXV3d3J6aIZaII7RdkokE2XSCq9cn0ER5zbkTWZ+nSpLEjRs3SKSSBEJBJicn6U5lKZf8IXxXbycOAoFQhLOnT/qYslSGnXfsQpIEFhfmUCWB4+dOctfufQRknbGRcb72ta8w1NdNT08vjVodwYVCLs8zz3ycSCTG7/zO7/GZz3yGieu3+ZM/+RMa9RIDAwP89Kd/ElXVePvkadqGwbVr10imOjh06BCSJPHGG2/wwAMPsHfvIW7fmmG1kCOeTq3rHi9ePI+qKf5WWfFpQoZpI4gyPX2DtJoNgppOpVSkbFlcvnaTTZs20dvbTSQSIRLynUGNRo1Tp075cbm6zpuvvU40meIjH/soH/v4t3jz6DE2btjMwQffxXNf/iKxSARJEqlWK8iKRCzuo99Klk1Xdy+uKJKIxakqJu2WjSS1mZ+dpKOjC6O8St1u0rYNbLuB7TTRtACO49FuG9iOjKTJODhE42FECRaW5shkMty+eZONgwfX7Lt+92saBnfcuZdK1acuFQolFhcXWVpaYmxsjGNHT9DZ2cW73vOwL5j3XD9wznO5cXGS5577Cjgut27domW3wYXlnE+B92yHtl1D01XAptUsoci+zbVR93Wjt2/e4PQ7p30Gg2Vx8sxJisU873nPe9i+8w5cx2Lrls20Go2175u0ftSVI7H1hFLX9XBdj1jMh287jg+MrlQq3Lx5g/7+Xur1OsMjm1leXsawTJZyq5iWQzKWxLTapBNpNE3h69/4MuPj45SrFdLZLKGQRs6sUyrmCAV0zLZFV6YbK+7Plaenp33XV2F1HT8oCAJiW8AVBRQ1iu1YCJ6Ia0tICLi4sAah+cG/x+/QwV3bT4BfTD3b137jeShSAMf+0WhMwv9Nc/j/ypWMJ72uxCgf+tAzJFMB/uIv/xCkaR5/Yh/77tmM2W4yP7vAYn6ZWGeGTdtH6OrvwVQcLMPk8HcucvbNGT725Kdot9uEtQAjIyMYbT/NUA/4g/5Kpcpqfh7PknnuH7/HyNY97LrrANenb5GMBynmchx94yif/bmfZW4+j+XK9A4OsmnzJhrVCgvzs3RmO1haXqBcKLJ7xy4/DiEWR9QU6rUiXV3d5FYLGJZJI1dmeXmRzp4ObMPCcQSGxzejqirlso9dW5xfYHFxkVQmzdDGDb7wuumSzqYoVUsks0lCgSiVSoUrly4Si4S4NXmTno0bGBneSG5lkUpplcWFeYY3bEWQRDRNYbVY4NKZE0QiEWanpklEfZjuzvsOcP78eXbt2sWxY8fo691AKCDz/VdeJJVK0JnxpULvf/oD1Bv+Fr1Stzh8+DDj4+Pce++9AMiyjiBBtVFldTWHWfW7zd7eboIhf3ShhYL/h62yh4CAh4BLeWWFRq1KyxbX5TWWZTFzc3YNVWfSaNao1fxlkysKxFJpbtye4pkPP8Uv/9K/JRZNc+eddyKILhNXL/qaxXoNPeh71COxJAFZpdUySHZ24rWbhGJZiqUa+aV55man+anP/E9cOHWCuZmrSJqHZ/tjEk0NYBgOeAJqrJNys05HNoFt1Gg22xRyZbaObuZX/80vMDoyRKFWJxwOgW1Qz61yZeI2V65cIZ2IMzExQblSxBUFUskOxse302i0eOz9j6NoCoGgRstscfztY7z1nTf5xvPfIt3ZhapplNs1P8/cA890EQSRQCSMILpYdgvPs2mvRZdEI3EEQSEYCNFe03Bali+vG986xvXr1xnbOk4wGGTzli2kk/4pplKpMDMzw8aNG6k2fJNCNOpL5ATJ57aWSiU0TePq1at0dWTIZtOUy0Vsz2V+6hatdtsnoekaxUqZ3Mws6UySSCTC8vISruSrCrp7e6g26szNzTG3PENnNo3gQW55kaU16ZYPRvGdVYKir9cJ13VRDAlLdHBx0BQFbAtJ8qWKPwgK9Bz/OC6K4vovF2+dFWtZFqIVxBFsInGVQFTBweD2ldwZz/N2/zC168eigKqK7v3+b/45rmvzT1/9O2zbALdOMKRQb8zz6Z/+CVKdIoLoMnl7kkbdJB5LM3THINmBLO2qzdnDF3FLQeamCzjtMAElyL579rBtuJPj75xgz967OHPuNOmeLjpjSQJimFyxRaFhcmtxFUFUOXn8BJLd5oH730Wl2mRkbCczi3nGt+/i5s2L7N+/n/Pnz7NhwwYOv3aEoeGNDAxuYGZunm3bt5NbmvGPPbruL0Qsk5deeolDhw5hWRZTU1Pcf//9NI02q6urRGMxBDSuT1wlmfR5nXv3HWRmfgrHcejIZKiUygwNDdBum8xOz9Fu1CmVc0RTMaKRyJowvelb+QyTeDJNyzBxHIeL77yNHvBTID3PZXCwH1MQ6ezu4u0jJ6gWKhx8+F28dfgNxreM8Xd/+wU+9KEPMHltlka7wT337eXK9UvMzxb42Mc+RrNt0NnVzdzcAh2ZNK5j0zbqZJIJ1GCI+fn5ddlVo9Ggr2+AaMzfrkuiRrm0Cvg+6b4+f9uregKlahFBktH0KIWVRSzD4ObNm0xO3ECRZHLFVQRZotluEY/HeevYMT7zmc/wree/w40bN3jggXexZccY3/z617AMEzwHRZRwBIglkuhaiHgyjeRK61HJ+XyeWq0GosRHP/Jx/uzP/wQEC7NWXiPcy2vFp5NIOstqbhE8h76+XkqlEma7yZ7dd/L0008j4tKVzZJOxnFdl+nbt7h48TLnz12iu7uXS5fPEo7oSLKM0WgzOjJGZ28fm3bdRSoZJKSJTE9M8h9//d+zWmuQyxd8Y4hjE0vEqNdslpcF/vG5b3L9xjWe++s/IZ4IkumIcn3iAoplYWsB9t37IJdPvoMtt5ElCVUJIEs6oVAU12yDLGHjIosSQz19qLpGs91m89atjG7dRigaIRVKrmEY/STOju6sz3do1tF0HxYtuiqOa3H9+lXfrmtWET04ffosgiIzODLM4PAAt25M0Ko3aNQqlKolarUagWAQSfFHBucvXqbRrBGJ+HQy0zS5fv06CwsL604xUfTTPd0166UgsD6zFUVx3Tr7z2mvNqLtrcsOf1BA1wMCAcdxcG0F2zNJd0eRAh6W22D+SvWHLqA/FlbORCJBMBzgj//oDxkY7GJpeR4BjaCWZNfO3Zw/s0wyLbB33w4yUYNq7hpNiuRuqDSKVcY2jzM+to36cpOubAdhrQNVCRAKqgiyxF133cUbb7zBwYP38caxI9ww2iSCMVo2BGMZpq/eIJLMkkrEqRZXWV5YpdJosvvuKPJKAUn2fxC3bt1i48aNCIJANBHl9u3bpDN+hKtr2+uOkB/clOKxCKFohLblxyjMLy2ia0Esx8N1QBAkmo0mtm0SiYZ9eLLpx2WUi0UUyT/y+12lhqKpQJCkmEQPKRhGa23OI1OvNejr7kTRA1TrK6SSaTIdPWuZ4RtYXJxnaONm/v1//g989GOfQNECRCIu9UabRDzDjYnb/OSnP8OZ06d49P1P02rUEPEIihpbNo1x6exFlnM5RreMcceu3Xzu83/Bgw8cZGR0mO+99B0O3Hc/kUCQqakpenp6yKZSRCIRwMFxbFaWC3R2pPyM8MVFJicn/WVbqYKmy6h6AKNt02r4C6jBwUEyKZ9cPuAOkivkuXFzkslbt7h7z37+4e//iX/5L3+ON958jddffxVLcNgwvInTb79NJhZDFkRqtkG5XCYShlgitf4Gs22fACVJEjdu3uLP/uzPePd73s2Jtw8zOL4NSZJ4883DjI3vYmRkhOnpZSSxiCRZlCtFpLXFlKIo1CoVRkc3ke3IYlsGtVqDRqtJ26jQ2Z3gzbde4+DB+5idnUaWVUqNMm+88Qa//r/9R6LxCGa7id0yePnll1nMrdKwnDVbqIciKhQKBVxX4z//5n+ht7ebQqnIs8/+JLdvXyWo20xcOIuLRLXWJpPuplG3iWQiyJJDJBLBMCzq9SqyIKMpGvVqBU1RuT5xE9MxuO/ggfWFpiyI1Bu+5CkYDJLNZjl39gySJDAwMEC91ESwoW04RKIhxsfHaTab5JcWWJqdZWRkmPmVRSYnr4DgENB1KuUy8po1Oh6PE08kyBcLTNycpLunk3LZd0tdvHiR1dW8f1NVNTwPXNdCdF1E/Nmh7bp4kgT4hdDzT+C4noUk+1ZM0QNF0PxCKvq/57rwgz8lir6OtOGuHeFFx9fzrnEbftjrx6KAttstvv/qK+zatYtzZ44jKxALxUgnejn99jQf/PAH+cbX/4HvfONtfu7nP84d4xkELBRJIqyHaCzUiasB0t1BopEUkxPzVOsFenq3UGuuOQ9Gh7h9+zp3bB/182oci2K5zvzCNB1hiQ3D3eSKARYkg+WlWVYKRfK5RY4df4uBocF1j3w+nyeVSpHqyDA1M83c/AxG20LfunV9QC0Iflb6dKnAjh07OHnyJMPDwwwODlKrNfBEAVlWaTRaZLJZQuGtzM1OMX3zJtUde4h3pSjmVmk2m4QCQSRVwbJ8uYmqa9TqNrotMj8zz/77DtIyXWrNNuVylUDYIb9aYHjjKMFQlEQqhes6RKJJfuu3fwfBhlQqw4kTp9iyaZTNW7Zy+/Zt9h+4jzNnT3Hg4CHOnTtHOhnnzKnTCK7H8WOv81u/81/Ira4yNX2L+YVZPvHJj1OtFMjllhke3sCFC+d44IEHqFbLzM/P0mjUkFSF+fkZMtkUkqigaCohwYfyuq5LqVRiwZslk03i2ha3bs2gBXR0XefW1BS2aTI9PU22s5NypUrLMOnp62N2dprOziy/8zu/QzQa5eMf+yR/+vnP8+yHPsjP/dzP84XPfQ5VVvAkb42S7kdblPJl+vr6ECQRWfUJ+CMjI9SqDV544QUCQZlCqYymBth3z33+1nlmHs9TyGY7yedn/ROGqqHKEovz8+iqhiSIFAsFquUSZ8+eJRmP0j/QS6l0md2771j3wrsuHDp0iJmZGYqlHESCxDSVt48eZ3FpBUdSsNa25iCiqbovA4vG+fu//mO+9tyXCAZCCLbN8IZezr7zNrGARtvWEDCIxrKoWgRV07GtOqKkIEouqqZimy75wv9O3X/HWXrY5d3w9+736f2c6W1ntvemXUmrYsmWm2yDbWwMwZQAsQOmJQSShwRMEgIEQnkSyAOhBQKuwka2rF5Xq7banW0zO723c+b0cvf7+eOeHZv38755E57k+eDz10oaHY125/zuX7mu67uNqCnEEnFkQUQPq7SNDggiCzOzLCwvEY9Eyee7OHb0BKVSiRPHDwPQbLRJpHNomkYo7OP5AQ1gaWmJ0eERunr6KRWXGRzood6pIfoBarq/vx9VV/Acm83NTWRVIZlJ09XsYmLiJlevXtlRT4AoKLs64cCUIeBYxu7DSpYEOjumFmGnOLq+hyQL+H7QlQoSuL4Dso+zk5IP4BMEs9zpSHVdRVYkZE1EljV8PDZ2/UL/46+/FwVUEEWWV1e5++yZwF6m6bQaNSKRCCdOnaZWb9EwBU6efpjtbWHHaZRkdnGKXDqFYbaIRDV8W6BWvYKiRjl7172YtovttbCMDoJkkk1HkASDaqeK43hcuXqVyRszfN8nfhTT89jTn0M062w3GgztOcj6+jzZVIrtYolEKroLSatUKuS784iywM2b1xnsH2KruMHg4OBuZ+W6Lq5rc/HiRT7xiU/wxBNPsH//fubm5ugfGkQURfL5PLVGFd916Cl0kUknmZu6zdneC4F7x3GJhYOgi1qjgef74HtE4zGuv3WFrr5eJEnh9defJ55K4nZEJFWlr28Ax/EYHRthcnKCu+46w/TMbTpGi/e/91E0RSUej9M/NMTa2jL57iz/13/5PdZXV8nlk8zenqL3vvuYvD3Npz/9ab7/hz7DxdcucuLUcU6fP8NX/uarDO8ZxDSa1GplTpw4wfpmkW88HTjCookYw6MjLM3Psbg0h9Fukst20Wg2EUWRhcXFXZnJnr37qGxvEIuFOXn8MJNzS7z88suUy2V6uro5ePAglUYTw3ZQVJ2lxRV6enNEIoGusF5vsrK8yX/8jd/iFz/7SyjSuxk7eJCXXnqJkeEBbNtme3ubRCpD3+AACAKSqmDs4EQETwgoA7rCdnmDtZVlIKBJ2rZLPlcI8NWeQSwWQ9c1PMvGtWxajWbw3vEorXqdrkKO0f5B5uZnqDebKHKMqlFiY2MOSfaJRNKBVEgI8CCmItFo1GhWa7z55mXqHQMtEiaiB/gM0zQppHIYhoEstHGaJq2OhN3pMNlZot3aRhI9fCGgnpbKZfRwmLbRJh6LUG82gog736XTaSMpIpZrMbc4x+mjx4kmA0vr6soaqVSGo4cOB/ZaSWJjcw1NDTE5PckdIkJxaRnHCXhRPi7RaJjz588zPzdDJBZG3pZQ5DChSJhao0O5XAZg6eYiptlheHiYjmUyOzfH6uoqiUSc+++/n7n5GarV4Gvb7WYwnkvBqI24w3r33ICuqbA74d05LAmCtEvUBRAkdomgd6ysAvbuv3en0Po7nycAUZD+TrXr70UBVRWRge4k5a1NPNOlZ6SbdscnlUpR2q5gt8N0mtucPPVhfv7nf54f+7Ef41d+9f/kt//tTxOJCDjaNrXGFq22w4ULF/B9iXazQSqWZ6PTIJKM0Wo4rG0sI0kSrVaDrY1NsukEH/noB5hefhNZTBIK5bh28xapZBTcJs3aCh966Dv48z/9Av/gx3+c+alpDu4d49r4OD5w//m7Wd3cpL5dQ/Hgtdde4/iJu6jXA7lNKhFioL+P5597jgfue4ilpSU8wUWQoNlukPUySIKM7busrG+w79Bh5qYWOeUIgIema8iCBLZAtVQhk0nRaFZxPZFEJksoGqNUKtHf10ehUGBtYYG4oiEqYTY3igyODpCulrk5NcVgTy8/8RM/wfiVKSo1C1+IUK3ZHDq0h/L2Nook81Of+Ummp+b5zo99D4VCgXvuX+LW1Ax79uxlc30ZOMpLr7zM4WNHef3Sa4EPPxzm6vht8l05iqUKJ06eIRKJsLK6wdrWKr0D/Rw+fJitzRLyjkZzeGiIWCz43i+/dZlGo0EulyEcDqGEVN73ne/n6pXLbK5vsLA2w/XxKYrlbWLJBA2jydStEpFYgnA4wgMP3Mdrb7zJ9//DT/DUk8/y8e/+B/z4Z/4J993/Hr7++FcIazqteg3H6NC22xiGQafZJBqNokoSoUgc07Gx8RgZO4zgGDsecnDdwBnluy74gUY1Go1SL67gyR7ZfBpJEam2myhuB6NZY2b6NiISq8vL3Lxxm4GBQVr1FocO76PW6JAt5BkbG6O8sUWmK8Wb4zd4/OmXMUUNLSITj0eDAI5Om0Q6RTqRYLu4hW01EDwX1/WDgu7bCKKN7UjUJZ93HT3B5vw8LhaqqtJotcim01imTbVcw7Y6KIpCMpmk4wtMTd2mbbXRdZ1wOMzFV1/gjTcVevI9NFpNitslCoUCe/cfYGRkhMnpSURB5tixY/hYzMzMgJTm1dcvIvkee/eNYsgOnU6Ler1Kd7YHx7EwrA65XIZyfZOFlWkWFuZwPQcfn0ojONh5goEnWNiiTSSn73TrXtB5EtiAJUXEFzwUKdiF4gdduucRhNl43m7B9PBxPQ8kD1HyQXEQHXdXGgXg4SLu7ER1Xf//Wpf+R15/PwqopqAlfW7deotwQSaUV0ioGXzVo201QcwTD8dZW1rj7MmzXHr5Eg8/8DDXxm/y0EP3MHxgBEG0GR8f59lnn2X//sOk010YTmBfm1+YxWjXUJXgKWMYHZKpBJ7l8/prl+gfHuCZ575KoTBEJjtIWI+QTEVYWlpAEC2OnRhD8Osk4yLRuERvX5qvf+NlHEVmdGwvr8wvMb+4SG93D8XNDfr7B/GcDrZtIopBSvu1a1eJx5O4vsv29vauhOmOn/rOhXBoaGhHXB1ibW2NVr3JXffcR7Vapaeni/n5bZKpBCsrKxi2xcGDB3E8l7W1NfRQCESBSCxKpdXCMoKuSYhFWVxZJh6Jsbwyz33vfID+gW7GRocxTZNarcKDDz5IqxUAz0qlEqurqzz88DsolUpM3prggQce4F/+wi/wr//1v2ZtfZ3Z2SARvdFoMD4+zvGTx+jr62NtbY3+/n50Xefu8/fieT5zs4tUKhXevHyZU6dOYVkWs7OzVKtVzp09Tzwex/OCIGfDCQT2fT297B3ew/zCLL0D/Rw4fIhSeZuBgQEqW1s7ekGT559/nkOHjtBuneGTn/wkf/iHf8hP/fTP8f3f//2k02k2VtdIRCN4UpAYdSd0uF4PfM+yFEJTAjdUo9mkXdsmm83iujbxeArf92lUykiyAq6HREAQ0EMhyuUKmUwmmBZ8m45poWka1XKNs2fPkohnSKXSTE9PkUqlmF5cQZQlZubnOHfuLCsrq7z22mu7IDtJDY40i4vLKEogXk/oOsViEQ8BT5QQvCBDwPZ8HF/CE2WOHj2KIAisri0HZALfQA9FMW0H27IQcFG1AHNcLG2iKAGtNCyHd7389XqddDrNm2+9TiQa5V3vfoR4PE4ilWFtbZVCIYemhahUt3HcDn39PVQqFbK5NJokcuXKFcIRJcjqVBSWVlfQdZVsPoftWiSyCVZWlxgZHaNUKlEsbtJut6lUKoiiSCwWw5UCWKDv+YHPHWm3W0QMhPUQmCVEUUIQJHxPCIB2orIbiygpQcSiL4LjWPg7ITiO5yIrIrquIe6EMt8R2f9dX38vCqjlthk6EeLoOx7A9mw8fMJyDLHjMbinD1WR+UjiXjqdFkeP5ZmZmUHVyrx88TbrGyv840//IIIIw8N7KJa32douEcvmaRk1VhcWSGeSxCMRilsbaKpIOpXCMQ1yfXkK+TybW2XOnNmD5QhUt7fJJDKkkwmWFi1uT71GOKayMT+J46uUilX0eBJbkBgeGmXy1m16enpoGE3S2RQLc4u0trcZHhtBjcRYWl5BNC08XGRVYnN1A8dxOHDgAJcvX2Z0dC8gk80GB5N9+/Zx8+ZNzt51nNWVZW7cuMG5u++lVinTaTcZ3bNnZw+bRdN0arU6+VyB1ZU1Kq02IT1OXJZQVImwrtGsN7AsC0nWkPUwD77rIaamJrjrzHH+/a/+Kp/43u9hbm6O9bUlzLbJ+977QYYG+zBNk+WlJb72+BN8x6Pv5/f/0+/xa//mV6jVapiNFqFQiJmZGWKxGO9+97uZmLhNLldgeHiYfD7P/Pw8r7z8JolEjBs3r/EjP/IjbBY3uHnzJsPDwwwMDHDfffdR3CztHN/UHWCdh2l1WJqf49LUFHedO8PQnoNcu3Ztt7DnEkm2iyWi8RipZJxWO9htHjt2kk9+8pP8/n/+Y770pS9x6uxZdEnhi1/4PGpY3dVF2naQC6ooCvV6CUEMiOKyLBMJ6bQadVzPxveCbk5EAEEgm80GQdq+hed5HNjXz7NPPc2HP/ydtBCZnpzk2NETTE1O70qzVDXQxx4+fJhorkDv4AB9AwNMzk5TK5XxXIFWqxOgKEIa9XqAaO7qyqBrYWbn57Fdn3rLIBzRARnJaOOJEgYKsVSBVDrJ2toKEEDxQppC2/bBtbHMOoJv07GDcBVJAUUTabZriEKAnClubpFOp9na2NzFw9RqNSYnJ2m3m+RyOc6fv4dkPFgneV6IzbV1QqEQtXKFqds3sSyL0dE9ZDI5otEwy6srlEolZuamSSbjFKtl3njjdWZmp0gmkxhGG1n3iey8p2EYCChAUODudKCyFKx6JEXC8R1UJbRb8O4UQEFQd4XygiDgY6FrGi4OIVHHxUPZ+RrHsYK8WlHfPTKFdjArf5fX34sCqugySsbEFNeRFBXJF/HbZerbJdKRJJYrUhjoRhB0+vZ0s+9oHN/3ufehQzTrLW4t30TXdXRdZc+hg1SrZbZLW/T1DLMugWN7hCIRFhfWKG2sMTzSz6mTR8GF8bdvoIUV2g0HUZb4R5/+MEZDwrIcurrup1SsYNsWV9+6yoWHvwukLDMrCwzt2Uu50iAWjrG6tcaBQweJZVOsXXyZbDpFx+rF8Dxm5xd45JFHeP31S6Sz6eDJHw4DAeq4WCyiaQohXWF2dpbRoX276OR4PM7BgwdxbYNCLk25WKK7q5eVhTV6uvtoGR0a9RayouE4HooWwfR9VjfWSSYSGJ0O6VSKWDzJ5laJ1bUNsrkcPQMDfP5zn+OhB+4nmYzz0EMP8rXHv8pGa4tCvoflxWm6u/p549IlfuGf/wv+03/5fX7hl3+JP/2TP+HjH/84E7cnuffeC1y/fh0Q2NjYZLtSIZ/Pk0ikAjmLILBv3z4SiRixeIhavUQ+n2d5eTmgWlYqPP7449xz/l4ikQim2aFer9HcrhAO6wg+xGIxZubmkNUigijy6KOPMnHzFoLlMKvP0WjU6LQadIwGkWgcURQ5ffo0/+7f/TuOHDnCdrnKtbevcOr0Gd4afxvbDtxckhTBNE0sy0ASg84kEonQbDYQCGyQ3d0FND2QgCmKsivPCofDGO0I0WiE7kIPgutw5bU3iCSjLCyt4AsKRquDLwYPyVdeucjIyDAvvvgih0+eoVzaZnlxEV1VeP65V9h/4AhXr98mnU7TsVp4HiSTSVzHZ25uPjjGROOIeoiu7m42NjbwnAiSIBCWFHoHh5mfn8W3PGRJod6oUd3YJhqK4/surufhyyq+Y+HsJNf7iNi2C24nOArpOpYZTEuG0WZzax37qrVjrVVxnAif/9yfMz09w+joKD09fRw6dIjZmalAw5xJcubMaZaXgwe+IAjk+7NsbW+RiEZQVBk1pDC6f4ThsUC+trAwT7VRxMNFUkQiSiBvuhPQLYqBPEm5gyqSQBUVPFFAEhTAQ75zed/Zhd7pQBVkHM/F8QE8JFEIdsCigBQSsDwHcO64VlE8ZVdw/z/7+nuhA+3dk/F/6t+/G1HwEByfcrnOaGSAwXQWwXeIZOJcubHKW2+9tVtcAOQwmKZFPBJHU3Ti0W5UGdxOh7XFdfYMjZHtLrCxvsULzz2HpujsHd7DdmmDaETh7NmzrCyu0z+cYWZ2kxOnjnPlxstUNhssLa6ztVnj6OG7UBQNPdpF/9jdhNN9KOkk469dpjuTY2lulr7hXgzHpre/j/rGBs8/9wx33fcg/X2DtNttBNHHNNuUy2VikQStVouRkRFCoRClUhlNU7CtDuvr6+zbc5Baq00iGUKRJWZuTzM42Idtu/g+mIbN6uo6PT092J5Lu91m7/59TE9PY3Vssr1dhEIa68srnDp2mOW1VYqlKslUhsWVZY4fOcylNy4R0VR0UUKOyPz27/wHPvKdHyakxNi39yAvX3yKcDjK/n2HqVWbHLjrOM89/QwPPvAA3/ja10knU/R29/H5z3+enp4e9uzZw8r6EsePHyeTyaAowcPg2NGDvPLKS3R15/jc5/6CT336p/jt3/5tHnnkEWq1WgBc2wpiEgyjjW1bHNt7gM3iBm9deQvDMjlw+AA2Kusrq2RTac6fP8/n/+tfsLa2iqzJrG2sEgprSGqQI3vu/AUmJucoFAqMjI4FtNFUkp/62X/CsSP7A259q7XrnBrq78V1XZrtFoIkkgwlePDB+3nzzTdZWV1GVWViegzPCw4/q6urZPNdqLJITy7F/r1jvPz88+w9dpDtrW0UWcYxbWJxne6ufsrlCl1dBTY2V/AEhd6eLlaXljE6LRZXiszMzlOuN+h4JrZnIss6mhrCsuxdbaOiKLgIVOo1VC0UmBNkn0g4RqlYQ5R8UtEkIVWnXC0zemCYsCgxOTNDxzBoWzai7+ymR0mSRCQSQRGFXWlXux2YJkyzFYy6qkIqlcK2WiwvL/NjP/YZatUG8/PzPPTQw7vZnoZhUG9UqNVqnLvr7uBB0OkwvzlPNKxTr9a4+OKLrNZWEQSBUEjDsg10PTBi3EGzBEUz2GXeKWaiKCKILoIsIcoCggCuJAZpTIK3M9J7CMI3nVQAKiKe5+AJPr4AnU4LURaQlTua0CD4JRDfu7uHszf+avXbU0jfN5r2f+q334dkg7NcpT/dxdhAX4Cbbbd44+YVLl+dp2YYeIKI4MjISKB38ORA4qAqCqoSRhUU0qEEhWSGTCJJITdCpVjlxlvjhLUwq+tTdOW6iIdDmGaFD37wYbab25RLHeaX11itlKg2tsiERujUOhitJidO3ocviujJozhCglAkxv4DIzz19SdIRmIM7x1laW0VPIeuXB7bMLkxOcG7Hvkgt2/fpru7wOZWQJ1MpBOsr6+TiMZYW1nl+NETu+gHy7IoFAoszs0zum8v0XiMSq3K1sY68XiclZUV4vE4qVSK69cn6O/vp9NqMjI0EFxTN7fI5QqkU1lee+01zt99inK5TCQc5oVnn+P06dNk+ropVyo89thjuKbFBx99J5cuXeKll16mWNzme7/3e/nzP/oLPv3TP0koEmN4YJh6u4PvG3zlS1/g4gsv8bGPfhzfh76BPu6//37+4i+/yMnT54nGIlSrZU6eOszNmzewzBYXL17k6NGjvPrqq/QN9hDSdFRZCQ4y4TBtw6DRaCDLMmfOnGH82hUQBNrt9g6GI9iDhTSdRCzB7NQstiLzie/+GL/zm7+B2ekgiyDIQViGZVk89NBD/N7v/R4/9y9+kS996Uv88A//KBE9wqc+8yMMDvQjex4hRUaTFSqNMo7jkIiFSMZj7N97hHK5jOt5bGxsBDgVLUw+lyEWDQV+/aEeZmZmePC++xm/epVcLoeAuptDKooip88c49WLl3ZGUZlcroCsClRK67Tbbeoti5nFFaqNOrFYjJW11Z0QYIeoHsL1wRNEVDkomNvlwPXjOA5hPeDQHzx4kHg8zuLyBn19fYyNjfHCCy8wNT2NZzeJRMOEwzq+72JZDooS/L63222q1Sq4Hp4XhI6LooiiyliWtTsiK4pCLBZkN/T09BAOh1lfX6erp0AymeTty+PEYgli6Qh79uwJgsTVgAsl6TKWZSKKYNkG1dom6+vrdDotPD8oWg4BYC64hos4vrO7k5WknfeRBRRNxlc91JC6E+Qi7o7foigiCsFD4Y720xeD713cubSLIjiugScHgnzJZ4eN5PKt9e+Z37/57SmkR4Cw6TMQy3Gjs0m6kCOW1tkqruEpGn/9+LPIYhI5EqJhtndkCuCbHq4ItuMGXnWlCp5PTNGYnIVEOMaRww1qGzV6h/rwDZ+4egpJElhZv8WefQk2KpPoyR50VyBmJFmdvk4+G2N66jYn9h+jrnhsrM8RS+eI5X3wfGr1CvVyhc2VNe5+9AM8+ewznD5/F6+9cYlYOMLCwgJHjhxhevo2R44c4uLFlzly9BDz8/P09/bQCkXQFRXB9VheXmZsbIyZmRkOHTqE67rku7tYXF7iwIEDeF6w19I0jYGBAcrlMltbW4TjMUKxKM12I3CsZNJslLZ3xjabWCxGPB7Hsizwgyf74OAgbccC4OyZM0xev0mxWObgwSP8u1//Df7FP/sFWk2T7/vkD3L2zN2EY1HstsU3nv4rdFXk+PHjiEiIssyFe+5lYWmBv/irvyST66ZWr7JndIiuruxOV6GytrrI2NgYq6urwQ+q53Ps2DGef/Y5Bvv7uTo1hb+TrH7w4EGeffZZwtEImUyQP3n8+HGWlpZotTpUq1U8x+Ps2bO0LZO//LM/51Of+hTlcpl/+2//DQPdfWiahu1afPGv/oKHH7jAT/7UZ/gnP/OzPP3002iaxh//2Z/y45/6FIO9fWDbVOoNREUiHg4Tj0aQZIVX33qDkZERDMtg/8EDTExMcP/9xxgdGSEeizE3N8Pa2jrZbI56vYHRMXEtB0EKIH+Dg4NsbW1x69YtDh8+TLvdpt02mJtbQFIgFYvQ29PP2pVxcrkcxWKR2k7kX6fTwRJcPILgDH+H2CnLMpFYGM9xMdodsoWuID5urcja6hZHjxyhUqnw/NNPEw1HGO7ppd7Zpl6v0un4+L6LIEg0Gg3K5TKdTodCoUBI1YJLudEOqAG+hCIHhAPP83ZpAmfPnmV+fh7HcTAMIwiCCYX4ju/4ELdu3SIUDw5z+/bto1ors76+TmmpSL1eY2NzjVQqwcrmKvV6DU0LENi2Y+JYLuChqjII/q6q487PuyAI+IIHvo9lmHRME1X2cHeK3p1OVRCUXa2oj48gC/ieh6wFna1j2giSAj4okooACL6LhIcg/j87Iv296ECH9ub8f/l/PEBrY4Njd52EkML2+iaZfBc3ZleY26zywuMvkcl2I2gaLb+JLzjggHvnIucJuDJIooPkuwguSL6GJHrE5RhD2RGSoSRCxWertMnIWJZCv0L/UAxLVrBMn2gyzkajxPNPvUqnCHEpxN6RAebnNugfGqN3+EEqDZW2aSMhMNDdy9L8Ah3LRIuGsXccLtdv3qC3u4czZ85w48YNksk0o6Oj3Lx5k3g8SiGf5+rltxkeHkaPxmi32yQSid2RLRKLsrURXEuz2SyVyjabm5sBybDdDo4fhsWBffspbW1w+/YEDz34DlZWVgLtYj7PwsISg4PBeCoKAm9ceo09e/bQ3d+HK8Lly5f5r3/0J/zET36G4aERrl27EVycGy1OnjyJGg7xy7/0r0hEYqTzWSYnbvDxj38XL714ke/57u+jWS9T6OliaWWZeDzL4OAgPoEaoFLZxnEctjbXKJfL7N27l3g8zvTUTZaXlzl7+jQvvxjwmg4fP87m5ibLy8vU63VShRxD/QO0W3UmJ27y4H33I6thxsfHMQyTdCbH5MREEODS08OVK1f4p//s57gxfpXf/d3fZf/+/biui2EYnDx1F6tr60iajqIovOu976FVq/Iv//m/4MCeUQBiKZ14NIpt2MGRKB6huLmJpqhYHYP+3j7e8773MnlrgmwmQ1ehm9mZW6RSKWanZ4jogczm4JGjvP322+TzeXp6enDcDs1GgFpeX99EVXXS2RTTE9cDumrTIBSLMjExwXaljCBJbGxs0OhYiLJEOBINJDqyRFjTMdodwmpQVCo7zClgR5cZdFbYLrVKlU6rRUdo7/CRgp+pIIf1m/bHO0e0HRYJoihSq1Wx7aBw7t27N1AjOIGn/s6Br16vE46GdrrZMIZhsN1okEqlCGKDPVKpFPVaBcsyKVdKzMxMUSpvk8vlAj6S2cFxHGRBR1EEPN/F911kQd4dqe90iE2jHvwMy8G6wbXlnXSmIGNBFEVk1f2Wg5KAFgohyQGXPuhWwVMlJEHccceBY7W/KbL3fSzL4tLXp749O1DJF9BUmWMPncNX25hek6G9Y1y6OEVh7156jnucPnaUX/nF/0Am3UUyG8HyO3iyiScKIMiInoijqgiSheB18O0gS9B2TARPYGptimwiw3AqjdmoosSG6eoeZHlxDjES7F06VoXcQIq+gQIvXr/MPe/7AFarQm9Phlq1iLK1QiK7n63SNr19fTzz4nM8cOE+rl6/xsDeERbnFnB9j1A0SEC3LRN8j2Qixu2JSQRfpLe/L0D0ppK0jA7r29vs27cPz/OIJeJcu3aNo0ePcu3Gdd7zyLtp1hu7JM6trS16e3sDzG00gW87pBJJYuEIjUoVTVfZ2lohFovR1ZWn1WoRj8eJx2L09vayZ88eqs0G6WyGE0ePkf3Jn6RtWszMLtJqG9x113mKxW3i8TB/+t/+nNdff5WxwUH08DESiRiLi4t88pOf5LVLbzMy0osgiaTTaW7dmiKXT/G1r32NQqGAYRik01ls20XXw4TDUW7enOD1116mv7eXjbV1YuEIvuOysrLG1tYWnY7JI4+8B0vwqVXLdHX10Gk3+epXHkOSw9x9990gyywtrnD67rPEwjFkUSGVyPLiU8/Tsk3+0+//IZ/97GeD/+dklJdffpGh4T3k0klcBJ555jk+9l0f4R/9o3/E669eQvR9XNdmq7TNUP8Q58/fw+LKPKLnEw9FaLdaPPzAg5hmhyNHjjA3M0e73eauM2dZWlqiK5cnGU+wsLCA7/sUCgXGxsaoVqsUS0WikRiuG6Bd0ukspmGTSmXwPLBMh7XNqeCBWsgxtzDP6NgI167fxnYcXHxi0RidZotaq4KiBLF8giCgqAIQPCRisRiVRikQmUsyii6BoCP6Prbl4AuBDzykq7tjL4DnulgCeJ6D6wW7UVlVuOfeu2m1WhSLRSzbxncdstnsriA9k8lgOSaua9PVladSqUAoyAJdXV2mt7ebaDTKyvIizz//HIoqEY9HSUejVDY3kSQRyXMRAUXywQNZlGl3LNquvfs9BnIkhaQo7RZUs2OCIyG4QYeJFIyiRitYRdxxAQqSEdA5XRvXC97TwUcRxIAGgI8a+ubhaZfZ9Xd4/d1Ynv+rXzbEcirtRI2K6EOoj8e+fIXu1N386s/8GWtv1JGUDr/6nz7L3Q+fIoJC3IoRi8QJRyPIuo+gWYR1m5AmE0tmiecTyCmXRDqCEPVoSFXWzVVu1Cfxel1qlLhyeZJv/NUVSrc0pt4so/tZNla26RnbgxCB5199hXxvP1LKoX9vhvLmKsWlFXLdXayubJHOFfiLz32OQqFAs1ZFkmV6urrpyuQCfKwDpuWyMDvH6N499Ax3c/nyFXxfYGBomI5lkwyHmLl1E6vTRhYlxvbspbheZM/QIAvzM0iSRDik06hUiIfDVDa3SIXCxFNJ6s0aiiKRS6cpl4tguyiyjKKp3J6dIRlJoUsa9UqVdDrF5OQErbpFeatKpVghHo+juB5Wq47nuhi2RaVR5/nnn+S1554Bs8Mn/+EPkkrIfO93f4SVhVnmZ25y+OAAg0NDbKxv4joeZ8+coF1pEtFDhDSdvr5eiuUNZhdWOXL8FFuVCkP797FVarD/8ClsQSM/OEqpZRFKJpmYm+M9H/ggb14dZ2lphmQ8wsrKEs1mG9sBVzCo1IvcnrxJqbjB0uwiRrvDjRs3KJa2yXV3c+bMOd4eH+dnfvaf8uC7HkCNKGiiSnVlg9uXr+LaBk89/ji//uu/w7s/8FFESaLVrOJ2BCRfYX19nZcuXeTYvv2cPHwYz7V56KEHyeQzHDx4kFQ2Tr47SaE7ge17ZHu66N07QjyTYrh/YCf9PYmmSdRq23i+T3Fzk5WFRbL5HK4koIZ0QpE4R4+fIJGJMjIyyAMPvIPhkf0cPXIS23LpSidRXBM6NZrbG4Q1FVmAVqOK53TwnBa+a1Atb/KhD76XSFTl/OHDRARot2o07SZ1t4VlQcdwaDTbmJZF0zZpdppIgoNjtbFsm3a7iSy6HBgd4p677yKZSfP6G5coljbp7e1l79793H/fA8Si8R2sdItyucTGZmDVbbcNYrEU6XCC577+JG+98hIvfONrPP3VL3H9yhXOnDpBf39/wF0ymthWh2ppm/p2nXqxxvpamfW1YBVRrTR3gXfNZptKuUG10sSwJQQxRMdwcTwfTZPRdYV4PIK4c5w1TQvHcbFtB8/z8V0hIASYPooYwXcUJAOwNTwnhG+riK6A4IsYhoWLgOH83cb4vx8j/GDG/5PHvhs162O2wmhCis//wdvcvLxBrVanYizxwe++wKl7jpHOJ3nj4ptcfP4i0WwEX5XxJR/f9fBlEAUVSZHxBAfHNREdGVxwd0YTXRaQJYmjg4cpzZTIh7tIRgvU29t09Scouav0Hxzi6qs3eP7xF/mhT34czzdxTI/N1QgnTz/KxSsTDA3uQ9d1YpEwzzz9FPfcc565+SV6enoIhULMzc2RKfTQ11XgzUuvksikOXT8COXiNpVKhXPnzlGtVlmZmw8W5rrO6Ng+2m2D2xOTxBMhent7kUQVPaxRKpUIh0LM3J7iwIED2EhEoiFs0wDfw7VsNopbIIhEYnEMw6CQ60JRJDzPodlqBB1sYZhqrczIyBC/87u/hS6LyIrG93zyk5SqNVbWVlGxePYbT+G6Lj1DAxzaP8bzzz/P8NAIoVCEfD5PvRXgImzbZu/evTz7jWeQNImRPXsIRUIsLs1zcN9h5hbmSWfzAMxOT7Jv3z7Gx8eJxwMp2vm77+Ltt9/GdYNQB9+3KRQKrCwvY7Q75DNZkH0mJyd3L7+jY/up1+v09w3S3z+IquqIYhDOLKkSjVaD3t5e/uA//h4RUWF9c5Ncfw+HDh1lanaR7WqFX/ml/4PP/ONPkY6lUFSJaDRMoVCgVt5k//79HDlyhEQiAUAoFsVzLCIhHaPTptU0iMSitFot1heXMepN9hw4QLlcwvddQqEQbaPN5uo6siiR7uritbcuc+Geexm//Baua5Pv7SKRiKGoEV65+DrDw4MsLC/w8vMvsL65hhrSSMTTeL6MJIsMDQ1QLBbZ3FxHj0QDR107ILzGZYnVjXUMxyYSi2K6DjgBzK9cLgewO0FElyVE18aybMKxFHv3j9FuVrh14xpKKEw8nQE3GJ2jkXiwAjDb9Pf3YzsW8XgA0jt89AC27bK1VSKdytLT10eptMnG5grtToMXX3gmEOtHImSyKWYX5miaLTzbwXcBX0ASBDw36Po8Lzgc+aIPBGO36/j4fnAkUuXgZ9ixTSRR2R3V78iXHMffiUB0/lZdEQThm8n0jgNISLKKrApo0aDuOV5w5feBrdnat+cVft+Bgv97X3oU24dc6BQ//enP0h0/SzrSz63JKSyhzuDQKH2HRA6cyhMraEiqxi/+5L9i/4ExtHAE3xNwFAdfkHdcCC6iArYt4bkuqqRiWy5Go4rvCcRDcUKeTEKLEncTrC6scuHeu3n+1ecYOtbFyOBe/ubLj3P32btIJaOomsDsfJnBgbu4dqNGX/8BnnzySQ4eOMDe0TGeeuopPvLR72JiYoKRkRG2t7fp7R1kdnYa2zap1WocOnwQfQfzUSwWuf/++5m9fTsoBkNDNJpt4vEky4sLHD5ygO3tIvV6i8HRYMRvVGvomoau61Qq2wwNDXDlyhX279+PaZrcvHWDrkI3tu0SjUbpGRikXq+SSidot1uUSiVa1eBSfOzYEZ599lmOHz/I66+/zpGjR3n54iucPHmSiy+/ggqcOXWKX/w3n0XRdD70oQ+xvLzKfRceCETiHYtOp8PU1BRjY2Ok04F7J5PJICsS4+NXWJiaZH5hhe//wR8lEc8QTWl8/etfxzAMzp49i6IoTIyPI2sB1mS7UiaZymCaJi+88AKiKHLz5k3yuQyl0hb5QoZUKkFPXz99fX2Mj48HCN5ymb0jJzh37iyyqrC4vBx8yFSRmKzxu//ht5A1FcHzufu++3nmuWdJ5zP86I/+KL/8T3+Ovr4eHnzgPorFIg+9834mJye5++67kWU5wGPYFrZtEo+G8T0Xo22wsbGB5EFle5t2s0WxVCYc0enp6WZzc5NoMkEhk+OlF14k090NssKFe+5l6tZNTLNDtjtPOp3GcUVWVjdYXFxg38F9fObTnyKTSzO0Zxh8CcNyicWCldDi4jzRWBjbDZLVFVXFw6ddKweHGdfFdoNDjygpu5C+cDiMqGrEwyHOnTpBs9nipYuvI6sKkZCMrsh0bAfDcQjtUGF1PUQ8lmTf3j00m000XSEU0oJgllKAdO7t7WV2dpb+/l5szyYa07C9IAy7WduiWN6m2W6ytraCaXs063Vs08H3BHA9HC+wUn6rhj0ogmLwNTsvWRQRhADWZ9vut2hFA7+7IASDdIASt/7WDvWbbiMH/GBNoYYlpJC/ux++E3O3+e1aQPcfzvm/8+X3Irgp/vjXXyetj7GyuE5czzI7t8Dew3u49NoNlGgDInU+8y9/gEhGR2h1+I+/8x8ZGtyDFoliY+ILAh4iCC6C7OAig+/jOz74AtgmzZaBY4vookwiFCGGyvKNRYZ79jAw0Mfbt1/n5OkzzM0uMDw4gtXu0HJLZHsLGGacPb3v58lvvEpPTw+f+8vP8+Hv+AgjIyOsrq0HuNholFOnTvE3X/k6j37w/bx5+Q1efeUiF+69ZwcvGyYSiQR7z3AESZK4MTHBiZOnSSRSXBu/jCwLHDi4jy98/jG++3u/j3q9Trm0TSqVIhaJ0mzVULXAwxuOBlKTycmbhLQQiUSKXCaLooe4PTXBvn1jLC4uIAgCb775JidPnuLgwYOsrKzxtccf46GHHuL11y/R19/DoUOH2NwqMXl1nHKpSK1ZATWELKnk812YpkkuVyCXze/aVDc3NxneM0oul+EbX3+CocEB3nrrDSKayszsPPfe/yAPPfwubk9PBOuOZpNwOEy5XOa1l17i2MkTGI5FV08Pr7x4kXe9611B5uOOThHP5qmnnmJmZoq+vh5SqQz1eh3Pc+gY7eD3RE/j+oGY/L3vf5R6s8nC6jLFtQ0efuBBfv7nf54LF+7hrx/7Mj/+4z/OzakZVtbW+YWf/Rk++6/+Je975F3cdfYsJga2bTM0NLSbqhWPx2k3G2i6QqfZZGtzE8mDVqXG7du3SSQSyKqKLEs7onsZSdOZuH6TQwcO8vaNG0STKfp6egmrCqlUAkfwWFxcotE0yOW7abVaNNpNrr39JgtL82xXy8iShuP5O9pnic2t9eCA2Azoo81WCz0cwmw3dtOLfN8Pruc7/nBBEEgkEpy/9wHmp6e4ceUyyWQKT1AQJBnRt1BlAUkL4QoiIU1EllWUncAZ02zTbrcJhTXOnTvLxsYGRsfZsa8G+QCG3WZpaRFbMBgZHeL29CSGUUbVZNqdDm2rQ0zUgq7S8fEcl3q9Sdt3cGwf1/UDW+ZOEpUoyphGUAg9T0RCwHGCtHlBEHcL3h3m0Z2CescPL0nSrsbzzu+BKAp4voioiITCMrYc7EbFHZS0KAhszFS/PQvogWN5/9c/9y5mbrZo3t6PWUzy9AuPoaBw77338cSzT+NSJBbux3AN5qpv8uh338/7PngOTVT5D7/5fxJJJEllwsiShqTICDIgWHh4iIKAZ7t4LuiCh+UrNJse9XoTWYBsQiTUDjEzPsX3fewTXHn7JqFkhFxvL8898xzHDh7FCJUZPtpLq6GzfrvAo+/8BBcvXmR9dYNyqUYikaCntw9RFFlZWaFQKBDVYvQN97O0vkxXJsftmzdxCVwv3d3drK2tMTo8ytLSEol0mnyhm3y+C9tqc+XqG0QiEZaX1rlw4QLLy8scP3KUJ5/4Btl0mpNnz1CuVSmWKhw5ehxF17j48nOEwxGa1SYnjx1H0UOsri7vLNIFotEoq5urbJcqHD16DBDpdDpsrq8xOzcDeBw+dICbU9OUVpaIh3Vsp8PlGzP8wA/8AH/4h3/E4cNHOXv2LOtrG5imyTvf+U6efPJJDh8/QV9PF9eujrOyvMRdp0/x+luXOXf3eeLJGKFQCKNjsbS0RD6f5/r163zjG9/g5/7ZP6VU3qbebpHr7qJdqhGNxdiuVujt7+PZ559Hcg2uX7/JJ777++jvH0CQJSYmJvjqV79CPBGmUqmQiUUZGhomHIkRjSe4fu0mhe4Bjp8+RT6f5+rVq8QTIRpbG7z56mu85/0fJl/oZX51moff8QCrS4tkEynUqEw4HA50hKK4m1WgyRKm0cY0DVRRwO2YzFy/RaPdYnltlf7eQRKJONVame7uApfeuoIuq0TDEVBVOrZDMp4gl0oSiYTQoiFUVaNUalCrt8jlcjz13JPossDaxiq3bk/QqLdRdS1wSbXqOE6QKNQxAz1oKBzGF8CxO1iWhecEF2zbNNmsl/nUpz5FtVrl8ccfJ53uAsdGE8HzfEwHfEFE8ExEfOLpNLFUmpAOsqRSKHQTCoWp1yvkC4GFta+vh62tDVwCAXutHqwHKtUtfMGj1q5Q79TwBBdRg0ajhiCB4wedIJ6HY7s7XaiHaDo7IDgZTYugCRK1Wo12y8A0g0g7syNitk0cx0MSpJ0c3b9dQAXxmylLd0b2O+P9nb/n+UGRljUJPSpiikEnKyHgu0GNWJ+ufHsW0L2H0/4v//Z7+Zu/vMKVVy3OnHqIvXtGWVlaZX52gmp9nYrhkc0kMIw2IV1haXmBR3/obu65/xi+5PBf//xzxPUwkiKgx2V8wUHVJATBx8fF8xxEUcB2RRDMQJJRs6lXHRRPIpNJkRQV+sQomhrjtavj3Peud/LE008x1NdPtitBtFdGUSRefmyN2obKe9/5IQrZAa7dmmdmaYkPvvdhVotFFpaX8WyP7u4Crhvsivbu3cuhQ4eYun2NP/6jP+Kj3/lhBgYGeOXF17j3wft57Ktf4fxd5zhx5Chtt8XiwmwQ4nHvQ7TMFvgig4ODVCoVLl68xOkTp+jt7eLVV1/l3nseRFE05uanqFQq9HR1oysq4WyOeq2C61jguoQ0nYbVYWlpiRMnTuB5HtvldWZmZnj2mee5++67ue+++1hbW+PqlctsF7e4cW2cBx66F9eR2dissXf/Po4dO4breLQNE1UPs7i0wrlTR3n8a1/h3LmzTE5OEQ7FyBVydDoGoVAkGKNEFwWRuekZbM9laGwPjmXT09OF6+10UIi8+eabpJJx6vVqgOWNxvB8gamZOTodk2g8RDSaZO/YIQqFHPMLk7z49LPcvn0bX4BMPkdvby/NWh1F0chm8rzrXY+wsLmMJsm88eolejJ5hoeGGN1/AFGEWFxHDwUHm13Wu7rjn/a9naxXG1ESoG6xtraG5IHnuEzdvk0iFSMRiwc4CsNgYWsjME7EY/T19TEzM0MkHMX3ffr7+8lms1h4tJo2AirzC7PoIYlnX32RYrGIbZicOXWat966ysbGBq5rU69UAWh5LdqmSTKRBk9AEUS2yttEUwnajSYfevQDlEobPPXUU2QyAQnVF0QkSULVNCzLQtZUBnqHGBkZwrFNarVykEkQBlmWCYXDaOEIoahErdbg5InTdNpBV3hr6jqGYXP48CEmJsfpG+jD9UxK26s0WxVEyaMj2ti2GRQzCSSF3Wv3nbHZ9aUdD7pIp20iuT6e46BL3+JNd3w6TZN6pU2t3MDuSHQ6AcnU8zxcx8fZiboTxUAG5bg7kiY/SGASAN93diROaiDIF+2dYivhecGudXVm+39fAd2Byr0FrPq+/35BEIYJiJwZ4DLwD3zftwRB0IA/A04R4Iw/5vv+wn/vvceOZP0f+dlj7Os7i+TnqdY7PPanT3F7co7jR05SKVWpFus0jRq22+aed5zl9NlTJLpdms0ib77xCl1dPUytrO5IaJLI6k4qS9jeeUI5iJKA44LjBL5fz1VoNTzq9QaO4xEVFIYSObJKlMnFOfRUnOG9+3nr8hWOHtiPF26ihwTWb3tcv9QhHc1TLZsooQixdJwH7rmfV167RCKTZXF2gaGd0IxCV461tTUWFhYw2y1Onz7NG5deI51MUSh0I2kq4XiU5599jv17xohnY0QjQZjuxRdf4/0f+BCVSoV0Jsnly5d55zvfSbFYI5tLBZTH/UeDMUjyeOqppzh/1zm6CgVm55ZIpRJsba4zNjKCIAhcvnZ1V46iKApf+cqX+MhHPsKv/dqv8cM//MNUKhVkSWBpYZ69e0eZmrzNjYlxPvDoR/jKV5/iwMFDhMI6e0ZGefvtqzz0zofJpHO8fflNfBx0XWZpaY1DBw/zlb/5ChMTk/zCL/wrXnrpJR790Pv56pcfY3F+gUfe825eee0S73v3e4jGwmxvF9ne3mZ0zwBf+NIXed+jH2SzXCJf6MJt1ohEo9iez+raBtGYTiHfTbVaZ3Nzk2efe5LissFP/PRPMTg4yM2JW7zwwgtM3Hidc+fOsX//QcLhMLNTizz44IPkCnk2NjYoFAqENZ1MJr1D2mzjiT7JZHA86nQMAIx6E0UJHsaiKNKslQL5jhccLyuVClpYxrFsRJ8gZLinn+L2NhulLS48+ACT0zOkc1my2SzpdJqlpSXC8TS1aotoNM7169cZG9tDrVhkZWWFr/71V8hns7hYLK0sU63XaJkGSDKSqIMEHaOF0W6zuVbk3e99H6fOneWxL36JRrWGKHp/C+U7ODzE3r178QVYXFxks1hEV3RczyabTSHrIq1WC1lxsSyLRCpJJB5DkFwajQae7xCPR0kmk8TiaVQlxvTULJ7voMZsTKuFJHs4bicQ53sehtHe6QbBFezdUfubRyABz/ORpSDURBOCkGvPcZEFEc8NvPyu6+LtpDxlYjl0PRwADMdvUC5X2ZqvYtsgSzICwZFJRMBzCDpcT8CTXFRNQlYFZF3CF5zdAur7QUf7v7uA/jRwGojvFNDPA1/2ff+vBEH4fWDc9/3fEwTh08BR3/f/kSAIHwe+w/f9j/333nvkQMH/yA+eQCdOLpejqytHKpxnbmqev/izLyGgceTIAR561wVWt5d48dLTbG1vEdZ04kmNvt48d999jrbW4fmnXqRZtZBVlXAigiT7aLqMj4kgeHg7OADb8pBEHQGN7VqdUrGBLih0xeMkPIGe/m6+8o2/4V3ve5T1YpVcPI0r14klBVQ3T225C6+jcf3KFNuVGuFEiOlbc2S7Chw6epShgWEcx6Fer9PuNNneLmFZBmE1xMbGBiFNx7VsVD3E0Nge4qkk62triK7P0WOHEESX8fFxBgfGiETTJBIJOkaL27cn6OvrpX9wH7enbjE0NMTI8D7isSS1dpXFhQVa9QZ33XUX45evk8mkyOUz+Dtd1Ne/8QSeF4idDx48yK/92q/xMz/zM1y/Po5lGSiqRE8+zxe/+Hmi4Qi3blwjFA/z0Q9/L1ulBvv2HySVStBsBqz4Cxcu0Gw2GR+/jqbLXLhwD6VSmc2NEpZj8NRTT/PRj36MeDxOrivLn/zhf+HE4aM0jDaJZJK+vj5uT03Q29tNV1cXM7cmuXxlnFAkzNm7ztOyDJ748udIpNIcO36Snp4eUtlg51utVgmFQkQiESqlDjdu3qTaqFMsFvnkD3w/ffkuHnvsMS5fvsyBAwe49+xptutVYvE4g6MjJFMp7HaLWCyGqga7S8V1vyWoN7CU1poBcTMUDoTsVm2Laq1GuVymXC4zOjpKo1NDItiZthpNHLON64HlefQOD6NHwmwurZPNZsnlggdqX/8Is7OzFAoFpm7PoOth3nrrjeBAJYr4jguijGk71OoNbt6eQg3pWKaHg8PM7CTf9ZGP8O6H3svnvvRFWpZBp9lic22dVqtGPp/n6NGjQaTjYqBVtRw7UE+4LqGwjiT5lGtFGu06qXQCSQJNV2i06tiuRTKTCEic9W1a7TqKopBIFCjkBkgmMzQaDa5PX8TzHBQVJDnQ1nq+giTdGaFdBMXf5Rp9s6i4CEhIkowsqYiej+17AcJGkJB8QJWBINfTdU0kJNotY4dumyCdzpBRwliWx+pyiZmZBdbn67gOxCJhTMND9BRsHGRZIBLXcHFB9Hf2pQquG3xv/9sKqCAIfcCfAv8G+GngUaAIdPm+7wiCcB74Rd/3HxEE4cmdX18SBEEGNoDcf48NnylE/B/6xx9mY6FIx9oiFIbCYIbunhx7R/exPL/G1Ss3aDQrCIpHrV5C11VsC8KJMCfvOkw6l0INO2hugj/9j19A1sNEs3HkGGi6gKr7KEoQtipJCo4t4DogyyqSqLGx0qBaqSMrPomwRDahk45H+foTL/GdH/0eXn/jEiND3aSyErKS4InPTWCUVWQnBb6Cg0k2laHtuiiaiiprtJodLNugUiniE/h07U4bURQJqRqyKNE2YXB0BElViEYiHBjdi+B61JpVVFVlaXmDTHaARqPG8Eg/jUYdSfbx3QiHDx/gC1/4Ap/58Z8hGo2zXl5naX6BXCb4kNa3G1SrZXLdORKpBFeuXuXggQO7Yn2AhfllBMEHweXpp59keGSQ4wcP8Oyzz7KytIBrW3iyzPlzD5DO9DK8Z4RSqcT169c5f+4s8/NzPHDhXp5+/iKjo0P4eExO3Kavb4ipmVvs27efcDiKpmk89tgXee8j7+aHv/8H6erv5T/8zm/z7DPP0G43uXDhHpLJJBPj49QbNWrbWxw6uI96tYSPTbNtkEplkBWN/YdGuPTay8iKgKpoDA/tI5IIIcsysXictc1gfI6Gczz++OOcO3+a0dFRlhdn6B0Isko9fJrNJrYTQMru7Dol19799R2YmeUHO2QfF13XaTW3g6BlKbABekIQCuz7PpqiIiFQa20Ho6Gk4TpgWA4RWcXzgv2lbds4PjiOgayI2JaAJKrEwkFGZyadptNqs7lRZmVxievjN4mHEkzcus1qucWv/8ZvMDM9x3/+/d/n3rvuYX55iZZlMDayh+NHjjI5eYOVlRXC4TBdXV3IaqBOaRsd+vr60CNhTLNFx2rSNOuEEkoQ9SaJ2J4NUrD2almtXXBhLBa45VzfwfdkOp0O4bBGOhbGsgws28TznCCsQ1IQRH+3gHqCvbub3K0r3p2DkIgoygiejyF4+JKI6oHs+CB7KIqEpKv4Imh4O382MvjBDt9zWrRabUAkEo7RG+smlcxQ2W4wP7fM9OQUzRpEIiqyouKLwaoo+H5kXDcoTX+XAvo/Kr//LeBngdidmgdUfd+/I7xaAXp3ft0LLAPsFNfazteX/n+9eTgSCopJs8Px44cZPdDHf/7cfyY0LbC5vUR3vpv3PvwIhtnij/7wD7DNNl0jI8hRj8MnjnJj4hrpzBmMYof522v0hfpZK5bxJZmWX0MSVETBRxJkBFkAz0cSFGQlSLTGsYlHojg21FslWp5DyIawI7J/7zBLc7OcOXOSuZlJwrEYouTwwIPn+foXL9LpdBDwMZwWjWoNOaRTbbaIhMJ43g42QLBxXZNavcKnf+SH+a3f+i268wVUWcF2FCYnb6GENEKazsT1a+TiKfLdWUbGRmm0G6zfuMHQ0ADLy8v4OCSTccx6A6PZ4t0Pv5PadhnBAcHx2C6WePjBdzA7NU0uE9hAC4UC12/dYHJykpMnTnD06NEgRadeZ3h4D+12k3anwcGDBylXSnQ6HfbtG2N5cT7A5SYDUuPm1gT1ZotDhw4wMrqHSCTC9ORtzp85uSsbSaYSdDodXn31Vc7fc4Zz587x2c/+611r4OrSMuFwmB/71Kd54/XX6evr48tf/iL3338BTdM4eWY/6yuLJCJ9jPR3U1zXcEWQZAXDcvAQMNurnDk5jOebuK7PdnGGSk1E13WKWzItoxN4uW2XfYeybBQnqDRmEAWZ7fpykNxzR+KiRHdAY0HCl6t46GEdSZKDMAtJQrcCZ4sg+mxtbRDujSI5DqKm0O4EWZ6mL+O7wYfbAcKJGCE1hCqHaDY6WB0LKRrkkcZUlUqlgiqJeL6KZRkk9TiKHCbsQLVaZX59ipWlZRTJR4rA3RcOsqdvD++47zg9Y/fwy//2V+i0LY4eOc7ly5f52Pd8go5jce3KVZ588kmSySjd3d27LC9PCC7nB7r3s7W1Ram0he+7JHIx0l1xFtZnkSQRRVVxHBtEF8e1kFUB17cIRyOYlh1ED7ptfE8gE49j2S1qleBhr8oKtu2BIGKLAaddlMQA5ib4u9Kj3ZcfhCKLorgToExQdAUB1/cQXQ9JErEtH0EJHFW+IASedlnHtl1kWUNUNWQ1iDO0LIuN7TVWNpfwHI98T44Tpz+I1fBZXFjh2vUJbNtH1UK7dE/gb39f/xOv/78dqCAI7wfe6/v+pwVBeAD4J8D3A6/5vj+68zX9wBO+7x8WBOEG8G7f91d2/tkscJfv+6X/j/f9EeBHANLp6Kk//LN/zuZWiWuX36Bc2mRxeQ1ND4MEguyS6k1z6NABhvuGSKtprr99nXhOQZNEbl2f4tjxs7zwzJt0Z7uYnJhm/NZtegb7kXIuXd0qoZSAEpfRlG/xyAoanqOALSDJKeKxLFMzE5QrRfSoQCgssadnmEaxja0LyCGZSnmLgUIemnDlzTWuv1XEMUKBJs2xcEUFQVExWjV0NcTevaPUG2WWFleQJI3v/I53Mj5+nVKxQkiPUW3UiUajwdO33SGXy+0E5wYgr1gsQTgSY2tzk76ePuKJFCOH9mNb4NsmEzdu8pmf/llqjQ7huM7C3DxhPUI6nWX8+jX27dtHX18ftm3zl3/5l5w6cZxWx+D21DRHjhwhl83w9NNPs2d4iJvXx3nPe97D0889xYV3nOf5Z5/l1ecvct/dF5AicVL5HoaH9tBqVBkYGCAUCnHz5i3q9Tp7RvaRSqVYW11mfX0d3/W476HzvP3mW3imSafV5PrN1/j4xz+Boih0jBrhkIpnukxPTzM3N0+j0WBjczkwKCRjaCGNcDRCMqcQiUbRojqWY9FybGyzTTykIisaFhJSyEEWQyiKho+NKPmIUoSQqoHnEwmH6dwpmjsdjyRJhJXMTrL5nauugWMHhw3fv3PZdRAdD6tj4MsiogKG2UKVwWjb1LZrhCJJYokotXqFTqdDp+UxMjKC2bF2ue71ZgdVVdB1nWqtjC0HmGbP8yhtb9FoNNBlFQmbVDqK7fts1dfoNNs06y10NUSn2cJ2ozRrBgdH9pFKxvjGE8/SahkcPXwXa6tbFItFVovLqKrK8PAgW1sbDA710jfQz8TELUqVEoomE4uGUTSFjtGgp68LTdNY2ZoLYupsA0QBJAsIEo+CODwFXxTQZA3PNZFEP5hgEPFcAVUJGgdHdgN8huchCQLuDpNI3NF0Evwbf/tSjry7I92tS56FJGpIsoAouUEoiBh0si4+juui+ELwZ+XtTASW+7cu8a7rYnTqtBsdCukuRvr3INoC07OzXLt2k2rFIp6IsDLV+l8/wguC8CvAPwAcQAfiwGPAI/wvGuG7uuL+A/cNki10UakUeeDB+5i/scJLr72GHJVwxTYNoUxXX56R4UHSkQyjg2M4psHrL7xOV3KQZsOm1ghQEdulGgPDI8zOzeHGbIaHE6S6dEJxHUUJ2DAB8TBwLrmejSwHi/GOYbG2sUWjvU0oJlFIZlB8iY3yNkdPHWVjfRnBMtE9gY0Vk+0NkYnxdUzTRTQ8EGSQZLK5JD2FApOTk3i+E2AbHJ90KsLDD7+L11+7TC6XR5D9oBuRFQ4fPszG2jqm1aLVahGNxDEMi/0HjrK1tYWIhKLqyKpCs20y0FVgaGiIesukb2CEtmNz6+YkJ0+eJp1MIUkKmUyGxcVFPM+ju7sb1/VAkHj9jbc4ceIE49ffIJVIoigS01OT3H3XOWbmZ0nlUkxO3OT5bzxNRI/zgY98jCefe4mf/MxnePvyG6iaRiaToVoLpCypdB+peIytjRWuX7nMG5de5Vd+9RdYXVkhGY/huzae3+HmxBSNpsFacZNQSOMbTz3NQ+94hI98+GPMzS2RymVxHIff/79+jwsXLnD48EFefekJKvUah44dptlpUq+WePR972N9ZYHNYhEkDUkX6HTuIFSCD6sWDRKMms2AthjWMzsRcEkURQ00m2IYRdaQZSXoHu02qqqjquqOu8XDdU1wXDZ2dL7XL7+BKPkk4zES8Qz33ns/M0tL1Ks1LMtgdGyEuZl1Dh46gu25pHN5HA9kBCRJwLZtpqYnSeczTEzeIhRSUDURyzJp1xtsri2wsryAJwaRjYFrS8C0LdrtNpn8GH293UxPTWAZTaymTbtlYxkauhYjEokRisk0GjXK5RKyIlKvVzBtC893kFSJeCKB47QxbYNarYKqy9i2TaIrTqtVR1IB0UPVglJnW+5OMEewN5REGQE/uC2IKqIoI+5etGVcMcjblEURSfCBIG9UlrSgk/QFPOxdzaYoinjON3Wduwnzkge+jI+Lj4Wzc8UP3IbB+kV12S2gvu/ju/ytfaumBalTIiD4UKtUkUWRZDLJQPcgMjJXL7/Ns389879XxnSnA905In0B+NK3HJGu+b7/nwRB+MfAkW85In2n7/vf9d9733wh5r/7nfsRfAlVV1A0jY7b4dTZu3j71mX2Hx6jN6+ixBU81cdsm7zyyit0J/eRi3VRXK4yMzfH4toiLdNgZO8ohUKBXCZLy2lhtks0mtvYeOi6h+8JyHKQkygr4As+qhRFJIQmh3EQWF5fodasoGsSffkuNrbWiaaidHdlmb11k7QWp91ycAyF8qaP5yrsGzjAs08+zz3n7mZwZAAtrBIJx3jmmecCF0c6wez0DOFQFNN0cB2fVDbG0NAQi/ML2LaNCGiquJNo06TRaNHdP4im68iyyq0bE+wZGEFWVRTBZ3V5ha1yHVnReOCd7+HgwcO0Oh1EUabW6mCaJvl8EPpgWRYry0X6BwaQVY12y6B/JE+9UqVeqxAK6Vy7Os76+jrvef/7ufjKy8zcukE8meG+Bx9mo7RNJpWgp5Cju2uY2dkpItEQlmXQ3ZcjrGsszs5y7NB+2p0mGxtVlpYWeeXlFzFNk/37j7P/4DFi0TRvX73C/NICr7z5Eg8++BAf/s6PYRgmsWSeiYkJTpw4huD7fPWrf83hfWOsrq1x6PhhBFnAbNQQfI+piWucPXsXpVqbWrWNaQYcKtv2kUSFUnUreHD09HDgwAE2NzZ48YWX6erq4od/+EeD5KtQQHKUJRVJkjGNQJQuSuxesI12h1anjeCDLinUG9ssrywSioTZM3KASq1JX6FAZbvE1uY6outjuRZdfT1E40kaponjuaQTcTRNQZZl2u0mpZKFrqsoqsDW1iaRSAjTMFhZmCEeiSKHdG7OLLK+vk6z2eSDH3qUF198EdOvEY1pbJc3aNQqJCJhbAsG+w9imX7AmJI8VlaWcByLSnWbZqNKrVFHVWVcXKr1GpGwgi94Oy6mIFRZ0jwQfVycAH2hOAhI6LqO43iIogT46FoEJA/HMXAFeVfgfiegA3a6TMFHkyV8P5A04Qd7R98XEOVv1h5JkgKbJ+waNGCHsCmoeL6DIDp4qgo7BgtBlkAQ0BDxXB/b3hHO73SidzrewJSxcxwUAwidKCng+0getOsNJA++9oe3/l8toCMEMqY0cAX4Xt/3TUEQdOC/AieAMvBx3/fn/nvvW+hJ+HffO4jTtHFtB9M2SGTiNOptfAGaRg3RM8kMpjl617EgiXxtg3LZICJFSafThKIaStTGEwUM30YSROy2gSt6hJXgCWrYHpXSNp4rIYkBMzsUDgiAEjKiK6ErURRNplipslXexuh0SEYj6BGRhtGgkE8juw6dLQfT6uDZAmZLRhKidComh0YPsba4Siqf5NrETRwbxsb2091dYHCoB12NcPGVV3nxhYvs3bufar2C67ocPngIESiXtkknI2QyWaanp+nvH6RYqdKxLQrdPXTnCtCxiSdSzExNYLY7lGttJEVF1SNsbpVIZTOoWgg5FGNsbIxkMkkulwsAXlIMRAFND5NKpREUj0uXLjE6PMTVK28zMDDA8uIS9ZZJSFPpzSf56hNf48jxE5y7+16+9Lm/4t7zpzkwNsr4+GUKXVmOHD2E6MdZWloKAGg73e7owZNsbGywvLzI8y8+T76nh317DrG0tIyuqbzx+kU2ynX279/PyMgIExMTDA6MceG+eyiXikTDYVzbot1xcXFJZJO0Ok0uvfQKH/7Qo3zly1/AcX2On76LdrvJ4SNBHqUih2nUOzQqJURZ4pVLr1Kt1UjEs7zjHQ8zOroXy7Lo7uolHg9SijodA00NEdKDw4SqBmueVruJ7/q4ApS3iqi+yNU3LxFPRPERqTcMDh46STit47sunmWzNDdLttCHIIno4SjReIJarUY6m0BRJGLxKLOzs3Tleuh0Oti2TafTAcDybQTXpry9TatjUbdFxvaMMj01SW27SLlUQg9bpDJhtqvbdHf10jYqOLZPo24RjyUD/3tIY3NznXw+T7NVp1kt43g2tVoNSZWQFIlatfwtEYy3EEWRZHLnsCMG+lfT6yAIAroeRlV3sMGigyhpeNgg+XjSt3SMOzpawfNB8BDxCSzuKsIOGO7OulGRvmmjFIQAXwzfRHQASAjgy4gSINjYorjDkZfYUR8hIeC5PqIo73Se7BbQO8BGUejg7+xbBUFCVkNBsRdBlRUE3+e/ffb5b08hfSob8c+dH0QwXMJhHdszmFqaIaQl0WQN3/dpmh3iyRh7D4ySSCWwLINQViaZ1fAVE98HVzJRFR3RC2G0HOZmlyiXqjQbwahgWYEn3XVEXEdEFAVS6RghPUY4ohJPhMnl0gheMM5UajUarUC6IYdMOq0trE6dYwcPY5s6yzNLlNfLKHKUoydOECLNtTcnkC0BVRPoiA6iImPh4Usy9XaLhCQQVSIc2XeITCaFbdh8/aknkdUIyViSqByhYlc4dPBwIB+p1ZAcl3Q6zeuvv4WuhYNAj+48gutRLVdw8fFlkbGRAziei2Eb1Op1RD9KJBwjlysE+OGr44ihGIePHkMPh2jUW0RiUVZWVqhWq+QLGRqNGlbZIpYKo8c0vvr4X3P89H7q9Q1Onz5IJKRwYN9+rIrAymqRcLTAV776Eufuux/JdvmTP/wD/vHP/CxfefoZ/uH3fZzf/s3foFndZt/hA/zN40/wXR/7CEtLi6wsr3Po4HEQBU6dOkW1WkFRJZYXS6TTSfSQupNupJHqynH9+nWG94xQqVXJJgpUa2VCmoznmjhWh66uLI1GEVUBTVaJx9OMX73JdsVBCyeYXZ7mrqMniERilCsVunp7GRgYIKzpRKNRPM8NPvBC8GcfaIcD+Uy91sIyTG7fmGRpcZHJq29y/zsepN5ocfrsWbZKJURPIxwNEBTzc8soYohENk48k0IPJwnFEmiagyoHNkVVUajvYH11XadWqwVqAC+gtvb09qOFIlRKVZaXF1langfBJhTS6BiBXXhhbp5GtcFWcZ1yrUQ4LlMsbgbIZy3ChQv3UqtXSCRibFWKO0A9i3BY30EFB5d0WZYDKqbrYhrt4GBY3KDWrINjkst34YsC0XSIjY1VqpVWMHl0OsHRxxN3k+B9wds5Whl4roAoCQiijSUEhVSTZER8JFHElT0kUQEEREHGR93t/BVFQlVlZMtFkgQS8RgSge3T9jsIkoDpuvjIoAi4Anj44Hh4dvDXtg+4INg+jmDi+wLSDr3TEYP/jiQHBV0QBB77pRe/PQtoOhvxj55IE9UiZLJJUqkE+44eoFZtU96uc/3GFUKpDL39XVh2C0X3CYU1evfmsP0KouoGYlhHRJJUrrx5mxvXpllfbWMaIImQSkXQNIVUMkwmnUeRA/zEwuIcoqBj2yaJRIzungLpZIKevl62toP0m45p4GMTjUrUtjcY6OthdGSMV56/yKG9hxB8nRu3ppif3iQdKhBVEoH2VLBwfA9PFgMZhiQi22BstxguDJBMxLk1M8mJ02e4dmMCXY+STeSolFcIhULU63V6e3sJSQrz8/Ooqk67bRCNxNluFsklUoiijB6Nkc3n6NTbgEDbcEimUqQyPViWhSjIJBIpVFXlxsQtCj09NJptHMfj0IkLRGMhVM2n1a6hqCLbxWUEqUMipSJJJgU1SigUoVwymZ5eo7TVQgppHD1xkv/2ub/m4IEz7D+4H6NRZeL6NUb2H0GORJm4cQXHNJiZuM3g6BAbm0WisTBXrrzNh7/zuyjk+9BCOuPjV7n46ss89NBDxGLBIWhsbB/4gci5XmuTLaT5xpN/w9j+ESJRlc2NVWqVdY4fPUBYl3CEICRlc22TPUMHWFxYoX/gJJ6nI2tRWkYDq9lmYX6RlbV1PvkDP0Q0GkVXA3eZogQ4C00LuqxINNB8mqZJo9bkT/7oj7l69SrRUJhUTKVQKLBndC/JdIZr166xtVllaKQb17URBImpm1McP32CSDLOgUMnCMVSSFKHRDTgK+mahmk5VKtVfD8Yu9vtdvDz4nn4iFiOR61cpVKpkEiGQbBpNGuM37zF4vwC5WKJ4eFhDu0fxfFtDLtOs1XnzctXMdsdZEWgr68LSfbYKG7h+z6G0WZ1bSVACScTqKqKYRh0OsFBK6yHaHXa5Lvz5HIZHKvNrVtTVMoN0qkY4KHpCr19fawXN6jUyvi2gie4aOGg2bFdG12WEJDxfQ9RcrBxd7ntwk7H6ov2zrgf7FZ9gd0jkywHX6P4EqIYrAJCqkYsFN7pel0EUcX1BAzXwL1TEAURXAHb97A8f6eAurhiEFIi8M2dK0IApgsCR+Dzn/2fL6B/LwKV8TySyQSu7zGxcAtlVeT25iyOK9Dd20PvgR6kUBw5JhCPxOjqiyOIHr5aQ9eCNGkBlbWZBi+/cAldTtFfGGWkO0zDaOLYApFIGM+3yMQCqNX8/A0kSWL/2AACKpsb2zg2bK81aNYbtFotRFnE8x2qlSKSryPaOpIQZ3Vlm65cnnseuJeF+RW2S5vYokvP2ACCKWM0HDqWi1UvI2syoq4ieiaeJOB2fOy2Ta3VpN5qcPrYQaKaxNlDh3jhhVfplFvoYR8xHEZTFVzHpOk4ZLryrK2tEY6GETWf0f4+7IaJIkfYKJWIJhPousr66ibhUJz1xTU2i2VEUSQSiYHg0W63GR3ewxtvvIHjORw7fpyZ2eep1YvEkyonTx4nFkuQTar4lobgqdy8MsGLEzcZHBlmYWkD11cxDHj43Q9S77jISoLF1Q3uf/hBVhbaTC/Ns9Wo8sEPfQRVlWnWDLLZLNlsnkg0zu2piSArtdNheXmZh9/5EEuLcywtzPOb//7X+eKXv8Tf/M3XqJSbOxddkXvvPcrtmbe5654RtBCksz4HDg1SLqqU1qZIRlK4jsjK/Apra1V8O0ku18d2uY6qeUy+PU62kOfSS68QicS4cP99tNttwuEwjUaDfD4PO1hjx3FQNRHHCa7ntWqbP/qDP2JrazMQ0bsOLVvg9vw8a8VtKpUavd09OK5NOpUjlUrw+huvkctlCIX1XbzJ5kaR0dEeHCcoJBsbG8Tiyd10+GazGeCWo5HADmrbeASHDk1XabbKRCI6PjYHDh4GQSKVSZOMx4jHYyyvLdKxmiwsLCMKwcdaFGF1bQHbbZJKpdja2sKyDGIRiWgsgit5eF4bVfeRFAlRNmk7FnJYYrU4z1ppAUXysX2Lgf5uegt5isVNLo9fplIpkUynSMTiyGIQjNM2W5iuiWM5tBoOsiTs7Bs9BMEBJej8PMFnh6uBqu6M6xJ4UrB7lRURw7IRBB9b1FB3ZGeW2aHdNJFVAV8W8PwWgqQBXqCOEEVkYUcKJQrBw8z3USQBXxCDHa4QJDjJ+AjijnTKuwOo+59//b3oQPPZqP/gO/cTLaQYGu1FEDxmV2ZBUFAjGkpYJqyqROIqmWwUUbMRJB8tZOG5DkbT483Xb7Fy28QyXSR0dCWEbbkIYR/XEfCxUVQBTQFR8olEFVLJDFevXiMejyOgYxkC26UmTsckFFYJx3WicT3AvLZ3xNWSy8c/8QFuXZvAcKHW6mC0fVzTQZbDYPi4LRvXETDLHZAEpJCCLweCbNd18TomnXYTLQJDe3qJamFmrs5htj0+9B0fx/ddrl8fx3FNhkf6qdcDR5OuqyiKRLmyTT4fpSvZS7tuokeyzC2tEovE8B2fg/sPMNjXz0alQr1eJxZL0NvTFwjzV2fQIzKqbmN5HfA77N8/iqJoXB+fo7TVoZAZoFG38FyV3t5RFtYrLCzO0tOdYWpqhh/4/h9iYmqaVruGquq06iYHjx5DEF2mJq/TaRnMzy5w5MQBQqrG9K0pDh49xttXL3P02GFu3brJ+NUbfPpTP8Hzzz3Nux55mK997W92QGM27373u3j62cd51yMPMjFxnXvfe4JITMKmztb2EtXNFmbDJK5lkGyV1bl1Ytkxstl+rt+Y5tiJE9y8eZPK9ib33/8gnbbF7Ow8lmGi62EK3V1cGb9OvV7nez/+SUZHRwmFNWRZxDA66KEgzcu2RL7nu/8h1a0tega6kJTgii5IoKkqsUgcuxNExpl2E12N7VyIPWrFIqFYFNsXOH7yHr7jI9+DJJnoioKPjSyBj4RpmkEavBz4uJudNoZhICsagqRQq1RotRr4WNyauEa9XsHxJPSQjOeYLC8usLG+yOLKIq1OnXPn7kbVYxw9fIBsNk1pe5PXXnslKI7tNvl8lnK5TKvdxJUC+dAdKqaiKKCDaZrBKK4ryB64rkCj3gTZRZZFEvE86USa8uY2S0srNJtNZFmmq7eLUCRQMFiGi20FhgEfC9+2sCwH2/IRBYVQKEKQ5x4gRSQ56BplWcbz3Z0uVAZZQpRAESUkcec0Jfv4goek6YiSirxTQAVJQhUlFE3EEQLtqOfYCLaNJ8pYlgN+0HFqanBQCtKfgofNn//CC9+eI3wiqvqnz/Vhyh6m32LvvmES+QSSpoMioEUVEppCOhNDDYnBpVBwEKQ2uPDmq5Ncevk6MXkPrusS0aIIfoCbUFMS0Wgc1zWp1opYjonttAlHJXxPIJFIs7g4R6vp4lgKnqPh1EwMq4WkicQTOogeZqON7To88u53MLdwA7cj0TBtam0Lz5URHIGwHsFqtvHaNr4PES/F1vYWruzhyx6e5KOqEvfefY7+wTSoFkImhIbKYHyArZUyl6/cZGt+hVOnTjIw2EO702Bubp1yuUw4rNHT2wV4RDWJL//lYwz276fWdLEdaLdsFEnkxLEjREJhDCeAiS0vrzIyvIdEIkF+QCCckDHdIpJiI5lhpqdvs7FWo9PUwE2y5+C9WI5J02zgCz4jPQPMTk8hOAKH9h+jtFlnvrzMnpFBnn7qOR5+x7txpTCqBv193fzmr/0695y/h5ZVIZ/O4Zkuo/sP8dobF8lkU/T0dPPUk8/y0Y98gmajSrlSotmsEwqFmJx7C1kR+Nh3vxc97CFIBhWpSr1VwvKqeL6JZmRpNy1Guw6zMl1m4socuf59HDp8ijcvX2V1a5mRkSFKa6u0223uvec+totVbNtmcvI2zVYHQQ6SfdLxbt73vvewZ3R458PkIysetmPw+7/3xwwPHubV557H9AyanSoeLkgEo7jjo0gqsXCEplkhpCVpNBog2MQUhVK1giuISEqC933go5y76zh4NpouIQoepuXusn3u2FJtL/h7tuNhuz6V7SLz8/NIsodlB5bg1dU1ZEmkkEshCC6vvf4yLaNFs9NkbHQviDq22WFxcZ5sNs3JUycYGEizsrLCE098jaPHDtPpdKiZgeJAUZRdN5Ytm4QiOtFYDMNsI7vB0cXGQdQDdIZthHA6NrlEBlVQgkSsapX14jqtVhNEgWgkRigUIxIJ4bgd8ATsjoPZsjFaJsuLKzh2IIQKhwPbZziZDAJPVBlph4EkhYLjk+fYgT9eEpBUEV9yESQNUVJRJfCloANVJBlJ9VDCOpIuIXguCj5t08M07d2c0VBYQZJEZEXcsXQK/NnPP/vtWUCjEcU/eqqLrj3d5EaSSKoPGii6hqqLxNM66XCEaEwLdGmCiWG28FF4/aUbjF9aJBnOkUildlgqMlo4RCikI7jBeG87FpVKEfwWluvRMQw6lkk8HiediSBIMrduTtPaspAFPTg0uT6yYpNIK8iCzDsefifXblxnu1LB6/gYhoHnS0iKCqIMjoLgg+QJtBptZMsFQWGtXEMM26S7YgzuzTAwNIDvu3SMFpMTU2xvb3PXmXPcdeYMuqoHYmLPwzI7WGaHcC6OJqtYhoknOXiqja6o5GNdTLw1y2/+qz/hwN7DKFaETCqN7xokkmFqjoko2bz70fsYGOxhu1wmmQ5R3KjwV3/6OAszRYb7BiiXq2TSeXQ9SiyaQA4FhjNZVtncLNJs1oknUliOwL69B7k1eZtjp05TKpUDB4qiocciHD9yhL/6y/9KSJWQRYHrV8e5+8J9xGIZUqksxc0tHM9heHQYX3T44z/5Ex599AKO36ZrT5auvjTRLpG1zSVMu4rtWUFIim+SjvUS8goIdpjXX7jM4MBeRD9NJp2n3Wlwe3qWw4ePcOnS6+CLdHd3s7Jwm1w+TzQeIxqNUq7W2djYRBRFEomA/Fmvtcnlctx99z2EQiFi4TCqJvOlL3yZ555+iUMHTnLx0jPEkzEEERB3ELyuhdFuIUsSoZAGloSoBSLztmnQ152huLVNvdEBSeLhh97FI4+8BwQH1zPIZlO4lkOj3cIwbUDE8T00UcW2TWLxCJZlsTS/gC/6NDtlbk/dYKu8gaYEbHPHNYlGw2B6tDptEtk0Di6SrmK1G6yvr7NdKWPaLo3qOo7jcOrUGY4fP8niwjIra8v4noWsCPh+h04zCA3xBAdF1bFdcK0OclgnnI6B72EYBq4loagqqqruHKZcRMEnm44j4GLbJp6k7OA5mjiOg++KJKIxQqEIIhKu5WDYAqqs4tkO09OzVGotXMsNaKEdC9EHV1B3sj53Uuv94MCkR3QyuRS+75PNZ5AVEUUREEQwBStIZ5IB0cUXfSIhbSfMRAhCl5XAeSbJPoIY2EU//0sXvz0LaCyu+Y9813Fi+RB6XsATHLRwDE1TCCckEkmVtB4iElWRFTBNA9M0uTG+wgtP3KA3M4wiO8i6j6briIpMJBIjnkgTQkQUFYrFIt3dBcr1TRqtJpVKedeXLKpKkF4eiTA3McPGdBkBDQEVWXHJ5mKcvfc0V96+gWm4NFtGIM3wRSzbR1F0FFkDLxgPHNMBy6FUKhGJRVETYdQ4JHIRtJBFNBzB8yASiVHoHkBVdb78xS/QbNX4Zz/3U2A28JxAxB2PxgARs91BCas4qoutmYiuj+iLZJPdLNxY49/98n9hf/w4S0vz9PTHCEUEfvif/ShDw31cfesNurIZPNfm83/2BKl4N4XkPnAiRJKBLrZU2t7JBVAwTZPx8es7shQRSQ1jOS59/XuYmJgmEk2gR3QkSWH//v088fUn+dSnf5gvf/nLHD54gK2NTVzLZG2jwtGjRxkYHKTaqDN9Y5L7H76XulnEDxsUy+vc+45RtIiK4TcoN0vU7GVkQUVyI4SFNKlIN64hUinavPniDAfHTtM70Isih2i33B0fv821q29x6NARGo0G8/PznDp1ijdffwXbtskXChS6AxTwjRs3CIUiWGbgeR8eHSOTztHd3cfY6D50zUXTQvzTn/55uvMDTN2eJ5aQsRyTthF0rrsyHd/bYdarVKt1coU8HcOg2qijyS6JRJJavUmt0eGee+7l7Jm7OXBwDF1XcFwDVZJ3H+amaeP6AtLOEcl2TGq1Co7VoVwr02hX6OnNMn7jGjeuvY2uqziuiSD4OC2fjtkC3UdQoNyokUt0I8sijXaDRDJKIqYhSUHe5vz8IoVCgZGhPeRzGVYWF2g26kH6vtfEclo0m01UNUxIknAFqHbqJONRouEIoUiYlmlQazVxRYJcB1nF7BgIgrBzLGIXRGdZFrbr0aw3sAwTQZCI6CH0aAxV1rA6JrZloag6zXqLtaV1NtfLOJaH4EooooZhOCiyhm+7we5SkEASg5FeNAlu8EEgsytYhCI66XSSZDpBd183ekgjHNYxrRaNRpWmbAWp/kqghRVFka/+2mvfngU0kQ353/Mz9+BpHcQIKLpCJBIjGtIJhQRSGR1dFND0YGdRr5lUyk2+9BevExK7ycezeH4NNBdJA0kO5A2hcIKwKKFpGpKooaohDMfCd+1ArmN2WFtbpWPYeJJPSFeIKD5xPcbVy9NsbTqcOLGfwaFuFtZWaNQ7GC0Hy/AJR0O0Gwa1aodYOImARKE/Q6VZp1WvkYtEOXv+DLVGnaZd540br2O5Fv09g6iyQrvZRHA8DGx0Lcq583ez/8Ae3nj7Re4+PoZpGEHqt+3w2pOXefjhh/FlD0NsIyV8DK+Np4l4gkg6lMZq2Tz1Z69wz/l76enOEdJkbKlJPNzFH/zuF9habNKV70WXktRqNXL5NJ5n0dUzjO/7u6zv6elp6vU6rVYLVdGp15tUa20kWadvYJgb1ydJZ/K0rQaqqrO2usH73vc+YuE4Tz75BMeOH2Z6ZgLTNDh4/DAvvvIiH/6uD1LoStE3FCGdi+MqFqvFOTzJodFax7EcZFEhpIYYKxynVbd56+U57j33Hp786ot0DR2hUMhx++YNtsslHnrnh/ja177GAw/cz/LKPIeP7GNu6jaWZdBqtWi1GwHGwrOI7YQzJ9MpbNsM4s+2thgb3QfAzNISpWKFhx8KTAiFbAzTcPnZf/LP6enqplarYTkd9HCEtmHQMS1sy8X3PBLRCHpIxbUdmu3GzjFEJJFIYLXreB5cv3GLfQcOs7a2wT33XOBHf/SHUFQRRRVo1RsYlhOoPHwBUVZQdgTftm2ytLTI+NVXuXbzGqfPnqJt1FhZW+N7vucf8Od//mckkhEq1RIz1xZxBYOBfVlQHSRNR3BVHNcCPHzPpW20EEUxmJo8h3w+jyoKLC0s025ZfOD9HyIcinJl4g1iURXL6GAYFiICtu/StjpIvocqyUiKiO066NEI4ViUcDjA1FSqNURRRAuFd/SeQUSeKIpo0XBgY1U1JMGnVqtRb7ap1epICMQi8d3GwnUEQEJXVDo1k8XFVeZuL+JaPrqg4djgISDKGq4joKtg23awMxV8JHHH4y4IeALIqoIrBFgWWfHJ5VMMHRhCURSqzRqyKiEqMs/90ZVvzwKa7437H/2pIwghDzkio4VCpOIhwnqIWEQjmdQRJRdJdrAsh1rZ59lnXkHojBDTM2RjCTzboCUY+HRwxRrtjokih1FkAU1TUOQwqhIDX8Z1LBQJZqen6LRqiKKK4dgYnQa6bBNLykhCgvXVOufP3cvV8cu0DB+jZWK2HSRBJhSOYRku5a0Koh8imcxw+r4D2IrP4vw8za0iffkksiZTbpUZOjCGKAt87WtPggc9hSRRXUPXE7RbNk3DIZ1Lcf6ewyR1l0OHD7CyNI/ge5grEtfHx3nw4fuQIrBRXyLcHaYlu7Rsk7ASIyyFUH0VLI3iXI2B7gHmr63yp3/0l8S0bkQUYrEYLatJLJ4mm80SiWq06iapVIpEIrGrE6w1m2hakG60uVmkVm7Rahv0D44yM71AuVpjdGyAkZERlhZX8DwYHOvmjTdfZWCwwMVLz/J/U/ffQXal6Xkn+Pu+7/hzvUkPJDyqCijT3VXVvtlskk02TZMtDUmNRFGGoltS5IijmaFmRyuFNkKr1UoraZcyw9CSol02vRNFsr2tLu8LVfBA+sybef3x5/v2j5OFpiY0I7I3FNE6EQgkLhJA4t6b73m/932e3/Nt3/7NvPuDj1Nv+UgnZzI7YFZUeeCF0RRl1ektt9foNhbJDuETv/cpXnziOo+/470sLV9CSJfu4hJSVXnzrXqD3/md3+E7PvzfMJlMELIi/3Q6LXZ3K1zg1auv85a3PozWJa+//BwLS4v4YYjruqR5ShzH3Lp1m+mxBrO9vMx0EnH+3GXe9rbHOLHQ5+hozE/9v/4lRR5jWQKUjbKreI0i15QlFEWO73p4TgVazsqMw8PDY1kOOAowgms3bvL9P/gjfOmJp1hZWeFr3v9uTq6vEIQ2WZyR5jl5WZHaC6OxRIGU1SmrKAo6HUVapNzZuMPm1m16iwscHUX0eh1sR/LEE19gsDlmlgwIuykZEUlRojEEXoBne0SzGC0FWZ4gJcfSIjBljNE2jgqgUGxv7/Ou9z+OpQoG+7u4tsOs0BhlyHWOThKUEAz3B9Trdfr9PsYYprMx9WaTdrdNVhbEacQ0Tu91o41Gg2kaVXNNowl9F2M0pbFQKIqiZLB/wHgwoigK2u02K2urzOdz8kSDMQR2ALlh9+YOzzx3hSIHZTmURiJLgW3blEVVy2xRcUeRx84n20Jb2bE432DZElOmZGXOysklas0A6Uqe+M3X/+ssoP2TdfOX/t5jOK7BD6FeD3FCn8AOaNfqhJ6FlAmpMYzGOS8+dYfZMEGUHVwVooxGmRzth9RqDbRJSIsD0uKAJDd4voNteTh2gMkUjqyhU8kbr7xGlsbMkyHusWMiyTOcrk+rGXLh9Hmee/oVdKY4ijXpLEEWGlVWeedWCNK3eePVTU4snOcjf/lDxERkaYSKCtYXWnzyU5/ljesbJEWJ63t81/d9hCg55Nb1V4nnEbPYQSmH5YV1ijQFUXDfpRUWWw1We21GkwOk8hlsRHzmt5/hR37we4mLm+xkE5xll7mMiY1FkUtqnoudF3zqF59hetPn9dfuUGs2cDwbZRdonWHyCqTsuBZCGLSx6NTqVVqpbyMchV+vceHC/Wxt7uC6AW9ceYGi0IT1Ntev3UJaNrPhmFrfoxAxJy+u8O73v43V9UX8mmKeD4mTCVoZhBZk8xJRSEw5ZHnhNDW7Rz5zuH1jm5//6d/n/LlLXLz4MPM4I/Ab7O7u88DlS0RxwgMPXOaVK6/geR6LvT7xPMLoavExjyNeeuVl1tbWWFtfI41ihsNDXn3lZb7hG76Bn/nZf8PFixc5deoUSZIQzeZsb2/T7XWQEiaTCWVp8+JLr1Jr9JBS8WM/9je5ee0Wv/dbv0MpM5zQQgqfWtjEcgKStKBb61eE+Omo6moshVQa17LZ299hPDxCWIb8uGA/9uh7mE0zJsN9fvhv/SiLSz2MLhhHY9IooV5rUuaQRjGz+YT5fIzyNTfvXuczn/wED7/lAT79+T9i/fRJHnroEdbXzlIUml/4+V9icXGZwc4+r199jkfedYqZnkItoClEZW0swbZdhG1R6srxVJGHdAU6Lk1FJDOVgcBTDkLYnDt7gf2Dbe7e3uDE+gq2L9EiQ9mSYp5Xs8S0QGsQZUa30yIMXMZHh7iOg9Pr43oeeanJCg15TGk0XuCihQYpMKaSNtWCEJMXlEJQ8wOEkexv7TGdTklSjTAc0800jrGBAmUJJuMZu7sDbry8RxQVmNLGdUJkViKtiuhkLFCOjTq2lmI00kDh6D9Bh6o88/vX/+wwka8KHaiQAi+wqTVsao3qLqEsjecrHFtgWwYtBHmkKQvY2zmgHfbwbAvLMjiWg1QWcZ4hydClxlM1AtcmyiekaURRRBRJih9YjGaHbN0eUKKZzIfMZjEq1whh8AKPuzc2+Mi3fwMvvvgiRS6ZDKdYNZfEREjHIZmlWGVAkRQoNPfdf5q1xRWSdISxDY5taPebbB8dcDSb4NXqWNownU75O//9v+Yn/+53c/HSg8TpFFu1KIqS62/cwZSayfQI+UbKwtvfxjzLMEoSZ3NOnj7BiVN7/Mqv/CYf+fNfg51pxNzg1YIqg0ZCWkyxXYdIRoxMynd85Ov5qX/1c1x+6Bzx2MH1umAKRuMp9VrzONTOYTo5wm7U2b27S7PdpN1a4MpLr9FqNdi8fZ3FXp9bd26Rizn4RzQ6Tb7pe97J/Q9dwK/bJGVEbGZMortMp4YoqpinDZZp1FoY1yY3EA8znnzqGhfPLfAz//YX+IG//kNYKmA6i1G2x6XTl9jYuMO5c+doNBooq9oOdzodXn7hRVxpEYYhGFheXuaTn/4U/X6fy5cv89kvfJaHLz/ItWvXeOCBB7h9+zYXLlzg5MmTjMfjisq+tkazXmN7e5s0jYmiKZs7RywvLTKZRnT7a8xmE7IsIc1ijNLk84xGUCPPDHmZ0m51sKRkOBrheQ6tVoOdnW0837qXCKmUIs3je4Lt6XSMpQLmcSViz01GM/QYHB5iH2/gsySlWasznByxvXObV668wPKJBd7/gXfy4isvcPrMCqiUF1/9Ip9/+nMsdJf4gR/+Pn7hZ36R4XjEt37427m++TS1ToM5GYUQaFXBibUsKfMMpRTNZp0oijBGoiwQUiOQlKXGsitSFcALrz5Pq11pZp966kskeczKiUVaXgMZJIDE9jm2QaeUSnP97l3yJOXi+QsU84hoPEUoi6WlJWyvwhzOommVk1SW2K5CuS5pkVMmKbZdLYws26J/cpU+YAlJNJ+zv7PLbDIFUcPzLFzfpqmahI06ly7dz9HhhJs3trhzexutJAaFZTnkeYnSCiMkllRfjgDNcwTHTinxlZfBr4oOdPlsw/yffurdBKGNH1TSgtDzqXkNrLKk5rskRcZkJnj5hVvMByBLi3pgY46xVbbrEM3mFLmg2ViiFtYrEEQ+YB4NKMoUALsZ49oenmqytbnP7//Ol7C1RTts43oOKoC3vesit25sks0Kjg5mNMIWhgg3dEnSnDfeuEsol/B8SakjLl5e59G3P4ztB5Ra4/s+tpA8+fTzTEczdjcnCF0BGcbTCRt7N/jeH/1unAY4osrfadTrlFnB6GjMa89f513vfozzF08yGNyl1wop5w6zuxZf+MSXePyxt7G22iWxp5R+jOhI4iJhpEcoy9D1z/LsZ27wz3/8N/imr38njzx4no/+xu/S6i7Qay6SHW990zQltH3yosALPWbRnEajwa2dqzSaIZ1Ogw983XsJ12p0F5oYL8VYCUYV5BlQAtrgWC4LYRtH+gjtsn37iN/9rd9n625KI2jTbCxwcuUcSVnl8bz3fV/Dr/3mb3Dh/H2U8SG//bu/x//0k/8Xrl+7xcpyJbp/4aUXecc738VoNKHVarC3s1slZNbrbG3dZW1tjXkcVVvmNOXd73s3N69dx7Ik0bza/C4utHj++efp9Xq0Wi2mwyH7B1UY3ng8JAxDwmYLqRzu3tllNo9odxd5z7vewd/7X/4uKydO0ltahKyC8K6unSSsN5gOh4RhlQvf7XaZz+ccDLYRujrOjo4OycqkAgnrglOnzoFRZFnGX/nBv4bj2UyHh5W4O0tJsylpMmV4eECkU2xbEtZcXFsyOIwpy5zeYoOtvRsMJ4eMkn0s45GNJV/69NP84I/+KNqkHE3usn24wVykWFQFsyyroDlMWWHqkgxLVflBWT6/RyyyLIssS7C8EIx9DPPQyNyiVqvhugFpkjOfzxlMNqrY7JUVwjCkKKd/YnZZkZZEPOfw4AjX9VhaWmKcVTSmXqfF4mIf13U5SsZkaPKiwJYKW0g83ycpCpIsx/E8mrVqe17mBZaUeITs7W8RxxE7O7tYyqNWbwICx64RzVPSKOLgYMBsMOf667cQBTh+A6VsknmCEpWKQSkbjKi88ZbFxo29/1o7UE1Q00iZ43nNKvzJdnAt+x5NBSlJk5w3rtykIRcInYC9aIDv2oRhiDA+vm0xS1JMnmEyTT1ooQwoD/JyUj1pRuJKG0saLpxZ56//1T7PPXmT4f6ErCh4/9e+l6vXXyOa5ySzFKUE2sTYBhZ6deq9JnMds38tRqU2ypJIVdBb8oliUKWiLAr8WkCSxdSbTW69scv64jqtRpt2vUV/ocNv/+rv891//SNkIsINFcqpOpf+Sp8PdPts7G6wnHewfQ+NxvYEfl3SX+5y4/YWD7zlImKumcYR870hlq8IGnXScsbeeJPHv/4Sa2/7HM9ce41nnnmev/8P/gc2t2/zyT96nkfe8hA3b14jyafsjPfQynB4NKTba7Fyos6f//DXc/7CGRzHQpuc1MmYiwHZvJqhKccm0D2W2st4IoBE8NP/5Gd46cXX2Nk+4vzZB3GtGt3eKr3uAjdv3uXsqTqlrdARPPHME1y4eJowtPBbK7zvfe9nOBwSpxGtVovr16/T7/eZzWbV7LNRZ3l5mdl0ytUrr3P+vnPcvn2bh9/yCI7n8vGPf5y19TUajQaDwT6NRoODgwOyJEECs8kES0oM5fFm2KLf7xIEAdduXOfgcIznN1haXMGr1ajVAooiYzIZMZ7FLLQXsW2b/b0t/NmQIivJ8oQsraQ19XqVOuooiyxPKujwKMV2bIpSE8dzslQzGo0otebw8ADfcznYP8KUCVEy5PnnvwA6xWkGNFt1bt09YH9nmxOnz3Pu7AX++ON/xNd+w/v44pOfp78Y4jo2s9GIb/ymr+fK1ee4cPEcN67f4j1f914+8cXP4PgWpgRhRBWqJnKK0uD7fkVgNxpLueQmw7KqguL7PoUoEUiUJSv2myqIswlaG2pei63bW6ydPoHWmr2dXSxL0u40aHc7FMdM1dJorNCht7pMMk8oS02r3mA0GpGnGZu372CMYenEEm7gox2DpRTzeEZepBRJTqvZREpJmkSVQ8txCZstlLJo06RpQk6dX6csBbdubrK9tUstzPH9kN5Cn5Onl4knEY+9/TLzScStrV1efvFVclFBTCzjwDGeryxKkPZXVru+GjrQtftq5n/+lfdgWyGOHSKFRcN3qLl1VGkweURMwac++SL//ref4qHTD3H25Fl2p7exREnDreEoDykssiwnSxTdzgqe22B5aY3B8CZCzUEUpElEveGRFTGj0YR5XFAWPpaoEdYDbmxdYXAwJIkKdFpidI5jlbiFi9stwRNceuzt/MEvPkkyTpBofuR//EsYb0bg9RkeTHC8BrYrefbp57CESzww3HzlBp1Wl96JLl49YG+2zVG0xTs/+CiOK7EtQeCEeG6TUBZsDPZACi6cOc1ksEkn6OJETe6+MWCwl9I56bO+3MX14TDaRniGqWeTqxk5JSazadZP8v/42z8DdxdIZwOEnVCW0O01eOjhiyyvdFm+r4/XDpiZCYaYwLGYo/E8BwDHsehafbqtRVQZohOLp7/0LJ/69Ce4e2UDpwxY751hN4PJdE6hBb2FVZZW1zjc3efS5fsZjUY0Wg2eeeoZPvSN30Q6S9BJxtryCp95/gmWVlboLyyxsLCEZzk888xzXLjvIo1mC6VsWo06SkpGh0dsbGywenKF4bDarI8mY27cuIGwBPdfuEir1eDG9Wukacq506vs7e3x5JNP8vjjj3O0v4sxx9G/eYrjWkjHJo5zBkcTxpM5UQrvesdj/M5v/gb7gzHnLj6EJyVHoyP8WghobKtK17QtH6UshFDVgjNOENIQzaZoNLP5iDSLCIMaZSmQlsP3/+j3E6cR0pR4bp3peEBpZhTlIUU2Z3c6JIpmSAqENmzsv4bjhdgqoLvYRSjDfOuIWze3KHLFaDjnwXddQKJYWV5nc3ePxkKXXlvy/PPPopSg1DnKz8jzEtvyAAtL2Rij0Lo4bhIqhmqpKwiIUjaIAmlJFC6mcBG5S6PeZBrvk+cphhzPczHCYh5NSYqYZqdJq9NEOi5KWJRZiWPZyLRKxRRlwXh0RKvRJAhdCkeRFTn9fh9Vc/Fdlzwt0GlBGidkqsC1HUKvgpbHRYYQVUBco94+vhkU5HmBkjZFoRnuzdnc3MSUBX7gsrywSJQbiqwkT2A8nvDqU1e5ffsuSVypYCzLYefq4L/ODlQKhSUCLOFgC7CkIHRqiEwjbUWmBPNEMzoYcmZ5gdF4wKvXU5YWWzQ6TeLpjKOjfTruAhaGYnrIuDQ4yy7jw7soJHc2t0jzEbariJIm01GG0RaB30Xb4PqSeTJmclTi5G0KpuQqRuJgUkNsDHbqECdz5tMZH/iOt/Prv/QfWFleIuj6ZMaiyAWTWc5ywzAZTcmzGlKBH+Z4rs1g65CD7Tn9k1066x1yqyAf5vi9GsoqSbOE0KpTKJdOY4nt7Q201oSeTZSPEZ5i4WSL6OgAFUjSukLVbQK7TzabYfQ+TmBRSkFmG2b5Lf7uP/oB/vZf/r/zbd/5QU6dXqbRslFuxjwfY9mC1J2jZUJoORRpiE2NVd+jV1+kZte5ceU2n/rs87z80qvs7gxx7IBWq4PnNug3HyDLcu6OxgglUNKAEczH++yUCcsLy8zHQ1YW+sc5TA/y5NNPsrq8wsrSEqUvuLC+zixO6NQajPYGPPDwJZQN4/GQWi3g7p3bnL94jsCvcTgZkhYZxjGM50OWV5dIIodTy2scTo5wbYdoFvPg5UfY2tpiXhZkBh58+C1QCuxawKmTazz95FO06lURbPUWEeMx1miEyWNOLp/E5CUf/IYP8VM/9a/YunmNSw8/yPD2IcqqOJML6z1u376NPh7XKKXIkhzQaJORphGJLhClhgIyq2A0m/L4e9/FPJoQzcYc7G2TxxGT6RGlTpjO9ymKlMZyDcu2SYscI8DtVbNq6Ur2J/sURcGlM/ezvTOlyGLCpoOpecznY25uvUqr3eHu5htMJi4X7rvE3bt3MfkUgcS2qnwiZRUYUaCEXy2qjQb95agM1LEESLkoVAWoljk4OUdJgh9U75M0S8hMgik1jlejFy4Qz+cc3DpEhJrFxcXqhOYY3NA7tnZCGHTJjCCL5ni5TaMe4BvNdDBinGd0em1ai12kbDOJMwQFWZoiSioYulsD4GDvCNd16XT7dDohSZkzjyIaWvG2Ew+jMOxu77GxsYeywXEcwkZIs9tmfe2daP1O9vdGvPrKVV5+5Y2vqHZ9VXSg65fa5h/8+jdX0aaWi21ZNNw65AbbkUyTEYejmN/55T/ERC697gnKwjCfRDSaIc2WR7dT40tfeIkXn77NWx64wGKvTrtlYfwQL6hRmpyj0S7zQUFRaFZW10jTHNf1CXs2CJdnnnqZwOuiVMZ4PiJOppRpCYkhKwS9BQ/jxHjdkIfe+ggf/fk/4MPf9kHO3NcjK8CMA6aTjIWVNrNpzAvP38FzJZbKmQ5nPPGF51j2VlhaXiCKKtfHldHrfOdf+nbqywrHV9SCOoH0cewKMIHIadUU0WxKv9lFj23yfYcDsU/3dIssn5Mdxgy3Bpx59CRzk5BYkOiSzET4QpEexNx+eYtWo0fNa1TWPVNgKYfF+gl8v5J4Pfn55/n5n/8looEmnhf4QZ12axHLso/jHBSuW3WmGoMQEtu2K11kmSGFjbI8tJG0212cIOTkyZNkWUZRFBwMR9y5c4fv+PC38/STT/Jt3/ZtPPfkk2ghuf+BB9nc2OZdX/NujDG89trreJ7HuXMX0MZw6vRJvvj5L9CsN9g/PKLf63Dq1Enm0ZTNu3e5dXuDd7zjHUwmE1ZWVpBSsn+4zebmJmdPneb2jZtIx2AJSJMIoasoivvf8jivvPQqSlYkocPhgMlkQpZlzGYRn/vc545tf+oeoxJTCbChEounaUpRJkTz5Ji2DtoyrC4uYYrK3y4dl//hf/xxNrfucLC/yetvvMrm9gbvevfb2d/fxXElQkBuNJ1uiygZY9mKqZ7h+S7GVJ7yJI04uh6TR4aLF+4nNRGypUnSiLKIAUF/YYXZNKHIDcaIypU23aXavFfEfiFNZUE+BiC/mQ8kbQ8lBIXWZELjGImQ1Y0BJBiFVmA093KkZFZFeniOi9ZVoTKmxA9sjg53yYuI1sIi7XazyqMyBoQhNSUWBlkUmKxAzGOa7Q7t7iJRnDGPEtzFGr2lDpoSrW1EKbGOZ6LReIrnutieW8V2JAlu4OM2KkRhmRekaYbARuqcNE3vJanKIjhOp20iqQID/85f/tf/tXaglR9VH78oju1CWdGvtYFCG+JpgWvVCVttTC4IvIBav8Vgfw/Xkcy8Ge/+hgu8830P89Gf/UOEOEmRh4jwEAYuUZyS65xQrbJ+YolGt0VeZsTxnFanztNPvIKtbFaWlxkc3UAToyxNmZUVCNZ2yIsUy4EizRhNh9RbHssrPWzXxnJstm4eAT46L9nbO0BYAjtwsC3oBX2aiw0m+zP2XzvgoYuXmI/nrNTP8vznr/CdP/iNjJMBaZngiwpbFwQNDg72WFlcwXJChCxwAoUIJTeeuUr79IPMiiGNeoOLD9zPweEBXtvDxlAYSVo0SVRMe7WJub7DJE6omwWiQ0PDW+bTn/w0r73yu+ztjdCFhec3ULKN7Xs4NRcpLVLpUKbFsa3VBWGRpilBo2JKxmklaZHH7pkyzml3+tXriiCNK1RaURT3dIFlWWWPp2nKbDZj/czZe6F0lQPG4dSpU1y9erWafwUBxhgODvbodhps3d3A6IJer4PrOdTbTc5ZLvN5pe3c3t7mwoULxJspZ06d5Wg4ZHn1BNLKmY0nGK3pd9psb2/zyktXOLV+jnq9RaklWT5lPB5zcHAAwPPPP4tnw3Q6vZevU8B/VHSMMcTJDKMltu2ytLjG2tk1bl29zmw8Icoi/tx3fSfj6S7D8SbTeJ/mgkMmFriztYXjOByN48oaWURVEmge4bkKv1XHNhJtwFDg+Q1GJiEMAwpdcurcKablgNm8ei2KomA82iOs95jPMpRUDMcjlpYWmEwmzGYTXNc9LqKVXrL430Q5v5lLZNs2ojQICZa0wUhAoYU5zo/SYAT2MQnJCBBKUhpdaaXdgLOnzpJnEQfTCZt3NvE8h26vg++75EohMRhhELag4blYtsXB4T62FaCkRIxnDMZDsBSLS2uoerNC1ikbT1U3tjhNqliZZgspJaPpmCiKsJRLp9NBKIlJUzSGVqfN4vISvtthcLjP3u4W0XRU3RG+guurooAiuBfyVWXVOOiowHFsClMwS1Jee+UOvtWh21whcJukeU4yGXLh9EVKlTKJDpjvz7CcGX/uB76O+WHGr/3cxzlZrzOfShrNJR55y+OcfWidja27TJKI1ET0ljtsbd9hNp/i2zUOdm/QXfUI2l02NjZI5jGe4+CFEDgCI6u4iDhOuXDhPN2FNgVzNBaiLChMSppFbO/cxQ76lKT4lsIxDqdX1tnSEXZacG1zh3g250T3BMPRPrs3DmiecMhNVBURuw7GRuBRFgGj0YBGmFG3JK1ui/tX7sexFPWezd7tHZyWy9rSKcbJkFwXmMIgSo3BIUkN7/ua9/OpP/wM//xnfg4d26y0zhKNIhB1WrU6aSlAGuJ4jhISlVeZ3ZKE0q7eXFrY7B8eAVCIvNKGhnXKoqAoC4TlgFGMoxnDKKJfz6uwvGNXlXBszp49y87ODpcvX2Zra4szZ84wnExwvbCKotCayWRCo9G6B7qQUlEUFeZsNh9z5tQKvcUFnn32Wd757vcwm+fYSjEcDllcXEQIwdbWFv1uj7IsOX/+PK+9foVmzSUMazRqdW7duMalS5eQjodQLp4fEsUpWaYAj3mUc/v2TX7sx3+C3/yVn2MyGlMcx0xokVPk+j+KsHAch36/TxiGbG5usvP0DraA0Pc4eeY8J9eXuXr7NXI9R9QKlJ1zqt+iVmswHs0YDQv2dvfJ44SybHCwv4+iAn6vrCxRlBmOYzONphgjSOKM0XREL29TZpo8MxjLAl1iCck0OcJ2A/I8RViGwcEhQRDgOB5FkaN1VbSEqJa0+pgkT3EcPwxV8VQGIU0V5aFdwMLHqXTFJgUjKcuoeq84NtpUiyQhNdN4zCw2hI5Ho9ak2+5UkdymYDYdM0kiugt9vLqPtCRFXlIKgfYrxieAzgS6zMjnKUpLnGCMxuAEPotrK1iOjUxthK4gzck8IrAUyvZQyieNM5J8hi6qJdlSbxnHcUiNpuM0afd9TJ4h0cDv/ZlL11dFARUIlDC4toWLi2sCCjFCi4S8NORzw2BjTiBc0ukMRysaQZ3FE2fRFEziA5brXfIyY3d/F6scsz/c5eI7Q+y8xq2nd3jH2z8ElmKiN8isI3ReEAQeipy7d/dxPYUu54RuQBj6dJtLvHDlOsqWJEVCzSRoaeHX6oRBwOHWEW9991uJZIJXhMgZNP2QXOdEkxlZqgmaOe1OkzzNcLwAFdjk5SHTIkYFPhjJ1dFVWvUWX/rENf7yD30rB9kVtCpRniSKBZ3WMpvTAV7okzuCHJu4KHEbPrO9BOe8h1rQvHLrWR49+15qxsPkKaUjcbShiHNkaXFkch7/0AdoLa5wtDnhl3/64/hOk6BskpY5lBpdpHh2RporsqKK8q2ycCwcxyGOU2y7Cl8TecniYp/haMQsjqoZqAFTgidERRYqZ8zmhiRJsWxwAh/bgnk0ZDYac9/FSyBKRoObUOQ4NY/9YY3AcUkmUPc9tnY26feWcF2Her1HaRy6S01sx6HV6qFziU4l2s65fesWtmVx+fJlrl27Rrdzgtu3b5PGCb1WhzKe0Wh1GI/HPPzWd+P6PkmW8swzz3L61Fk8z6O/eJL9/V1On73A4+94N//iX/xz7nvwbXj1Lp/73OfwPA/XFwit73VhjucjU81g/5ADM0DrgkIIoiyh3TvJ+7/+PRzsb2HKEcYUGMtgeSGBFzAaHtBoBTihRaPXpigtZpM52mmSpzmbtw5IoxJblNTcOnlaUNp1snzK8mKf0eEAmhCXOY6wUbZDlqdUmOISZRmK0lBIh6M4IQxrmCzBlCUizRGqOhJXRVQjbEVpDEKAlJW/XGBVN3OhqlNhLDG5jXENpZ3h+wFGK3JtkFYJIqKwLHQpkSimZOQix9aKrttEaAtXWPT8FvF0xuH2Np12Db8R4DgWwjJ4dYc0jclCF1E62MYh0gXzZAvHccnmFsOXt5DS4tT6RdqdJTJjcFyPua5AJEVWUKYZnvQhrMYVB4MxcRzTXVygUW/iWgodJ6TR/CurXV8NM9AzD/bNP/69b8dWDu2wjynBFHMsRzGaRjz1zMu8+LE3aHttes1FgrBFvdmhUe9RqwW0eg7T+IjRbAshSwozIzcRhoKlpRVEabFxc8LwoGA0iQnDgLDmc/HiRT72sT9iNptR8wOkqXSZnZU+/RPL3N3Z4Iuf/Qy9Wp1G3SUMXRzfw3Zq7M9mfO03vR+lDFbiICNJPIqZxFM2DvaZpiVLa4tVfEKmySPD8GDCxs195nGGIqBMSnZ3dylzzcF4i5/8v/4gzsKIUksc28emx2JvkTc2X+PU6UWSeIdQeTiRhz2usx9v0XzY46g8IBsm5LsWF06cQ/guw2JaYdHSgjIrKS0LowQyznnjhTdYaZ9jd3vMP/m//TLry4tkE4FtbIzWFKKSVBVFUQGGVVVA5XEeTUWLsiiNpsTgBT7iOAJYGkk8r6Q8fhAQBCFpmtNstFlcWcX3bY6GAyzbp8gFrVaD8XBEs91COBYf/MYPcev6DVYWVrh69Tonz56m1W6zsbHByZMnmUxH2MeZ7YPBgEuXHuSpp54idCsYsm3brK2tIaVkMh+zvLzMnTt3CMMQnczxghq9Xo/XXn+D0hhOnDzNfB7TbLYruIyxsCzJ1vYGk8mE27dv0azZxHGV5hoEAVvbdyiKgi9+8Yv3lkmWFFi2wpiSfr/PI29/hIWFLju7d0jzCYtLPSazIX4jINMlOSX1ekiazShMirKrbPTCFFXqJYJ4nlDMDdF0wvbGNjXVwpY+8zynUfexHYn0JIsrbSzXYRqNKUzlFjJCUx5rHEsDhui44EMQhETzBFtrtDGV2F7rCs7xZqaR4BjUohGoKn9dVIoDmdlYSlGoHG3nSKUr7aeUaFmgFFimIsxrrRECSkokYCFxpML3K6uw0AYpDGhDoarRDmj6C11c16bQ5XFBr7r9khRhgMKgtMBzXEASTTLSRNNsNjlz331Yymae5MdfsyQ2afX9kOfUajWyPEEY0FkKppJZffjBn/ivcwYKgKnILVoXGA1SVETpKEq4cX2DeDLGSSU+PlL4NOqCehAilcXe9gDL1QROj1LH6KygFXrUGy5RNqbecDhzvsNhQ/LCcxuEYY1azWc0GlHk1WZPqSq7W5gqHjeKIhYWO9Wiqevi2B5BPUTZ1QTdtis9oTElnuOST3Km2RxtWUzTjMWVFWotD1OUeJ5PNo8o8wyBxac/9iWUUUgUrmVjWQ6TqOD3fvNj/MUf/hC5FTGfz+i3F4jjlDLJKJKc2TQilTPWuidoqQabb2zhlA0cZ4bVchgNMw6mY7peD8dySbIYcfzmk1JSak1Q91g92WX7xhWW107x9/7pD/Gv/vlPY/utCkAxlwStRrXAkg4oRZynaKmo1wPSND0upuBY7nEUcFxto5G4tsfqUp/9/X3m6RijSkASFxNGR5Ijk9HutVGWxMiSaTSn1m6yfzTkoUce5uN/9MecPHGKXBvCRp3xcEyn02A0PMD3HOr1JmmcEM1iDvb2uR1co9tpsHHzJidOnKjwaVkVb7yzs8OJEyfwfZ9arcbhdMRgcxPP8+j1epTGABa93gI3rt/k3LkLRHGKEoKl/gJnT51modvlypUXqATiMByOkNLDdQXf8i0fwXVdZrMZSTLE9Sowsec5vHLlOdKGxXw2IC/H6NIGU6KLEmMKwkZQzYyNxvdditJQCoFSOZChhSDsOngLLvOZpNmtkY4FhztTZFEileGV117Edn3i6UlqtQBjlUhP4IcutldHluXx110iZEGhDRh1HJndooxm6KLSsgohMG/+fC+/nSp8UVjwJkQejbQ1lrSxLI/CsknLGSiBtKjC3SwbUoGQVSdbqgLnTcOLZVHmBXlZQaOlsvDckPk0QkuBexwnPTlMcW1Dp+ejHEmqC7AElivRaUmRZCgjiLM5gW9Tbzq06x6zyYSrL7+I4/r0llZodxZA2pTHI5daGDKbzZAYPMcBq1qEjWbRV1S2/lQFVAhxG5hSeU8KY8yjQogO8FHgFHAb+C5jzFBUq8p/AXwzEAF/1Rjz3H/m769gAGVJSU4aZzRqPgUFluuwuzvCD1tMpymunFJmBqlzBDn1ZgOvpjAmQ2QelgzohS5lERPtRxhZoygb5FkAacn5C2cpyjkLi00+/enPkuf62Bcu0GVJnGSE3TqIhE63B4AubYSlcDwH27WwLIf2yWUMBZZS3L16i6AImeQJmTZ4zRpBL8T2C8pU4YuARGUINFmcECqFTj20MczjGFsaXLfJp//gKj/043+TUXkN24kYT/ZxmnUadoudOwe0Vhqk+YhBss/+9iF1t0t2qPCXOuQyobZiONgZ4aeNakgvU2zHRVsQFyVZXlBYgpNnTjLY3mf/cBOvc4If+8m/zq0rd3j2Sy9Rc1o4Xp+Dg8ornqYZjjDYdolTK1AlJMmEXFfHQBQoS1KGddzAo9G0OX2qycONE9i+j2N72LZ7TP13cD0LaTQUinia8sXPvsju/jbvfd8HeOpLT3Lu9H0MR/vHm9cc13I5HOzRaTcxpSb0A8aHu/R6PY4GVhVU5gSEtQDbsfB8Fz/wODo6IgxDDg4OaDQaHB4e4vs+XlAjz/Mql8j3UcowHB7S6bbRphJwHx0N8H2Xg719Ou02p9bPsLNTQa3TNKXWrjOdTrm7tcnly5f5/BNfxHMLSl0tcVZWlljodxHGEHg+R6MR4+EMZdlMRkOswMHVDul8Rl6mSGNjOQFCS5AWhdGUaKTUzMUM4RlcbXH9lRs41AhqAe2lBktpB13AzuCQ+Z27XDh/lpe+9BLrJ04S1ELW1lawHAVlgXE9MBohbYyymMURTdurstZ1ieO4pHmOlOI/+r5UxkJwnLYpDUpJUBpTlFAq0BLHdZFKU+gMZdvYwsVYKYWu5qk2FlBWMdFlibItjFJMsxQlSqZ5jqVsAsenUa9DYciTnDLLORzM0LogzuacOXMKYwAHtHAodY5wLDKdok2GY2lk2yBMhLQ0hTlie3tInOb4boeFhQVsIwnqLcoypSg0SVGCkri15p+lbt67/iwd6NcaYwZ/4tc/CXzCGPOPhBA/efzr/wn4EHD++MfbgX99/PP/4WWMwLIkeZ4hVSVLy4uCJM0pDdiNLooZo8kYG5iNDIVMiJImtdjDqBzXCXEsSZYUlEXCfDpiPssoigZe0OXkiVMkeoDjudzduM7h4R6tY24iVEgsW6ljTeYM2+5jKYs8lfcsb1KC5Vo0GrWqC3MsTp1cZ7o5RRGjE02t1URaAqUk5fEbJ4kShNEYNEZrLCHJ0TiWBUZQZoJaUOPlZ29z6q3OseA7YzKZcPHsJa7ceIXA9ylMQqpzeitNzLbH0c6M3lIVj6CtmEanzcbmJg9evkwpcvK0wLFssDTKsdFFRhIXNFtdbt7YpOFM8QOLBx87ybkHFvjkJz6Da0154FQX6FZ2wGIGcO/4rpTCVg04HtzrNGdS5mRxxGw+4ebBq2SbMaWGoqiWUVlW4NY6+LaFSTNOr5zi4pn7+LqveYyd4SHGzDl/dpnlhT5RnjKbj9EmZ2fnDo1uE8f2jhMUJXkRgahYoEeHI5aX15Cm4lIe7h+wv7NbhabV68dRKB4LCwvk8wnD8ZSiKMhLTVivI6Sm3vA5OhyhdUCeV7Erk8mEbrfL4PCA1dVVxuMxu7u7ZFnGcHiEEII4jiiKnLIsGI/H2I4iTWOm0yn7+7eRUrB+6gQLlkWWp+TFnHqnwTxNqjTVNGZpuUehc+bTOVGU4oQOyrIoZVk9d5bGtW10Xr1XLA1uzaPRr3Gpfx+z8YzJ1GU2mZIXsLZ8huHemL07u7z+0musnlih1+vgdBXKtpGOQasCaUu0rkAjZZpS5BopLcQxG7OKJxYIXT3nbxbWsizRJsXSAlu5VRKnTsGUVUxJaciLHOOkKCQSC0c5GFFiBMcbfgukhbAFGo0SFZlemyq6xmQlnXqbdm+JvdmALIkJvJDx/piSEmVLvLqPWwvJyxxTWriOS5pHTKIZNhlWoTjY2KNd72FJD1f0mR4OmU6ntFotGu0avuth+5K01BR/hkL4J6//f47w3w68//jjnwM+TVVAvx34eVMNV78khGgJIZaNMTv/+3+VwbFsXOFWQ3nHQVFwlGbsbA9o222KtEQKRb3R57d/+1Xe+Y7H+cDiKY629rnzwk2UBX5DI6RFt7vI4WDCKy9fYePWnI/8hW/igQdPcDjZw60pGo0OH/vjj3Ni6RxFYgh8QZZCZkr6K8soJyXOI5Sb0+xIFDla22RGVZ/vWQT1kELY5LFCzg2HWUJmLIajAy48cBbbKykEKEuQJBGFLvFrXYaH1/EbHkWmsLWhKF1MabApUZbFL/ybX+D//G9+DEsdkZkpOCV7gylh0EYUOR4hSmiEEzIjYj6esVj2iOwM20hyH9xWnWdfeIH7Tp3Flm7lNVaghCAyHjk55x9+hFFsuHrlNqdPnyLLhqysLvDBD38td27d5sUXBgRel8CDwGmilaEwJSYrIINcTUkTjcKG0iJJUubzjDyr3CB57pKMK53t/t6ALMuRJmJpYRnPDblyMOTaS0/z0H0pZ86coV6rs3Vjgz9+9WM8+uijzGYzlpdX8X2frTt3K5thmlOkGfWgzeHhkHanRpJnKN/Q6nSZxRMc32IwPOKhBx9mY3cL33aoeT6TJCIvLZaWT96TI21vbXPhvgc4Ojqq8o3SgqKc4foOnc4Sd+/epb+wyHA0YGVtFWkJBoMBszhiZ2eHPC+4des2vh+wl21BVuA4HrnSDI+938XWFoHjcv36Vc6s9lnsn6UsR5TxPrETs7lxiyzLqNUarC4tMU1y0iRnNJpi2zZezcZ2LbZv7lEan1RIzp9sE2VjMjPHa1g0ew7oHuPDGWtnVrl705BFIUUCaMn+5hHugcvh4SG9lQ6Ob9HpNinCDDds4iLIRUGj7jNPRyilKwG8rIqsUNXx3jq2Oxqj0UqT6hxpHFxCUhJyk2AhkAUYaYMQKNuq3jfmy6mcxhh0USCkrIq0qI76hgRt2eBKJmLCwc4uNTug3+ngeQ7jyQgtq+gRk2kmOwfMZjP6i3363ZBpUiCEh7FtyjJnoR9QFilGg2GTeGKQYxdXN7FywWh+SBnYBJ0WjWbwFRXBP20BNcAfCyEM8L8aY34aWPwTRXEXWDz+eBXY+BN/dvP4sf+ogAohfgD4AYD+ah1Leghj86UnvkCWpLzv6x9Fa3j1pWtkkSKOIhqqRjxX+H7Ic89e59WXr3P/2XUWax1KnVO3OuzvDrj+1A6T8Rwperzv7fdx/mKdg/EbSK+DsjW3b9xkoblEmVVhVpUgOGVltYtmjIoh9B10pgm8EDs3zOYRYZwR1j1wVHWUVxZmZijznFkeIf2AZreGF0qM0lAUKCUpTIbjKGyvEsdX1OxqbKHsaiGjswLHcdje2ueFJ17jkXcukeuc6eyIoNmh3miQRgcI4SBdSVwWoAS1wCeb5/itkNIUSMug3ZJaq8lob0Sr1cD3bWZ5etzxBsSxJppnvP2d7+DO9bt88uN/yLd88zeyceMOp0+vs76+Tr9/kp/9N7/B3uuSfqPPPE0xAkoKbGUwJYReHUs4aF3xAN4M7NLaUJaCuqoRZRkdexXhKOK8xMk71N0maEEY1khSxdVrW6ytrWE7Lc6cq9NoNWk3O8znc4YHB+hCEUcZ8/kWb3/7Y+jCMNo9ZDw8oEgKvEyhHZtmGBzzOON7UcEvPfc83W6Xmzdv0m/1mU6nDIdDlpeXeeCBBzg4HBIEAbu7u5w9e5bxLKIsS/b29gjDkDzPCYKAej1kPB7iui7jWZXLPpvNeP755/F9n+HhEZ6vkCGkUYSUKQJZHS29GgtLi2yNx3gHB5RpxKnlJXoqYx5FJFaKchziaUqa50zGQ1phjWatxTAdMTsck01TLBxsVW3DbTtACxCWhVCSrd0tOq02vm84+UAHWQQcDkbMphlZomg5bXI0R4cT4jjmjdfvELgeQllcuO8iXijR0sGz2lBmSEq0yZBuRUgyUpCZFNd1kTnoskCqBClLSqr9gaUtQCMsgTbmnmjeGINUx4XzmFD1ZiE1hmOkHBRSgqy0pJQaO/QoZMGoOIJ59ffaumR1ZYnRaEyWWCwunMC3XUb7McPJGKFgdfUUnm8xSw7JREpSFgyjfdYWT7F4ehVVeMxmipXmOcqyyd7BDqPh1p+1dgIcs6v+89d7jDFvpTqe/4gQ4n1/8jePu80/0zrfGPPTxphHjTGPNjuVpMdSNo++9TE+/C0frmJOS9jeGpDMQBgLo23u3jkgSw2lNmSi5PqdW1y9fZ2UnL39mMkYdrdnCOPwwMX7OHlugYyIQhRMkxmu53Dj2i3IJa5tH+eJz9EmRciCbq9Gt9PEkgpdVtk6ua40j2WWoyxB0Ayro4SWWIUgTXJyUZIkEfVWiHRKbKdyUVk2xMkMREF/ocNwODwm3XBMysnRphKZZ2lOvd7g2c+/iu+00caiKFOm6aRKSixslAxIC0EqBLV2nXq9Tj7LsAubanersVyJch32hkMs28eSLp4XYjs+jnJY6C6DtCk0/Lnv/A4sW/LEE18idGts3tpGWZpaK+Nv/q2/wMkzPtNJhMwdAtNDxXVU0SJQIaSGdJ4gMoMvfVQpKKIES1eSroiY0oFYpKQqxfc9ZpMhk+kRs/kRSTJiPI3Y3N5jOJ6xPxgyGk/5wz/6GHmesrzYJ5pPcV2XPM85PDykKArKsmR4eECv22E6q0Tvb27I8zxnPK6kKgBra2vH0cLV7zcaDU6fPk2tVqMoCmq1GkKIe/rNSotsI46lWGVZMh6POTo6otVqAXDmzBlWV1ep1+sMh8Pq2J9Jjg4mHOweMR6OMYVGmIoxG2cxXujh1+oYaZhnMV965mluvn4XYWzOnDhHzatjKwer7tFabaNrhsN8SFEU1Ot1igKMFtRqAcPhmPF4hs4lplBMhlGVlJCWzOcppYFZOqXRr9NdbdBZbVC4CUHPpbXYYnl9ld7iIkY4lIXixtW7vPLiVX7zV36PK89dZz4oUZmPXYSQKsrEYBkLIewKDyfdaoMuC4xIAF0lrmuBQmBE9X4uiuLeQurN9/ybwOn/lHAfUWHnqoKtQRpymZOSUaiSQuWM5kNevf4qo9mUk2dOUWu2KI0EYdPvrdFuLBKPEqZHER51lpprNFWbMFwkygy3R7tsxnvkToYMBAvdDoudBWrH9tA/6/Wn6kCNMVvHP+8LIX4LeBzYe/NoLoRYBvaPP30LOPEn/vja8WP/+5egGiaPj6j7NYzOmMcRs3nK7uYhTdOlNDGz8YC93QMczyMrMoxRpFJzJHOS4Q4y2WI+Tbj//jMsLficuxggl0qqCZ5Nd6HL7Ts7TIcpq60ena4DNcPN1zfxPB/LrmNZEl0a0qJkMo9oLvbY3trHFh5pkpBENkGrhuUKSEvqKmR/tkchNHlhCOoOwiopTVZZ4DA4LmQUZHlEHJc4x7O8oiiQlsAUJQKrujtbFs98/mXi+Xfh2DUKeUicRQS2A6nGUTbYUMictMzxHYunn3mGt773cbRrMLJE2YrSFQRrS9w62ONtly8zOdhB2IoiK8jSmKIURKT4AXzfj/4A//43f5+f/plf40d++K9y5+YhvRUfy57zQ3/3m7nypZif+9e/zv2LbyWdC+J8TpxWszklBKbMOTpMabdb1ZHvGNHXa3dRymI2rbq6eZZjK5t5nOJYkhJzz80Tx3EF9K0F9Pt9rl27xqDZ4MK50+wN5thuDdtW7GwP8KvkBl559VXOXbzA0XBWxTc3POr1OnfvbhPHMdNkTllWAuput3vPjhmGIdNpVZiP9g5oNpv4vn/M7pziOA6jURX9sbhYkZiGw0OUEjzwwAOkRc7S0hIrKytcvHiRsiy5ffs2n/zUfyCax2xvHVGUKXmR0u0bWgsarUsa9aA6eosIqxlwFBfMbu/wsU9/lssP3s/lyw/Q8lKmWUasS+IMcHwOh1MyI7CkpNZpYURE6PvoLGW4uc9wFLG4sIRLg9k4oVarId0Eyy4r/W1oYy07FHnI6DBiPs4wvk/QsKGwyVKN73dxvRqT/ZRPv/YU83mM40hOnOtx/6X76J5pk5YxaZJSOs49jajWBUI5yELh2S6lysmlxvBli2ieV9bRNzvQNx8XljwuoMcRHDkoKRCWxNIaWwqyY/tspSRRBL0+UggwkkE8RKKwPLf6Dvdc6l6LLDrEURYkhmhUYCcNToUnOHPxDNd23mBSTIn8KUn0BrdvvYpjtRmnX5kT6T/bgQohQiFE/c2PgQ8CrwC/C/yV40/7K8DvHH/8u8D3iup6BzD+P55/VkJ6R3ikcY6xYWYioiwnHUM5s9FlZQuczQri0sYYiWMpHF9j1yys0ELYiq29mHe/+714fsrb3n+RxYcXKWs2BhvPqhGGIbu3dzl98jztTgenJmku2OyNbuHYkjzbZZ7s4PgRYlogMouw08BgI4UgQ5OaEtdxsH2PfKDJC8XIzqmFTWzLVHHJMkFaAksHWLJGlkik8hmOZqAkWAptZUgPZOEgjUVpSuSxGD3AZbyVE4qlKqzOxMzTKZZfJ41BZg4qc8EXJHZKr9HHHiuUdMHYGGEhpENuSxLHsHN4QC0IsUuwHBdLKjzhITMXnTisr51h9cQq3/ChR/mDP/516o0W42FBHrnUrBonH3T47h/6eob5QSUnyX1cy8UpHdzSQhiJHwZESYwBykqHVgGRjcD1ajhunbrvgilIswhhScazCVt3bmLKjNubd0h0gaU1rqVwlYWN4trrN7h681VOnV5BlxllGrOxdasyUEwmNGt1bFGSpyO2N24TejZ5MsZzShquz9FwRKbBlx7ScfGCGuPxmLLMuXXjOlrkoEqCmo/juZRFznQyJppP6PeaSFEwGx/huXaVSFmWlAnsbuyhtKRTb9Nrtblwbp0/9+e+i5NrF5lOc1ynRTQzDPZmDDbmlHO72oLnJZ60sJSgc6pL6hb0z6ywPRnwe5/6GJ9/6im2Ng5p2l16bh0nc0hHKY7l4zoWviVpdQPKecbw5iHDOxOY++zfnbPx+ojZtmC8Kdl6ecj4rsDXC8jMUDoe+Ba91YCT5xq0uhq/BVaY4jcqePn6+glKx9BfXeT0+TPUWm02bg3497/1WX7xpz7Klc++gT8LCa0AkxjILBxVQxhDQUppFWhpoJTYRiB0JQu0pIMpq3m5pVzyssTIElOAKSTSOEjjYDyFkQLLCNAGIRSOsAnsGrJwsIyiQCIsF8cNELYHlk0mIpQssI2pYEROkyRzsLw+3aV1mgtLFErz5BNPs+wt82D7AZx5jlNmeE7OQkNxvtH4igron6YDXQR+6xikYAG/bIz5QyHE08CvCiG+D7gDfNfx5/8BlYTpOpWM6a/9Z/+F46H+m7a4OI6RwubO7VusLJ1gcpDjOhaDwS62dBBaY9ngejZh00VisXv3iK9951s4u97B8hSJHmFKm9wkoCy0zEizCEu6FFlBlEUsne/TWilwQpdMl7TDgGa3RRbNOdgf4PXbNJbqFEWGcFzSNMXzejiOhS1cpDKMZ2OEVd2JOp1W5emXElvZ2JZgFsdYStDsd3jpxdcpUoNvuxhT6Vzf5J2+Caooy5JarcGv/NKv8jf/zl9BCJtpPEMaC+ycfB7jOx6Rq0ApOp0O+WGBSUuUFljSwhiwbYWbl9hBjSuvvsYjlx9EFYAtULZNWlZRCVoKBkcjvu7rPsinP/Vx7rt4mV/96C/wF7/3e5hMJjhIlO1y/6UT1K0G//Kf/ibL7RN40kOXAsu2Eao83toqpAStC4KgxnQ6J8/zKkK4NCjLwnVdhBBEUVQdlU3J7l6KUYr+4gL7eUSr0WA0GVeb7jRBCsUXPv8Ey4srbG1tYFRJNpmwtr7OlatXybKMwK90vdvb24RhyHw+R1kunW4Tyzbs7Q1YDVfRWUy73SbJChzPxfMthkdjgqCG1pper8fh4SFSymq5VK9Tr9d45bVXefs738H29jZK2NRqwXF4nc90OiUMQ7zJjG/91m8lqIWkyYRf/bWPMhjs4/s1Nu5uk10bEYQOi4t9lpb7zA7neMLHc1yEMKi6wnYgmxpeevoW0kgCr0s5U5hIUu+2aTo90rHh+rPPE89yakGf2dGIer2JXQsQhUUUxbgsMd8XON0TzPcTfDLcwEPZKbgZK6cWKOKco6MJ01FMlo1YWeqwGPdI0xxKgx/YFP0muizZ297l1ddu8PJLVzGeRtqCR972EKdPryNdG6FL3NCp6PfklLIad0kDmhJXWeRFgtAWjispTeXTRwhKXWKQiFIihURLsN702luQF1V3+KbIH7h37FdSIr0WRWaY5ZrhYIQwDt1Wm06rw2w4odtp4zshpW149errZPOURE84c+osnX6fp554iYcvvfNPWTL/4+s/W0CNMTeBh/8Tjx8CX/efeNwAP/Jn/ULe3L7fm4cYi7u3tllfO8XN8Q55NkOnJZgCqcD1HBqNANtX7G0ckEYZDT+mKPY5nGzR6bcws5JS24yHM+5beJDR6AjHsrGMxLYkrmujbMX66VOUM4kbeAQ1H6secLARI0xJrR4wTWbU7AYCycLCAqAxicGSFpN0hm0rsrig2WkBJVKA1CUyS7F0jkkS6u0Go9GYNAZTpAR+HVOKyulxPAs6fv6YJzEvP/ca0bjE2BZ5mZJmCXM9oe4HqFKDqWIyskIjSo1dSCgtCplRHB+NbaDIUxYXF9nd2GH9xEnmRcksmYGxqQV1CpVTZAW25bPUWyX1Z7zj8cf47Kc/zTve8U4Oj8YsriwinIT7H+3xE3/vv+Hf/NRvYJkVwCcvBUZpbG2OUx+ruNg4SrFsSafTq2hMZYZEVamJliA+ZmfqPEGZAj8M0GXGaDLFtStIthFVRK+yXWzPZj6fcu7cOW7cuUYURTQajXtypTStEgeOjirEWZqmOAha7RpXr75OK2ySTsfUmi0mkxF+vYM2EqOrm/fOzg7r66cZDof0+/1jOdIYpRQ3rl/n/vvvZ2dnp8KntTrs7u7SX1hnMhmhtc9sXs2pXTdndDQkT+d82zd/K0Hg8/GP/zF3b26yfuIcnU4bqSCbGaT2sZ2Kht7rdaoUy3hGUWhqgcvhwQjbanN2pcfS4jpalwxHB+xv7NNyl+jWK4DKmeUlysIwOBiRpimnz5zlwQcfJEozbt25ydbGAetOC+EXBD0JtkG6ktCx8fw2eb/N0WDM7v41lNOg5lhQQp5LikySxBmnz56nSAt2d/eJoiph4fkvvMozn3uZWjvkwv1neeujD4DI0KZEWAK0qD4WAtAoobBsBZRfzig6vqSUoA1aaDRgVLWIkkYez0sVZZGQmQwsG3nsnlJK4hQ2a6srzPZHzEZTjFNjOknI4308ZRNlCduTfRr1GjXd5Cg9JCyaRMOU5774aR5963tx3fDPWrKAryInUpIkCKhiOJKE6STjymu3qecZb3/kXXz+s5/DsapZR1iX1Bs2rY7P7u6cg/2YB+/r0TulCRYzFlbPsjc/ANvCtlw8UyJswfYbOwRegJAlC4tNcjPFKI/Ffp/N8T6eY1ELA7TIefChS0yyDGNyuktddm/s0V1psLS8iOs5lOMK1iGUQUmBEgLPd/B8A+QVis9WWLEhmWWUU83rz1zFkjZ5mjOKpwSBh7EqCtGbg3YpJWVaooTLM597gbd98DS2NSBN5xSyQVoWlBpUaaptpzKMZyNcIWDqEnQ8Ch0jkTihQyIMcRLTrzfpNNvMd3axbZssh2g6Q/oSBwszy3nXQ+/gd37jt1k/sU5alnz0136NP/8d387wcB+vZiFbis55j5/4x9/D3//+X2C5sYgq60gtKXR2rBlU5HmJZTkEfo3h0RjPd1CqOpZBxaQUogpd8zwf13WxlYPS1Rb/4OCArCiYpwlGySooTEpmsxn7B9vYjofrBdiOx97eHlmWsdRto9RxPEqjgTGGKErwlYNtu/T7i5g849q1ayytrhE41RwujgtarQ47OwdsbW7TaNYZj8f4vs/q6jLXrl3j7Jn7uHr9Gp1el26nw/BoiufWyDPNfJZh2VW0cbvZYmVljVk0ZzysmoLpKOb8mUu8550foNOtTihJknB4eIjneXieV5ke8ozZbMZnn/gCZ9ZPQ6lYWQjpNpsVIV4pdnZ2SGMLZXnUmh5BEHD58mXOr5ziC1/8YqX57XQp8owrV5/mzu0NTpxc5UPf8HaefvFJUgem0xgZGPxmSOAJOs0euSqoLzZgEYwdcPvGLaJZTEGKH3QIwpAkjtHGcPLMMo5YZzqdMp3NmMxnmASuvniDl55+gayETsfh0tse5PJDl1AOjEZHWDVZLYhKUYFHlDgeIGqkrNxSlrDuaVALc7ytNwJKgzEaZUtsWyFFNXmMoohmvYGlYfvOFv1am4cefhvXbm+DVGSmpMSwNUlA5DSaNlIo2v4CR4MDxjKhdabDa9uvIDZvfEV160+7hf8vexlzfPeuCqTWmsOjEXGUo5TFnVu3WV87hdAG13UJwsrRMovH7O2OqAfwyFvWaCy7dE40GSVTLD/EcnyEUNRaTTSSNC2xLYNlG5J0SlZE2I7kvnNnSecR5CUUJZYlaTRqdFoNsiSi3W4yHlVxE0FQZV7b2DSbTYSs/MJ5nqNseezlrWa20rKJkoSaX0fHMNuPsGUl+UAXRLPJvc/P8/zekN12HVzb57Of+iKO7eNYkqLMqqWLJTmKZ5BVzqY4ndFZaKEcg8k1uiyRvOkbNmArFtZWmMRztvf2CY/RcG/+W2Sacp5RRiXpOOEj3/Rh7t7c5uTJUzz22Nt48skvgCiIE808MViejfbG/IN/+jcYTPZQtsDCQkruSVOq/0/BaDSpYMNZghDVa/zmScNxHGzbxhhBnuRQgCUUQRCwvLyM1rrarrsOURThed69m4wWEr9W5+BoSFBvkOQFV65cIQyrQhuGIbdu3aJeaxNFSWUVnCU4fo3FlVXKLGc+PiQaHzKZTJhO55w5fRbbtu9h6950Ma2srDAZxzh2iHvc2bhOjdFwSq+3xPLyCdKkWlTNplNu3rxJo9Hg1KkzeF5Av79Iu91jNovZ3x/xyU9+kaeffpnbt/cZHCSMhgW7uzMGg5heb53v+I7/ltUTFxF2NTNPUkOSae5ubZIWOZNZjHEa2E4LY1ym44yNrds8+ND9fP03fg2nzq0xHO0RJQlhI6QwGXc3brGw2KbdqdNudshmmoONEaOdiFtvbDA+mFPEguH+DD+wsTzFydNrnDt/mvsuPcBb3/YIly5d5OID66yd6OIHFkHNYXV9hf5ChzxOmA2nyNLGtxyicclTn3mef/XPfp5f/Le/xmBzDKVEYINx0AVgLCrhjjke/0gsIY85reKe1ElaqnKvyEqL+qahBaDb7Vb0LlJix7A9P+LpN15isdmi7nooaWOHLdxml0a9yc7uHtuHOyQihUWbomWIg5RgxaPw/wtaOf9LXwJRUa0dm0TPKVXO7p0dXDzyWcmXnv0Clx+4yCMPn2dwtIdfs/FrLs8+fQMrtnjvNzxM91SNoOMSC43xa9iepCgTtA5peR6Duxu0QhtXCJI0qyyOWjOLIlQYIusNSrmAkn38potKStRhQqNwOLHU49WaxVsuPYgVaGxc5pOCHX3AFI3ntKAe49sKLBe0wFESOy0hAlsY9gZ3GU5KlDrWTAK6kGSRRKrK3YMwSAVKlxhKbry6CWmAooUUE0oZkefgFBZRMkfWWhjlUOt32bl5h5ZsYrVqVZwwJXlhEFKSUyDrDnvRgK5pETh10iRBeQ6yzFFSoeOcQir8doMPvP39XL31GicWV8ikzS/+u9/nb/74D7F19zb9hTY9r02xmPI//z//Bv/6H3+UZnmWEkiTBCkEnmNhdEmWVxa7NwXZSjgUuSbPCuI4q7KspKQ0MIkjrNgmsBwibVhZOsksjohGE5SSzBOXHM2sLDixcopr19+gLHN8v0mv1+LFG68zGo8JwxqzeUSn22M4P0DJAFMY8rJg72iA1poXX3yRixcv0mw20Uag9fE2WYKNTRKnbOzscP+5C7z47HPYgcvi6graFAwHB6yeWMH2FK9eeYWlpSUsx6bZPEWnt1plRilFmuZcuvwwt27d4uT6aabTKWurp3nk4ceZzSdsbW2x0G+zvHSCK1fe4JOf/GPiaMz+/j5RlKCLikV7sLd/HPhWPV9gKJI5WBYYi6Dm47WajJMEpCFot+mfWOHWzSv0l9q8cu1FLKckS+bUWk2U72IphW0EMtckScJAxliWhWVZLJ3wGGxNicICx7GYiAxjSqSjsB0HGVicWFony6rX9fH+28ijBM932RvsEacRnudUCpKsgnQMRwP2rx1yOBxy7sJ5QJIpSVC3qDUdpA1FaciKHN/37h35tS6QucCIFGFXWlLLeHiWR1mWTMcz+v0+Fi5xlGOHHkmWcGW8f3yTtnGFxpWSQnRotGtkZcL+5JAkntLv91lcazKbjlE99RXVrq+ODlSI6ggvBHlRoGyLN964gW25zKIY1/d44+oOC0tdev0mGJfNWxPSMXzLh97DxQsdOk0PzwtxHA/brl4AKQWO4+C6Lhub29i2ixE2QkmEEjQaDbKsOjb7vk8UVQFYRVIipIXjByAF7WaTzlIdN7CPv9kg13OycobllmiTIJUm1hmZPl6GCQtb1SiLiuJ9sD9EF9wTEld3WdCmIMsy8rzSmhZ5JekQKNzAYntzt4J3WIIonhCn8TEFPce8yV4U1f8zyzKypKLVmGNLs5Rf7orDMOQLX3gCRyrqvgcUlEKCBXZNYZySu4O7nLn/Itdv3YZScXJphfe+79186lOfOg5tG5AkEbZTp943/Hf/y/dwde8FynKKbVcbdEfYODhgLIxWFDnkWcUFVarqMmu1WpXVHkUURQEYsjxBK8E0jri7s0WUp0RZSpqmDIfD4242QwhBp9Oh1WrdIzAtr59ic3eTyWSXbsfl4UvrSJlSlBHTZMY8T+9ZNE+dOlXpGIUgz3OOjo6wLIvZbMbCwgLzeZVOurW1xcWLF+l0OlX08PHzaNv2PfL91tZWtQSk+r/Gcc7du9tsb2/jOA69Xg/XdXFdl+nsiMOjAwSKc2cvsrmxzS/90i/xhS98jl6/w2AwYDAYMBwesrm5wXg85OhowGQyYjIZcXR0xOwYepFllc335Zdf5sUXXmNvb8DW1g7b27tEUURYD9jf30dZEi/waS0s4dUaIG20kaAcZklcMTylQEuBsI8RdNLCtjxcJ0Dr4pjJKvEDF6RkHk1Is4iiTLl+4w2Ojo64c+cOaZpXfFijAMX6+gXOX3yQpcVVWp0eDzzwIAKPZmuFhy6/A0+2uPLiHa6+vMl4vyAZSmYHms1rRxQzh1D2qdlN+rVFluqrtN1Fmn6bMjaQSVRps785IJoknFw5zXwcY+Hg+CCtEi1KSgrM8b5D2tX3fafTobfQYR5PidKExaVVgvC/3Bb+v/iltabT66Ix5LrkaDxkf/MI3z3JzJRM44xWrc5sPuGxx9/GL/3879CqL/ETP/IRcrNFs5sRuDa1Rot5WdGp4zxFCAfPrrbSjuOB8ihzMEianWZFdhEK11XkeQ5AFCVIR+CGbhWMlcbUPY+lky2a/RDPc8jjgml6iPQ8lJDkcU6zUUfYAmVLdKExpaDIFRiber3OzZsvInCromKqTlRTzQLf3MRXxbXCqQkUgVvjMx/7It/2196Dsn2m4wNsKwTHJY0n5FlJEASYokKg6VJTJCnClZWchGqrL4zEdSvL6P2X7+cX/t2/469+3/dTRAWFVYErLAuGsynKDjhK5jz+jvfy3LNPcubiGdxTq+w/t8POzg4XL5xjf2cbRIhdB4IJ/+T/8+Nc/9IdPvYfPkkeKVzZIUs1lu/dO9IDOI5LkqQIIQGB7wdoXVbOpSLjwvn7uXVrmyTJELaPfyzGjqKIWsPQaLRwHIedvV06nRbzaArA3Wt3aPc6TEc7vO3Ry8TTiD/+oz+iubRKrm2kHVBIQ6/WIk1TFhYWEEJw+/Zt6o3WvVnkm3rOEydOsD88JJ7H7O3tsX7uNPVWzgsvPsdCp8PN6zc4uXaCyXhCLQjvxe52210OBvucOrlOs91iY2Oj0kAKSb+/yLVrVxiPpziOx9bmDmWR0V9oU5Z1tra2GI/HzGYTAJI0Iokm+GEToxX1WkBZCPI0w7arbunN2OKi0Gxv7eKFFlqklGVGlMY4voNw/SrFwHGwlcKnOh4LJSmdCgQNx1ttyyLJchaXVkizmLzU2J5dxbdImCdzsiwjmif3HHVLS0uUQiOsKj1iMotxXRdl+9ze2OC1166QpRFeDZwENIrD4Q7Xr2/jWholGhRJQTxVOJbN4XiMUhZ76ZQ7yQGOW83TLVHppqfZ5F6zEAQBS0tLeHmd29MNLpy5n8FgH4oIg8FyXApTUuQJOi0oTQmyQvo5oYvte8SzmKs3b9BqtL+i2vXVUUCNQdk2WVlgBFXGTC7IdQlSgVAsr4UMRxOODqd8+4e/hSLNGM9vsXSyR60Jrm9I84iMnFxoNBaOVa9E0QeHhPUWa2sn2bm9i1+rOkBlO2iRVPpLparUvyjFC1wKV9/rUBzbprMQ4vmyIsxoi6AZMktShKxYkYvdJTRFNQdEkgsgr7pNx5UMBoNKQGw4tvhV0h9pCcrCHBeaL0csoA2WhJeee5nv/OFvrWQ/TsB8lmAbXQEx8pI8K/GlotVqI4HNww1aze6xNOrL8A9pBMPBgJVeh7On1omnMZZyuL3/Oo3QYXw0pN5aJnBbRGXG6XPnuXntOiIv6ayGXHroIr/50f+A0oq1lRNkkymuv4gkIzdHrFx0+KD3ONlY8OxnX2d2dMRC5/yxI8hU3XZZuWnyrErGNMbguxbKsciLEksasijGUQ6z4RidF1g2zGYz5nGClBb9xQX6Cy1ev/oGly7dT5ZlGAGzox2+4zu+iTt37rC7OaFeW2SeVUkNskiwLElq+0wmk3tOozzPybKMRqNRbdX7fY4GR/e4p9Xr2uNzn/sc9116iNXVVfI4xrFskihm485dHnroIY6OjpiMjxgc7LKyukQcTXC9gGajTRRVCQOvvfo6s/kY13UraVOguO/Co1y/cYXrN17nzu0NpLSOnVGGZrPOdDwkjaf4rs3o8AjPrQGSKIpQSlVYNikRQLvdpDAJeZ4wnhwwGAxYW19EqQBpF9iOwpaVvlZIibYkhTRIUc2V3eNCOk+mFGRY7nEGVKnRplrs5mWVbRX6Hc4tr1Gv1ysh/PHzmBYFQkOcFOTFIZRVhpbjCrTJKIyh1AValEhLYfsOnW6frMjZ3j1AHY83640a8ygmSRKyTGKpsoqMyQqiLKYopnQ6HYq5YfPGDps3dnDskCc++zRCGIKGYnl1iXMXzhPUQ7TR5JahTHMEVrUbKKubkON7dHqdew3Un/X6qiigQoPrtEiLEdG8YD7xkGUTYWzi+YRGL2Rhsc0rL73GcHDAw5fPsrTcJezY1LohzV4T14O53IZ8imN8yszQ8lJc4fD61j7tusXh3k2INJ3lFeqdNrmcIrIxZapIkiNsd41UW6SFQmUF0i5IpcFoxfrJM9g+1JwaV165g9tvgl0BW5UMsDyLXJXoZEaobIQWMPeQ6Qyv2eDqawe4Xo0sEVV2jJFoo5FUkQm2rSiKau6jjEQaic7gcGNOfJjgqRpH8YD1lZPouArBS6MYUQtxvRZWs83+9i264RqWtinkCCFtNIKiBFsZ2gsthBGcXz/Lr/zLn+PHfuK/Zx4GxHlGv9sji3OsyZi4XkN6Ne5/9FH+7b/4Z3zwA+8n6Nl883e+l5efusqp1bfgtmNG0wGW42DZdcp+wbmVZQYb+zymVzjd+wDzbMpgb8LVV7cZ7M7IpcQon7S08YSDEoZMa3zbwXUNy8uLvPLKKxwMDuj0VpnPpwT1GpmGNJ4QTuroTFEPewRejSSaYtma973rMkpK/s7//A95z7u/ttJyTg8opv69nKSFhQVm07QiY6Ul9bBBq+mR6YxXXn2DRqNJuz2n3WgwPDqkXa9zYDTdhR7vXnkf2xub5POIwPVora5x69ZNHnv7O9jZ2jzmeha4voNl28wPE/xaRWXa2trgoYcu02h6lEXK3u6I6XjGwmKTu1df5cprr7F26gTtuk+ZRkSJYTKZoEtBp7eEa9lkWcZCJ2Slt8Dy0hLt5R6Dwymf+NQnGU/HzPOInaOS7kIfaQlwNP11H68O0TSiWQtxarUqzrlIcR0X31VgGmRFSmoK6jWfPE/J0wgljuePSoFV4jkOy80enudVHausgzZMx2PyNKVUAi2h1qjh2CFxVGDZ1cLX930GgwF5ru51+VmWYYxhmo7JDpNKjmRpHOGSZdmfyNBSaApyXbENLM+nXT8FaBAlWRFV2U5GUehqtDGbzTAq4M6tu7z+2hv3lrOuH9BpL7LYX2Kh16TZqmatwrKx3RCtvjIn0ldFAX3zkKeUwrIkr79+pdKFlTCfzzl5epVWcxEprvP+938NWXZIrRbghZKyTAlDnygfglDoUhEnBmUC0A6u7VHmGqVszHGH53le1ZW5NrO8mhPmeU6axUjLvRfVIJE4tsd4PKXWClCy2hp7nkdxLPw3WmDblfxCKo0tHWzhYIuAyFRk9yiqJFp5XmDMl9Mc723CoRIES758lD/2BNu2YndnwNJ6h7Be4+7OJnXVI2xWIN92q0Vm5dQb9coKKV3yLMMoU8GpsSpxsjbY0iKblbSaXXyvzkd/5Td49FsvURQZ7W4T4wu2N3bxbInv+KyfOskDl+/n05/4DN/83d9ILazzwEP38ff/4T/jv/vb34t0JPNkzuJKkyK3mSZzwmaDtGfYHu5SZnMuP/Qgn/rjT/GTf/vv8k/++c/iOhbTKEYEdZI4RakqZC7NY+bzOWEYEnhNjkYRUlXd/Zv0pPF4TJnC3VtXue++C+xubbJ2YoHnnnmFl6+8QdjscOPOXWqtNkUJQehwdDRgd3eXg4M91k+cptXushvFlIuaIAgoioIg9MiylCzLGI1G97rTpaUldnd3aXU71Gs1RocVY3RnZ4eTJ0+yv79PvV7nzt0BQko8z+PKlSv0ej2UEYSuz4Wz5xgdHrG3t4dUJUWueejB+/jiE59FpLB64iSeFxDNxyjbwy4Lmq0ORiqUUuRJjFKC/YNddJ6xs7sFryje+a738H1/43v5w4//B27tvsyJ5RP4ocM8mdPodjGqga0sllf6WKIijQkhSBMb3/eZz2O6/QbdXov+cptnn3+SJB5jHIjyyvyM1midYZc22wd37r1fLbdZZSYZKj6AUWhTMJ1BnkHg13FcRVG6TKYlYRiS5RGzeUWYsuzqOG4JSRzP723cs3yG53sVylHnYKrkV6Ugy0qyMiPLCqQEIUtsW6JNQZEXZEU1G/cCj8k0Zj4f4PuVRE7KikM6mUyYjie8/MoMnVU3Uz8IEJZifX39K6pdXxUFFKqCJVRJkka8+OKLKLXKfDJHWYJer8uLz17h8uUHuHbzNR59/D56y22yMqIWhmT5nLSMiHINJqTtLrK6cobheBOTZuSJwVEBnlUn6Cra3R5+zSIhxrcllnLI85zpdExpBM5YsVpbxlIK1zUIMcFWxzCFrOJqFhgs5aKNi+/bWJZA2AJpFEUscbVHveYymTUZTSKkkGRZFaD6ZeK3uJeM+Cc9wlJKyqJ6zK8HvPLyNdZOfwBpKUqREzMnLJscHY3o9RaIrBwvzcizkpprmE3nCNep8myEQaiqu3Uch82tLU52Qt72+GPs7x2iyhDPgjtb27TbbXKZ4cm0osnrjA99+Ft4JuyzdfeA2kqI8gT/7Q+9j3/4j36ev/0Tf5FavcHB3iZrF85zeHhIahJ6F1b5X//Fz/IDH/mr7B0c8ee/6yNsbl/jW77+vfzRZ75YxSTrBK9REe21LpjPp3iew3w+R+JW8qHpnHkSYzseluWS5TH7syHSHPHU0R2++Vu/hddff512a4Faa8Z874Ct/UNqd7fo9XocDO7cGxUMh0NuXbnC133jN+GGNe7u3OHchQu8ceU1zp49DxJcx65GJ5ZFHMccHBywvr7O9tYWSilOnTldvT6xzRe/+EXe+pa3EHgVLDoIQ/b396utsGVRJDGu4zCdTinyFN+2ieIZd2/dYn9/nziOKXObZneBNIVmYwFJyVSMUcrGDXyK0uBamgfuu580TXn2S0+RJAlpMed3/uBXOHvpFI+9+xLbn3gewjkzPSBTKZnQ+E4TLSvoTGpslpb7BEHIdJKy0F9mdeUEb9x+mdF8n80rr5PII1Qtx/g2QU1SFBnKEmitAE2rFdwbc5XHLY8wYNsxDh4GTVmW9MI6SVLFyRjHwZQlR9EuxtJoqRnP51UhT1PAryA5xhCGIY1ajURXuVu2XdWELMooTIFQCiUtoFoGal0wn1aLZ1t5cAxrth0BKDqdPlEUEccZtVqNXJcMjgYoIXEsm1bQqxa3qUbmgo1bu19R5fqqKKBSCIoiZTYbksQFaQIiyZjNErrdNkkS4foSoTIuP3wOv2YzS2cIoZhPI+bZFNWAUTTDErCw1OZwb5+wrTjYmNCqd7GtAF1aNJstpGWT5xm2q6pE6LIkCDwsS+J61abXtl2ElIShYDg8xHNcbOEwmU0p0WgNUlmAwrE98iLGqGpu65aafrvH3c0BUlTRB2Dh2P7xFv/YmmYMHC9Z3nzsTQmHMRKpLJK44IuffZKv/cC7AVAC0OlxLHDGeDalXWtTIAhqIbrMiecxqmahHAOq6pKFsInSAq8WklsZYd/lt3/21/lrp76PUw+cYno4I8oy3EaTPEkpMoVxBN1mG68VIrVCGkWz6TFLxvytn/wL/Nv/9y/zYz/+vQhbsLO1x8LSAvvFgFJqvv8n/jKf+bWn+OwnXmOx5vI93/1XOH9fn6dfeZFxVGK0gCLDsmyUkKyurlbxuZaFMOpedEiSV11Hvdbk6GgbKVJ8v8k73/UOXnn5NSbzBE2NZqPLYDDAdgTj8RitDZQJUkoWFntsb2/T7DV56dUXuHDf/ZQCPvnxW1w6ez+T8bAS/R8O8LyK2FQUBadPV84kKSVGGsbjMc1Wi3q9zmOPPYagMoCcPXuWF196Cd/3GY/H9IyGOlAAAKZ5SURBVHo9pvMZgzv7+L5PksYcHh4QRxPGkyGj8RFZWjKdZczzHI3g/NkztBpNUJLJZIKlIYoTClMwn8VkWUZnYZG9vT02t67jNSS39q9w59Ov0VjwSIoJhcnQ0uA4NhpImGN0DsJhFCtq3RoHm9ssnuzzqSf+mERPyMsIYeVomaFsQSkrjqmwDbkpQH4ZpJ0bgxIKo6poDkdZQI7Oc2zbxZGSebJfWXtxKUgRlkCYHKM1rmfj12rH0GqF7TQoy/Lelj+N53iex2w2RpdVQS6NIs8TjAaBSxB6lVvJFNh+9XVZUlTqDCWI0xlGu+hUY7s2eZ4TJRFCWbR7bcosx5I2cVzR8gtdifSL/CtDKn9VFFAhQcgcIeHG9U3GQ0MbRZJkLJ9dZjDcpRMo+os+QQ2CVnXMjmcSL6hTqIR5PEVaFvXAJ5oeUVKC1Ny+tolba+E6IdPDmF7DwXMD3LpLZmIkmqOjo+pFVALHsaquNsupN1oI22ZxqY8lNZblgLCrjTb6WL5S2Q6VigCLUikc2+FwMGAyiSi1YGd7vxpelxKpjtmHx1k0b1KZytIgZbUh5Z6dVQCS8eaMzWsbrF+uI3TM4d4hVuHieyEH+wNWF08ync8Iw5DZ7i5CGExezcK01li2VWXTaI3TUmwf3uHU8gkefd+DoEtMURKGTXYPjxCWhV1omp0A2w1JEs0j73mEX/+13+KB7v0U5ZxmGJAUE97/tY/wyz/3/+V7fvi7SKOcw70jlpeX2D/YISsSHnrfOt/47V/Dv//op/m3v/gLvO2h01x66H7+4A8+Tb+1gjSGea5JC9CFqXJ9jm8qZVniBz493+NgMGI+n9Ns1nnPe97N/vYOH/21X6UQNdbX72cYjVhb7nCzzAlcSZ5MGGcp7U4d21a88cYVlpaWmMuCJIu4du11ep0eRmueeuopFhcXWVxc/v9R99/Bkq75XSf4ecxr0x5Tp065W1XX+/bqVreklm+5lkAWIQFCzIJYNAgYGNiJ2diJUEAwxMwubnYGwa6GltgYEAhJqKVWy7T3fVvX9DV165Z3x5+0r33M/vFknqp7RxpQxyiieSPeOFV58s3Mk+/7/p6f+RrSJKfTaY8yybW1tdDOaYNWqwd29vfQQhFFGmsMg16X7e1thsMhzz//PKdPn+bixYsIFRbIOwc77O4GttR0POH2nWthkKVzlHQU+w3d/grXblzlBmG4FqbgwdK5OCz5+Mc+g/WOjY0NVtc28bdfZOVUH7XSMG9G1FjiPEGKLkpFtMYTpxnTeoRKWqIkIu+mXL95GZW0vHb1OURs8LYlynRIBmQYbKaxpNMJurVSxUd4uGWgA3AqyNZJSRD9SBxOtAgVkfY1jSkxNUQ6QkiJlB4l4pB5Ng0qVsRSg58hpcN4j3ACkUgq10BsSOM4GNUZDQik1JhWkKbZERFEEIwP29qjpaIoQvDHhddTTh1pLxgToJJaQGPAuHB+vADrPKmKvqLY9dURQL2m8jWFN1y7tENOSuo1UWPoyZjCxnRSR9oB1VOIqA82RbiCSdlgdUHNhLSvceWAqKuozITargV1e2HpxkNm7YThSpd86GjsLkLUKJHT68Z0V3OMa4MIrKppTAGiA1agfAxxjSOibSS10TRRS6Q7TEZTBsMOigwfOSIhGSYDdKtI41uUTcn1yzt46/BihiXBL+1BFvz3ILPm8N6CcHivEDqIjahGkOuMKy/f5sRjj+FEjJIZVkg6aZc7WzdwtqZ0Df3BMcr9EbJ0uMrhkgSpBc4WIENAVVJCJPCp4PgDJ5i2FaNJwcnNk5wYnAqUxTQhTTrUSEpT0Rv2OH//w8znFf21LpWokVHDI0+doy4rPvJrL/BNf/Jp6rLgYGsvTJCFRa4n7Eyv865vfxNPf83X8K/+xb/kp//Kn2e+e40XXt3D9o4RtRbbeMpmhvWCYrpPrDbQaHxUc/z4SU4eO84Hf+Nf8YM/9N34xvLx332G4eoaANevXeTMufOMDlvW14+FPql3QENtHVLBsD9gsrdPZy1BS43yjv3bwfbjsJrjZUuaxxTVjNFoRJrmDAZDJpMpN67f4sTpY+gswltPXVWcvf88z7/4ZZIkwlPRNA3XL7zIWq4Y71zHtA17o8Cj7/V6YA2TwwPKyQzfKCKS4CtlfOjbL8RkjPWsrawynszppylNUTLsDoiEpPGGupkxne/RP63Ra1Da0B9tlUNJyKIOw36Xne0bpFnEuGoxrcfrUNF4D3EW44Wjblp0VmJaB8Kjl9WUjxhmq0z35iSdlMoHf3atU+RCclFJEe4TLF54IOh4Gt+AdXifEEUapEBqhdeSSAY77ChZiCzjcHGM8iCMQxOudx0lWJly80bQJlBJoC7bhUFeraqjQI6wxFKRlhFppoEh3qnwubynqVpsbTCmxYuCWTnFmIYoytCij5ALPVLnKBaQuD/q9tUBpCdkIJqE65e2GWTHGe2NObZ6jBs3rxOlsLK5QtrrhMlc46BpKCZT9vZvYaOK7lpGOxbkus/B/i55rNm5fhVnI7rdIfN5ibUCIc2RSISUkjSLaduaOJEcTvbxwiNFuFCMcUSRQilJpiLsrGS8u08kFYpgzaqUQsUaL4PQr/Hh9SeTCVVjWFvf4MaNGwgV1qolTW15ESyB8EsxEQCkB+mP9CuFEHzq459EuRhFhIw0rQnDFdMG2Fdd18hIUjU1p06dYnQwxjmJ9+ro5vFOBjB7rJgVU06dO8md3ZsIaXn5pQt00j5nTj5ElOWsyZSsscycZTKv+dr3vpcLr77G9GBO1EAkBUku+fpveSeXbj7PP/uf/g1J1KWsRjRNwfrKCUglUV9i8zk23eOv/9//EjcPb/PjP/ln6ecZg0jT7/SJopiqasiShLJtaQCDp2gMtY/I04i/9jf+Fi+9fI1f+ne/zukz5zEOut0eXsD+/j7zsmJlZY1Op7fQGzA0jTnSGe0NBrgSEpXhpaCWjrlrMKbltdcu8IUvfobp7JB5MaWqZ1y69CovvfQizgeB5jt37jCbzdBa8/yLX6ZpGuI4Znw44ub1G8znc/b399nZ2eH69esURUVVNVy/fpOmMXS7fVZPnmDz5EkefvhRHjx9jvvPneXMyRMhe5pOsHXF4WSPui4DG8lKdna2qNuSVsyZsEuRjuisZ1S+DAuhlmSqQyRjtITJZLQY1OTk2YB+Z0ASZaAg7XVQOqW1Aq0jpExRC2k4HSfEaYZNYq7v7TE4cYJGxWRCkeuULInRsSLOYvJckyYRic7J4j5JpNFS4IzFGY9EEakULRO8CzKLrhUoYtKoc7Qrv7jUAw8YohSnYlSWce7hBxHJ3YGrUmGKn8UJiY6IlUYhsE2L8xVNOydJJTpyeGnwNGQdzXC9x7HjQ07dd4z7zp3iwUfu59z9Zzh9foX1Exlpz5J0DU79Zx1Aw8CkKltsqUhEj6awSCRKeVbXemSDnDhLSeOM4nDMZO+AM6c3ue+hTYgbVtaGRHQ5sXkfbmFZun1ziyztLtTHG6wJpXGed1EyRcmYOEqpmprjm5sYY6hNjZcSLxWNNaChqAuUlLRFhatbnBJoqfDWUZZzwIEKdhfBW9zgsKysrrG9u4dxHucDZGIJLDfGvC5ASimP2DFCCIQiXF2LUrCYlchWkegMKwERHCDzPAh2dDo51rVBl7OoaIoaa8AueMfOBupf3TToKKJ2NUk3pWzGGFexsjrgU5/6FE3ZYJynnZcc76/QywcYY2mM5+3veCc7O7ukMkFaQZRGtBT80I99N5iIV1+6iGlbRvsjpqMJeX4Moi4u0hw/eYyCkk988TMUtuSBB+/j8oXngRrTFig8nbRDbzAkzWJm5Yi90TYXL75C3Uw52J/xDd/wXbztHe8FHeNRVI0hihLGowOM9RRlTZrkKKGJdYB5TcczdJxgvSfPeoAiikJm3viaupmjI5hMD3nhhWc5HO2wvX2bopwwnuxyZ+tGYHg1DeNxUL8vq4qiLMMwwxjqsuTwMBiWNU1z1M9umoa1tTV6vV6grWpFtrAJGY1GVEXB2nCF937D1/H0U08xn03ANBzs71C1JdN6zKTaZ9rsM3MHtPEUPWwQkQ2O05EmTfp0kyG9dIVu3iFPOxzfPI1pJXnWI4v79LMhkU6wDWi6rPVO0E9X0CpH6xQhIqSIaBvDe55+B4+eOk+zN6fYmpLSRVqF9lFwjdAxzgra1gIqMO2QITkhJom7ZGmfleEGkcxQIiGWGUrFaJ1gjMcYT9NYMBLhNDiFcxJkjBcKoTROgJcieNVLEYD6IphPBkuTBCFUYE0t7MVn8xFVPcfYKvjQK4GXlqyboaPgMJClOXGs0VFL3hH0+pr1Yx1OnV79iiLXV0UJHwzZA+pZOomrQdrg5ZwPU1ZWc9LVDCdgdDhDTD3aKlo1h7TieG+F6d6c02ceYOdwH5HGWBUhZJeNjU3WN3JefOF5up1eUEwnJVJp4GbHHuP26PXXmc4aprOaldUY5wVVXVPWAhUDWpFlMfc/9CAXRzvEJoCOkyTB+gYUSCkQePJuh/2be6g24szp+zgYTbA+xhpHpBTLZHM5IV4GzeX/rbhrf+C9R1iPMHDz8m3e8x1fw4Xrr9GNJHHUo9sZsL29y9r6kEGni0oimtKQqpi2CSWi9R4dqwBklwoVe8qyIE0lg7UOZTtjpZfy3HOf4YGzp/BGUCaO2cEOK3pAHfUQVvDw409y4+Y19scTTpza4LDcQyeKfKj50z/+nfyz/+Xf8r7veA8PP3GW6eSQ/upaGCIoD67m/rMPk1rNi6+9zI//he+nMgd0145x8eWaam65fv0mGEOcGq5tv8L6iS7f+73v4/qVmxzsTambLm9969dx+cpFLl++zOHhPrEKlcD+eEQ/75BEMa41wVpCaYQWrAzXKMoZldNkWUanG9PuFoBitxxjrVv00yoO9g4W+MUOw+EqSim2d/Y4depUkNjzHpkoTmwc5+rVqwy7XepZwXQ6Jc9zrF8osPuIU6dOsbe3h9aatrWY2iDR6DSlu7aGmc842NlmfDhCqJgf++E/xa2rr/JLv/Lv2Dl2lbSXoVNHN+qQdzVxD4yf4o0EIUhlD2U1abQOpuW++8/w5Zde5OzZc7y8/zJZmiKlo5+uUU8r2jE8+fSbOHZshU98/EOoYQpO0ZoSayxJnPDM555ByYhEdnnswfNI7QNCZTaml0QI52llFynDsBXnaEpJkmToKF74iwmmhyUWhRAa2wq0zMBDopMj1MmSigxheOgI+FDpA/20aRpM0KJaPE+jZIpzDttaYh3T+hbXWjwCKSIQgWXlnKOowiCyrBqc8EiRABKhLUqEwW0eBR96eQ9j7o+yfVUEUEfAcb320lWk1UxHY5RXdGNNZxiRHIuJaKkL8IVno3+STKa0SUE0KBGscfPqLhvviBmNX0WtVoynjkT0yDuKwWZC/cqYYrrPfZMVVocr+KQHRHigk02Z2xFGa2xlaAroZhEIQ9vWOCtpJiW2Muy0FhVH6Dbj9u4WG5vrWAlSWZT3CGLmkxZhImbzQ9JezOG0wqNQtEiZBCtWKfAelL9bwh+pJNmlRwwIBVp26AxXuHDhIqce3WB9bchkcoCzUzrpgMtbY+paszeq8Srj+uENht0V5uMZoptDJ8I6jxJB/7K1npaGcj7m+OZJdsZb9I91eeptj/KRj/wW3/ld72e3qJEy5mQmOZascWP3NiIVvPOd7+Q3f/ODKD1gsLJK047JOhLSQ37kz72H3/rVz7J+bJWNkwN2bt/ixH2bTLynmBh+84Mf4vjwLG9+9J1Ma8WP/cRPcn33CgejG9y6vcvK0KHVmO/6rm/lgQf/HJevXuGf/E//mDg6w5nzj3P/QwPkGJ547An63T4vX3iR6XxCJwkYXYcizjt0vaGs5iRxCIAiVhxbW2e+X1E3u2xvHXLq5DrYmMuXHUVRIKWkKEP5Gadr7B0ccDC6RZoGiMz27gb3n38cawRRoiknFU8++SST0SFFWyOinN1piXEWoTRmNuPq1atUTYNUEWtra3QJ57gjU7p5h8NZw/72HeaTEa3Z5Zd/5Rd5+9vexE/+1J/hdz7x2wyPrSCPBTZQRMDKttbQyTTKJaQu4f3f8/1c+PIFVteH/O7HfotHH3+C116+wem1RxGyYTLbI3Y5j519gjP33cf+/iFb129y9sw59ppddnd3ESIhyWNc6/AxGBzet9w6uIEXml7eA5URJx1sY1B1gdYC2zoQjpiUmIS6aPE6ZIglmk6a0FQzYiGh0UeaDVJJxuMxWsiFd5hGyZjah5619xZTFWgpUa2mdqCjiERqGqtQQiIVQYTHS5JOByHsgpnnEF6FYJ5ERFEatGmTCqEC0xEhMARBcgChIrT6z1hMJKxInkuvXaUpG6qqIslS4jQly3Ok1DihsXUAxFtraUyDioNV6ng6pzWGWTnCC0evN6AsW6SIUEphnKXX61C3DVUDiBjhU7TqEMkO8UIzUmuNtQGuYhb8cms9caxJkpQ4Tu9SI5XFuRap3CL4CWAxsWxanHN0Op2Fuv5iUIQ6Ut6/11Rr+R28zmBr8RiA8I4sjblz6yapTlntrbK6uk5RV0E/tS4Yj0coLbCmoW1rVoZ9qjLIx1lrsW2gf8ZxxuHBlKJoqCtHt98DJG1r2djY4Or1K1x+7RJNVdG2LTsH+3RWBiSdHOMsayvrrA/X2d3aJgiUBeuNLM45efIk3/zN38C/+6X/gBARaysDDvb2AAfOcPrsJp/5/Cf5H/7Hv8+Ny1dZHaxy8ZULvP/97+eHf+T72Ti5xv/1p36G21sH/K3/+r/ln/7jf85wcBx80AJdAu2t9Tz88KO8613v4fjxU0Q6o6oqJA5vFy6a3QHdbs5g0KPb6WNbh7eHfMs3v5t/9A//B86cPMtHf+8TtO1dV4BlSyUElVARTKdTZrMZ2zt3ePa5z3Fn+zK3bl/m1dde5NOf/iTT6ZS9g0MOR2PiOMFaRxMuMuq6CepTrQUkSd5hXtUUdUPrPOfOneV7vud7+L7v+z4GKwMm8xkf+cLHuHjzIlk/C7CipsXZFifA4fFKUxtPbQxWej780d/EestHP/FRhNL0Bit0Ol2+5u3vQCtFnmZ465CJ4Iu//0W+9MIzHE722Nnbxk4L1rp9UieQZYuuLbYy2MogLWgviUVCEmWkUUY5qSlmNYIYkJRlSV3XNGUVsmsv8cYzH8+RHqqyxBqBNRKpNV4IhFLMigIHtM7hBNStoagrrPcY7zAejFO0VuIApSOk0hjnsLYOBBHvQ/keJTjjaKpwjQsvUSLY5AgvsG1DHIlAn3YesbhPFQotgme9QmEb+xXFrq+ODNR7rI24c3Ofag60Cp0okkFE2o+DaAKSyEu0U8gEemsd6u4UrxJu3Nji7EP3ga6IpcRZwe7WISf6D9PpdKibMasbq0wOSqpK0lQRWT4gUQKnIrLoDoYqwFZkzOrGBqPxnFWt0EqQpJJIpTRtixJBfi3SnqY+RKs1JBHCa4RwSCtIohRkgEg0xhLEhuQimLVHAg7OucBLXrCPhAiah0smFEf/ntPrrtEUYy69conj920SqRiEovWOTpqwfesmvZ4m8oJunnD5ygUKC51hHyV0wJtagIzTJx9iNt+nqmc4BMOVY0gXI2SDj+FLX3yGd33L+/AxjNuKZ197hdrUQcwWyQ++//v59V//dab7E4YrGdpGuCiim0vOnlvnPe9+E//k//Xz/N/+259AVI66nOPxRJnmPV//Fs4M7+eXf+lf8+j587zna97Dzu4Wp04eZ3Wtx9/8mf+e+x94lJPHH0VHKbOiovAjtrZuk3Ry0kSQyJz3vve9jMZTNo6dYuvOPlJp8lTxJ7/vO/j1D36Y3mCdsqzREnqdjJs3b/E3//qf5hOf+Aw/9iN/ijxdI9Y9KmMw7WKRMT4Y/UnJeDJBSkm328UJg/EzJsWU+a0tvFSk8YB5MWNr+2a4mYH5zvbrrus0zTC2IdZh0u61YmUjKDtNpxPYh8sXv8xKPyXpKDqDhP5Daxy6A/LVCG9LIhTOWXxridMU4R3eC7yQtLahcYKtvZvkec7DDz+Kq+CRBx/h+uVL1PMZWgmaec1nvvBplNQMVlcYleOgiVs2RERY72jqhiiKiI0mimIG3QFxoknTY+GPsR4bLwwAXc3e3jaeoC6fxD3aRQDyHnq9IV54yqIljnOE1agkotsJ1FrvooUehCHALx1CSKwrF/oNgNeh16kkUkcY78FZhCjwzi8UpTRSKJqqCnKJKgIf4WqJjiMiLfHeLszvkmBYJxR4yBZyls45lHdfcSr5VRFAQXCwP2M2bRAiB+vpDBJE6lA5yAg6eY92NqdtK1bvO4uJWnyiaRqNFBlrmyvsH2wjYg9e00kzYhlol3O3Q5QqameweKbzOevHNN6BEppu3GdW7bGxvs7kjiXvdokHq2zducWpEzm6E+GNZHQwxiYSoWKyuEca5+RpGvJOGxSc3NzgmjZMXvsJo/198lxTF4RM2gWFoaX+om3aIwbSXW8kcRREhRCI2NLpZ2htefnlC5x/6GHwDTutoVI1Kysr3L51i7PnTpHlXWSSkamI4vAQ4QSmDU6dUgikUkwnBZ3ugNXVNebjQ1InmE4LsiRmsN7H1oJr167xwCOPo7VmWkxRkUY4SVEZWh+y1b3DbeI0ZpBkaB8jZU2a1Dz4yAZCP8mv/vKv8z3f/90L+buY8WxEFiu8n/Nf/MU/w/Vbl3nk8Yc42N2jdZ4rl6/z5Jue4GBvSpavYX3M8Y11sqzDpZtXuHHzCpESvPNt7+ITn/wI3d6A1dUhJ06c4NrNa3zD172LYS+m0+lgXEKaetIsopjt8ld/+s9y9epLfOJjn2dj4xyXL11jPq8orDnKPo1xR9AbtRjoNaYlikOpqrUKNEMaispxZ8uTJh2yNA3Z/WJI6I3FYomihKyToyLB9s5Nhmt9Tp48iTUJ21s3sM2ESEt2D/do/JTTDxyniWY406CEAikoywItBVIovPNIPFJneB9UrJqmYXfvOo8/9iSf++TnWFtZxXlLMa/J8kAiCKaMkq9799dz8dJrlFVBXZYUtqVpSsChsxgZx8hG0dSW3d0DwNG0+0EiUkbIBe6yszJA6yRkxs4ujAZkqNBcmLYrHzFc7VBWFSCxtWFWFiilUdaR6IzWNUhh8NjQr5c6cJz8QuxHKuI4wzow1kADUicLRpKgKi3WmhDcrQtarDKwAgHa1gZoIH4xoFXgwu9c7QFBpOJg6Ci/sgj6nxRAhRBD4F8ATxKo6z8JXAD+NXAOuAr8sPf+UIQI8I8IxnIF8BPe+y/9x97j2o3bNLVnNpmTyx46sfTWM3THIFWLb2qa8YTjm+vM9YS264llxu1bY06dfpDGlCgdIyLPdDSm1+sgqzrg0oSjP+wjpMT4gtbPmc0PSJIYHTnSKCNqNcPBCncuXidKUopZTbczoKqmNI1FtAmRjom1omhrGhcjXIqzoCBMY2tPL86p6hIpFUmcsrOzgxAKISTOi6OyfGnfISONdS78XHhns/hxxJePPCKFOIq5eOUarQvyaXGa0rqWbt7HmZa68qSDnBpDVbUBsVAUpOkALz1Oeuq6JIoU8/mc8aRBSk837mCbAhs7HnvyMT7zsRcYffnLJHGH46c3sU2L9Y4oy6mdo2oMJ+87w/7skJ29QzqDAXVRk2eW3tATpzFV28MbyW//5u/xXe//bmTrOXF6g2tXr7J15zpffuZ5ptOSnzrxf6HfGfLz//IX+Qs/+Zd45PEpVWl55eUd0rhHWRsef+wpBhsDnnvpBS5ffo1yNuXMmTNknYRbN3cZj/dZGa7hXcP0cCcMN3SGcxZj5/yNn/kJ/r8//z9ycEcxL1Nu3LzNwWROY+rFJFceUWiR/ghmtryprGjAC5QM4HmERUUST8u83GNWhHOqhERJSSwUVsKssNzebrAuaIhizZHvl1KK2s1YWx2SJpJGlrTTGXoc9BPiXg/jQEuBRhIbTz/phutBd4MbgpNcv3qNb3jXe4mjlKRNSFM4sdnn9mHJ7t5tDvf2ydIek9GUX/mlX2Vt4zh1M2U6PyRKDGme0boWTYxvKmYuDvhjHbCeKEnZlPgYhLcYa6j2d0NmJ6BsDMpVxHHM1FSA4NixY6Sqw+ygorU1xhv0goBSzoIwiBNtYDu5NohZE6FECjggmEZGElwlsMKTRBnG1jgbgdY4b/G0mLZFiQgpACuoa8PU7AYzwG7QRNAqRYog8COUCn1QG75nLLRVgxB/vGIi/wj4kPf+B4UQMZAD/w3wu977vy+E+DvA3wH+NvCdwEOL/Z3A/7z4+YduAs9495CElMjUdKOIXhqhNRBJnPIU010a1SHZWMHrBmcsIupRTiy9jZTWOGw0opsktCMDXiGzjMoUaJHgtYGkQmjDvNqn9WtkakjbekSsiHxEJzaYYsLk+i5nHrmPUbGDso71Tp/ZrqfoxLS6JjddZnt79Ps5OomJk1AqCByybcl1HxuNaZMp42qEUxYhG4RTwUzLA5aFK6HF+yAe4vyS3SQJZY0APPlKRu1balORaI2uW2TSI4prJtMRjROk+QpVMWd/d49umlELGEYZd8ZT4sEaUjoSpVC6g1ICayOUTEliSaIUpRoDMBiuI2nppIIbV17hwdOnmceOGst0PiJNEhAeqzUiSTFVyfxwTOd0h7J0ZFGHVDmG0ZzOfQPS+DEeWH2AW9uvsWv22bcVbZoSba7RW2u5dbDPEw89whOPPMDe9lV+72O/w1/4iT/PhVdepGpbdHqSm3v73H//Y8RRzrPPPsvBzja+CRJrebfDxvE1RG3YunmdXnaeZlqQdXtMitf4a3/5r/BvfuHnKQ47jMs52/t77I/2McaCD66Q3hMyI6kQsUHqcM1Z6RBSo2SCWvS5tdAYGbIg31akscIbS916kAHOo7oZsa0DZvJ4j9OnN1k/tkqW9lhf31jIJlaMpuMgxo0lSzo4q/GuwnrHbB7K2SiGNE0ZjcYIggGdUhFZ1mEyr3jv172P6xcvIqVk89g6J48fJ9Ka4aan+9BTWNuQd2K0SheU5ZyyDEGsaPaOJuKHh4eUZcnUBVPAoijC3pQ4pxC1QymB0jF1Ux55l2Xe47RgOh7hrWM4GBC1lrYcg3fESoGBeTs/MvzrdDoBj7xoUzkHztVMvUJIS7fbwQmJdWFin8RAY5BWIrxHiYWNTiOhiZEqqNpbaUhzMJOMNB5gDZRFw3CYI1wo660PzgMIj3EeZIxMJZY/Jjk7IcQA+AbgJwC89w3QCCG+D/jGxdP+JfBRQgD9PuADC3fOzwohhkKIE//H3vCSG5f3mB42RDqlM+ijMpBaIayknhSoUtEb9MgGEW1cEMeK21du0O3EuGTGeL5NJ9ekacpr25c4v/kYxUGBtR2SSGIlgeIoHUU5wtg5jU2JVYqjg5RhYGVlwbhsOJ/mZK6LKlrme3MmBchulyiKSFTCxZuv8dBT92O9CRg4D6kQuKphul8ECKcS7B0ckOQpxrbhZl0sdEsFqCiWrxMRudfzZXlxd3ohg4yimDzJeP7ZF3nze59kUuiFOn3NcDhkPB4zzLusHVuntoZcKezogLIoyHLFpJrjRFDiDwOrQCNVPvT+qD1plgZtyRYORyNG0wm600PiqWuLaRq6SUZnkPPwI4/x6Y99hNlsxnDSYXZQk/VTHnr0UTaHp7jwylX2Dvb5r/7O3+Kn/8Z/gdMVDz1+hpvXD9i901CXNb/4K7/Ij/6JH+Ad73warINWkMUZTz/2BPv7LXuHjjTTTMYjzp9/kDe/+a38yq/9e67euMn1rS3WVlc5eXyD4XDIF79wlZXBae7sXEAevsI//+f/T/7+3/37yGjA3thw7do1dnZ2jr7jZYZ/b/mmZIokqGMJ7RCiQRoXAhfgcKRRzNrqCmsrQ9ZWhiHzpGFrayfgO8uSg3lLNTpEa8nVmzfCuZUaKQITJ45TjGuxtsU7Ay7052xbBlWyOA12IwtLFO8FWoXeedMEWuXjTzzFr/7G7yC9W2irxqG0NxYjPEtbjDiJ8E4zHA4DPbQoGI/HNHayvMeBUBVl3J1GB21bS7fbpdfrkec5URSxstpFCEE/GSw8rI4zGAyIdUQnX4iOZBmts9R1jY4ipnXQFFg6plZVRdu6hSPAPk1TMakqqrKmLg7Z3DzFZFTgsLhORN2WICNS30Ug0DrBmuAFb6xHWkUvH6K9RiZDzDzgPtd7STCri6og4EKoSMP3rogiiRce5/74hkjngV3g54UQbwKeAX4GOH5PUNwi+McDnAJu3HP8zcVjrwugQoi/CPxFgPUTPUQ7YP/OjFO9HiqVqMwjI00zD0IFadSht5LRygq/MDDbu7PLfQ+cpXT7eDWnNRpEl+FwFe8FWRaDcJRlSWc1RWsFognanW6Op4cXKVLEIRvLMkTsmRST0INREXneYyWOkKlnNC+wrkaJhIPpIV568l6Ot8ELSLsgaTcvJnTSBC8SWlPT7Xaxfh/hLWJxA7VtoI0eydkt1MWllKE3u2BKtW1L1u2g4wgnDcJJvvC5L/Gub3krmY4ZE6bFWdbh2pXLnD9zDqRGRTFNVZLGCb5qsQkLLUdBXVfEcQKLY9uF0VtZFxBJBit9DnanpJ2Uz3/xc3z9e7+T2jRIpfHG4RRs3dnl5NqQd7/jnXzsd36T3Ci+47u/i8n0gJcvvEDeiemtZMzbmm9939fx+889y3u+4W3s7ox44OEzXLn8aaIsZ/3kBhcuv8q7nngzn/rYp/imb/lmrl69yrWrlzl9+mGuXbuOtjHCWTpnztPtDPjO938fzz/7LJ/4yEc5ODgIMm87d3jigSd56aWX+NZvfTs/8Ke+g//1X/xztndHoGFnf87+/i5CeMxC+gwEQklUJBcIDLvgTbfESYRpatI4Zn1tjeFwyObmJi+99BJp3qMuK5698iXAIzw0Qi5aNUG/QCIxSJwL/8eGDMk7i5SK2tYY1yClQhLhWoNUDu8j6tahncUShL6FCyiJSAe85OqxTdbW1vjSs18GFIgwkJktlI10pHBWYq1DL5hHeMX+4ezu4qFSokgtrvPgyCCcQ+roiPkTZBU9RkoOC8dhEWTubuzuAxz1jq21KCEpZ/OQ2c7nCOVIotCusNYi04DfXF733ntWV4fkndDPffTRhzl79iy9fkaWx+RZjzTNqb2lsTWNLamMx1UV4/E+W9u3yLMeSmk6WYIAbDVnOmpggahp7IxidIj3lryTBuUz5UGCkMGx19bBJdb5P74SXgNvBf5L7/3nhBD/iFCuH23eey+E+CMhUb33Pwf8HMCZh9d8O3WYOXROJajU4GNB01pOb5xCFA29vEPeUxAbZBQxmVlUFBN3FEo7dK1I04jZbEakU5rGsNpdIc9zJu4A7wPkScWeJBdUdkxje2jdQ3gfpoUyY3VjncOd2wjfoCNBURWMjGDuIlSk8VLTFA0tDq/hYHTIsBfTVi2JTuh0UoxoGWxsMLcTxtMRDkl30GV2UC0a3mG1c87hWkscxwtg8VKZPvRKlxPhNE8CjMWCaz2vvnSVm1evobsRvbzDZFKw0k9pjKWoasqqxnrCwpFlzOqGurQIlSwy4wAFcxak9LBwoWxMjTGGM2fvYzZ9lbo0eBVz+dJFhhvrxJ0Miacs5+Q6Y3Rnj7MbK/x3f/Pv8NyXX+Qzn/0CKtc0afBXUlFEblNkrvjCZ57hc1/MOX/2HFduXuPNb3+a33/my8xmBdfLW7z1iTcTDwf01wZcufQqq5s582aHtNdy4vgxrlzd5/Kl6xw7XrG6OuSRBx9l2O/zsY99hIPZBITjs1/6bfK44e/8P/4pf/dn/1va5jSodarKMj3cYTobY61FR/LIFTRZALa990gt6PdihsMNNo6tUc0LDvb32ds9pG4de6MJuwcjzNZo4cWk8YveWWVl8NzyYVFShEBpAWsDbM2bOVIGqJz3DqRD+AhQKCUQWLyUR9mowAfqsnNIoUnTnFOnTnH92i0mhxMSpYMgt3ZYq/BKB2Ea6VA+AiKsdQsonsSYELyMMeFzOnMUKJfwucZbsBa9uJ2FChz1e61ZpJfLexjpHJ5A+LAqQQLxSo4QNmSKQpAKiVmIieSLbF9KSdEWVJMGhOezz7zIs8++hqcNaBYZBRdPBU1bYNuK+azC+ZooFiSp5sTmaQaDFR59+CGGwyHdzZxer0Nba8pqzmh0QFFOKYoZolVEaYwU4JynbCqm9YxBZ0i/t8pkvPdHCV9H239KAL0J3PTef27x/39LCKDby9JcCHEC2Fn8/hZw5p7jTy8e+0O3cEI9WoOUDhkLdBZWx+uXr7PZX2FysMeT596K10FcYDIu6fb7LCsOYRXDlT5XXr1JLz5BedCQrWVkWcLB3CwUnzxeeqxrArXT+wUryKG0RsqAoxvfuINwLUpYVBYTSYEZtYFC6D1pFB8pJ+V5RttWaCFweBrbhN5ZFDj7zjl0HNHtprRzj625J1BylI1GUcCsApjWHj1n+fiy1FQLC4dLr17kTV/7FuZNMGUr62DYNp8HgdrxeIyoKnqDIZOqpq1a+qs92rY+ulmCH/fis4hFy8BaOp08WBD7kAXfuHmVU2dP4kKyg61axgcN3/Z170RUEz74y/+eSzt3OH7mDP3hCofFhH6eEDtFb6XD7s413vLmp/kPv/tpnnj8aZIkJVEd+sMezV7L4cGInYNDsl6f27u3WDu+graGYmr4um/8Wn7x538R165R1ilKR9x3+gwnN09w332n6fQ7fPDDv45oDDevXeNDH/xn/MIHfp6XXrpIluasb56nLHeZHO4cZfjLTChYJAezvV6vF27qYo+bt66ze+c2sQ69z6o1VHsHODxxlqKcwvmayiz7Zp5EBoto5zzaS0wkcT6UxXGchqyrmS8yUI8UgtYanFALZaMQVL31eOcwzuGR2KZGqYheb8CpUyd4/rnnkTIKPVln0BJQFofHeoMTDi9AtuH+kSIEzKo0JEmCVhDpEOS1CBjjUKqHLfZheGRNuAbrtkUAkb4bKnwbFg2tNd56rJZEOkANhRA0ZUWlQQmBcCBxOB3gR9LLxb2usQiiRQAXeNqyJUkUQgowQdZRWYlrJUokHOsPcDpAp3QE0xEU0zmj288xL2cY0TArx+TxOp1OxvqxFc6ePcW58/cTZTlZJ2U8m7Czu8W8KOl0erS14ebhDdQf1xDJe78lhLghhHjEe38B+BbgpcX+54C/v/j5q4tDfg34aSHE/0YYHo3/j/uf0NaGdlpzcmMVFwOZxziL1QUnjq3iSsPm/eeok4IokzSFYeu1qzzy5MNkWURVT6hMSTleZefmiN7mBlkq8aJiPK5JRESzmGhiK7TOsNLRNhNE1kH6HontMeh06Q9WibIxTQEycRA5DuuIuRYgaiIvuHDhZXw8pZb7FFXNMO2RJ32aGnJ6DAZdoo5jvlfQthalBDqzDDdytu7s4ZVEGg2WAOx1YNswFRReoJWkNTZwgWODFTVKC5SQbF3fpqO7fOFTF3jyzW8nUjFStVTNAavH17m1u8Xp2Rm63T77owmbWZfLV66Rn95gNHckWoQSxluE9MSig9SC1reoJCeLNZOqIs0zMArTCNbzIc3+DKEkeZ5z/sFH6KYJn/vc55CJYuXpx4m+NGV/PkfXfdaHJyjKQzoZYBvO33eCg50pP/z+7+C1F5/nwYcf4sbtW7zpbW/lkzsfoZg5xrM9Nk+v8juf+DBvffJd3H/8LAc7L/PcF56hLD3IKbe3LiCjIMxx8uQmaRbx1qfeyqMPPMLHP/3L/N3f+Dn+/S/9Gz74wZdJ0zcxL1vqG68xnY2ZzhsQCo8kTpKjDLQxNdPplPlC6FcIBWTUTjAvQoBcSrF556gmBi9MKH25Kwhj3QIKI8JilC78qIRSCGcwRYWSYShijafBIn0c+oSuPerDStEs7zsAsrwHwGi0x+7undDW8TUeibEG4yWRlEftB5xHAF56PH7hRWTQQjMvC8zCbymJE1rfgGjp9zPG4ylt42gijepE5J3wvqkPnwcncK3DGYcUYVIeJ2ERbhqJEJL5xLG9s0+iE2jBCUGWJQAkIsF5R7wo34tihowtkvSopRKnKXXbBoNEWnQEbauROkLFHSrnFggVTVOHNhfOMRMgdYr0Mf3BECfA6Iitwzl7s9f4wguvoBZ94qXDwROP38/JB9ZZPbGG1qdomuo/Fgr/wO0/dQr/XwL/ajGBvwz8eQL09N8IIf4CcA344cVzf4MAYXqNAGP68/+xFzfG0rQteb+HTiMMDucUuU6wrWGwusng2AC0IYoTrly6itYxWR683+umIIoVwhtsWyJVULKONfQGfUb1JLAgxCJdVaGEa12AYrCYwtIIOp0MHUkODw9Z28yRUgEaIdojrcpbt24xOJHiaYgTASK4a8Y6xhtHr9ejahouvPYqSRKhFQgMURqRdnPqssa3bsGOWGIQzV1FJqFBKgQW5yzW1yQqQXlLMZuC0Fy/fIdIp8SuCW6XRcXKykleufEy2zs7nD1zjkOtmC8MyLTWOGOOznhoIzh0JMGKQBjIOgjnkX5Kv9dhPqlxWuGKgiuvXuCHf+RHWNs4zuc+/3l2iwmd7gC0YFLWnD53hqvXbrO7u8tDaw9gGktbHRArhfA1WhmEcrzwwnOcO/8AWZYwnuzT6We0ZY+rt65y/MwaK6t9PJa3veOtPPf8F9g9mPNXfuan+Mf/6H9mOi+5cROOHztBHDtObJ7iYHdMa0p+6P3fwc/9v/8//C8/94s89uS78D5B2OADPx6PF8HtrgqWc466rmntckjjj34uh3d3h0t3y9clW+yN2/K45e/uuqzKo1ZM2xrcIvtvnQ1Vy+J5S2wwYtn/FotAU7zu8wSdWP+6963rZQAOFhjhA9wdimgZAqtEURclB9aSZQnDtS5SCVaHfcr5NKgbCWjbBlGz8EAKfXpv3aISkrRN6IU2rg3ygL0U1xp6qymbJx7iud//fXy70OydFwGDKTWIAAHb2FjlsSfup7sa88KXv8zx40NWV1e5deOAejzHmpYsSnFVUDdbfufOORR3VcuC2pgHnYSsVcigq5su7m3vqdqWLE8RStM2Df21AcYYXr1ymy9fuIrynmI6I18E+j/q9p8UQL33zwJv/wN+9S1/wHM98Ff+qB/EIfDCoyOPjwUOkE6gI03e61O7CZHKKSvH3vYBD9z3ADoSOB1jWk+USCajKTiBt45+t49wQTggEorCG4QKpYrDgxRY4zDOgm8RMiKKMjyObrfLZDIhHyhWOjlNubhxnCfSmv39fc48+gBSLmyDlaBpDPFCST3r5LSiZG80Qccp2oP3hrKtiLLQBjDWItqgFr/cAtUyxgqJdy3OB1muTi8nVorZ9oimaHA2wtSwfXvEA0+cZF5NqaYlEkGsdXASTROGx9aYjCaBz20dtmogjRclE8SxprEG6cFaAlbVWpRxbA4HfPnKy/Q6G3zXd7yPhx59jF/74G9RGUua55g0onCgrER4zXD9JNHOhKoomezP6ffXKKua4WqP/YMtsmHO9tYe3/It38Kzzz7HW97xLnb2djn/6Dm+uL9LaWbc2rlBJ0soiil1M+ehRx6gMtf5zQ//Kj/8o3+C//CrH2Z76zbPvfAZqvpxhPCsrQ9517ufIhcNH558gW/7jh9kZ2dCmuZMJ3cwpqHX65EkCUVZH5XwR4LWSh7doEHMJZyP18kL3rMFgLd8Q88axEKcYnnc0kN+Sddt2xYp/BHTLEz17xIojgYs6q64jNYaL5bUYXWX6stdqq+x9uh9j4gXQoTyeflvFdg9ggDIt41l3s6Zz+esrndoBi152gkW0m3wHGrbGiE8eRyTphGNbULfVjhkMgCgrlsaL5C+Jko0kYBJcciTb3uMduZ48csXUCqiamqUSgLQXQkODkZMp1O8qFjdWGNtbY1pMaWsxrzznW/h5VdeZPv2rWC3IbLXLR5JnB7hdJsmZK4ybom0JpIiuBpMy4WASxhA20lBHSmiKPSEldJ41yNLLVhHujFEeEeAs//Rtq8KJpIHdBJDq4OSigo8VxaanHEcQ9aAlNR1Q551Q6CxDhUnOBeku8ZbU5RMyOIOERlJ0qG1d/ngQitQwcBKRxHOLTIAb0CqoEKTJCRJxP7+PsdPD3EOmsYc3ShLyFASZzSNoZNnKBmjRQK1oy5KVJQhUsV0WlOVjjwd4Ox+oOApT5ymuHLBAFlM4u8VE0E5lAbnHY8+/iBaxyjvmR1O8S2YVtDL+ty5scWJ8+tIL1EywrYtnU6Hoq64vb1FOZ3SFEXg5BtLlKQLu5JgoxF44OClDio2IpT3ed6j04cf+u7v4umHn2LSCH727/0sWX+Fhx57EqdUcPs0AVUgvWZWWo6fOM2lC69wuH9AP89ApFy7vUfWkUgVk+fp0d8ZRYo01cR5wrkHzrJz4xa7h9usrg6ZHVZ89BMf4+1vfzOnzj3OxYsX+fQnPsGP/Kkf5IXnX+HDv/Uxsjih3+kyGl3n29/3Jj70K8+Qd08yqQ5o6i0iZRgMBkwmI2zdHtnWLgdGcRyHPpw3b+hJh2vyXjqt93chTwDWvr5fdu9zl1PmNwa04DRwd3go5OvFK5Z9aWvvWks4FwZN3uujyXi4W+4OYvzi2KWS1/I9LeqeAMpRNu2FQykJApxV7O+NEcKzublJURTkHR2o1QRjt/msodvvkKQR1rcgNbYN6AGhw3fhrApUyjwmizSttcjM88RbH+Xll18N7QTjkTLCOY9pVYAQiZTxbsn44BJZL+X8qTOMRjtsbg544MHTXL12i/0bM5rGwMJzqWnuZvTLxSHSAt/WzKuAb13dHDKZTynLijzvkmddbNngjME0TajIfIg1QkscHhn9Z61IL2klqBxUEiOFRLqIru/RjyOaZIZIahLXY/vGIZvHz5LkXUTcYiqPbzxpCs9fu8Hx4XGqYk7aT/GxJYsU8zZAjBpTY3UnBJumDaoxpiSNUyQWKbIgW7cSc7B1A2VOIcs+orE4HVoL8+2WXn8Tm62RpQOGKidaiMhmKuGwnBJlXSo/YT4ekyc9ahvhmhppwPkcJQWdYU4xm0M9ByMxtSbWWWC8KIHMPWfPnWH1ZIyz+0jRZ3vXAH2UNhjj+Pxnn+Et734K3cnwtWQ+Dwyscj5jMtoniVNM7Dh1rM+l3X0amRG7CKTAKY+XEu002ktcU5LGGoHjzMpJ1s7kbN/e5h/8k3/CdjXl+IlH6OQZF158lrc+8m5IA7i+MTWRinGlYpj1OLXWZ3d3l+39jJNn1hndOiTOYkTUsLa5ztaNbZ56/CGuX73McP04s4MZT7/1zXxo6w6Xb27zxLk3cfm1F2Em+c73fhem2uZd734LN7au8+LF59i5fcB3fdu38du/8yFsu8sv/sIH+MD/+gFWT76FnpVY27L+NW/j6tWrlFVBf2WVarsljzJapWjaOdbVONtinAC9pM6GgCWXNFp7d3ELCudiMWH3sMz48Fi/gPJ48NZirQ/8bfV6YRhrLUK6o0GhkgKBQ4ggrWbNwkzQ3w2s7cLmBRv0hr0CrSMQFosPPXKp0NIsUBseKWLwGqRdOMeGhVgvNHeREiscURLT6yRInTE7qIhOZDTFDL2eoiOHxNK0FmsrimlDx0WB5eZqsiyjbgt0ronQ1HWEbU3AfAJppKAraZqGp972MNNJw5ULt2jqgkQEZf82dMZwbRsoqVPJxWoLYxuGwx73P7DGmTNnOXfSM5sfcOnKDcoip62Dni1eoaQFV9CWLVmeECeaKIrYPdwjTjQ/8uf+JDqVaC3ZG21z6eI1Lr12g2psMCKhk3Y4tXoCWziy5itTY/qqCKAAranRURj8GOsRroegJelkEAU6VjGvqeYVZ0+fWcAdBLPZhEgnCCKsbbGupqzm9LsDpAp9rZDyS1ZXV7Fzh/VB6MMZc+TwJ7VCLnpkKomJ8wyZRMyrEutCuSIjxe0bd4Ik10LLsLGGNOkgHFA7mqpCa4kUkvmo5NTJ47hC42qPFjFPnz+Pa1qyJGU2GnN96zajwymNM3hqnBcY0fLwYw/SG0YYX3FscJLnvvQy3oXpKQ6SJOPKpSuUZY1IRKBtTib0+zm3b2+xurqKjhQIhZAxTVlBnkKc4IwnUkEYRHoL3iK8o60rpPDsTCe8fPFlfGPor68w37cI44Ji+sEBcRzRVBNI4iA+7S3ew7yqOX7iDOPZnPF4zOr6gBOnzrJ7eI1eEnO4d0CWZYH2N77DYOUYrQ+MlpWVlYV0nMNimTUVF25c5emvfQevvfICg9UBhbK88+vewbVLBwxWB/zMX/9L7O1vsb01x0UjynLOxsYJ2rYJ2F4B+4f7pGlK1dqgHhVFCBvUkaSIaH3ITI96m4ufy97l3f5bOAZCoJQyMFuWupJyUaYvN2vbIyaZX6A9HMHGxTmHdw69yKCaqjrKqKS4ByJ0j9U1sPDOsqhUv+4zKxmh0oi6NgtRDxF0DxZZ53JBCMOuJSqki45AKYmOJOur61y5dBnlLMNjHWQqIVZ4BL4NwxcfteTdNNBctadZ6Kh2ujG2ldi6QXjwSNCWLM2w1rGS9rn/3Fl+70O/F3CxgtDjF2DxR9Y2tbFIKajahouXLyGV4PHz93PqvtOsba7x/HOXGI8NTd3ircETBJdjFdHUARxflQ1pEpPIhF/4uV/A4vjRH/shNk+vk6War/nap5CRZlY6du7s8MoLr7BfjEhE+hXFra+KABouME8USZq2JM0V3ShGUGFkhIl6SJGyc2fMIF+hMnNk3KBcQjGfcurEJuODaeAQxzHgSdIoBDoZcJXGWOIoZe6CFSpCgPQ0tiJZ9KC8sKRZjNWO4fE1hFbUc0Mcd1B1jbSaW1dvcfbpc/STBGcsPo6pK0PiIpTxJEJgm5pyQSEVXpImip2tKVoJdg4/S7wAK0sP1dxR1y1rx1ZZPbaKoWBwqgtpg04Ea4MTfOTXPklbOYTPF1kSaKkwNbzw7Au86esepZv3GDV7RwOpuq6ZT2fEccre7ojZ4ZR+t4NBE0cKbT22qSAS9Dp9dicj4l6PQa+L0QnjbceZ+06w/eJLbG6e5OLLNzl73yZra0Oubl1h5fhxZqbFEYKDcJ7GWaTyxEmGM5ZZ0RB7QWsUVePIux2oYTqecGxllWo6J+1m3N6+zWOPP8HnPvc5JuUErx2D4+u8dOsq8dYmPtN847d/Ex//3Y+zc3iDx9/yVs4+2Of8+U3e920/wvu/58fYVIqzZ8/jvad/vE8nP6Aq52RZB+EFuy24psYagbOhly2lpm0W7oz3DPHsgid9r6xgmB+G64TFxD30vxcBD7sIduFaRobnLyE7IZMN/XepAzxMoY4U7OWiH7oUA7471FpSHd2il2qxC+jR0sUgLGCeNE1Qyiz6rfHr2xBC4LwnThPUwq/IOo/SEiUitIwY9AYUc8vO1RHRSsTw2AAdp4jI4Wloyim+bciHfZIsRS+IAq0ryaIYmWXM5zVCaCwt1lt0HCMQVHaXd33zm9ndmfDi85fRNpwLTYwmQjpDG0m0kszrBmUtcaJ58eULCG1YP77KN37zu6it5cUXX+bSxasIF1Ty/QJXvcTY0kJxUJBHXQaDPp/96DO8eu0ym/cN+f4f+V5QntreYWVT8o33vRljHIPhCn/vz/zCHzl2fdXogYLEe4lAI0jpRh0ipdFJhEgSlM5pCsvacB2pHDIyVMUcZ1qSJGO0NyPP+kgRY41Eq9CbDOyQoMYex0Fc1S8gJgCNqcOwxodSTSlBnqd0shQtJK62mLKlrQ3FuKAtDDpWaCRZFKO8JG0FaeVRXoVSHR+GFtUcFUkGqx1W1hVJFhOlXYhSrIxoVYSME+Juzt7skOt7V1m/b4W8kxLriJObZ/jCp57FFjHS5bRVuLGckCihSVPN7Zu3EAuRkjiOj2AaTdMgcCipmc4rullOIkRgltRzbD1jtZuSdXpMipLOyhoNku3xDKET+uvrNISJcNHUCx6xhcjxyrXX6KYZ3rZYFwJQrCRlE+TV1tY3ME3FaDyjruzC0/3u0CVPUtI4oZzOEMLTmJa0k5PnXYg8WS9nXs546ZWXAyRFSG5s3WR1c8h9D5/gU8/8Ot/xPd/EB37+X/MDf/J7+NDv/hYf+/jvsLV9k6KcsLu7zfr6Oic2T7HSX2HQDeLPvUG48T3QmJaiLI+GN/f2QZcB7437cvC0DEzLIBau4YBqEMIjFn5Wy98v93sfAxbVzx+MP7zbEw/oESn10bUsvMQZjzN+0VaVR4B7pSRxHB0RMY5eS0CUxERJHBAB1mIXoH+tQ4WSxxneeGJyit2G3asHqMqT6AiVCOJOhhVQVy1lWQOCOErJkjQoKvmGTj/FqQbp9eLzOQQOg8dpWDm5zje+792IyBJnGmfBNI62aXC1hdYjLSgX7r3WCLxNmU0sH//kF7hx8zrv/tq384M/8J2cOjNkdTUlTgRKsyDLSLwO/VivJDujQ0bFnLMnz5G4Af/w736AX/2FD7OZniG3A5q5o20Nh5P9ryh2fVVkoM470iTHWYmUGcIHu43hIKG30mda1dRWINAM+6vstfso7ZkezHDOoIVkOilQKkzkV7tDBIHJIMSCntcGIHFZVwipj2Ak1gQ+slZhOh1FEZ00ITICWks/7TIdN8Sx5rmXX8SZIGSQxjE4H1w4ow5iVqN6GrHIM+qiohUNcUfjjGX9xBqH+w3FgUEogXMeBxipaEzLA088Qnc1RuSORGZgHL/3Wx+lPtBEohs+m2woTYtacKNXhytsb++yt7dHdxA4yFVVMRgM2NraYnN1lWlZ044KzpzeYGuyRzT0nNxcI5I1dTlh7nOQAuM9XmhUFDGbzfEIDkaHbKyvsjOtOHHmNAcHt9GZ4uLNa7x192nibo4VUFUFnd6AXjIEYcn7miRJOJwU9IY9jPV464kjiyIgFZxVxDqibEqkDGZ3m6dOs7N1I1hZVJoHT50h8hIba3qDPs/+/me579z9/Mzf/LNcuvwy5+97iqbRPPbkLlvb1/nEJ2u++Zu+lU6nz6c+/bFAv9w4QV3XGCnptDn1rWAMV9ct1rijYLfM+hB3iR3LLdAVfRi+EKbZRxki9whfi7sTfCEWmejiepASjBBHPj8BGnSXMHEPOgd4/dBqOYS6C5G6O3lvmoYoZkFFbRcD0sDpr6rqqA+bZVlokciAcIHgWGw8TCYTtrZ26Pf73L69FyxDWk1VNVyevEZ+POXMk6ewXqKSmLZo8I2ltY5BPyHPu9SqxGGp6hm9lRQ171DVk9CyaD0iTrAChJaYxvD9P/Q9XH/1Ns/+/ishAbAgcMEeR3u8cWRZgvMSIzXjsQ+L/f6ID/3Gr9PJI77m7e9gdWWDZ7/wChcvXiKONW3rcImkdQaRKLTPKHyLK+coFO946lF63QH/9Gd/gdJY3vcn38Ojb36Auf3P2FRuSX/DtyTWkFnPibVjyCRH6w5d2WH/0pi1zT4zv4uWEl9qNIJYQVtW+ErSiTR5HOGsJYo7yKiP8jHOl3hqutkqTaHQPiWRMZJgDOf8mNrvUnOAbRuiJF5I4+UBptHpIGXEzq0Deus9VtMhqJQESValiHFO7DNEnaCiVVwmGLcTZpVn3tZMzQ4umZEMIB0ktN4xK4NRmxMFTz59P2vHIFEVK1mf66/e4QsffoVmO6HbXcWrBq/C4Eg50MKgtCHrQL8niGVglMSdjNF8SqfXpywqCudxwlFGBT6eQbnFQ+dXSJViZ6/icC5ovcALjfU+DD4weKFQpLSVZf3Uccp2hlNTpuN9tNAMugmvvPglMunQTSAXjOoZ86Kimhumk4akOySLPPODQxKlUdJR40BJrDH0xABGEYkJJnBVW9Dv5zTG018dcG3vEpdvvhJwkC6mFILN+x4gdhmCjOu7t9mNb7PycMpgmHLy7EmuXb3E//aBD1CMDkmUYGf7Os98+RmmdUmUZGiRsLF2GuFSJBFSBB57WzfBdto6TGNZtIWxrVvsLLK+INRxN5AZrK0RwqIJQHuW03QvECoCqYMHuVBoyZFqviS4KywzzHCowDkQQi3oniEQB+3PMImGu0Ioy62pLWXREGh5Eu8UTlSo2CO1x2Hp5h26eYcsykhEQuQjRGsXvfmU/f1dVtYGxAiwBqU00kbUpWLr0pTLn79DVvYYyDWStIdWEbiaebnHpBqjlCDyntXhCtZ7SCriToxXCoMPk3Rj0bYljiwHxRbHzq3ydd/6NHFnjtIW5RpcDe0swtcJzbylaR2mdWghofXM5pY0O4Zjhd/92Bf53Y9/mq/5+qf483/pxzhxdgMRe5SKiHVCHneI44Q0zlFpBxHF7B8ccOPmNb7tm76Jtzz+MB/5D5/iH/w3H+DZD1/4imLXV0UGuoRhxEoSKUWqI65cu8yZxzdxUUVZzjGmZWWQY9oCGREu9Foy7B7j1QtXmExmHFvdACsZDDc5tnIK7wJ4OhYRtpqT9TsY2y5kwSLm8znWGKazfbrDNVrjaRtBlsS41lNPKiKbIlxDJjXTgxEPPnQ/J1bWGdAlt4ZypyDtbCCcpfYl3jZ442nnc7xUCB0hsMhIIyJB3IvoZ4q4Kuj1O/TXc9JU0o16vPryVT7/268SiRThIoy1zDnk2MYqTWPYmu8iZAh0KrYBHxrH3Lq1xUMPP0waDxD+EGs9adrl4HCXPE8ZrIQy58yZU7x88RrGa/orqwhpUYubVikZ1L2bhlk7I4sFnW6OaEsiEXpL3cE6+3sTVjprvHLtIm/5+veg0RTegW/CNF4qqrZBdTOYzqnalp7rEOuc0jga74nimCRN6K1lvHjhMg8//iDTScXacIOVfo+qLOn2O6hI89qFCzz6tqfQdR/fas4/fIyPfPp3KdqaY+dOceX2qzz+rvMcblXcd2KN25e3+P/94ge4/8FHySKojCVai7l+9SrdLEVK6HY6HBwE3Gxr7w6KICSCy9L3XlD8MmC9HmC/YCFZezQIWW5vVNcSIohZ32vpYox5nTKUtYE/vgTVL2FJy+P/oPsmvFcwNKzKhjgJQt0gUQq0DjqmaRqscZSUSGGYTudYmsCUEzCdzAO5xNR4GXqtTVNjMUQypp0JXnn2OoOVFR56+hRFc4BTMca1lLM5JJbhsI9U0O928Y2jmDdESYRUEVVjAnXaSaQAgaZkjuw4vvtHvoub17b44ie/FLJVPLWVBF/e9uh78N4joogWjRCeQW8DnOLXfvMjtG3N008/yTd8+7v50nNf5ub1WzSlwdfhPTUR6AXeVwpeeu1VjDH8ifd/H+V8ysc+8tGvKHZ9dWSgLBRbCCZrtJbV1SFZVxOnEbNZFfqhSmDbGtt6mtIhXEIer1LNDUrHQZSjlfSyVfAx0sdo2SMiwZmG6exwMSwIdqzOBoHhtm2PmCnGGIJcYGA15N2c1pVU8wInIE5TcI7ECG5duERXxAx7A0QUMavn9IYdEC3GNngnFr3XOJRwpsVJg9cVp88fZ+34kBPHN5gdTvj4Rz7P1rUR2nURXqOFxhuPEoLJdMTu7jYrK8FmwXtHdxATxeHCmo1LhA86kf1+fyF0oZhM9/A0HD++xs72IeNRBW0EMqVoLK0VWOPvuUCXE2eD95YoUkSxZn1lhaKaE6UJTW2IdULjDMV8Tix1UCY3YfBSzQt0lOG8QscJxgqa2uGNoqo91iuiNGNSjMh6MYd7+zjnmMxmWB8yDWMMx0+dpGorXnrxBcp5RRrFfP173s19p09xOBnT2AYnG7rrEdHQcfqhPsfu67K6mRPniteuvEy58IxyznHi+CZJkpDnOYPB4Kin+cbAtBR6WQLZlz3LJabyXrzuvcHtXsjSvT+XLLDloGr5uD0afNxlPy2PW0Kd3vieb5Q6XO5LcRgp9cKDqcVZDwvDQusMRVFQ12UQIvZLqbsQlKqF/1Ucx4t/h/ugbWuEl8QqJhYxVILR7UNe/NJLiFaR6YQ87ZDGCU3TsHewH7QYEAgtSDspTjjiLGa41iNOoyDh5xzOe5w0GFmzdXibk/cf5/t/7HsxukamltbWIMKCY63FGLPg9NuQGHmFdxrnJDrq0e2vcfHyJX73o7/N8RNDvvGbv5ZjG33W1nuhxRFrhAAVqdCKiTw60Xzhmc9z7do1fuAHfugril1fFRkoC6AyzpPHCZvrx+j0M7ySlI1nemB54Mw5qrLCtB5bOqTukEfgTUSkOyRJHdarxpHqIbHsgBbEqkOqusRKkmQBXsLCAlUIhfOGpo4wbRgiWVfSFp40XqEsPFvTQ8bNiCuv3CQf9kn7XaqmoWDKxvFjlNMZe/NDbGSwsaKlQMWerd1toiRwe3USk+YJo9GcfkezsrKGEIprV7Z48XMXSJMM2aYIGWO1xasGaxc3qoowrWc+M1SzA1YGQ5JUEXcgyoIndjWvmR7MoRsA+IejHU6f2EQmNVmmuXjxEofXp7z5sbfQzkao1eDtHWgbEhbqOlUVQPbOB4C91JLxaMa5s8fZ2b9DkqZ0ugm+bVgZDrn8yis8+dRbkM4iW4krPVnUY324TlUVaDTsjzjYn3JsPQeV0ziDxoMyqMSzttrnYH8HnypGsz3WV1eoqpKV1T6mhgvPXmF9eBwnJsznW1x+6SZf+vzzPPb0o+zu7hDHMSdPn2TezilNzft+6BuxSvGxj36aV+9oTmycoNnZ4ZEHH+HKlUts7+4wnhywNlzhcLSPuYemGS7Fu1nnvWD45RaC2f9+8HMvdXMZfJcB7ygoy7tmgsvJ/pGZ3UKbdflx/qCM895MeXnc8t/BLmZBC24NQkGaatq2IYoUdTOlbiAxWYD1xQLXhtZBHMeUC8pvUcxJupqyqkiiYLqWxBHSeZxtcNZyeKfmSwfbrJ9d4dz9Z8izhCaOEEGdhMOdPfprK8RxRBynQdDEl3gUURtTV224xlpBlAYA+9bOHTodxU/85T+BbSL+2T/8JVSswISFLkmSMPBKYooiGD1KJZAqQtkotLB0RqQ9d67d4OJsxrGNTR594nGe+eLvMz5sMU1DMy9xrcEIg9IKHUUY5fjYFz/5FYWur4oMFC+QPgefcGxlhY7wkIPOU4qZJ2ENKzzTsmDeFDTTKWpaYEXDfNZweuNpfKPxPiNLhxgDke4S61Vq14DMgMB1ra1nVlqU6qFVB9NC7T1tXaIaS+ISXB2RxQlpDq13eJVz4epVuqtDRJ7gEsFBWmMGOXo9ZWyvU3GIisLF2JaWatYi3KJk05487XDf8TNM9ipeeOYiX37mNcZ7M5QI/u06AkSLkMEDXojQu8qSnLJqiaOMiJT5vMApQ9zPEXGKVxlFZbizuwde0+vGrK9qPBOee+YVdm9NUaJPPBiwU06ILOjao4xCssQTKvAaZyXOahpnqYxFJBkiTbCxIE4y2tqhkxDkszzn4oWXKCd7nOkm2MLSESkrWY/9/X1Gk0NII7JeQl3OKSuJriraqqb0Dh9LpuUBa8dzdg+2SGRCdVhTO0dv0KWYHXJsbYhOUq5d3qYaz1kbDLn46iVmh4pnPvUixcEMaRv29u+Q5hEb5/p8/Nnf5Pt+/Bv56b/945x9YIP90SHGO1567UsM1nsM+h2UBOMNaIXSIRtbTsS9cCA9QoHDItTdYHY08JEeVIBs4YO4xr2ZasiY7F04kgIh7WKotHhMhOGibUNm1VoDUhApfdSPxfnXZZr3Mo2WwRMAZ4mURInQp5Uosiijm3WDK6e3eOVw0lKZOfN6QuPnKGlJ4iCanOQJdeuQmcIJyPMUFWmSboxX0DjLbEHdNA5Mq7hz+ZAvfuJVti7tk/kBkFJbRzTUFG3FtJlB4iDzxJ0EnUXoNCLr56g0VGVtBb6NSaMOVQVXb95hd7LF3/jZP81T7z1BUZXEUbDjMGWBbTy2rWnqKXUxp5oXC4V9AcS0NqGpBIPeSaZjz0c+/Gmstbz1HQ/y+BPH6fUNxze6dLobIDKckJTWIpPeVxS6vioCaDAdVUgXwM1eKmQcZNz2t3cYdnsIL6mLGlsZlHAIaUK25Bz7+/sLcHtClnYXTpeGui6CpoKP8F5iTZCHG4/HVFWDVimdfDVAfrxDS3XkFqilYjqZM5/NmI5nlNOGOE5RsaCVhk6vQ1GX+EgS93K6K33u7O3QeocTgnlVo3VMmvfpdIdYD8/+/gWq0qBkAigE+ghv+Dq9xSPwf3QkWCvc3Qlst5cHqEYcaHqmKWjnU9pmzuHhIcYoppNm4X4YYYyh28248OrzKIJWgDVB0s8YQ9M0r8uMhAsukyGTiknj+OjGljIIsSihmJcVd+5sURcVnU7GvJoyKWfM6zmVbZgeTElUhpYKbCgTg110MExLshStg0K6UgpjGyLdIcsHdLp9vPToTHCwcwflPd5atm5tEUehYrj46hUO9qdURc30YMKx1TW+89u+lc9+8mPYpuCxh8/x4PmTlLM5zdxw+fJl4kSzvr5OFEWcPn369VAff1ed/t7y+Y2P3XuO7sKY/OuecyT8sXju63jq98CZ7n3usq1w77lY6nfqe+Xk7oFcLbe7tFO/sP1QR39bCLbyaF8Or+59HSkl+/u7KCWJIk0cp6RpfvSZlvbPbdsGCqQIw6+mNlx47gqf/cgX6aseJwbHyUkDCgGYjMa08xIhQj9WR2ExieK737XzC10CEWCHRdFw5fJN3vqWd/C9P/qNTN2Y1gZ4nq1bTGVoS0tTtDRFuKaKoqCqqiAQLgStd5w5c4qTJ06gjOezn/gctJ5v+6ZvZnWly+ogZaWfEQnQTqLtVxYKvyoCqPcQWUG/00coSdLroXsxZVkz2Z2wPljBliWXnn+ZlbhHr9NF6oBPm40nOGOIlUb7mMFgDa+CGVaiJEpmRLqPpENTezqdDvv7+/R7Q1YGJ1kfPsige4zxwRxs0D1sjcF6R6ITUpVy5ZUrrPaPMxz20bFA5ZpZPUf2EpqOolCGUTsn6+fk/QC72h9PSdI8NK29wxpPoPf7wMnzodG/3JYqQfcOK5a9WWkDs8QvMqLB+gCVS2pXMqsOcW6OoGR/7wb9Tp/Z1HI4NuTpCuPRjChSdLoRSSqIE007m4Fpw8LhfGBVOY9C4FqD8oKmaqmKiqzTw8wrsjRlMpkECJBpiWREp9vntavXONg7pJdq6nrOaL5PPkiJYk8vz9lY32BleIy927dp26CcP5nNcVJhEOAlg/7KQvhBBVUsr1FJRtTNeOwtD/KZT/42gobPf/7zvOOd7+G1i5cRXrN1Y8SXvvASxaSlnDdcevUSN69fx5uS+WSX93/ne1gZGs7eF7QLPJadnS2sbXngwfPs7m6HimHBIHpjX3O536u8vizV35gZLnuYy/N37/PvHTot32PZ11seF3qZ6nXPWwbP5WdcBt7l57t3Wwa65YLctu1doWgpiVSERKJl0PB0xtHa5ijLdlgOx4ekaUyWZSRJghRBpX+58NV1HT6rDFkoVmIri5snFNstH/zAh/j93/kSq9EG3XhI6lP6cQ8aw53btxFAnqWkiSZLFVGkyLIEpQStqY98qrK0Cz7i+rVtkk3NX/6v/wxve++THM5LcA3eWExlca0D65jNimAFUrfUdcusNMzKklu3buJaw30nz/Hkw29mf2fORz/ySSazMd/83nfxwLkTFKNDiv0DMv+fcQAVAmIt6KbBklTEQYKrLVvSNGdSzrlz8xLvfvvXcP7kWdZXN5jP60UmZRj0+igRxBqKYkbdtrSNx5ng+6NEjpIp1ohFL6UlwD1i0niVYX4fTaVRMiVPEtIsoSxLxqMRmpirl66hkpgoj9FaopBESYyJJG0c9ko4uoM+UZ5ipaQynrQbY1xNlkdEmUDGELpsJkh7ca/3+91e2/LGzbKgRBOILYtMRVpUtJAoEwYhW1Y2+pBZ1teClUmcdojilE43YzKZ0LYWIRT9/hDnLJEUKARKSxYUG5q6DvRCpYhEFHRGRZjoNnXN6eMnApSEe2iGWnE4GoXhX12RRBKB5fb1K9TzKUK2XN++Rd4f0ukOUAR4jpA6iJEQ+OVtaynKOVGkmFVT0MFywSBYP7HB8FiHONPsHOzTXz8WylU0aTRgMqp57bWrHByOFhRdx8mzJzh28hhb+9d4+m3308oRIjMkSRi2TCYjhPCkWRiaBPYar/vu3xgYl9PzP0yl6V6c5vI7WmaCy9d94++XwfqNfdbl6zVNczREWWZ/977Gvdmuc+7IKvuNr+29DyaMC8jW8nrywuGFR+pgaxIlMVmehHMrNGIhOHPvorF8X6UUUiiUiJEiQvuMYXKMw62WD/7yx5ndtkQupypaVKTZWD1OPW8QDnp5h1jFpFlMFCmSJATRpi0XHu72aLE4OJxx9eZ13vSup/jOH/4GKjsj6cRYLLWpKdsC58AYR1OHIC+twtaWoiiYlQW7+yMm04Kss053eJLOYJNf+bX/wHg640/96A/y1JOP8tCDZ/9oQWt5nr6io/5P3gSeWHvSCNJMo2No6pL9nV10nHB96zZZJlgb9DjYPqQqDVXlyPOgnH7y5EkAlHYMVwe0zlIUNdIlCBSgiHQHa4NUXWjWC9rGIUWHfuc0/XwDZ4K1RRyHVVjroCE47AyQmUbqkCmmIscpT2VrKtdQCUPtW/bHI2prqE3oISJaVCzQiUIoT7QoXzwt3psQSLkLYblXl3I5iDDGHHlZSwm9Xi8Ece9YWxnS6eWIDCb1lPFoAki63S6tqVlZ6VHVwaembS1xlHPj2nUiqbCmOaIALllMQgjm8zntwg5a61DKrQ6GDHq9o2DgCSgFVNAtdRaq0YiVPEUJT5bGjPd2mTcjKlNTe4GKOkeTaK2DYo8XgdOvFxKB1lqqekqWRSR5hyzvgIzornTx2lE5i48innriSdrGUpYNnWTAtcs3eP6ll9kfHzKaj8n6GcdOrnNn5xrHz/T4/h/7DgoOSZKEXq9DkiS8+OKLFEVBr9d73XT7Dwqgy8f/oNJ5ub2xzF8GnKWs3fLc3hvYlkH5XouX5eZcUCFbnpd7y/973/PIk2jx+L2qTMCRm4G1nqoKsCVjgs3HvX+zUsFWJADxl5J/d2X27kUnuHuuUYHCycCQMpWgKRTFTPKZ3/l9vvDJF5iO5zS+xRpFnvcRRBzsj0nTjDzPF24A4ZwMBh1YJBdNUwOeJFqlMfDSpRdZO7vCf/W3/woPP34/Oo0QEbS+PMqOQzvKUE0KmnmNsQ1FWTKuKqrGUDaeKF2hIWX12CZCaUaTMV62vONdT/+nB6x7z/tXdNT/2ZvwxJFiMOhhhCXpprQi4dXXbjA53OHkCc1jD5xgd68g759mPJnRHyZcvbrD5tp5hLdsnjxO02hqQHdjKl8itCfWKWnUIdYROEuSaNppQ+NqXOTpxcc4OXyU1c5ZyhEoI6GB+XiCc46bd/aQySpxluCkpBGC0nuKymDbCldPw2TPx8TpEJlY5tWUYjJGJQqUQUcWKTxp2gGXgNd4qXAiPrqxlBII2aK0wQowwmNZmM9FEuMMrTT01jLi1NLp96hnDc3I8IWPPIdocsbzCqk1QnmSjsahSbt9DB4fqYAS6CuaFMpZg2wSXAU0kqYMi0qaZBCnOKkDTMQqnB5StoYormnaCWlHM7HzhRlbzLWtHQpjKKYzUgRSK5Jja9hW080iFCVxN0fMBbGNkUYirEc5STfP6MgOBzdGCB0xmQSnyG4ek2caJQz33X8SqpY036RVmpVjm8ymNaKNMJWn0x0yvVOye2PErGi5urPFzdEepx48z854QpwL/sQPfi0TdYMqmnPm/vsoK0e1EMlYbkHh3AdVd8/dTG1B01wC2iUJiqDr6hEImWGdQ0gZOPDiLkVzmd1KKXHIEKTw4ECICO8X9MyjDNQd7cY0rwuuywVIIpAInLG0dROkHxd0zkCJFjgsjSkwrsZLdSREsgyIbdvSlg7fElwRpCTrdjic7DGrxjRmgjdTnG3BW9zSPdRblA8ceO8V0itiKZBaBIqxl2Q2IjMDilstz//OK4xfmRO7nFxlNFVJp5sxn9WUVQNRoGF2tCGOJGkShcCsFU4IvCnRQqJVwu7eFld2X+Zd3/4UP/iT30llJySxQougX9o0DVVV4doGUxvKqaepBaZ2zJopczthbmYkOuHJJ97C6upJXr54ncJLfvnDv/EVha6vjgBK0POMdMZ0XhKnGXu373D98mukkeHM8RVeeOEOUnYYrB6jalqEUjT1nH4vo9tLWN9cCReLbRj0EoryEOMLmqbGWUkcZUihiDPJrTs3FyuPRyqDs4qNtYc5c+KtSHcKLfrYOiVL1nn+hVeI85RBJ6WXJ0jlaUWFxuNbR5Z06XR6C41HSW0qxtMJB4cTlIyQMmRxIXOx7O9MqQuPsEE6zvt7BxUSKfVRP0zroHTUYDDKkA0Ub/6ax1BJy8HBiKYxFEWJ96BVTFM2NGUNDmIV47EMB6tH9rH9fk6SRhyM9mltg21rYjS+cWivkAaiJbJNCKqmZjKZILTF+IbTp+6jmtfYRiwEKcKg69atW3Q7q8ymFVmSYGuLchFOSIqypjHBFC0brFG0ntpJaqupXGgDDHt9RgdjpgcTlNRUVcV4PEapiChK6PWDtN5wsEYxLXjP176VnZ19mlmBKyxm6ujKIVcvbXHh5WtEecrB/JCJLdk4f4qd+SG9zVV+6mf+DNN2h3mzj61nyKp9Xel8b5m6LCGPSuAl3OgNkKblcfceCxArHUSNvcc2LVj3uiz13kx0+fN1k/U/7E55Qz81iiLCQ8HCeLm/8XN5wN3zM2SRGq2CZ3we9egmfaQPtjJt2wZ/L78QHZcCpFgMkCxCGrxvEdK8Ljteti1ChqpRZLzy3HX+3c/9Kpe+dJNjvdN0sjWskKRxgmlqrKvJuilZli90WoMKlfdmwcTyRzFibiXPXniF/fKQv/mzf5Vv+t6vZW4OyXKNdiDmnroOwXS5z+dzqqmjKQy9NGE4yHjpype5fXgT3Y2J+ylR7ytTpP+qCKBSSHp5B6mgN+zQ+Job168zWM05e/Ysr774KkUV8eCjT1E2BS0NSa6ZjWcLRoUlzROKeg4YTDNHUGNVjZAe5zxRlKFUhIod8/mULEuompLdgzvMizGdbJU8OU6s1qFNsG2Mlh3mZYmlXogVtAjfkkUK5SCNUkxtKcsaLz1ZN6W1DfP5lLYJ1DxjlpNrHRSiVExZGNoGpNdY43DWLxR3uKvIg0dFEicMra45cX6db//ur2feHmIxC+zmcnKsKIoC04TyTKnAM59Ox0RRxOhwQl2XGNuQxgnWGzq9HNO0eAdSqlDWLUH1LKbKMgTKxgY1/5WVFfI0O5JKCyIVgqIsub21jXOG8fgALUE5FoOPiMZYGtMGa2Yvgr2DFDgEvV4HYxxPPPoEO7d2AEldt0Q6oWlCabY6HDAej8mSLsW05tiJFfIulOWcpraYytPUljQesLM95tbNbUBw9cY19g4PSLt56KvGjr/6t3+K048cx+gaK8PwaNk3vDcALkvs5XZvkFj2RZeT8T8MaH/vY/ce+8be570QpTe2Du7d7n38jb+/F8y/DJxvfM97+7RLJac4TsnTHolM0D5ComhbGzj+ArRWRJEGghbAvf7py/7s8v2XPVit9QIeBsIrfKMZRENefuY1Pvobn2O0VbDWO45rAyOpaS2ttUeokzzPiRNJFN9V7A9KSwIhY+Kkw6wqefHiK2ycO8GP/rkfQOegE0+nG2OMO9rbxmJah3MC2Xh6ccbt69eZFVOqpsR6h0MgVcxXsn1VBFAhoNdPSVLYPLVK4+bc2b7NuYcfpNM/xmgf3vnOb6Jqag6me4jIEHUEw946adIhiTvoOIHIBw1Q3yBVS9mMkRIEEVolQdFGQ5LFNNbgsMjY09oxralZXTlOOXdoqbENHB6OSFJJZ6CIOhGDtT6+regpybDboRPnxCojS/MF2yhAoLZ2t3ELkVzTBl96hKfbzfHOoLymKcE10RGkxJgFVQ0VNDaFQGiJ0J6v+/a38eZ3P8LlrQtM5vvoKAnTfELmKaXGGAcO5tMZpjbEKqaqSuI4ZjSaIKVk/dgK4IjSBJSkLGaU1tJ6h5VgpMRKuXAXXdAZAaUzlEw4vnkM4Q2xdDgBUit0HJF3O7z8ypcRqqFpJgy7KbYpsA5mRbXAwmqySDPoZJi6CB7krqUoCqSUTMezhcJUzmgUBl9xHKNVhHct23d22Vg9wblz9+MSw8/+g/+OUTFnWlUYFzFpZ1S1IVJ9rl3c5srLN0O2fbBPVRVEkaKsS0o1523veys//FPfz3yhKbvM+N+YXf5hQ6NlELqXyfS/e673R+0AJQL/f1lpvLEf+kZq6L29zjdSSI/M56QMLptaEydhcc7yBB1JsjwwrvI8XwxownnScUSUxKR5RqfXpT8YkKY5sYoCxtfFSK9pG0tjA8VAakGUaNI8QceKKNGABh8hRIQgPvruXrfLClyNlsGZU0uN8in7t+Z86N9+nF/7V79FMXVo1SHSXYxRzGclvV6PKFYkSUSSqKO/w7QusI8aC04QRzmmFVy+dAMnKv7CT/047/ymN1NFYwaDIXGc4B00TUvTtFT1lJV+j9deuUAxq/CNwzfgG4+vBcr9MQVQIcQjQohn79knQoi/JoRYFUL8thDi4uLnyuL5Qgjxj4UQrwkhnhdCvPU/9h6x0kSxwipP1TTs7u7SjXJOHhvQ1gWrwxNsrB/D6yk22kcqiy3BOkk/z0ljTVMbRBphtaWlxIsS58cgg9qPW6iVJ0oTd6GaTUmV4NDd4naxQ0OLVS21mZOQ0I1Sbl67Q94bQJTS2gmrmeSBzQ0yEtw0vC5xRGsko505aaIomzuM92oSMQRhUTIHESOTlk4vw2uLkgJXBvsPtxD0lS4iEinONNimATknG7a8+1ufJhEdvvDpz+NNi047zE3Av8ZpTOsbVjt9RGGRKmI0niN1jNQRLm6YVXuYeoIxjijqYWtDZBtMdYCMGqxoMCq0CbI8IfYS5RR5kgd+dV0AoJIOhZ8xPNWjaAWpCowlIo/RCU0Z01YJ3ibMpzP6eYp2oQUhU4mTNTuzMTLrYqymddAqRWErHn3sfvbv3CGyOYmzuKakk8fYYkYOZFKTZat0FfhmzrxuqNyMH/qxbw/fU9ohlTlVWeDbilTm7G0VXH7tFlkmuXHj1SChl/QQOmPeznnbNz7O3/vnP82UgtbNg8oWQfnHogKkzUliy+t6i94LpASll9lmoOu6hTiwFdBK8JHCSLHYFV6nCFejfICL0d7NVpcBNWT0Ei8krXUg1VE/ViKO+rJKWJJIkMYS4VuECgPGWEmySJMrRS9LydIYrQAcgyRnJesyTHus5isMkj5dvUJM8BiaNzN84mmMDUGl8gircEQ4FF4EO5wggGzQxqNNhBIh8BjTYF25GEz+/9t782BLz7u+8/Ns73aWu99e1VK3FtuyLa8wNksAmxhwpgKTYRIcp+xAWCqTDCGZLKSYgprUTBaSSSWZJGQhIQwmhHWAsISJjbHB4A1JlmXJWlqtVi+3++73bO/2LPPH857bV4oBS8GRrLq/qlN9zntOn/s+5znn9/6W7+/7FQSfYUxMi43JkWkGMuCbhkLkhAP4yC88xNVP7SPKBbL+MkIP2BvPmM2mFFmKRjBMUqS15Drg7ZSWGik9qsNt50Wf0dRy/6c/zdk7T/Pe7/hm6mQTn++T9gKZ1ohGcXp5hY2NDRrraZqSctpga0/TWFrfUtv6+XtPPg8HGkJ4LITw+hDC64E3EZU2/1+iNvwHQgh3Ax/oHgN8A3B3d/tO4If+wJOQktF0BEbQ2JYrz2xw5z3nWF05wSOfeYJ7X/06fCiZlHtc37hKmuU0ztHr50BXu8KR53nsIneYOe89AkPwGilSpIhkskIryrLEA2VdcVBeZN8+xZWth9gePYUIDodnc2eDLEsxieLEydNUTU1Z1rjWsrK8TJpECrzl5WVOnDiBDyXeWq5fv47S8hCG5L1nNpuR5Bku3KI7c62nrVUE+ssQnRklyYLjy77yzdx5/gI3r2zzwfd/mHJmKQb9yP4T5vg+usaCp5zVtC42CoxJaa1HyRTvJIPhElna44nHL7GyssJsNmM2m7G+vk5TVrgOj9g0DXXbALLr0sZIyIuIFZxMZiwvL9M2ZUynSCAkgEQoyWRWxjpsFS8K3pWI0NI2M5xv0J0mU5H3IUhkiEqS/UGO0oFHHv1UR74SKe9q2zIrJ1gvqJ2L8FkBGEExKFg/ucrb3/E2tnc2EF4gW0U9cTRTS+INT1+8zoP3P8r58xf4zGceAgVpojFaH6pd/sDf+Uv4FJZW+zFSI0TxNymwSuCO1CV/PxjT0dfE72RkV9d6rmMUDp3lvFN+FEA/HwqZp+nPhSMdLRMYYw6fn3fx27aNKqPW4o8I3EWCZ3E4mFEUxSHOE+EomzGj0R7WldR28qyuu3MOX7fYqka4jgksCLzrWKOkB9E8a92dz4ipvDIkJsUY86wyxfymgufRhx7nP/3cf+bxT15BTT2LekhhCiaTKTqL52gSSZrpKCLp/bPgXHHSy7GyssSNjU0e+cxF3vutf4Z3vPNrKdsRwTQsn+zjg6Usp5RlyWxW0rY1VT3FuYa6nFI30z/ITX1u3/U8X/924GII4TLwjcCPdsd/FPim7v43Av9PiPZRYFEIcer3PQkl8SZgk3gFv3L1OotrSzFF8JEgY1Jt4kNJ1ZSAZGf7gF4vZ148DyFKtcYrYSeWFhyRaShFCIMU2WGBu26aQ0e7P9tm1Oyh8kB/kJHlims3nqZyM3QGRa6RClrn8Dh80yJdQCIY9PqUZcm1jes0boIPlsmoxuiErFegOpEtVHSoDg51xaUQ1FNH8AptIrXdHfec5TWvv5vW12zeuMnjDz9FonL63ZCBC47I6Hj0BxjpwpwLtN5Ttw1JkjDsL+CcZ3F5lf2dfTKVHP6foiiYzWa0dXP4A2zado6YOiwnKGnwnShPCIHV5aUIZg4hDgN0Xk1mmjTJkRh8GzvIihZookCej5K+Tes6sucobxElpHdYW1smSSUbNzZZXl1jPJ2glKA/7LGxcZPe8pCJLymbkrIukYngsScf4fyF0wwWEvY2t2N3v1W0pSO0sNhbZndryv2f+DRnbjvLxaeeIDMJuU7Q0hCEIllS/O3/+/u5Od6kCWVUxcSCjE7Uqf8yrf9cdjQ9h1uEIM+FSB1NyY/WTOeTPnNHc1RO5Ll/2xEOI15pInGxc1Fio2otbSA+bixzurwkSQ5rjPNGT5CWpp1R2RlB2A6D+WyHbYREukBoIx2dcLdIZ6Iz14fTafPSwxyEr1RUwjQ6fVZtd36hsLYhDQY5NVx+aIMP/uL7qXdqEtsnFQXlpKaqKrIsO6zZIiKHqzaxXCZkAGGxtuHs2Tu47eydfPz+j3HyzAn+wnd/F69+3d2U9TYHB7uYRB3WhJtyRj2b0jYVIXj8ETmW52PP14F+C/AT3f0TIYSN7v4N4ER3/wxw5cj/udod+z1NSIEeJBQrBZeuXWVt/QwqLXjisWd461u/kmm9T9pv2BldZ7jUQ5ucto3kwdGJxs5bmhpG431CcDjXdtMNFd5btEpivVEIkixlWpW0zlI2NfvTlhktUz+laUpGo012Dm7QUFGHKdZOkKql9hMsJcFOSaSinsxou+mM9fV1gnQ0E0u5D3lvqetaKlzw5EVB3itQCTTOxg6tDyjtqKtd8oHnvi+5m5WTBT2T8+inP8vNG/tI0cO3JavLi1S2xQE6KNJMxQ590zCdlLSti6m7MkzLito6EikoyxmD5SFXrlwG5+j1evR6PUIIUVrWxXlsrTWTcgYqkovYdo5TVFTtBGVkJL22liLRwJxyLXKIWg0PfOqhyLo0qyjLkl6SQOviuUmD9dGBKmXAC+qyRoqUpvbccccFkiTh0qXLSJ0wqypubm2S5oad0S439q7wyNMPMmn3Oaj22J/uUbsJj3z2Ad79p7+JxeWc7d0dtrf3IUjG4wPqSYMh5+IT1/nMw09y+uxpHn7wAfKu7pykPYK2NOmUf/rjP8jdbz6HlY7QzcILIi/o52oOwbOd5tEGj9Y6snHhIrdBHPUCbjnOw9n7IxNMRxs8RzHBcGt4IUodgwv+sCuupIk3naCSNNIoCtXRNurDgQhjDFmWdeTLjv3RiLJuI3qksWR5j7p2HW60wwgriVci/isFwujI0mXM4cV77pQjImC+jpjFWOspy/owcpx/biEEWjxN4zEiRc40abvEL//kh/j5972fg+sNty2ep99bwFkgKIzOWFwc0uvlzHlSm6ZCEJugu7u7XLhwgdff+3oe/dTDPPPURd702nt559d9Nc7XZFkCIjZZJQZvJdODGZPRjGp6Sw31+djn7UCFEAnwx4Gffu5zIX5inxth/Hu/33cKIT4phPjkZFyytLbMpJqytbvD6dNnCWj2dicsDIboNFA3IyazffYPdmNqV9VRRKqqOn3oKKMxB9R676PeTGi6iZ1I5qCMJity+v0+yE7qoDBsHjzDzvgKMp0yGR3Q2IbGV2itWFpaINCAtlhXUs722d3eITUmckrORy61YjZt8a3AtoIkSQ6/+EVR4EPUylEaovyDQBnLHRdO8No33sNgmND4mvs/8iB2FsAJbJAUuSYvEoKA4AXBR8b3qqpi991GMbH5F3gymZFmBVkiKdsp/UFO05Y07QznHIPB4PDcUhPlHJRSnDp1qpuflggRa35A5Omlk7D1nuFCn9ZWhODi5yotrXc0dctsPCMEQVXNaGuL1gkyiKgwqZPuh6dQMuqi2xaqqmV//wCC5pkrV9nd3aUsSxyRYvDpp5+ioWRvusXBdBMbLLsHu9xzz13s7m5y48ZV3vNn340wsLi6hM40OjOU0xlt48mzRS5evMLDDz/EXRfu5JGHH6VXDGJ0pCRtqNicbvA3/o+/xpk7zoLpZtQ7gZkXYnNG+jmBSMySbqWd89vRLvnRjvaR38nnbGjNswbnHFkX/c3fu+kwnyEEvPsvO/bWWkajEU1jsS5Q1/FC2TqPEBw2npxzeDqhvZgyREiTiLhYozOM7h1GzPO0f35ubRtVStu2PZxTf9Z5dM3SEALSOVybIFwP6pT3/+IH+akf/RnG4xKlUpRKCV4dylEnSXJYpvNe4j1MJhM+/vGPcvvpO3jTfW9m5/oW1y5fYX15hW//9m9Da3U4sCJIUDJFkOLqQFl+4SPQbwDuDyHc7B7fnKfm3b+b3fFrwG1H/t/Z7tizLITwr0IIbw4hvDnvGdq6Yro3RvpA1tfsPrPNhTN34aWlZIt9X1J7SV4M2b75DNLv08s1mJrS7mPbClUkTMoYljscVnqCtiA9Lvh4VQ6CzPRoaoFmgLB9eqrPeLpJabepyxmfvvQIrawphilpATppSRNJYXKSvE9bGMrUM1OBUee8tXKMxyOuXplgdB+jAsq1CDtFe0lVtVRyH5UAOiEYRboQ+NK3vYrFM33GB5aPfegxnnl4QlvGhpIIIEPF8LYC0bcQGqQCmUqSoJjul0z3GnyrmU0aEu9JlMe1M3xVofIhg0GPxx97EBss47pma/OAtYUzDPJVknyBJNFgW/au3mDr2k20NFg3Q+uo3U1IUW4JvGBxeZ3awtqZBbyrENKB6Fjt9Yyl5YTp/jY9mTLZr6j9hH6SEGYe4RUyAMHRtnWEyriE0muS/oCzd9zOyok12kYwHk/QwjPa2mIhLTioK0wvp8GzMxpTt5abN7c4e/YcMkl47MY1nrl5if/pXV/P5s6TiFAhfKC1noP9KVXdsLCwwPWnd/nsY5e48567eerpR+j1JEm6QJoMSRLNtY3H+b6//5f4E+95B1ZNEYklyCgWJ6RDiXhDe1SiOufi8EzRxPFajUA6gVEJIsiOVckhicMSBIWUCUqJQ/YkJSRGaZSIjEpHQfzzCDR22lXH2hVFEUUsgnesSsSBCWEw5PH9U4VVnqTTPkcK6rZif7TDtBzFMgEeb1vOnDyBAfJBjs5TdJYgjIq8ujrDS4lPBCEF2QYKZegpRaYFhdAI5+NgSTtDVjOcn2JDw7SZULoRIZRoKUl0glEBESqyYCJONnhcGvAZoFq0COSiz3TX8zP/+lf4xR//ZWa7JWsLp7DNrc+ryDMG/RyUx9GCjMxnH/nEJ3jqylXe/rXfwBvveyuf+PCn+ezjT/C/fMd38Ge++X+kdZYZFRM/Y6/a5cr2M1hZPtdFfV72fBzou7iVvgP8IvDe7v57gV84cvw9XTf+LcDBkVT/c5sQCKWZljPW1pYZ9DL2dw9YWVtmOhuRDwom02mczGks4/0pSwsrcf61sQjilcUg0SHOeUsf8E17BFjcTZKElqKY68UIhDB4BJoMV8HBwZgkTbFd2h3rLpEtyvo4EhlHGMXhREeQgbKc0jrYvLlHkhaRHk5LhNFYAmmvwHpHMlDoLLB+dpFXve4VKHq0leL+j3+acuYZ71dRjKtjikcHFpYHSBkjwCLNkCJGFjvbBySm6FLBW1f3uq4Pr/ZFUSCEYDAYMB6PaZqGXl5QTmfkaYqQgbatWVgc4FxLWU2fhRmcz1ibNIuNB2C4uHw4aiiVADyVaxFGc23jOvfcdTe+rJFeMR2XGJ3jgqRuym56KQLUW++QytO0Fb1Bnztuv4ASmq2NHbwL7O3tUbcNs2msVwcaGjvGthOadkySaUyaI9A8feUqt91+jje++XVIHegNMpIkQ6CpZg7XKHSS89BnHuapS49zcn2JJz77IKkRJEaQdVHXtYNrfOnX/nfc84Z7GJclmDrCdDB4aT5nU+m56f08BZ7XBJ/7mkh4bQ4/5+fWHT8XxnNeZ5w3kOavV0qRKklqEorEkGlFP0sPIzXoMK0EqrbhYDKmbGpa77rfhidJNevr64xGI4okpZ1V6Ch4A6KJKghSIkWCFBkQG4BhDtUKU4QvQYGXilrGKSXbQvAKKRLSZIgx2bOA9la2tNRM7B670x32xA0Wzhes3Nnj9GvWue01p3jF6+8lXxjwn3791/nkgw9FykUvIxeGlxidxaaYNuBvNd2s9fx/H3g/2/t7vOWrvpyD6YRf+/AHeeLKZb7mHW/nj/2Jd/JNf+ob+VPv+ZO8+9v+NF/x9i//g/zf57TPi1BZCNED/ijwXUcO/13gp4QQfw64DPzJ7vivAO8EniR27L/1D3r/AKhEcfX6dV519z14B8Yk9AcZplDsHGzF4njrWOgt8czuM1w4eT6mGTZgTIK0EWYRBF1tdIBQKrLAawvS4XxNIDqT7Y09mqbCuZbgJaGUOCl48vGnWBj08OWUYtBnsNAnydJIajKd0O/3SZMMJQ1Zv087nmFDgw0VXjh29g9ijdY7rAh4KdgfHdDLCzY3rmMyxyvfdDfa5mhj+MhvfgocKPpYC9YGjJIEr0FE1u7hSs6srlDSUBR9qv0xs2nL3m6JIokKl+UUYwytbQgBptMpSX/AcDhkOj5gaWmJZ565yh2nzqG1Zuv6DdbOnaGsK4YLA+q6RGc51lqyIqeqqkNS4KqJbDyDTLKwtERwjhMn1zjYt4es7Uoqam8RWcJDD3+a6cGYul6gSDIORhPkIKf2M1qvI4yHEDvUPmBpuXLpCusrZ1kZrvHk45c4de5NDJcW2Rnt0uvlsWQQldU52B+jEsfG7gbn77nAM5d2ETLwWx/9Hb7ia/4Iv/WbH2J/ZxepMookY1pW7N8cka30WF08wSc+/gA+lNx51wWuXrvEyfVTEAReS1RhGM1GvPu73817vh3+6nf8AOtDSdMaqqrqOKjj5yLVLRKYwHOcp5w3fwJSHmGU956qapBSHXbkD2WPj3TmbzVcbrE0zR2y4lbKrJRC6ghxyqQhkQWpTAhG4pRFoWjrhtlsFveyE5q7BeYPlGXDPffcxYd/84MIDKbjSFVKULsSrRNa20YFOmL9e9ZOSZM81vOlpBYeoVJaH+vnOq0IMnRTTBKlJLVvSYc9hr0+aycusHZ6DS/ayMbUtkzNKNJVImi9Q3S0eifIEepspMfbLZEStJFc39piNpuytLQUyYQAoxRBemxbkQ8XeOTpxwkhkPSHSAS9QRRCdLqmpcY7j1MO2ft8POF/aZ+XAw0hTIGV5xzbIXbln/vaAPyF53UWItDYOkZY+QAZDOtrJ3F4Wl8zbWdUdU3TOtI0YzIqUSLBO1hfX+8wXJI2OBrvsErQeIc2KhJ3YHEuRqMBTZr0mc02cb4hUOE9uFaQqR7TacnyymKElmjN+qmTFJlCiE6aw2hMlqKcYjSZYIMnNBYbLE09Y3t3C2POYLLIsC+FINcJewcH+LLmvvvuYff6ATpo7v/dz6KCiU0BG7v61ntcFxM3tkamApWCsgKTFdjGIfFsbe7gLCgVYUSIW9RpUqsuCr0FpO7lt74hl59+mtOnTlG1LfNRubZpMEWGUoKqqsjzLEZKicJ3cCahFcqk7O7doNfLGY3GiCAQgogLNJLFE+t86Hc+wpe89Y1YHDY4Ll18gle89tVYE+KcOBJvPYVJ0cJTNxW9YY51U1zrqcvIpToYDNgfHZDlCik9tavBa7SO9dtxNaG3sIhUUf7We8uTl57kS9/yJn7lV3+ZVBgQljzt6rwjScgXOHHqHI8/fQOfFNx2epXLly5y912vRCcFtY+UcC54gpF8z/d9Gz/0j/4tRg4j7hKHkBpjNM7f0k46OsroiRyXMfKMGbdSCoQjdNNmRt6CIh3tyB+16Dhv8Xwewn+67vacDs+qQGsdUmXIRMXpH+yz3ruqYiPHz+uwgHctQip6WQ9tFO9615/i3/3IT0ZyECmjYikCpQKDIqH1Nc5PI99EgGk9QyeK2ll8IpCqZTgYcHpxhd6iYX19nd5wQH8wQNHgpSMIT9t4xtMWlTaMR5soAbvjESKRJFJhVNoROid4YkMsokISRFAooWgrSz9foJcN44CMELimRakErTu4Ex5kh4KQEp0llEQctuRWxP9fYy8JSQ+tNZcuX6FXLNBLF7n+zA0unF6nN/C0chrpziYNTWVxrWVtZQkhApnsk2lDXY1RMjqgNtTUYoZVQ4SHxgcy2dCGlgpJYx1pllCXE1xrUV6jrCRpc3IxxFmBSQVpr49KCvZ3djEnBuyXOyRJjmglsyTj5o1rnDt7N3kQhFCSZIatSyNGO4JeUWHyBG0czhrKSpIUPWZWsuAUe1enPL0xQQQNOsrb5mlGXTUI4Qgyvt66hrO3DymdoOj3kGVJpiQ3DmbsbVSkQiODpa08SZJhVB/bTvDBUfs4jeS9RZGQJz2kN5RNw83dfd5072vZ29ln092gDC3NwYyVpUXGSY1qJJSSXl7gWstwMWE6G9Mrhph8QMUOJ06tcemJ6+TFIlJZWpvTCsHEz5hUNYPeOpvuKugEbyuGwlCNZzgDIjfk/V6c0DI5eMvqiUWuPXUdF/ZZHiwx22pZXR+ys3VAVY8YiAyB6FABFdok7E2nnDp/O1pWyKKgsYLdyYhsS/Bn/8y7+LH3/Vx0IiIhyfqMphPCjmRFr5Jmqzz2yE16QnL7+dM8c/0id931SkIlmFUteZYzo+Tsfef4P3/o+/m+v/K3UFWfdpwgkwopC5AJJgUtFa7tuuudzo8SgIgOS0iFFx5knICzXmCdJzOepq1Jkoy2iRdArXKiZEiUrajqGVolXWM0ZkJ9nVLphoNqjMd3hNga37Z41VKFqGbg2xZCiIJu2iO6eixS0GJJbI/gWtrJjNfe+Up+9md+Gm0MZT0jqIBWgtVTC5w6fYI7LpwhKSLpdVEsRUiTVlS2ZdRMSU2CkQZnLbvbOyzonImtGLWWvdEBy8uRHtHoDJEYVpb6LAxTBqMCS81trziHr2FpaSlODuoYIM0OJh1uuYq8n64mQUWomY8E6MLFlF2qhNoKWtGQp32kEzTWonuGwvTJM03jJlhhESS4bnhCYA5lbZ637/rDdIT/Nba/v8+5c+copzNm4wl5Hvn5nHNUVSQFyLKM8TjOsTvnEGlMb9LMMJ61pB1nom1vETvEq7bDB3/YlczzmKJaa/EhatwoZbi+cQOTJtR1HPHLsozVE8t4P2VxcZngZTc2ablw4QLltAUXWF7us7u3wWg0pixrFocpQgi00BiTUeQpk0mNQlCWJVtbI0zoA1FAL9Ea11qC9x1xMiAcs2rM0srtaGPQSoJ0NI1je2v/cJQz1tA4FN2ap38xxfMIyWG398SJEzRNQ56nSKMjzCZobN2S5hk3b26gTvTJZAIYmqZCm5jiEeKMeppoQGASQZZ1uDxxdJSPiC9tI+GLbT0nT5/l0lOXWb5tjUbE857NZsgALS1FlhKCZzKbcvr0aa5f3WN3d5dzd5xne2//kBldSHFYt4sprqdua4YLC0yrgPVx/Tc2Nzl75gRvf8dX8cFf/y1oATy9pKCcVuzc3GblxCrDfMhTFy9jUslwecD2zgbr6+cQGK5e32RxaQlnW9Is4e/9g7/F97zn+1lZWKXumpTBQmMj0FsJjTYSk2pSmeLa5vD7e2giQppCcFjbUpheFISb/5DnHekOMzwcDtnZcdi2gzzlAtt6GhGnlAQKujS/+wPx+96NKfsQ8awAxhlwsZnXtpZUZ4Q0oJViOm2oZMujT3+W+778rXzJiTWSXopvGw7Gm7RtzX41wZXxN7g3uUHSRYUYhUgV4/EYCfTyPl/z9rfx0IMP0CdBGE3QMXKXUh3iXZumYmd3GrkqhKdwOQk525uTW42zJEUHwXC4yPJyNzKqU8pqAiGqgTaNZ3ywj8ejjUBKQZrlJNKgjGGYKJwJICSeeBGDed35aNT/wiLRl8QsvO0gF8uLi8xGYzJtDn/4+/uj+KWpLUXe58aNG6RpAsKRdboqzrmONszjHUynUWnTuurwB2dtiw+WqqrJ0py9vVgDlSqmRdokXLm+QbHQo2ocSutu7lcidY5tDEpGYmZQzKY1ZRnT/42N6/jQsnFlh0G2jEKjhQIbSJVmWKRIH5BOkeYZSSbwnXyZRMRUH4FBIrrJES9rrHCcOHMKrRQShW8lBzsVN65O8U7GRpWfc006EJ6qmuF9VFSsq8jwnWWxkbS4OGRj4yYqN3z0Ux9n+2Ab6TQCTdEvILRceepx2rbEujoCq0ODc4E5P6RtY/NISc/CQo7EoYXGE3Ady8/Z289x8dJTJCLHucDS6gof/Z3fpWdSEi9QPjLgB+fxBA5GcdpoeXWdXm9ACILtrR3SNMe2nqLoE0cpO+16EYmTHYHt7U0WVxYpeilpmkZcZJLwod/6KP3FhDe/6T6KXNE0NcF6cpFip5bxzTH1fsPC8AQPPvAoBwdj0kzw5BOPolXgxNoySgaKPKqbNoz4h//2Bzj9yiFmACIDKyKmtW1i4242rdjfHzGdls9q5OV5zvLychykcDWBBiEtZVUhpMT6CBeKJDIeZST9YS9SxBEIHe+A9Y66bdifjCk7/HGUIvY4D57ArJpStzPqZkrTzrq/5SgZx5sYs3Sqz/nXnOP1X/0q3voNb+arvukr+Y8f/mVe/zVfiutV3Jw9w9Obj7I9vYrPK7LlBJFLVL+HS1J0liJTQ9LLo66U0PR6PfJeD68cjz75CH5Rk671kLkgzSSCFCkSlBZRUE470n5BWixQFKvgBqgwBJvTVjLKejeOg3HJwXjKjc1trt/Y4sr1DTZ3drm+cZOqtegkY3l1hdvuuI0zZ09w+/kzrC6topXi6pXLBO/o5YZgWqxou2ZY+izI2OczYfZ72UsiAnXOsr6+jggw2t3j1OoZ0lRRNxOk0DTNtGNTUty4cYO18+fROo6mORfreLPphLwfr4rj0Yx6pcFoGcH0rgERO9VSRvlfAOdbrBV411KVkmeubHDvG89QTyrSfo40cWJJa42RBtvG0UNjBLaJIHCAopfRtAdcfmqDRBekuiDRCcpkmDSltiUqUUzLmmK4RN0GEh0jOZRAIOL0jgSVJhGfKmvuec1JnJYkIUXbqJp58fGrCJ92cBhJ3PfQjYtOQHq8D+hM0zaeJJH0e0Mmk9gAu37zBqfOn2WYJZTtlGGqSYyMXKBZwfnl8yAMbeMQoSVFgXRAYH9/n9Qk5FmPncs3WFlcwTYjWgcT2dLYFoTgtnPnePihz3DHK08xtRWlm6K15uKjj3Hy/DnaskImJkbaMjLoT2cxuon4zMjEBJKmsSwsD5naEdIQZY9bi7eQpD0aZ7nn/F3s3v8Zin5ObR1tVdJbWuT++z/DV33pV5CKHp986NNMxjO01AihmEwm1HVNUqyQJSt8+sGL7O3uc+8r7+b6xmXWVk+jNNS2ZmltidH+PtYEvvOvfSu/++GP8tM/+cskxSJYT6I0bWPR2qATTdVWJOZWd308HjOdTrFOYUzOwsllsiw7vFiORhP2dvdxriHtJRSFJMiS1oPQDjlnWRINvhsFrusZ4NFBYkODd22cNEoU4NDCs7yywHBxQG+wgC1aQmvJdELrLF4JMuXRqmZpZYnpLKIsKjtFJjKSgDgfSw9CRc5RoXAQRfRcxFppITsGJhkbQklKkC5GfAF0p6aZmNg4VDI5RB60XY01+EDwnrapY1YkBLbuMLJ4mtYf1vqFFGgpIn8uIsITg6IqLZ6aMJ1QpAVLa6usrq1jconMBYvS4co26mdNZqg0BUTH8uQQ4os4hbfWsbq6egjoXhgMIgjezPWsoxSxtf4QBuF82/FlBpxrMYkihLnOdUNd1ywt9nDOxijVxiuOs7HTGTVj6ihnoATj2QzrHDpRNFIfjqZJEzkTpVCd/HIEs+dZQV1HudW6GVPVM65fu0lf3oXWCUYYgtI0wWFtg0wMFjrGe4FwghCIKY4PWB9QHXZQKcHSao9zd6zHbmQXZW7d3KKatmiGh/K78xmGSOIQO6ehS4GaxpL7W/yTcyjMtJxilCdLUtpmhuwVTKuSxaJPLSy+Y/EnqO5i0yKlwugU5yzTaYViQK/IcM0OSmVI6cDfAok3TUOiFaOmwnnJ0uoSly8+xR333EXbETfMf0hGa2xbkqbpodMJIeolzTWBxo0neI8jAqGtd/RShW8c09ksNr+sRQiNTjN825CZjMcfvchr7n0t26MDrty4xu72bsfTmtC0FaODKb1BH5MNeebpLU6eWGJpYZ2dnW3OnrsNZo5Z2bC4vERdRyLuL/vqN1Pbll/6yQ+iZR/nb6XgMbKRCHFrhPOQLd5KZuWU/Z0RaZrgbEmvl5PnObffcZp+f4hUjjRNMSZKbiuZxXJQN+mTJAlSJ9imwvsIWI/yMHGfm6aKMiVGkqSQFRlegHAZEGjHFSuDIUm/IB9oFhZXSPKCvYMpzgUCBSrTGKUxQpDlUddrUs5QJpavZnWJER0bvoBicUhZThlVB1RNJBRRuoeXka80dE3OOVpD+IjDUNpi4pwvwgUEbVQr9aHTfpeHDSKQBC/wUqCFQM6RCUGiZBKJSmjRSrC0tk7wntlkSlWVtAcVi72MvkroJYLeSp9SprStpa7bw9HiF2IvCQeqhGSoB1y9fo0ipAzzITM1YlKVtEEx3p2Q93N2N2/Sy3OcDTgbyBcHeCPwUtFMWzJlgAG9/iJ1XaP8Il4ZbGgJQqD1EKMnNEzw2lPXgqyAzBR8+soTDJZjNNYupIRUIrOENCvQCGzolCu1RMhIMpuYLDrYYAhVoHGaWmlqIVnouoNZlmP9DOsatAygQPcUPrSIEMlwg3VkXRkrKIU1I+545asgdRiboL2nqT07OyXOKxQNVkSaNBk8AU9iNFIIvAxYX5GGQF3vYZ1EZgY/DSgN/X7OweY+K8UAkWUklSaTOVvuAJ0oZpt7qBMrYMBKR9tG7dksj3ri0muE12xWU24/u8ZTlwWiDWgTaFpJi6ZyLWvrC1RTicTgcKyeWObik/s0lcMIh/MWb6CxliBTkiLSDa4uL7O6ts20rpmUnmJxAdtKElnQuhlNCJhGYYIkSTKGiyuUwcTUv5whtcSHnDbJsL5kJ0y4uP00r37dPTHSrh2zaYMSBmU0090xqnH0V/sYM+SB+y9xz4WGV144zQO//UG+5C1fhaFhbzLFBYV0jp0Q+LK3fyknT67z7/75T6FZwjctRsaISSqJd7cY5qWMTjRPLXbmCChcqXAupwoa6QX7O9cwyQ2S3q2Zcu895ShO9gT8oeBbsI46OEQCRkmSrBcRJtYhBQjvSFWGElEmWSHY3ptR1WWnsW5IU0NZlvzl7/4ufuJH/j3O5uyPG9pQ470lSRURRqqxtqGsJsxmESKXZGCMYjAsuOuuC7zuS1/H6dVlTgwWGU32GE3HKGXIi4LxbIoLnkZY2tKjlCfRCqUhdxIlQxwAkB7RT3Ad1EvjEcKS6CzWf31s1vlQP4sfABy1nyBkHGlNZEIzGkU0jgGUJKGgqQwbHdFykiT0zYRer8f6qSFlk1B2rGPP114SDlRKyaxskSqhKPpM2hnBt7jg45XYW2SiGO1PSXsFJs9xCLRKmJMKR17NW2DmNI3CcFkmEGJeoPfdyGOKUobJJEqDKBGYTg9YPRmlGay1FLrAmPglG+QFc+b4+D4glcK2Dc4p6qaruVqPyjvCAhxpGtNRRYFvPT7EiDVJElqlIgwJwbSuUV7jQovuSW6/cAovGggtRmuMlOxs7jMdVyiV4mp/uHMyEp7GqDr4zokKHLeaaKYDc1trGfR67O+NkVrjiKOtgYif29/fP4y8bQeXcd6jpWRhYZH9/X2ci8X35cEStmpYW1piY2tMphW2bmPs6iXrK+uUVUurJUYrXvvGN3L/g59if3TA7bef4dredSQaLxqaJlAUQ4p8yI1qg0wrimKZTKeIJuCcJ8symtksNgNtiDAi56jrmsm4Yqm/wPbOPotLPZrgkMLG1DPAM9eucueFC9x11wWm05Irz1ynKiu0TgDH/nhESAWDlQWELnj0sYucPjHkne94Ox/5yO/winvfRO0Nk7pFmAznGkbVjAuvupM//1e/k7/9A/+UlXRIKzqFAU9kcO/sKJD+EOPZRdpNU4FoyPOMJJUI/Wxe0luk3JFwuyxrTCboD4pYMgmOup5FbgViNJb3egx0/D3UVUUQgrTIUYmOQnW+xRFYWFggNRnXrm4wXDpD1cYxaKliluW9IEk05azGW0Oeds7dGKqqZH+34dOfusjDn3yMaVkhDRTDjNe85tWcPL/K8u0L9PuLEcMrW6Y0WCJ7EspjPUzGNdY7iv4Q7xxaSxAxm0QEpHCRyFlE0qGkg7DNv9veeySaoOJosDY60glqgRAeGQS+qmlF/AwHgzh6Om1aJgdTbh6MSbKUPH9hjPQvDQeqFDs7+yzmQ3rDAozH+igpkOcZOtXkRcrBeJ/bz5xFJSlSp50gmSRTOQfV3iEQeZ4yxXneNqYBIaZERheHjRfrGoxR7G1u4ZmSFkOCcodOBOJccHzfiNkjxOigbSIrUqAhyxI2b1bIIEl1isTHKMAkSAxtLSjyHCUDWa7JC4MdWbIspeoAzsF5vPacPLXAmfOrccY8BGw7wc08m9c2CTZq6CgNXt66Ch/2YH13AeGWzG3btqRE4baqqsiSlMlkA+89o8mY3Gh8aePoo29Ba5LGIk2ksXMioKVka2snsu8IjcdjZIoQFeduO8XT166h6IGPKo9V3dDLM56+fIU7X3U7dVMyaiYMFgbMqoqDyRQZFLYGmUmsD+wejJjsTVlZW2ZWlbQN7Gxt45vYYEySlDCNqZwPAoRGm4zWWYJQDBcHXP/wBqnMKNb6BN8iQ0bbtiQi5UO/8xHe9pYv47WvuxfnPbu7B0wnJUIbQmMZ7Y3xQbJ8aoE0X+TXP/RRpqMpt589wyMP3c9dr3wN+cIS26MJCAUKJk3F7ffcxl/+376dj33gY1x68hnKSYtrReRJkLIDzN/aj6Pz8AjfyVeIjprRYQlkWXake29RGpQSDId9sixhFmZYHyndjIjlJucCVdNSlRVSZfRFJFt2CqomRm3zoYe6CRwc7PM/vOtd/JN//M+wreDGzZtYBCLEYKMqG7SRCFHGGiGxnONDwHkgpHgLtYcgJDJJQMF47HjggacxD1zF+Y+jpKe1FUkmGAyX+co/+jbO3XGaoD37zQZpkoGSGJMwbWYEaynriqat0FqSpjlFv4/SkUCnbSzaxMEDJRRN08QygVKkJkP60PE5BJz3qBAwSmC7zz1NI3521khkF1g1laCtX9gs/EvCgWqtWcwXSYJGuoBSMG4rpBSMJmOEAqylSFJs02KQ9NKiG4lLEUJBt/Fzxpr5KKLzNhJwhFv0dt4J+v1hnNZJEna2t0gTyAuNUJCIJEKHulG4+L5zGYtOvsBonK1xviHRgu3tbYb9BWzjujndFBykWUJwGVrVDHppBBsvpNixRxCYjjs1TiQ60ayfWQFiVzVNNFJ4Nq/tsb81RoW8ozJrECJBEBEI2sSaruy6+XgwgFf+EN6UZRnVeEq/iOqYZV1hckVZV+R5jogfECoxVJMpZthDKhlFmK1FCU2e59hpBSEgk4TGT1AqIAwkyuCnU4JwtEi8kIz2dsjkeVrv8ZRkRc54OmFzc5Ozt59ja38bZ1WE2ghosTiTsHpqje3NMdNZyXgyI1sdomTEBtqmIUlzTJIx5zoJAmblPp/65BOcXD5JspChsoxEpof1X50mfPgjH+brv+6PcTCeYq5ucGNjk93dffppThAwPpiQGCj6Of3+Or/9sYf4pnd+Pfe94T62buwiEkcqFFNvUWhEgN2dEefvvEAzmzKajLly8SZZMUS4OVv9LeKQOcuS1hLnJYg5y3yEZxmjEc+hz9MmoIVgZWWZsixjvTfL4kyWCyQ6IZE9hBJMJztYF2uURQsqMTG1NQm2qnDdOdVNw/LqCmdOnWZ7cx9tovMTCISbk5tAXUWUgZSagO+GUiKyYz5tGkJs7ADIDtSjUDReEKxGGkWeDEDCbCL5jV/7GNs7G5TVhOXVAV/+FW/hznvOs9xfYNruM55OKPqaNF+O2WCwjMoRo+kMnWScWD0ROQBCQCpFmsUarzYaqQQmaDIpafE4W4MWoDTGx5LIaDSKzTbdDTl0PQIlXpgrfEk4UBws93IuX77EwolzYAJN65FKUU1izWK8XZMbgxENwlkKlWC6m3IGXIw8vbJYYWikZqK3KfxKFMJqPNpJNC2EEtuWUHvKmzM2t7aRPUU6WIg8n4UkMQIZPNpHdQYpIjt5sA6Za4KP88ySKbZt2NxoMGZAYhpkKqlDoHQ1xqWEJtbyJD2qmUJog0prjDPYKvJtqtxz8twKaEfVSPKsijRzVc6VS7uMD1qU1BAEQmYYIQFPkLHZEoja3zIEhLJ4IXB+Rl0pBk2PLJe0rUVayUJ/QHVQU8g+ZgBNOyZNChovCUmKKBuCjXLM3lm06THIM+pqhAwVMgs0M4Vvoww03aSXDgLXOoIR1M6itIiyvt5CM+Hee+/h4lOPMVxKODjYQ3kdcd1Esg3vYRo0y+tLbG3uEHzC5o0Za+cUvtJkbgFNAz2NVinORko1qeBgYnnDl9zOx377Y/yR4m0snMjRaROjXmvZG48wC+t84tMP8KbXvZp2UpHYyKa+u7tPnqcYI5jsTboSwQLD1dt53398P1/1tW9gZWkBaWsWizV8tReZ201Ommb4ynP3K+5heekEly4+w/v+zc9x4uQK9WjGIOvhGodQioDBtSUhxKkdjyPNM/IiwzqLSRKcsJEDAYNKUnqLDdYGalsjlMa5gK4NMoRIXBIUTgq0VKz2Ftne3wMXEGkWicebBhkCqa04mJRMnUcIz/f8xW/lZ3/255GZwQURLwhEMSvXsTJFdEdEQ8RGbUbbdhR9nZ8XIiqMKqWwHS2iCBDqGqmiDIdQHts1b11t6aUJiRxQ1Qm/8YEH+M3f+BRKgt/bRyWC2y6c4Wu+7iu4/Y7buFlukWUJJxfXEFphhgl7O/vs7x5gZ56TaydZXz6Nl4HKz3DSExJxONk3p+5TQeFbj0k03juEL+OcPjk4hxdfYDq7L6SFELAukPeKONebROcwT3l0xyCepilGR8q6eHXvVAdxzDXO5xEH3BK9atuWJInTHI2NX+Y8j3Pf4/GYyWRClpqoEmgt1rpDwoM53ZiUMZ3PsizOnHdUYkrF+tZ4PCXYmAJJYqF8MBjEzmy4xfvoQ0NRZEihqCsbcc7eU2QZvTxDS4hDaIHWWXb3DpjNKp5FL9cRozybn1LS1A5nRZztD6ojJOnIFdqojDnXydneuhkF4aruB91JRjRNje+iznIaAfGz2Yyr16/HmpuJLESj8X4HwRl1WvUKY9ThOTnnOHHiBFtbW7E+21huu+02JpNJR7k3YW1tLQ4QuCN75SwH4xFZlh3uj7UN1jYkqerGct3hLPj8+9M6y3333YdSisuXL+OtJ1E5ddWilYkjwgjGo30O9na5cOdZ8kxw8tQ6gznqw8ehgNmspqoswcKZk7fx27/9MdrWMZ6NKZsDcp2QKIkWUfLYiqizvrq+xvk77+BPf+ufYHt3h7SIkZtSCqTCdRcV2aloKqXI8vRwBDQ2nKJaQaDt5FQUSmY4C03jcTZelOZrn9PWaXmL6i0iTJpDWsfJZMLuwYRZ0yJCINiK0e4eTzzxxHOGIG7pMT2X8Fkp1dFG3oqQjxLOzMnJD4cB5FxmWXSibuHwnKSI5TDpYsNI2EAv6bG4uEyaFFy9cpN//S/fx//6PX+H//gffpWty3us5Wsk1jDdnpFYzZmVk9z3mlczGBZsb+1yc2OT6aRBiuyQ4UpLdYizdgSEVmhjUFrjhIzqFEagsgSZvDBX+JJwoAjJ1RtbmCIF4zkod2LK0KUSUWEvYrXSNKVtHf3+EG1k94XsWL5bC87jWhuZWWwkEIn62iHOUAuF99DrFQTXsr+7iZeBfl7grcOkOVrHmlKapjjfonRASUBGpUy8J89z8iJKDljr2dsdkYSMRGQoD8o6Wh8B+cPFRZAREjWd7UcHKiWzWYMUltQIzp5ZJTEC7xqsrrEErJNceWYT2xIbTrLDjsKhA4313jglZNvIcxh8EslIQozwrGtik81HXGVuNJsb17Eu0DhFPbPkMiXThuloTNPBjKz10MbhhDTNcUHghKSVgsFwiAuKxgYWlhZo2hnacAglCyGQ5TnjgxESRdX6Q47WpmmYTCZsb28TGteRi0QC3mldMZ5OWVheAmIdtG1rprMRvX5KlivyJEUCrmkRPoD3qMSwdnKZwaBg48pNHn/kKcqZp0hz8ILMFCwvLZKlBZ99/DFWTgy5695TZInijnNnGfR6cZZaZwgM2zf3KSeOVPRYXzjHZz51kf6gx7TeRduKBWPIhINg8crhjUIkgsW1RV7zpnv5q3/9u2jtDJ2IqCUUJCYRaA2BFqkCvX7RSW2owwtxOR1TzcbYpkYRqMaCeiK4cXWPtgRFQl211FV7S32yifU7ozRaKYLzzOoZk3LCja0bbO1uUfqEIDSKhu//3r/Bj/yrHyV4TV03EdXiIgn5nEVqXr6asz8dJXlWSh0GGFrrw8boUU6AuWZUxF13kEAZf3tCxKxJ+RrpLAt5D+0ShMlB5nhbkKp1Tq6cZ3zZ8YlfeYgf/rs/xj/63n/Or/7IrzFohvTaHna/IpQtF86tcNupZQaZxs4mbFy+xvWnr9JMKuysQdpbhNQtHpHoKBeiDcJodK4Q5oW5rpeEA/UusL58gulojDGexESmdYDRaISzUZ5grp1eVdXh+GJsEhFp/qWKtGRSkihNsLeu0jGSBI+gtXGaJssyNq9fp+jn9IoC6QNIFdmg9K3IoCynpNpghWNcTfHWdqOgDRD1jg72S6SOXWtpEoKU1G1D1dRMJhOsj/R4ZVmzsLDQYSUrUI7eQoEXjqA9LjRIAjjNdM8z2W5xDrRODj8TiHpjkelHRmliodDacDimFiQhyA7/GSUepIiYwtTEIYTZrKKyFmMShIvgaK01XvhDJ6qEpp01LBSDCBiv2ji3HRxV3VA3lsGwF7VrjD784XgfLza2tkgnCUQdqqIoDmUaNjY2yJMcb0Mce9UpQUlEF+V6HwmV9/bGKHmLSNc7h5YKozWEKLpWtw3OtZw6fYKFwSJPPfk0bd1QVjOMAqNlpFtTkmy4yG9+/OOcunCes6dPsTDscef5Cwx6A8pyGj/XbqhjejBBhYLxgeXBBx+hPxxw9dplFoYZC0XGYp6igsPJikk9xipPf3GB1RPr/MXv/gsMF/roVMZpHOnJi4T+ICcvDMbEBlPU55kxnY1jWUqmKEwkVpk5xgcz8rQgOE81K7sUX+I7wbvYrIzWy3KEDzRty+7eHpPplKquCV4gvOOO207SNhVVHTvtSqaHUejRzG1+Eazr+pC2cR75ziPJeSYwb1bOG2VNJ5dT1zVV2dDUUTI7qhxEpy9EJKlJTNZlmo6mbWk7rHee5IgAqc7BKZKQc279dkyV8SP/5Mf5oR/8YX7hx36JZx68gh1NybzHtDVhdsDZE6e47eRpMmUY7exx/fIVtq/fQProIyKZSydtIiFYi1LPiw/+1u/wBf2vP2TzzpPqlFNrJwhtTWhmtG2NdS0CxXRaxitdkmNMiveQZ0WsvxCjsXk6r8Qt8a3gPU1TMZ1OY5oqNB5J1VoGgwFrK8sYHTXbMxPHL5U2JEl2hKfRs7y8RHCW2jYIrZCHjQFHkmp2dnYpZw1OO2SqaTxUroMJdXKyhyDxYHBOMJ6MKHoJg7UFFtYXaJWnpsFpj61ayv2Gjae2sWPdOUOBUrHmp3RsTsyjgnhVjyli/CwCzrcdFKWDzniB1gaTpmSJYXFhyNXr1wlESeR2VmO07uanoWkagvMxBbae0c1d6nFJaCxu1lC3FQsLS+R5D2Uky8uLh059ntaNZ1MWFhbw1tG6mMKtra3RNA1lWRJC4J4770I60aWbdOOKLbOyZGVlhbaFpy9dQ6sC20KaFIe8pPN00jmHD4FpNeNNb3oDTdWQ6YLf/NAHaeoDPDPy3OCMZ7C6ShUMycI6H/7Eg7z5S97AysoKUkrOnTvHyVMr1M0EJSPxxvbmFtOxJdGLzCaCD/7Gxzl1xykefvghchEolGCQaKycEXQcb2i9Is363HXPK/mWd7+LO++5nVm9T9POaG1JlEOZi8HdUlCwtsXV4BpBM3M0M/cszGOep4ff+bmTU0qhhKAuK6aj8WEE6XwLInJ95kXK8qBgdaHHH3/nO/jx9/0EprdGkhQkSdaNQd+SEnmuRMn87x+V+pifw7xEdlQsbl4Oiam6OGSmDyF0zth2wnAGB5S2ZlKP4tCIBkSL8xMEMxo5w8qa2nmsk4QmYTFbZT0/gx4VPPwbT/Bv/v7P83993w/zr3/wfTz8W4+B9RihyE3KysISd5w9x91nb4fasndzixtXrjE9mODKmlwZFAHlX1gNVDyXvPXFMCHEGHjsxT6PL7CtAtsv9kl8Ae3lvj44XuPLwX6/9d0eQlh7Pm/20ujCw2MhhDe/2CfxhTQhxCdfzmt8ua8Pjtf4crA/7PW9JFL4Yzu2Yzu2L0Y7dqDHdmzHdmwv0F4qDvRfvdgn8N/AXu5rfLmvD47X+HKwP9T1vSSaSMd2bMd2bF+M9lKJQI/t2I7t2L7o7EV3oEKIrxdCPCaEeFII8b0v9vm8EBNC3CaE+KAQ4hEhxGeEEH+pO74shPjPQognun+XuuNCCPFPujU/JIR444u7gs/fhBBKCPGAEOKXusfnhRAf69byk0KIpDuedo+f7J6/40U98c/DhBCLQoifEUJ8VgjxqBDirS+3PRRC/OXuO/qwEOInhBDZF/seCiH+rRBiUwjx8JFjz3vfhBDv7V7/hBDivZ/XH58DZl+MG6CAi8AFIAE+Bdz7Yp7TC1zHKeCN3f0B8DhwL/CDwPd2x78X+Hvd/XcCv0qcy3wL8LEXew3PY61/Bfj3wC91j38K+Jbu/r8A/nx3/38G/kV3/1uAn3yxz/3zWNuPAt/e3U+AxZfTHgJngEtAfmTv/uwX+x4CfwR4I/DwkWPPa9+AZeCp7t+l7v7SH/i3X+SFvxX4tSOP/ybwN1/sDflDWNcvAH+UOBxwqjt2ioh3BfiXwLuOvP7wdS/lG3AW+ADwNuCXui/hNqCfu5/ArwFv7e7r7nXixV7D77O2hc65iOccf9nsYedAr3ROQnd7+HUvhz0E7niOA31e+wa8C/iXR44/63W/1+3FTuHnGzq3q92xL1rr0pw3AB8DToQQNrqnbgAnuvtfrOv+R8BfB+aCPyvAfghhPgd3dB2Ha+yeP+he/1K188AW8CNdieKHhRA9XkZ7GEK4BvwD4Blgg7gnv8vLZw+P2vPdtxe0ny+2A31ZmRCiD/ws8D0hhNHR50K8rH3RQh6EEP89sBlC+N0X+1y+QKaJaeAPhRDeAEyJqd+hvQz2cAn4RuLF4jTQA77+RT2p/wb2hdy3F9uBXgNuO/L4bHfsi86EEIboPH88hPBz3eGbQohT3fOngM3u+Bfjur8c+ONCiKeB/0BM4/8xsCjEIZ330XUcrrF7fgHY+W95ws/TrgJXQwgf6x7/DNGhvpz28GuBSyGErRBCC/wccV9fLnt41J7vvr2g/XyxHegngLu7LmBCLFT/4ot8Ts/bRKQF+jfAoyGEf3jkqV8E5t289xJro/Pj7+k6gm8BDo6kGy9JCyH8zRDC2RDCHcR9+vUQwruBDwLf3L3suWucr/2bu9e/ZKO3EMIN4IoQ4hXdobcDj/Ay2kNi6v4WIUTRfWfna3xZ7OFz7Pnu268B7xBCLHWR+ju6Y7+/vQSKv+8kdq0vAt/3Yp/PC1zDVxBThIeAB7vbO4n1og8ATwDvB5a71wvgn3Vr/jTw5hd7Dc9zvV/NrS78BeDjwJPATwNpdzzrHj/ZPX/hxT7vz2Ndrwc+2e3jzxO7sS+rPQT+d+CzwMPAjwHpF/seAj9BrOm2xEziz72QfQO+rVvrk8C3fj5/+3gS6diO7diO7QXai53CH9uxHduxfdHasQM9tmM7tmN7gXbsQI/t2I7t2F6gHTvQYzu2Yzu2F2jHDvTYju3Yju0F2rEDPbZjO7Zje4F27ECP7diO7dheoB070GM7tmM7thdo/z+aWffeoY3/wwAAAABJRU5ErkJggg==\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "lena = scipy.misc.face()\n", + "img = transforms.ToTensor()(lena)\n", + "show(img)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[{'boxes': tensor([[ 67.7731, 21.4386, 953.7158, 699.8793],\n [ 202.9559, 4.7902, 940.4207, 679.3505],\n [ 29.5735, 21.2866, 376.5114, 424.0385],\n [ 0.0000, 301.0412, 1024.0000, 768.0000],\n [ 52.2440, 281.1678, 784.5737, 733.5809],\n [ 57.0902, 18.2170, 954.9303, 709.1071],\n [ 27.6776, 359.6552, 814.2780, 753.4029],\n [ 78.1657, 32.2182, 938.7345, 703.4693],\n [ 50.6699, 31.5133, 918.5210, 722.1469],\n [ 0.0000, 260.4532, 729.0366, 768.0000],\n [ 480.9375, 512.6833, 784.6242, 616.1514],\n [ 0.0000, 268.2257, 953.8960, 768.0000],\n [ 100.8516, 354.4102, 766.3854, 718.2952]], grad_fn=), 'labels': tensor([17, 18, 20, 15, 16, 23, 51, 16, 20, 64, 16, 62, 20]), 'scores': tensor([0.3728, 0.3323, 0.3065, 0.2696, 0.2288, 0.2064, 0.1333, 0.1174, 0.1026,\n 0.0963, 0.0725, 0.0574, 0.0549], grad_fn=)}]\n" + ] + } + ], + "source": [ + "# Get predictions from model\n", + "outputs = model(img.unsqueeze(0))\n", + "print(outputs)" + ] + }, + { + "source": [ + "Let's plot top 5 boxes detected by our model" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-26T09:34:59.912114\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "boxes = outputs[0]['boxes']\n", + "colors = [\"blue\", \"red\", \"green\", \"yellow\", \"orange\"]\n", + "\n", + "# We need a uint8 image for plotting!\n", + "img = transforms.ConvertImageDtype(dtype=torch.uint8) (img)\n", + "\n", + "result = draw_bounding_boxes(img, boxes=boxes[:5], colors=colors, width=10, fill=False)\n", + "show(result)" + ] + }, + { + "source": [ + "## Visualize Segmenation Masks" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "source": [ + "You can use `torchvision.utils.draw_segmentation_masks` to draw masks on image.\n", + "\n", + "You can set the colors as well as transparency of masks drawn.\n", + "\n", + "Note that this util requires a single RGB image of dtype `uint8`.\n" + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [], + "source": [ + "from torchvision.utils import draw_segmentation_masks\n", + "from PIL import Image\n", + "import requests" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [], + "source": [ + "url = \"http://images.cocodataset.org/val2017/000000281759.jpg\"\n", + "img = Image.open(requests.get(url, stream=True).raw)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "torch.Size([3, 427, 640])\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-26T10:46:04.209868\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "# lena = scipy.misc.face()\n", + "img = transforms.ToTensor()(img)\n", + "\n", + "print(img.size())\n", + "show(img)" + ] + }, + { + "source": [ + "We will draw a few maks on lena!\n", + "\n", + "Note that the masks contain tensors denoting probabilites of each class.\n", + "\n", + "Here is demo with torchvision's FCN Resnet-50. You can also try using DeepLabv3 or lraspp mobilenet models." + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [], + "source": [ + "from torchvision.models.segmentation import fcn_resnet50\n", + "\n", + "model = fcn_resnet50(pretrained=True)\n", + "model = model.eval()" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "output = model(img.unsqueeze(0))\n", + "masks = output['out'].squeeze(0)" + ] + }, + { + "source": [ + "Note that this utility too needs uint8 dtype image.\n", + "\n", + "You can vary alpha to get more transparent or filled masks." + ], + "cell_type": "markdown", + "metadata": {} + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [], + "source": [ + "img = transforms.ConvertImageDtype(dtype=torch.uint8) (img)" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-26T10:46:11.418103\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "result = draw_segmentation_masks(img, masks, alpha=0.2)\n", + "show(result)" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-26T10:46:11.879624\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "result = draw_segmentation_masks(img, masks, alpha=0.4)\n", + "show(result)" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": "
    ", + "image/svg+xml": "\n\n\n\n \n \n \n \n 2021-03-26T10:46:12.511543\n image/svg+xml\n \n \n Matplotlib v3.3.4, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ], + "source": [ + "result = draw_segmentation_masks(img, masks, alpha=0.6)\n", + "show(result)" + ] + } + ] +} \ No newline at end of file diff --git a/test/assets/fakedata/draw_boxes_vanilla.png b/test/assets/fakedata/draw_boxes_vanilla.png new file mode 100644 index 0000000000000000000000000000000000000000..bbc7112deb0977b8fd30b429e154dbcaceb1eb91 GIT binary patch literal 360 zcmeAS@N?(olHy`uVBq!ia0vp^DIm)gc2BhlA7G zf8Q_qE6Vd~qgdvgpE@E>CS1t&I=(Hp-nz%|+nqYS|M&kfrYnUhKw-hmxVd~R*6ls4 z5s{4%FnF-0#6Z=j*Lk;2SwpfkTM{b-`p*lCOTRPgd}ROMH;jF`5*?y2xX0M)&!H&> zsi{zvNvy}`SFVdQ&MBb@04o)F1^@s6 literal 0 HcmV?d00001 diff --git a/test/test_utils.py b/test/test_utils.py index fcf05edd11a..b9893cdd1ac 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -9,6 +9,9 @@ import torchvision.transforms.functional as F from PIL import Image +boxes = torch.tensor([[0, 0, 20, 20], [0, 0, 0, 0], + [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) + masks = torch.tensor([ [ [-2.2799, -2.2799, -2.2799, -2.2799, -2.2799], @@ -106,8 +109,8 @@ def test_save_image_single_pixel_file_object(self): def test_draw_boxes(self): img = torch.full((3, 100, 100), 255, dtype=torch.uint8) - boxes = torch.tensor([[0, 0, 20, 20], [0, 0, 0, 0], - [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) + img_cp = img.clone() + boxes_cp = boxes.clone() labels = ["a", "b", "c", "d"] colors = ["green", "#FF00FF", (0, 255, 0), "red"] result = utils.draw_bounding_boxes(img, boxes, labels=labels, colors=colors, fill=True) @@ -119,9 +122,41 @@ def test_draw_boxes(self): expected = torch.as_tensor(np.array(Image.open(path))).permute(2, 0, 1) self.assertTrue(torch.equal(result, expected)) + # Check if modification is not in place + self.assertTrue(torch.all(torch.eq(boxes, boxes_cp)).item()) + self.assertTrue(torch.all(torch.eq(img, img_cp)).item()) + + def test_draw_boxes_vanilla(self): + img = torch.full((3, 100, 100), 0, dtype=torch.uint8) + img_cp = img.clone() + boxes_cp = boxes.clone() + result = utils.draw_bounding_boxes(img, boxes, fill=False, width=7) + + path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "fakedata", "draw_boxes_vanilla.png") + if not os.path.exists(path): + res = Image.fromarray(result.permute(1, 2, 0).contiguous().numpy()) + res.save(path) + + expected = torch.as_tensor(np.array(Image.open(path))).permute(2, 0, 1) + self.assertTrue(torch.equal(result, expected)) + # Check if modification is not in place + self.assertTrue(torch.all(torch.eq(boxes, boxes_cp)).item()) + self.assertTrue(torch.all(torch.eq(img, img_cp)).item()) + + def test_draw_invalid_boxes(self): + img_tp = ((1, 1, 1), (1, 2, 3)) + img_wrong1 = torch.full((3, 5, 5), 255, dtype=torch.float) + img_wrong2 = torch.full((1, 3, 5, 5), 255, dtype=torch.uint8) + boxes = torch.tensor([[0, 0, 20, 20], [0, 0, 0, 0], + [10, 15, 30, 35], [23, 35, 93, 95]], dtype=torch.float) + self.assertRaises(TypeError, utils.draw_bounding_boxes, img_tp, boxes) + self.assertRaises(ValueError, utils.draw_bounding_boxes, img_wrong1, boxes) + self.assertRaises(ValueError, utils.draw_bounding_boxes, img_wrong2, boxes) def test_draw_segmentation_masks_colors(self): img = torch.full((3, 5, 5), 255, dtype=torch.uint8) + img_cp = img.clone() + masks_cp = masks.clone() colors = ["#FF00FF", (0, 255, 0), "red"] result = utils.draw_segmentation_masks(img, masks, colors=colors) @@ -134,9 +169,14 @@ def test_draw_segmentation_masks_colors(self): expected = torch.as_tensor(np.array(Image.open(path))).permute(2, 0, 1) self.assertTrue(torch.equal(result, expected)) + # Check if modification is not in place + self.assertTrue(torch.all(torch.eq(img, img_cp)).item()) + self.assertTrue(torch.all(torch.eq(masks, masks_cp)).item()) def test_draw_segmentation_masks_no_colors(self): img = torch.full((3, 20, 20), 255, dtype=torch.uint8) + img_cp = img.clone() + masks_cp = masks.clone() result = utils.draw_segmentation_masks(img, masks, colors=None) path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", @@ -148,6 +188,20 @@ def test_draw_segmentation_masks_no_colors(self): expected = torch.as_tensor(np.array(Image.open(path))).permute(2, 0, 1) self.assertTrue(torch.equal(result, expected)) + # Check if modification is not in place + self.assertTrue(torch.all(torch.eq(img, img_cp)).item()) + self.assertTrue(torch.all(torch.eq(masks, masks_cp)).item()) + + def test_draw_invalid_masks(self): + img_tp = ((1, 1, 1), (1, 2, 3)) + img_wrong1 = torch.full((3, 5, 5), 255, dtype=torch.float) + img_wrong2 = torch.full((1, 3, 5, 5), 255, dtype=torch.uint8) + img_wrong3 = torch.full((4, 5, 5), 255, dtype=torch.uint8) + + self.assertRaises(TypeError, utils.draw_segmentation_masks, img_tp, masks) + self.assertRaises(ValueError, utils.draw_segmentation_masks, img_wrong1, masks) + self.assertRaises(ValueError, utils.draw_segmentation_masks, img_wrong2, masks) + self.assertRaises(ValueError, utils.draw_segmentation_masks, img_wrong3, masks) if __name__ == '__main__': diff --git a/torchvision/utils.py b/torchvision/utils.py index 54cf4c3e4c2..39423e3b227 100644 --- a/torchvision/utils.py +++ b/torchvision/utils.py @@ -20,7 +20,8 @@ def make_grid( pad_value: int = 0, **kwargs ) -> torch.Tensor: - """Make a grid of images. + """ + Make a grid of images. Args: tensor (Tensor or list): 4D mini-batch Tensor of shape (B x C x H x W) @@ -37,9 +38,12 @@ def make_grid( images separately rather than the (min, max) over all images. Default: ``False``. pad_value (float, optional): Value for the padded pixels. Default: ``0``. - Example: - See this notebook `here `_ + Returns: + grid (Tensor): the tensor containing grid of images. + Example: + See this notebook + `here `_ """ if not (torch.is_tensor(tensor) or (isinstance(tensor, list) and all(torch.is_tensor(t) for t in tensor))): @@ -117,7 +121,8 @@ def save_image( format: Optional[str] = None, **kwargs ) -> None: - """Save a given Tensor into an image file. + """ + Save a given Tensor into an image file. Args: tensor (Tensor or list): Image to be saved. If given a mini-batch tensor, @@ -150,7 +155,7 @@ def draw_bounding_boxes( """ Draws bounding boxes on given image. The values of the input image should be uint8 between 0 and 255. - If filled, Resulting Tensor should be saved as PNG image. + If fill is True, Resulting Tensor should be saved as PNG image. Args: image (Tensor): Tensor of shape (C x H x W) and dtype uint8. @@ -166,6 +171,13 @@ def draw_bounding_boxes( also search in other directories, such as the `fonts/` directory on Windows or `/Library/Fonts/`, `/System/Library/Fonts/` and `~/Library/Fonts/` on macOS. font_size (int): The requested font size in points. + + Returns: + img (Tensor[C, H, W]): Image Tensor of dtype uint8 with bounding boxes plotted. + + Example: + See this notebook + `linked `_ """ if not isinstance(image, torch.Tensor): @@ -209,7 +221,7 @@ def draw_bounding_boxes( if labels is not None: draw.text((bbox[0], bbox[1]), labels[i], fill=color, font=txt_font) - return torch.from_numpy(np.array(img_to_draw)).permute(2, 0, 1) + return torch.from_numpy(np.array(img_to_draw)).permute(2, 0, 1).to(dtype=torch.uint8) @torch.no_grad() @@ -230,6 +242,13 @@ def draw_segmentation_masks( alpha (float): Float number between 0 and 1 denoting factor of transpaerency of masks. colors (List[Union[str, Tuple[int, int, int]]]): List containing the colors of masks. The colors can be represented as `str` or `Tuple[int, int, int]`. + + Returns: + img (Tensor[C, H, W]): Image Tensor of dtype uint8 with segmentation masks plotted. + + Example: + See this notebook + `attached `_ """ if not isinstance(image, torch.Tensor): From 25120fb71927e6b50ce55c6cd7bf7c9546f46629 Mon Sep 17 00:00:00 2001 From: Parmeet Singh Bhatia Date: Fri, 2 Apr 2021 07:34:11 -0700 Subject: [PATCH 329/357] [fbsync] Use TORCH_CUDA_ARCH_LIST to specify which CUDA architectures to build for (#3399) Summary: * trying stuff * Put flags back? * remove second one just to see * It worked but it's because it's not built by CI. Trying another one * Try using TORCH_CUDA_ARCH_LIST instead * oops * Add new env variable to build/script_env * set TORCH_CUDA_ARCH_LIST for the rest of the CUDA versions * don't pass NVCC_FLAGS venv to conda, let's see if it works Reviewed By: fmassa Differential Revision: D27433927 fbshipit-source-id: e207f7fe6a1bab322e41d6dcabe7eb2b8e70b246 Co-authored-by: Francisco Massa --- packaging/pkg_helpers.bash | 26 +++++++------------------- packaging/torchvision/meta.yaml | 2 +- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/packaging/pkg_helpers.bash b/packaging/pkg_helpers.bash index da2c3e4fa7f..826fb525e3a 100644 --- a/packaging/pkg_helpers.bash +++ b/packaging/pkg_helpers.bash @@ -56,9 +56,7 @@ setup_cuda() { export CUDA_HOME=/usr/local/cuda-11.2/ fi export FORCE_CUDA=1 - # Hard-coding gencode flags is temporary situation until - # https://github.com/pytorch/pytorch/pull/23408 lands - export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_80,code=sm_80 -gencode=arch=compute_86,code=sm_86 -gencode=arch=compute_50,code=compute_50" + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5;8.0;8.6" ;; cu111) if [[ "$OSTYPE" == "msys" ]]; then @@ -67,9 +65,7 @@ setup_cuda() { export CUDA_HOME=/usr/local/cuda-11.1/ fi export FORCE_CUDA=1 - # Hard-coding gencode flags is temporary situation until - # https://github.com/pytorch/pytorch/pull/23408 lands - export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_80,code=sm_80 -gencode=arch=compute_86,code=sm_86 -gencode=arch=compute_50,code=compute_50" + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5;8.0;8.6" ;; cu110) if [[ "$OSTYPE" == "msys" ]]; then @@ -78,9 +74,7 @@ setup_cuda() { export CUDA_HOME=/usr/local/cuda-11.0/ fi export FORCE_CUDA=1 - # Hard-coding gencode flags is temporary situation until - # https://github.com/pytorch/pytorch/pull/23408 lands - export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_80,code=sm_80 -gencode=arch=compute_50,code=compute_50" + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5;8.0" ;; cu102) if [[ "$OSTYPE" == "msys" ]]; then @@ -89,9 +83,7 @@ setup_cuda() { export CUDA_HOME=/usr/local/cuda-10.2/ fi export FORCE_CUDA=1 - # Hard-coding gencode flags is temporary situation until - # https://github.com/pytorch/pytorch/pull/23408 lands - export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_50,code=compute_50" + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5" ;; cu101) if [[ "$OSTYPE" == "msys" ]]; then @@ -100,9 +92,7 @@ setup_cuda() { export CUDA_HOME=/usr/local/cuda-10.1/ fi export FORCE_CUDA=1 - # Hard-coding gencode flags is temporary situation until - # https://github.com/pytorch/pytorch/pull/23408 lands - export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_50,code=compute_50" + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5" ;; cu100) if [[ "$OSTYPE" == "msys" ]]; then @@ -111,9 +101,7 @@ setup_cuda() { export CUDA_HOME=/usr/local/cuda-10.0/ fi export FORCE_CUDA=1 - # Hard-coding gencode flags is temporary situation until - # https://github.com/pytorch/pytorch/pull/23408 lands - export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_50,code=compute_50" + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0;7.5" ;; cu92) if [[ "$OSTYPE" == "msys" ]]; then @@ -122,7 +110,7 @@ setup_cuda() { export CUDA_HOME=/usr/local/cuda-9.2/ fi export FORCE_CUDA=1 - export NVCC_FLAGS="-gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_50,code=compute_50" + export TORCH_CUDA_ARCH_LIST="3.5;5.0+PTX;6.0;7.0" ;; cpu) ;; diff --git a/packaging/torchvision/meta.yaml b/packaging/torchvision/meta.yaml index 834648c07dc..8279c276433 100644 --- a/packaging/torchvision/meta.yaml +++ b/packaging/torchvision/meta.yaml @@ -37,8 +37,8 @@ build: script_env: - CUDA_HOME - FORCE_CUDA - - NVCC_FLAGS - BUILD_VERSION + - TORCH_CUDA_ARCH_LIST features: {{ environ.get('CONDA_CPUONLY_FEATURE') }} From e64578cba761438a51e6793fb58f8118f8ba71df Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 330/357] [fbsync] Ensure input type of normalize is float. (#3621) Reviewed By: NicolasHug Differential Revision: D27706959 fbshipit-source-id: 9221f3e789f6cff11d5640cb79dcb86e06fa42ec --- test/test_transforms_tensor.py | 7 +++++-- torchvision/transforms/functional.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/test/test_transforms_tensor.py b/test/test_transforms_tensor.py index 5ba63b9b6d3..1bd0099af63 100644 --- a/test/test_transforms_tensor.py +++ b/test/test_transforms_tensor.py @@ -446,12 +446,15 @@ def test_to_grayscale(self): ) def test_normalize(self): + fn = T.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) tensor, _ = self._create_data(26, 34, device=self.device) - batch_tensors = torch.rand(4, 3, 44, 56, device=self.device) + with self.assertRaisesRegex(TypeError, r"Input tensor should be a float tensor"): + fn(tensor) + + batch_tensors = torch.rand(4, 3, 44, 56, device=self.device) tensor = tensor.to(dtype=torch.float32) / 255.0 # test for class interface - fn = T.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) scripted_fn = torch.jit.script(fn) self._test_transform_vs_scripted(fn, scripted_fn, tensor) diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 5b630e72c75..7bd15dde4c2 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -297,7 +297,7 @@ def to_pil_image(pic, mode=None): def normalize(tensor: Tensor, mean: List[float], std: List[float], inplace: bool = False) -> Tensor: - """Normalize a tensor image with mean and standard deviation. + """Normalize a float tensor image with mean and standard deviation. This transform does not support PIL Image. .. note:: @@ -306,7 +306,7 @@ def normalize(tensor: Tensor, mean: List[float], std: List[float], inplace: bool See :class:`~torchvision.transforms.Normalize` for more details. Args: - tensor (Tensor): Tensor image of size (C, H, W) or (B, C, H, W) to be normalized. + tensor (Tensor): Float tensor image of size (C, H, W) or (B, C, H, W) to be normalized. mean (sequence): Sequence of means for each channel. std (sequence): Sequence of standard deviations for each channel. inplace(bool,optional): Bool to make this operation inplace. @@ -317,6 +317,9 @@ def normalize(tensor: Tensor, mean: List[float], std: List[float], inplace: bool if not isinstance(tensor, torch.Tensor): raise TypeError('Input tensor should be a torch tensor. Got {}.'.format(type(tensor))) + if not tensor.is_floating_point(): + raise TypeError('Input tensor should be a float tensor. Got {}.'.format(tensor.dtype)) + if tensor.ndim < 3: raise ValueError('Expected tensor to be a tensor image of size (..., C, H, W). Got tensor.size() = ' '{}.'.format(tensor.size())) From fac0a7d72ff93bba5853c97421b67b1e0a2d41e0 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 331/357] [fbsync] [iOS] Remove the context for building jobs, only keep it for nightly build uploading (#3622) Summary: [ghstack-poisoned] Reviewed By: NicolasHug Differential Revision: D27706938 fbshipit-source-id: 7f0eb5aef3d0f00acb8b09f13d688237f11b8a9c Co-authored-by: Francisco Massa --- .circleci/config.yml | 4 ---- .circleci/regenerate.py | 1 - 2 files changed, 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 437d613d9ab..c12f0b731c4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1498,13 +1498,11 @@ workflows: - torch_onnx_test - binary_ios_build: build_environment: binary-libtorchvision_ops-ios-12.0.0-x86_64 - context: org-member ios_arch: x86_64 ios_platform: SIMULATOR name: binary_libtorchvision_ops_ios_12.0.0_x86_64 - binary_ios_build: build_environment: binary-libtorchvision_ops-ios-12.0.0-arm64 - context: org-member ios_arch: arm64 ios_platform: OS name: binary_libtorchvision_ops_ios_12.0.0_arm64 @@ -1657,7 +1655,6 @@ workflows: - torch_onnx_test - binary_ios_build: build_environment: nightly-binary-libtorchvision_ops-ios-12.0.0-x86_64 - context: org-member filters: branches: only: @@ -1667,7 +1664,6 @@ workflows: name: nightly_binary_libtorchvision_ops_ios_12.0.0_x86_64 - binary_ios_build: build_environment: nightly-binary-libtorchvision_ops-ios-12.0.0-arm64 - context: org-member filters: branches: only: diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index d7d822db013..d70860de86f 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -271,7 +271,6 @@ def ios_workflows(indentation=6, nightly=False): build_job_names.append(name) build_job = { 'build_environment': f'{env_prefix}binary-libtorchvision_ops-ios-12.0.0-{arch}', - 'context': 'org-member', 'ios_arch': arch, 'ios_platform': platform, 'name': name, From fce4f6ff0c0ebcbe359943ee5b2a70533a1bc27d Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 332/357] [fbsync] Remove unneeded packaging files (#3618) Summary: * remove some files * Also remove entire packaging/conda folder Reviewed By: NicolasHug Differential Revision: D27706936 fbshipit-source-id: 21d775d0cb5d03926cf436a3e74e0d5f67928f33 Co-authored-by: Francisco Massa --- packaging/conda/build_vision.sh | 223 ------------------ packaging/conda/install_conda.bat | 1 - packaging/conda/switch_cuda_version.sh | 28 --- packaging/windows/azure-pipelines-ci.yml | 11 - packaging/windows/azure-pipelines.yml | 35 --- packaging/windows/build_vision.bat | 145 ------------ packaging/windows/cpu.bat | 37 --- packaging/windows/cuda101.bat | 59 ----- packaging/windows/cuda102.bat | 59 ----- packaging/windows/cuda92.bat | 59 ----- packaging/windows/internal/auth.bat | 46 ---- packaging/windows/internal/build_conda.bat | 15 -- packaging/windows/internal/build_wheels.bat | 12 - packaging/windows/internal/check_deps.bat | 67 ------ packaging/windows/internal/check_opts.bat | 33 --- packaging/windows/internal/clean.bat | 5 - packaging/windows/internal/clone.bat | 56 ----- packaging/windows/internal/copy.bat | 13 - packaging/windows/internal/copy_cpu.bat | 1 - packaging/windows/internal/dep_install.bat | 14 -- packaging/windows/internal/env_fix.bat | 31 --- .../windows/internal/nightly_defaults.bat | 200 ---------------- packaging/windows/internal/publish.bat | 89 ------- packaging/windows/internal/setup.bat | 44 ---- packaging/windows/internal/test.bat | 79 ------- packaging/windows/internal/upload.bat | 96 -------- packaging/windows/internal/vs_install.bat | 14 -- packaging/windows/old/cuda100.bat | 59 ----- packaging/windows/old/cuda90.bat | 59 ----- packaging/windows/templates/auth_task.yml | 17 -- packaging/windows/templates/build_conda.yml | 15 -- packaging/windows/templates/build_task.yml | 161 ------------- packaging/windows/templates/build_wheels.yml | 9 - .../windows/templates/linux_build_task.yml | 38 --- .../templates/override_pytorch_version.yml | 6 - .../windows/templates/publish_packages.yml | 8 - .../templates/publish_test_results.yml | 6 - .../templates/setup_env_for_msagent.yml | 25 -- .../templates/setup_nightly_variables.yml | 11 - .../windows/templates/upload_to_conda.yml | 10 - packaging/windows/templates/upload_to_s3.yml | 15 -- packaging/windows/templates/vsts_auth.yml | 8 - 42 files changed, 1919 deletions(-) delete mode 100755 packaging/conda/build_vision.sh delete mode 100644 packaging/conda/install_conda.bat delete mode 100755 packaging/conda/switch_cuda_version.sh delete mode 100644 packaging/windows/azure-pipelines-ci.yml delete mode 100644 packaging/windows/azure-pipelines.yml delete mode 100644 packaging/windows/build_vision.bat delete mode 100644 packaging/windows/cpu.bat delete mode 100644 packaging/windows/cuda101.bat delete mode 100644 packaging/windows/cuda102.bat delete mode 100644 packaging/windows/cuda92.bat delete mode 100644 packaging/windows/internal/auth.bat delete mode 100644 packaging/windows/internal/build_conda.bat delete mode 100644 packaging/windows/internal/build_wheels.bat delete mode 100644 packaging/windows/internal/check_deps.bat delete mode 100644 packaging/windows/internal/check_opts.bat delete mode 100644 packaging/windows/internal/clean.bat delete mode 100644 packaging/windows/internal/clone.bat delete mode 100644 packaging/windows/internal/copy.bat delete mode 100644 packaging/windows/internal/copy_cpu.bat delete mode 100644 packaging/windows/internal/dep_install.bat delete mode 100644 packaging/windows/internal/env_fix.bat delete mode 100644 packaging/windows/internal/nightly_defaults.bat delete mode 100644 packaging/windows/internal/publish.bat delete mode 100644 packaging/windows/internal/setup.bat delete mode 100644 packaging/windows/internal/test.bat delete mode 100644 packaging/windows/internal/upload.bat delete mode 100644 packaging/windows/internal/vs_install.bat delete mode 100644 packaging/windows/old/cuda100.bat delete mode 100644 packaging/windows/old/cuda90.bat delete mode 100644 packaging/windows/templates/auth_task.yml delete mode 100644 packaging/windows/templates/build_conda.yml delete mode 100644 packaging/windows/templates/build_task.yml delete mode 100644 packaging/windows/templates/build_wheels.yml delete mode 100644 packaging/windows/templates/linux_build_task.yml delete mode 100644 packaging/windows/templates/override_pytorch_version.yml delete mode 100644 packaging/windows/templates/publish_packages.yml delete mode 100644 packaging/windows/templates/publish_test_results.yml delete mode 100644 packaging/windows/templates/setup_env_for_msagent.yml delete mode 100644 packaging/windows/templates/setup_nightly_variables.yml delete mode 100644 packaging/windows/templates/upload_to_conda.yml delete mode 100644 packaging/windows/templates/upload_to_s3.yml delete mode 100644 packaging/windows/templates/vsts_auth.yml diff --git a/packaging/conda/build_vision.sh b/packaging/conda/build_vision.sh deleted file mode 100755 index 167d05159cc..00000000000 --- a/packaging/conda/build_vision.sh +++ /dev/null @@ -1,223 +0,0 @@ -#!/usr/bin/env bash -if [[ -x "/remote/anaconda_token" ]]; then - . /remote/anaconda_token || true -fi - -set -ex - -if [[ "$CIRCLECI" == 'true' ]]; then - export PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:.:$PATH" -fi - -# Function to retry functions that sometimes timeout or have flaky failures -retry () { - $* || (sleep 1 && $*) || (sleep 2 && $*) || (sleep 4 && $*) || (sleep 8 && $*) -} - -# Parse arguments and determmine version -########################################################### -if [[ -n "$DESIRED_CUDA" && -n "$TORCHVISION_BUILD_VERSION" && -n "$TORCHVISION_BUILD_NUMBER" ]]; then - desired_cuda="$DESIRED_CUDA" - build_version="$PYTORCH_BUILD_VERSION" - build_number="$PYTORCH_BUILD_NUMBER" -else - if [ "$#" -ne 3 ]; then - echo "Illegal number of parameters. Pass cuda version, pytorch version, build number" - echo "CUDA version should be Mm with no dot, e.g. '80'" - echo "DESIRED_PYTHON should be M.m, e.g. '2.7'" - exit 1 - fi - - desired_cuda="$1" - build_version="$2" - build_number="$3" -fi -if [[ "$desired_cuda" != cpu ]]; then - desired_cuda="$(echo $desired_cuda | tr -d cuda. )" -fi -echo "Building cuda version $desired_cuda and torchvision version: $build_version build_number: $build_number" - -if [[ "$desired_cuda" == 'cpu' ]]; then - cpu_only=1 - cuver="cpu" -else - # Switch desired_cuda to be M.m to be consistent with other scripts in - # pytorch/builder - export FORCE_CUDA=1 - cuda_nodot="$desired_cuda" - - if [[ ${#cuda_nodot} -eq 2 ]]; then - desired_cuda="${desired_cuda:0:1}.${desired_cuda:1:1}" - elif [[ ${#cuda_nodot} -eq 3 ]]; then - desired_cuda="${desired_cuda:0:2}.${desired_cuda:2:1}" - else - echo "unknown cuda version $cuda_nodot" - exit 1 - fi - - cuver="cu$cuda_nodot" -fi - -export TORCHVISION_BUILD_VERSION=$build_version -export TORCHVISION_BUILD_NUMBER=$build_number - -if [[ -z "$DESIRED_PYTHON" ]]; then - DESIRED_PYTHON=('3.5' '3.6' '3.7') -fi - -SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" - -if [[ -z "$WIN_PACKAGE_WORK_DIR" ]]; then - WIN_PACKAGE_WORK_DIR="$(echo $(pwd -W) | tr '/' '\\')\\tmp_conda_$(date +%H%M%S)" -fi - -mkdir -p "$WIN_PACKAGE_WORK_DIR" || true -vision_rootdir="$(realpath ${WIN_PACKAGE_WORK_DIR})/torchvision-src" -git config --system core.longpaths true - -if [[ ! -d "$vision_rootdir" ]]; then - rm -rf "$vision_rootdir" - git clone "https://github.com/pytorch/vision" "$vision_rootdir" - pushd "$vision_rootdir" - git checkout $PYTORCH_BRANCH - popd -fi - -cd "$SOURCE_DIR" - -export tmp_conda="${WIN_PACKAGE_WORK_DIR}\\conda" -export miniconda_exe="${WIN_PACKAGE_WORK_DIR}\\miniconda.exe" -rm -rf "$tmp_conda" -rm -f "$miniconda_exe" -curl -sSk https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -o "$miniconda_exe" -"$SOURCE_DIR/install_conda.bat" && rm "$miniconda_exe" -pushd $tmp_conda -export PATH="$(pwd):$(pwd)/Library/usr/bin:$(pwd)/Library/bin:$(pwd)/Scripts:$(pwd)/bin:$PATH" -popd -retry conda install -yq conda-build - -ANACONDA_USER=pytorch-nightly -conda config --set anaconda_upload no - - -export TORCHVISION_PACKAGE_SUFFIX="" -if [[ "$desired_cuda" == 'cpu' ]]; then - export CONDA_CUDATOOLKIT_CONSTRAINT="" - export CONDA_CPUONLY_FEATURE="- cpuonly # [not osx]" - export CUDA_VERSION="None" -else - export CONDA_CPUONLY_FEATURE="" - . ./switch_cuda_version.sh $desired_cuda - if [[ "$desired_cuda" == "10.2" ]]; then - export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=10.2,<10.3 # [not osx]" - elif [[ "$desired_cuda" == "10.1" ]]; then - export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=10.1,<10.2 # [not osx]" - elif [[ "$desired_cuda" == "10.0" ]]; then - export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=10.0,<10.1 # [not osx]" - elif [[ "$desired_cuda" == "9.2" ]]; then - export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=9.2,<9.3 # [not osx]" - elif [[ "$desired_cuda" == "9.0" ]]; then - export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=9.0,<9.1 # [not osx]" - elif [[ "$desired_cuda" == "8.0" ]]; then - export CONDA_CUDATOOLKIT_CONSTRAINT="- cudatoolkit >=8.0,<8.1 # [not osx]" - else - echo "unhandled desired_cuda: $desired_cuda" - exit 1 - fi -fi - -if [[ -z "$PYTORCH_VERSION" ]]; then - export CONDA_CHANNEL_FLAGS="-c pytorch-nightly -c pytorch" - export PYTORCH_VERSION="$(conda search --json 'pytorch[channel=pytorch-nightly]' | \ - python -c "import os, sys, json, re; cuver = '$cuver'; \ - cuver = cuver.replace('cu', 'cuda') if cuver != 'cpu' else cuver; \ - print(re.sub(r'\\+.*$', '', \ - [x['version'] for x in json.load(sys.stdin)['pytorch'] \ - if (x['platform'] == 'darwin' or cuver in x['fn']) \ - and 'py' + os.environ['DESIRED_PYTHON'] in x['fn']][-1]))")" - if [[ -z "$PYTORCH_VERSION" ]]; then - echo "PyTorch version auto detection failed" - echo "No package found for desired_cuda=$desired_cuda and DESIRED_PYTHON=$DESIRED_PYTHON" - exit 1 - fi -else - export CONDA_CHANNEL_FLAGS="-c pytorch -c pytorch-nightly" -fi -if [[ "$desired_cuda" == 'cpu' ]]; then - export CONDA_PYTORCH_BUILD_CONSTRAINT="- pytorch==$PYTORCH_VERSION" - export CONDA_PYTORCH_CONSTRAINT="- pytorch==$PYTORCH_VERSION" -else - export CONDA_PYTORCH_BUILD_CONSTRAINT="- pytorch==${PYTORCH_VERSION}" - export CONDA_PYTORCH_CONSTRAINT="- pytorch==${PYTORCH_VERSION}" -fi - -# Loop through all Python versions to build a package for each -for py_ver in "${DESIRED_PYTHON[@]}"; do - build_string="py${py_ver}_${build_string_suffix}" - folder_tag="${build_string}_$(date +'%Y%m%d')" - - # Create the conda package into this temporary folder. This is so we can find - # the package afterwards, as there's no easy way to extract the final filename - # from conda-build - output_folder="out_$folder_tag" - rm -rf "$output_folder" - mkdir "$output_folder" - - export VSTOOLCHAIN_PACKAGE=vs2017 - - # We need to build the compiler activation scripts first on Windows - time VSDEVCMD_ARGS=${VSDEVCMD_ARGS[@]} \ - conda build -c "$ANACONDA_USER" \ - --no-anaconda-upload \ - --output-folder "$output_folder" \ - ../$VSTOOLCHAIN_PACKAGE - - cp ../$VSTOOLCHAIN_PACKAGE/conda_build_config.yaml ../torchvision/conda_build_config.yaml - - conda config --set anaconda_upload no - echo "Calling conda-build at $(date)" - if [[ "$desired_cuda" == "9.2" ]]; then - time CMAKE_ARGS=${CMAKE_ARGS[@]} \ - BUILD_VERSION="$TORCHVISION_BUILD_VERSION" \ - CU_VERSION="$cuver" \ - SOURCE_ROOT_DIR="$vision_rootdir" \ - conda build -c "$ANACONDA_USER" \ - -c defaults \ - -c conda-forge \ - -c "numba/label/dev" \ - --no-anaconda-upload \ - --python "$py_ver" \ - --output-folder "$output_folder" \ - --no-verify \ - --no-test \ - ../torchvision - else - time CMAKE_ARGS=${CMAKE_ARGS[@]} \ - BUILD_VERSION="$TORCHVISION_BUILD_VERSION" \ - CU_VERSION="$cuver" \ - SOURCE_ROOT_DIR="$vision_rootdir" \ - conda build -c "$ANACONDA_USER" \ - -c defaults \ - -c conda-forge \ - --no-anaconda-upload \ - --python "$py_ver" \ - --output-folder "$output_folder" \ - --no-verify \ - --no-test \ - ../torchvision - fi - echo "Finished conda-build at $(date)" - - # Extract the package for testing - ls -lah "$output_folder" - built_package="$(find $output_folder/ -name '*torchvision*.tar.bz2')" - - # Copy the built package to the host machine for persistence before testing - if [[ -n "$PYTORCH_FINAL_PACKAGE_DIR" ]]; then - mkdir -p "$PYTORCH_FINAL_PACKAGE_DIR" || true - cp "$built_package" "$PYTORCH_FINAL_PACKAGE_DIR/" - fi -done - - -set +e diff --git a/packaging/conda/install_conda.bat b/packaging/conda/install_conda.bat deleted file mode 100644 index 6052ad08b10..00000000000 --- a/packaging/conda/install_conda.bat +++ /dev/null @@ -1 +0,0 @@ -start /wait "" "%miniconda_exe%" /S /InstallationType=JustMe /RegisterPython=0 /AddToPath=0 /D=%tmp_conda% diff --git a/packaging/conda/switch_cuda_version.sh b/packaging/conda/switch_cuda_version.sh deleted file mode 100755 index 342def93899..00000000000 --- a/packaging/conda/switch_cuda_version.sh +++ /dev/null @@ -1,28 +0,0 @@ -if [[ "$OSTYPE" == "msys" ]]; then - CUDA_DIR="/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v$1" -else - CUDA_DIR="/usr/local/cuda-$1" -fi - -if ! ls "$CUDA_DIR" -then - echo "folder $CUDA_DIR not found to switch" -fi - -echo "Switching symlink to $CUDA_DIR" -mkdir -p /usr/local -rm -fr /usr/local/cuda -ln -s "$CUDA_DIR" /usr/local/cuda - -if [[ "$OSTYPE" == "msys" ]]; then - export CUDA_VERSION=`ls /usr/local/cuda/bin/cudart64*.dll | head -1 | tr '._' ' ' | cut -d ' ' -f2` - export CUDNN_VERSION=`ls /usr/local/cuda/bin/cudnn64*.dll | head -1 | tr '._' ' ' | cut -d ' ' -f2` -else - export CUDA_VERSION=$(ls /usr/local/cuda/lib64/libcudart.so.*|sort|tac | head -1 | rev | cut -d"." -f -3 | rev) - export CUDNN_VERSION=$(ls /usr/local/cuda/lib64/libcudnn.so.*|sort|tac | head -1 | rev | cut -d"." -f -3 | rev) -fi - -ls -alh /usr/local/cuda - -echo "CUDA_VERSION=$CUDA_VERSION" -echo "CUDNN_VERSION=$CUDNN_VERSION" diff --git a/packaging/windows/azure-pipelines-ci.yml b/packaging/windows/azure-pipelines-ci.yml deleted file mode 100644 index 6f9f3468cfe..00000000000 --- a/packaging/windows/azure-pipelines-ci.yml +++ /dev/null @@ -1,11 +0,0 @@ - -# Turn off auto builds for commits -trigger: none -pr: none - -jobs: -- template: templates/build_task.yml - parameters: - package: 'Wheels' - spec: 'CPU' - msagent: true diff --git a/packaging/windows/azure-pipelines.yml b/packaging/windows/azure-pipelines.yml deleted file mode 100644 index d0240570012..00000000000 --- a/packaging/windows/azure-pipelines.yml +++ /dev/null @@ -1,35 +0,0 @@ - -# Turn off auto builds for commits -trigger: none -pr: none - -jobs: -- template: templates/auth_task.yml - -- template: templates/build_task.yml - parameters: - package: 'Wheels' - spec: 'CPU' - msagent: true - -- template: templates/build_task.yml - parameters: - package: 'Conda' - spec: 'CPU' - msagent: true - -- template: templates/build_task.yml - parameters: - package: 'Wheels' - spec: 'CUDA' - msagent: true - -- template: templates/build_task.yml - parameters: - package: 'Conda' - spec: 'CUDA' - msagent: true - -- template: templates/linux_build_task.yml - parameters: - msagent: $(ms.hosted.agent.cpu) diff --git a/packaging/windows/build_vision.bat b/packaging/windows/build_vision.bat deleted file mode 100644 index 46b0874c8d8..00000000000 --- a/packaging/windows/build_vision.bat +++ /dev/null @@ -1,145 +0,0 @@ -@echo off - -:: This script parses args, installs required libraries (miniconda, MKL, -:: Magma), and then delegates to cpu.bat, cuda80.bat, etc. - -IF NOT "%CUDA_VERSION%" == "" IF NOT "%TORCHVISION_BUILD_VERSION%" == "" if NOT "%TORCHVISION_BUILD_NUMBER%" == "" goto env_end -if "%~1"=="" goto arg_error -if "%~2"=="" goto arg_error -if "%~3"=="" goto arg_error -if NOT "%~4"=="" goto arg_error -goto arg_end - -:arg_error - -echo Illegal number of parameters. Pass cuda version, pytorch version, build number -echo CUDA version should be Mm with no dot, e.g. '80' -echo DESIRED_PYTHON should be M.m, e.g. '2.7' -exit /b 1 - -:arg_end - -set CUDA_VERSION=%~1 -set TORCHVISION_BUILD_VERSION=%~2 -set TORCHVISION_BUILD_NUMBER=%~3 - -set BUILD_VERSION=%TORCHVISION_BUILD_VERSION% - -:env_end - -if NOT "%CUDA_VERSION%" == "cpu" ( - set CUDA_PREFIX=cuda%CUDA_VERSION% - set CUVER=cu%CUDA_VERSION% - set FORCE_CUDA=1 -) else ( - set CUDA_PREFIX=cpu - set CUVER=cpu -) - -set BUILD_VISION=1 -REM set TORCH_WHEEL=torch -f https://download.pytorch.org/whl/%CUVER%/stable.html --no-index - -IF "%DESIRED_PYTHON%" == "" set DESIRED_PYTHON=3.5;3.6;3.7 -set DESIRED_PYTHON_PREFIX=%DESIRED_PYTHON:.=% -set DESIRED_PYTHON_PREFIX=py%DESIRED_PYTHON_PREFIX:;=;py% - -set SRC_DIR=%~dp0 -pushd %SRC_DIR% - -:: Install Miniconda3 -set "CONDA_HOME=%CD%\conda" -set "tmp_conda=%CONDA_HOME%" -set "miniconda_exe=%CD%\miniconda.exe" -rmdir /s /q conda -del miniconda.exe -curl -k https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe -o "%miniconda_exe%" -call ..\conda\install_conda.bat -IF ERRORLEVEL 1 exit /b 1 -set "ORIG_PATH=%PATH%" -set "PATH=%CONDA_HOME%;%CONDA_HOME%\scripts;%CONDA_HOME%\Library\bin;%PATH%" - -:: Create a new conda environment -setlocal EnableDelayedExpansion -FOR %%v IN (%DESIRED_PYTHON%) DO ( - set PYTHON_VERSION_STR=%%v - set PYTHON_VERSION_STR=!PYTHON_VERSION_STR:.=! - conda remove -n py!PYTHON_VERSION_STR! --all -y || rmdir %CONDA_HOME%\envs\py!PYTHON_VERSION_STR! /s - conda create -n py!PYTHON_VERSION_STR! -y -q -c defaults -c conda-forge numpy>=1.11 mkl>=2018 python=%%v ca-certificates scipy -) - -:: Uncomment for stable releases -:: FOR %%v IN (%DESIRED_PYTHON%) DO ( -:: set PYTHON_VERSION_STR=%%v -:: set PYTHON_VERSION_STR=!PYTHON_VERSION_STR:.=! -:: set "PATH=%CONDA_HOME%\envs\py!PYTHON_VERSION_STR!;%CONDA_HOME%\envs\py!PYTHON_VERSION_STR!\scripts;%CONDA_HOME%\envs\py!PYTHON_VERSION_STR!\Library\bin;%ORIG_PATH%" - -:: if "%CUDA_VERSION%" == "100" ( -:: set TORCH_WHEEL=https://download.pytorch.org/whl/%CUVER%/torch-1.2.0-cp!PYTHON_VERSION_STR!-cp!PYTHON_VERSION_STR!m-win_amd64.whl -:: ) else ( -:: set TORCH_WHEEL=https://download.pytorch.org/whl/%CUVER%/torch-1.2.0%%2B%CUVER%-cp!PYTHON_VERSION_STR!-cp!PYTHON_VERSION_STR!m-win_amd64.whl -:: ) -:: echo Installing !TORCH_WHEEL!... -:: pip install "!TORCH_WHEEL!" -:: ) - -:: Uncomment for nightly releases -FOR %%v IN (%DESIRED_PYTHON%) DO ( - set PYTHON_VERSION_STR=%%v - set PYTHON_VERSION_STR=!PYTHON_VERSION_STR:.=! - set "PATH=%CONDA_HOME%\envs\py!PYTHON_VERSION_STR!;%CONDA_HOME%\envs\py!PYTHON_VERSION_STR!\scripts;%CONDA_HOME%\envs\py!PYTHON_VERSION_STR!\Library\bin;%ORIG_PATH%" - - set TORCH_WHEEL=torch --pre -f https://download.pytorch.org/whl/nightly/%CUVER%/torch_nightly.html - echo Installing !TORCH_WHEEL!... - pip install !TORCH_WHEEL! -) - -endlocal - -if "%DEBUG%" == "1" ( - set BUILD_TYPE=debug -) ELSE ( - set BUILD_TYPE=release -) - -:: Install sccache -if "%USE_SCCACHE%" == "1" ( - mkdir %CD%\tmp_bin - curl -k https://s3.amazonaws.com/ossci-windows/sccache.exe --output %CD%\tmp_bin\sccache.exe - if not "%CUDA_VERSION%" == "" ( - copy %CD%\tmp_bin\sccache.exe %CD%\tmp_bin\nvcc.exe - - set CUDA_NVCC_EXECUTABLE=%CD%\tmp_bin\nvcc - set "PATH=%CD%\tmp_bin;%PATH%" - ) -) - -for %%v in (%DESIRED_PYTHON_PREFIX%) do ( - :: Activate Python Environment - set PYTHON_PREFIX=%%v - set "PATH=%CONDA_HOME%\envs\%%v;%CONDA_HOME%\envs\%%v\scripts;%CONDA_HOME%\envs\%%v\Library\bin;%ORIG_PATH%" - if defined INCLUDE ( - set "INCLUDE=%INCLUDE%;%CONDA_HOME%\envs\%%v\Library\include" - ) else ( - set "INCLUDE=%CONDA_HOME%\envs\%%v\Library\include" - ) - if defined LIB ( - set "LIB=%LIB%;%CONDA_HOME%\envs\%%v\Library\lib" - ) else ( - set "LIB=%CONDA_HOME%\envs\%%v\Library\lib" - ) - @setlocal - :: Set Flags - if NOT "%CUDA_VERSION%"=="cpu" ( - set CUDNN_VERSION=7 - ) - call %CUDA_PREFIX%.bat - IF ERRORLEVEL 1 exit /b 1 - call internal\test.bat - IF ERRORLEVEL 1 exit /b 1 - @endlocal -) - -set "PATH=%ORIG_PATH%" -popd - -IF ERRORLEVEL 1 exit /b 1 diff --git a/packaging/windows/cpu.bat b/packaging/windows/cpu.bat deleted file mode 100644 index 392a687f9dc..00000000000 --- a/packaging/windows/cpu.bat +++ /dev/null @@ -1,37 +0,0 @@ -@echo off - -IF NOT "%BUILD_VISION%" == "" ( - set MODULE_NAME=vision -) ELSE ( - set MODULE_NAME=pytorch -) - -IF NOT EXIST "setup.py" IF NOT EXIST "%MODULE_NAME%" ( - call internal\clone.bat - cd .. - IF ERRORLEVEL 1 goto eof -) ELSE ( - call internal\clean.bat -) - -call internal\check_deps.bat -IF ERRORLEVEL 1 goto eof - -REM Check for optional components - -echo Disabling CUDA -set NO_CUDA=1 -set USE_CUDA=0 - -IF "%BUILD_VISION%" == "" ( - call internal\check_opts.bat - IF ERRORLEVEL 1 goto eof - - call internal\copy_cpu.bat - IF ERRORLEVEL 1 goto eof -) - -call internal\setup.bat -IF ERRORLEVEL 1 goto eof - -:eof diff --git a/packaging/windows/cuda101.bat b/packaging/windows/cuda101.bat deleted file mode 100644 index db397d593c8..00000000000 --- a/packaging/windows/cuda101.bat +++ /dev/null @@ -1,59 +0,0 @@ -@echo off - -IF NOT "%BUILD_VISION%" == "" ( - set MODULE_NAME=vision -) ELSE ( - set MODULE_NAME=pytorch -) - -IF NOT EXIST "setup.py" IF NOT EXIST "%MODULE_NAME%" ( - call internal\clone.bat - cd .. - IF ERRORLEVEL 1 goto eof -) ELSE ( - call internal\clean.bat -) - -call internal\check_deps.bat -IF ERRORLEVEL 1 goto eof - -REM Check for optional components - -set NO_CUDA= -set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 - -IF "%NVTOOLSEXT_PATH%"=="" ( - echo NVTX ^(Visual Studio Extension ^for CUDA^) ^not installed, failing - exit /b 1 - goto optcheck -) - -IF "%CUDA_PATH_V10_1%"=="" ( - echo CUDA 10.1 not found, failing - exit /b 1 -) ELSE ( - IF "%BUILD_VISION%" == "" ( - set TORCH_CUDA_ARCH_LIST=3.5;5.0+PTX;6.0;6.1;7.0;7.5 - set TORCH_NVCC_FLAGS=-Xfatbin -compress-all - ) ELSE ( - set NVCC_FLAGS=-D__CUDA_NO_HALF_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_50,code=compute_50 - ) - - set "CUDA_PATH=%CUDA_PATH_V10_1%" - set "PATH=%CUDA_PATH_V10_1%\bin;%PATH%" -) - -:optcheck - -IF "%BUILD_VISION%" == "" ( - call internal\check_opts.bat - IF ERRORLEVEL 1 goto eof - - call internal\copy.bat - IF ERRORLEVEL 1 goto eof -) - -call internal\setup.bat -IF ERRORLEVEL 1 goto eof - -:eof diff --git a/packaging/windows/cuda102.bat b/packaging/windows/cuda102.bat deleted file mode 100644 index 93dd5a77dfd..00000000000 --- a/packaging/windows/cuda102.bat +++ /dev/null @@ -1,59 +0,0 @@ -@echo off - -IF NOT "%BUILD_VISION%" == "" ( - set MODULE_NAME=vision -) ELSE ( - set MODULE_NAME=pytorch -) - -IF NOT EXIST "setup.py" IF NOT EXIST "%MODULE_NAME%" ( - call internal\clone.bat - cd .. - IF ERRORLEVEL 1 goto eof -) ELSE ( - call internal\clean.bat -) - -call internal\check_deps.bat -IF ERRORLEVEL 1 goto eof - -REM Check for optional components - -set NO_CUDA= -set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 - -IF "%NVTOOLSEXT_PATH%"=="" ( - echo NVTX ^(Visual Studio Extension ^for CUDA^) ^not installed, failing - exit /b 1 - goto optcheck -) - -IF "%CUDA_PATH_V10_2%"=="" ( - echo CUDA 10.2 not found, failing - exit /b 1 -) ELSE ( - IF "%BUILD_VISION%" == "" ( - set TORCH_CUDA_ARCH_LIST=3.5;5.0+PTX;6.0;6.1;7.0;7.5 - set TORCH_NVCC_FLAGS=-Xfatbin -compress-all - ) ELSE ( - set NVCC_FLAGS=-D__CUDA_NO_HALF_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_50,code=compute_50 - ) - - set "CUDA_PATH=%CUDA_PATH_V10_2%" - set "PATH=%CUDA_PATH_V10_2%\bin;%PATH%" -) - -:optcheck - -IF "%BUILD_VISION%" == "" ( - call internal\check_opts.bat - IF ERRORLEVEL 1 goto eof - - call internal\copy.bat - IF ERRORLEVEL 1 goto eof -) - -call internal\setup.bat -IF ERRORLEVEL 1 goto eof - -:eof diff --git a/packaging/windows/cuda92.bat b/packaging/windows/cuda92.bat deleted file mode 100644 index 0bfcdc8e463..00000000000 --- a/packaging/windows/cuda92.bat +++ /dev/null @@ -1,59 +0,0 @@ -@echo off - -IF NOT "%BUILD_VISION%" == "" ( - set MODULE_NAME=vision -) ELSE ( - set MODULE_NAME=pytorch -) - -IF NOT EXIST "setup.py" IF NOT EXIST "%MODULE_NAME%" ( - call internal\clone.bat - cd .. - IF ERRORLEVEL 1 goto eof -) ELSE ( - call internal\clean.bat -) - -call internal\check_deps.bat -IF ERRORLEVEL 1 goto eof - -REM Check for optional components - -set USE_CUDA= -set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 - -IF "%NVTOOLSEXT_PATH%"=="" ( - echo NVTX ^(Visual Studio Extension ^for CUDA^) ^not installed, failing - exit /b 1 - goto optcheck -) - -IF "%CUDA_PATH_V9_2%"=="" ( - echo CUDA 9.2 not found, failing - exit /b 1 -) ELSE ( - IF "%BUILD_VISION%" == "" ( - set TORCH_CUDA_ARCH_LIST=3.5;5.0+PTX;6.0;6.1;7.0 - set TORCH_NVCC_FLAGS=-Xfatbin -compress-all - ) ELSE ( - set NVCC_FLAGS=-D__CUDA_NO_HALF_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_61,code=sm_61 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_50,code=compute_50 - ) - - set "CUDA_PATH=%CUDA_PATH_V9_2%" - set "PATH=%CUDA_PATH_V9_2%\bin;%PATH%" -) - -:optcheck - -IF "%BUILD_VISION%" == "" ( - call internal\check_opts.bat - IF ERRORLEVEL 1 goto eof - - call internal\copy.bat - IF ERRORLEVEL 1 goto eof -) - -call internal\setup.bat -IF ERRORLEVEL 1 goto eof - -:eof diff --git a/packaging/windows/internal/auth.bat b/packaging/windows/internal/auth.bat deleted file mode 100644 index c874bce493c..00000000000 --- a/packaging/windows/internal/auth.bat +++ /dev/null @@ -1,46 +0,0 @@ -@echo off - -: From the following doc, the build won't be triggered if the users don't sign in daily. -: https://docs.microsoft.com/en-us/azure/devops/pipelines/build/triggers?tabs=yaml&view=vsts#my-build-didnt-run-what-happened -: To avoid this problem, we can just go through the sign in process using the following command. - -:auth_start - -if "%RETRY_TIMES%" == "" ( - set /a RETRY_TIMES=10 - set /a SLEEP_TIME=2 -) else ( - set /a RETRY_TIMES=%RETRY_TIMES%-1 - set /a SLEEP_TIME=%SLEEP_TIME%*2 -) - -for /f "usebackq tokens=*" %%i in (`curl -so NUL -w "%%{http_code}" -u %VSTS_AUTH% https://dev.azure.com/pytorch`) do ( - set STATUS_CODE=%%i -) - -IF NOT "%STATUS_CODE%" == "200" ( - echo Auth retry times remaining: %RETRY_TIMES% - echo Sleep time: %SLEEP_TIME% seconds - IF %RETRY_TIMES% EQU 0 ( - echo Auth failed - goto err - ) - waitfor SomethingThatIsNeverHappening /t %SLEEP_TIME% 2>nul || ver >nul - goto auth_start -) ELSE ( - echo Login Attempt Succeeded - goto auth_end -) - -:err - -: Throw a warning if it fails -powershell -c "Write-Warning 'Login Attempt Failed'" - -:auth_end - -set RETRY_TIMES= -set SLEEP_TIME= -set STATUS_CODE= - -exit /b 0 diff --git a/packaging/windows/internal/build_conda.bat b/packaging/windows/internal/build_conda.bat deleted file mode 100644 index 18f0bf13467..00000000000 --- a/packaging/windows/internal/build_conda.bat +++ /dev/null @@ -1,15 +0,0 @@ -if "%VC_YEAR%" == "2017" set VSDEVCMD_ARGS=-vcvars_ver=14.13 -if "%VC_YEAR%" == "2017" powershell packaging/windows/internal/vs2017_install.ps1 -if errorlevel 1 exit /b 1 - -call packaging/windows/internal/cuda_install.bat -if errorlevel 1 exit /b 1 - -call packaging/windows/internal/nightly_defaults.bat Conda -if errorlevel 1 exit /b 1 - -set PYTORCH_FINAL_PACKAGE_DIR=%CD%\packaging\windows\output -if not exist "%PYTORCH_FINAL_PACKAGE_DIR%" mkdir %PYTORCH_FINAL_PACKAGE_DIR% - -bash ./packaging/conda/build_vision.sh %CUDA_VERSION% %TORCHVISION_BUILD_VERSION% %TORCHVISION_BUILD_NUMBER% -if errorlevel 1 exit /b 1 diff --git a/packaging/windows/internal/build_wheels.bat b/packaging/windows/internal/build_wheels.bat deleted file mode 100644 index a321c3ce6e7..00000000000 --- a/packaging/windows/internal/build_wheels.bat +++ /dev/null @@ -1,12 +0,0 @@ -if "%VC_YEAR%" == "2017" set VSDEVCMD_ARGS=-vcvars_ver=14.13 -if "%VC_YEAR%" == "2017" powershell packaging/windows/internal/vs2017_install.ps1 -if errorlevel 1 exit /b 1 - -call packaging/windows/internal/cuda_install.bat -if errorlevel 1 exit /b 1 - -call packaging/windows/internal/nightly_defaults.bat Wheels -if errorlevel 1 exit /b 1 - -call packaging/windows/build_vision.bat %CUDA_VERSION% %TORCHVISION_BUILD_VERSION% %TORCHVISION_BUILD_NUMBER% -if errorlevel 1 exit /b 1 diff --git a/packaging/windows/internal/check_deps.bat b/packaging/windows/internal/check_deps.bat deleted file mode 100644 index a159d4436d6..00000000000 --- a/packaging/windows/internal/check_deps.bat +++ /dev/null @@ -1,67 +0,0 @@ -@echo off - -REM Check for necessary components - -IF NOT "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( - echo You should use 64 bits Windows to build and run PyTorch - exit /b 1 -) - -IF "%BUILD_VISION%" == "" ( - where /q cmake.exe - - IF ERRORLEVEL 1 ( - echo CMake is required to compile PyTorch on Windows - exit /b 1 - ) -) - -IF NOT EXIST "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ( - echo Visual Studio 2017 C++ BuildTools is required to compile PyTorch on Windows - exit /b 1 -) - -for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -legacy -products * -version [15^,16^) -property installationPath`) do ( - if exist "%%i" if exist "%%i\VC\Auxiliary\Build\vcvarsall.bat" ( - set "VS15INSTALLDIR=%%i" - set "VS15VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat" - goto vswhere - ) -) - -:vswhere -IF "%VS15VCVARSALL%"=="" ( - echo Visual Studio 2017 C++ BuildTools is required to compile PyTorch on Windows - exit /b 1 -) - -set MSSdk=1 -set DISTUTILS_USE_SDK=1 - -where /q python.exe - -IF ERRORLEVEL 1 ( - echo Python x64 3.5 or up is required to compile PyTorch on Windows - exit /b 1 -) - -for /F "usebackq delims=" %%i in (`python -c "import sys; print('{0[0]}{0[1]}'.format(sys.version_info))"`) do ( - set /a PYVER=%%i -) - -if %PYVER% LSS 35 ( - echo Warning: PyTorch for Python 2 under Windows is experimental. - echo Python x64 3.5 or up is recommended to compile PyTorch on Windows - echo Maybe you can create a virual environment if you have conda installed: - echo ^> conda create -n test python=3.6 pyyaml mkl numpy - echo ^> activate test -) - -for /F "usebackq delims=" %%i in (`python -c "import struct;print( 8 * struct.calcsize('P'))"`) do ( - set /a PYSIZE=%%i -) - -if %PYSIZE% NEQ 64 ( - echo Python x64 3.5 or up is required to compile PyTorch on Windows - exit /b 1 -) diff --git a/packaging/windows/internal/check_opts.bat b/packaging/windows/internal/check_opts.bat deleted file mode 100644 index 003ad921328..00000000000 --- a/packaging/windows/internal/check_opts.bat +++ /dev/null @@ -1,33 +0,0 @@ -@echo off - -REM Check for optional components - -where /q ninja.exe - -IF NOT ERRORLEVEL 1 ( - echo Ninja found, using it to speed up builds - set CMAKE_GENERATOR=Ninja -) - -where /q clcache.exe - -IF NOT ERRORLEVEL 1 ( - echo clcache found, using it to speed up builds - set CC=clcache - set CXX=clcache -) - -where /q sccache.exe - -IF NOT ERRORLEVEL 1 ( - echo sccache found, using it to speed up builds - set CC=sccache cl - set CXX=sccache cl -) - -IF exist "%MKLProductDir%\mkl\lib\intel64_win" ( - echo MKL found, adding it to build - set "LIB=%MKLProductDir%\mkl\lib\intel64_win;%MKLProductDir%\compiler\lib\intel64_win;%LIB%"; -) - -exit /b 0 diff --git a/packaging/windows/internal/clean.bat b/packaging/windows/internal/clean.bat deleted file mode 100644 index 7489640f49a..00000000000 --- a/packaging/windows/internal/clean.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -cd %MODULE_NAME% -python setup.py clean -cd .. diff --git a/packaging/windows/internal/clone.bat b/packaging/windows/internal/clone.bat deleted file mode 100644 index 4ba181fa804..00000000000 --- a/packaging/windows/internal/clone.bat +++ /dev/null @@ -1,56 +0,0 @@ -@echo off - -:: The conda and wheels jobs are seperated on Windows, so we don't need to clone again. -IF "%BUILD_VISION%" == "" ( - if exist "%NIGHTLIES_PYTORCH_ROOT%" ( - xcopy /E /Y /Q "%NIGHTLIES_PYTORCH_ROOT%" pytorch\ - cd pytorch - goto submodule - ) -) - -git clone https://github.com/%PYTORCH_REPO%/%MODULE_NAME% - -cd %MODULE_NAME% - -IF NOT "%BUILD_VISION%" == "" goto latest_end - -IF "%PYTORCH_BRANCH%" == "latest" ( goto latest_start ) else ( goto latest_end ) - -:latest_start - -if "%NIGHTLIES_DATE%" == "" ( goto date_start ) else ( goto date_end ) - -:date_start - -set "DATE_CMD=Get-Date ([System.TimeZoneInfo]::ConvertTimeFromUtc((Get-Date).ToUniversalTime(), [System.TimeZoneInfo]::FindSystemTimeZoneById('Pacific Standard Time'))) -f 'yyyy_MM_dd'" -set "DATE_COMPACT_CMD=Get-Date ([System.TimeZoneInfo]::ConvertTimeFromUtc((Get-Date).ToUniversalTime(), [System.TimeZoneInfo]::FindSystemTimeZoneById('Pacific Standard Time'))) -f 'yyyyMMdd'" - -FOR /F "delims=" %%i IN ('powershell -c "%DATE_CMD%"') DO set NIGHTLIES_DATE=%%i -FOR /F "delims=" %%i IN ('powershell -c "%DATE_COMPACT_CMD%"') DO set NIGHTLIES_DATE_COMPACT=%%i - -:date_end - -if "%NIGHTLIES_DATE_COMPACT%" == "" set NIGHTLIES_DATE_COMPACT=%NIGHTLIES_DATE:~0,4%%NIGHTLIES_DATE:~5,2%%NIGHTLIES_DATE:~8,2% - -:: Switch to the latest commit by 11:59 yesterday -echo PYTORCH_BRANCH is set to latest so I will find the last commit -echo before 0:00 midnight on %NIGHTLIES_DATE% -set git_date=%NIGHTLIES_DATE:_=-% -FOR /F "delims=" %%i IN ('git log --before %git_date% -n 1 "--pretty=%%H"') DO set last_commit=%%i -echo Setting PYTORCH_BRANCH to %last_commit% since that was the last -echo commit before %NIGHTLIES_DATE% -set PYTORCH_BRANCH=%last_commit% - -:latest_end - -IF "%PYTORCH_BRANCH%" == "" ( - set PYTORCH_BRANCH=v%TORCHVISION_BUILD_VERSION% -) -git checkout %PYTORCH_BRANCH% -IF ERRORLEVEL 1 git checkout tags/%PYTORCH_BRANCH% - -:submodule - -git submodule update --init --recursive -IF ERRORLEVEL 1 exit /b 1 diff --git a/packaging/windows/internal/copy.bat b/packaging/windows/internal/copy.bat deleted file mode 100644 index b4aa397c6c1..00000000000 --- a/packaging/windows/internal/copy.bat +++ /dev/null @@ -1,13 +0,0 @@ -copy "%CUDA_PATH%\bin\cusparse64_%CUDA_VERSION%.dll*" pytorch\torch\lib -copy "%CUDA_PATH%\bin\cublas64_%CUDA_VERSION%.dll*" pytorch\torch\lib -copy "%CUDA_PATH%\bin\cudart64_%CUDA_VERSION%.dll*" pytorch\torch\lib -copy "%CUDA_PATH%\bin\curand64_%CUDA_VERSION%.dll*" pytorch\torch\lib -copy "%CUDA_PATH%\bin\cufft64_%CUDA_VERSION%.dll*" pytorch\torch\lib -copy "%CUDA_PATH%\bin\cufftw64_%CUDA_VERSION%.dll*" pytorch\torch\lib - -copy "%CUDA_PATH%\bin\cudnn64_%CUDNN_VERSION%.dll*" pytorch\torch\lib -copy "%CUDA_PATH%\bin\nvrtc64_%CUDA_VERSION%*.dll*" pytorch\torch\lib -copy "%CUDA_PATH%\bin\nvrtc-builtins64_%CUDA_VERSION%.dll*" pytorch\torch\lib - -copy "C:\Program Files\NVIDIA Corporation\NvToolsExt\bin\x64\nvToolsExt64_1.dll*" pytorch\torch\lib -copy "%CONDA_LIB_PATH%\libiomp*5md.dll" pytorch\torch\lib diff --git a/packaging/windows/internal/copy_cpu.bat b/packaging/windows/internal/copy_cpu.bat deleted file mode 100644 index f5b9d11515f..00000000000 --- a/packaging/windows/internal/copy_cpu.bat +++ /dev/null @@ -1 +0,0 @@ -copy "%CONDA_LIB_PATH%\libiomp*5md.dll" pytorch\torch\lib diff --git a/packaging/windows/internal/dep_install.bat b/packaging/windows/internal/dep_install.bat deleted file mode 100644 index db665a99f26..00000000000 --- a/packaging/windows/internal/dep_install.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -REM curl -k https://www.7-zip.org/a/7z1805-x64.exe -O -REM if errorlevel 1 exit /b 1 - -REM start /wait 7z1805-x64.exe /S -REM if errorlevel 1 exit /b 1 - -REM set "PATH=%ProgramFiles%\7-Zip;%PATH%" - -choco feature disable --name showDownloadProgress -choco feature enable --name allowGlobalConfirmation - -choco install curl 7zip diff --git a/packaging/windows/internal/env_fix.bat b/packaging/windows/internal/env_fix.bat deleted file mode 100644 index dd0aaf5f2d5..00000000000 --- a/packaging/windows/internal/env_fix.bat +++ /dev/null @@ -1,31 +0,0 @@ -@echo off - -:: Caution: Please don't use this script locally -:: It may destroy your build environment. - -setlocal - -IF NOT EXIST "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" ( - echo Visual Studio 2017 C++ BuildTools is required to compile PyTorch on Windows - exit /b 1 -) - -for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -legacy -products * -version [15^,16^) -property installationPath`) do ( - if exist "%%i" if exist "%%i\VC\Auxiliary\Build\vcvarsall.bat" ( - set "VS15INSTALLDIR=%%i" - set "VS15VCVARSALL=%%i\VC\Auxiliary\Build\vcvarsall.bat" - goto vswhere - ) -) - -:vswhere - -IF "%VS15VCVARSALL%"=="" ( - echo Visual Studio 2017 C++ BuildTools is required to compile PyTorch on Windows - exit /b 1 -) - -call "%VS15VCVARSALL%" x86_amd64 -for /f "usebackq tokens=*" %%i in (`where link.exe`) do move "%%i" "%%i.bak" - -endlocal diff --git a/packaging/windows/internal/nightly_defaults.bat b/packaging/windows/internal/nightly_defaults.bat deleted file mode 100644 index c02ac8518f3..00000000000 --- a/packaging/windows/internal/nightly_defaults.bat +++ /dev/null @@ -1,200 +0,0 @@ -@echo on - -if "%~1"=="" goto arg_error -if NOT "%~2"=="" goto arg_error -goto arg_end - -:arg_error - -echo Illegal number of parameters. Pass packge type `Conda` or `Wheels`. -exit /b 1 - -:arg_end - -echo "nightly_defaults.bat at %CD% starting at %DATE%" - -set SRC_DIR=%~dp0\.. - -:: NIGHTLIES_FOLDER -:: N.B. this is also defined in cron_start.sh -:: An arbitrary root folder to store all nightlies folders, each of which is a -:: parent level date folder with separate subdirs for logs, wheels, conda -:: packages, etc. This should be kept the same across all scripts called in a -:: cron job, so it only has a default value in the top-most script -:: build_cron.sh to avoid the default values from diverging. -if "%NIGHTLIES_FOLDER%" == "" set "NIGHTLIES_FOLDER=%SRC_DIR%" - -:: NIGHTLIES_DATE -:: N.B. this is also defined in cron_start.sh -:: The date in YYYY_mm_dd format that we are building for. If this is not -:: already set, then this will first try to find the date of the nightlies -:: folder that this builder repo exists in; e.g. if this script exists in -:: some_dir/2019_09_04/builder/cron/ then this will be set to 2019_09_04 (must -:: match YYYY_mm_dd). This is for convenience when debugging/uploading past -:: dates, so that you don't have to set NIGHTLIES_DATE yourself. If a date -:: folder cannot be found in that exact location, then this will default to -:: the current date. - - -if "%NIGHTLIES_DATE%" == "" ( goto date_start ) else ( goto date_end ) - -:date_start - -set "DATE_CMD=Get-Date ([System.TimeZoneInfo]::ConvertTimeFromUtc((Get-Date).ToUniversalTime(), [System.TimeZoneInfo]::FindSystemTimeZoneById('Pacific Standard Time'))) -f 'yyyy_MM_dd'" -set "DATE_COMPACT_CMD=Get-Date ([System.TimeZoneInfo]::ConvertTimeFromUtc((Get-Date).ToUniversalTime(), [System.TimeZoneInfo]::FindSystemTimeZoneById('Pacific Standard Time'))) -f 'yyyyMMdd'" - -FOR /F "delims=" %%i IN ('powershell -c "%DATE_CMD%"') DO set NIGHTLIES_DATE=%%i -FOR /F "delims=" %%i IN ('powershell -c "%DATE_COMPACT_CMD%"') DO set NIGHTLIES_DATE_COMPACT=%%i - -:date_end - -if "%NIGHTLIES_DATE_COMPACT%" == "" set NIGHTLIES_DATE_COMPACT=%NIGHTLIES_DATE:~0,4%%NIGHTLIES_DATE:~5,2%%NIGHTLIES_DATE:~8,2% - -:: Used in lots of places as the root dir to store all conda/wheel/manywheel -:: packages as well as logs for the day -set today=%NIGHTLIES_FOLDER%\%NIGHTLIES_DATE% -mkdir "%today%" || ver >nul - - -::############################################################################# -:: Add new configuration variables below this line. 'today' should always be -:: defined ASAP to avoid weird errors -::############################################################################# - - -:: List of people to email when things go wrong. This is passed directly to -:: `mail -t` -:: TODO: Not supported yet -if "%NIGHTLIES_EMAIL_LIST%" == "" set NIGHTLIES_EMAIL_LIST=peterghost86@gmail.com - -:: PYTORCH_CREDENTIALS_FILE -:: A bash file that exports credentials needed to upload to aws and anaconda. -:: Needed variables are PYTORCH_ANACONDA_USERNAME, PYTORCH_ANACONDA_PASSWORD, -:: AWS_ACCESS_KEY_ID, and AWS_SECRET_ACCESS_KEY. Or it can just export the AWS -:: keys and then prepend a logged-in conda installation to the path. -:: TODO: Not supported yet -if "%PYTORCH_CREDENTIALS_FILE%" == "" set PYTORCH_CREDENTIALS_FILE=/c/Users/administrator/nightlies/credentials.sh - -:: Location of the temporary miniconda that is downloaded to install conda-build -:: and aws to upload finished packages TODO this is messy to install this in -:: upload.sh and later use it in upload_logs.sh -if "%CONDA_UPLOADER_INSTALLATION%" == "" set "CONDA_UPLOADER_INSTALLATION=%today%\miniconda" - -:: N.B. BUILDER_REPO and BUILDER_BRANCH are both set in cron_start.sh, as that -:: is the script that actually clones the builder repo that /this/ script is -:: running from. -pushd "%SRC_DIR%\.." -set NIGHTLIES_BUILDER_ROOT=%CD% -popd - -:: The shared pytorch repo to be used by all builds -if "%NIGHTLIES_PYTORCH_ROOT%" == "" set "NIGHTLIES_PYTORCH_ROOT=%today%\vision" - -:: PYTORCH_REPO -:: The Github org/user whose fork of Pytorch to check out (git clone -:: https://github.com//pytorch.git). This will always be cloned -:: fresh to build with. Default is 'pytorch' -if "%PYTORCH_REPO%" == "" set PYTORCH_REPO=pytorch - -:: PYTORCH_BRANCH -:: The branch of Pytorch to checkout for building (git checkout ). -:: This can either be the name of the branch (e.g. git checkout -:: my_branch_name) or can be a git commit (git checkout 4b2674n...). Default -:: is 'latest', which is a special term that signals to pull the last commit -:: before 0:00 midnight on the NIGHTLIES_DATE -if "%PYTORCH_BRANCH%" == "" set PYTORCH_BRANCH=nightly - -:: Clone the requested pytorch checkout -if exist "%NIGHTLIES_PYTORCH_ROOT%" ( goto clone_end ) else ( goto clone_start ) - -:clone_start - -git clone --recursive "https://github.com/%PYTORCH_REPO%/vision.git" "%NIGHTLIES_PYTORCH_ROOT%" -pushd "%NIGHTLIES_PYTORCH_ROOT%" - -if "%PYTORCH_BRANCH%" == "latest" ( goto latest_start ) else ( goto latest_end ) - -:latest_start - -:: Switch to the latest commit by 11:59 yesterday -echo PYTORCH_BRANCH is set to latest so I will find the last commit -echo before 0:00 midnight on %NIGHTLIES_DATE% -set git_date=%NIGHTLIES_DATE:_=-% -FOR /F "delims=" %%i IN ('git log --before %git_date% -n 1 "--pretty=%%H"') DO set last_commit=%%i -echo Setting PYTORCH_BRANCH to %last_commit% since that was the last -echo commit before %NIGHTLIES_DATE% -set PYTORCH_BRANCH=%last_commit% - -:latest_end - -git checkout "%PYTORCH_BRANCH%" -git submodule update -popd - -:clone_end - -if "%CUDA_VERSION%" == "cpu" ( - set _DESIRED_CUDA=cpu -) else ( - set _DESIRED_CUDA=cu%CUDA_VERSION% -) - -:: PYTORCH_BUILD_VERSION -:: The actual version string. Used in conda like -:: pytorch-nightly==1.0.0.dev20180908 -:: or in manylinux like -:: torch_nightly-1.0.0.dev20180908-cp27-cp27m-linux_x86_64.whl -if "%TORCHVISION_BUILD_VERSION%" == "" set TORCHVISION_BUILD_VERSION=0.10.0.dev%NIGHTLIES_DATE_COMPACT% - -if "%~1" == "Wheels" ( - if not "%CUDA_VERSION%" == "102" ( - set TORCHVISION_BUILD_VERSION=%TORCHVISION_BUILD_VERSION%+%_DESIRED_CUDA% - ) -) - -:: PYTORCH_BUILD_NUMBER -:: This is usually the number 1. If more than one build is uploaded for the -:: same version/date, then this can be incremented to 2,3 etc in which case -:: '.post2' will be appended to the version string of the package. This can -:: be set to '0' only if OVERRIDE_PACKAGE_VERSION is being used to bypass -:: all the version string logic in downstream scripts. Since we use the -:: override below, exporting this shouldn't actually matter. -if "%TORCHVISION_BUILD_NUMBER%" == "" set /a TORCHVISION_BUILD_NUMBER=1 -if %TORCHVISION_BUILD_NUMBER% GTR 1 set TORCHVISION_BUILD_VERSION=%TORCHVISION_BUILD_VERSION%%TORCHVISION_BUILD_NUMBER% - -:: The nightly builds use their own versioning logic, so we override whatever -:: logic is in setup.py or other scripts -:: TODO: Not supported yet -set OVERRIDE_PACKAGE_VERSION=%TORCHVISION_BUILD_VERSION% -set BUILD_VERSION=%TORCHVISION_BUILD_VERSION% - -:: Build folder for conda builds to use -if "%TORCH_CONDA_BUILD_FOLDER%" == "" set TORCH_CONDA_BUILD_FOLDER=torchvision - -:: TORCH_PACKAGE_NAME -:: The name of the package to upload. This should probably be pytorch or -:: pytorch-nightly. N.B. that pip will change all '-' to '_' but conda will -:: not. This is dealt with in downstream scripts. -:: TODO: Not supported yet -if "%TORCH_PACKAGE_NAME%" == "" set TORCH_PACKAGE_NAME=torchvision - -:: PIP_UPLOAD_FOLDER should end in a slash. This is to handle it being empty -:: (when uploading to e.g. whl/cpu/) and also to handle nightlies (when -:: uploading to e.g. /whl/nightly/cpu) -:: TODO: Not supported yet -if "%PIP_UPLOAD_FOLDER%" == "" set "PIP_UPLOAD_FOLDER=nightly\" - -:: The location of the binary_sizes dir in s3 is hardcoded into -:: upload_binary_sizes.sh - -:: DAYS_TO_KEEP -:: How many days to keep around for clean.sh. Build folders older than this -:: will be purged at the end of cron jobs. '1' means to keep only the current -:: day. Values less than 1 are not allowed. The default is 5. -:: TODO: Not supported yet -if "%DAYS_TO_KEEP%" == "" set /a DAYS_TO_KEEP=5 -if %DAYS_TO_KEEP% LSS 1 ( - echo DAYS_TO_KEEP cannot be less than 1. - echo A value of 1 means to only keep the build for today - exit /b 1 -) diff --git a/packaging/windows/internal/publish.bat b/packaging/windows/internal/publish.bat deleted file mode 100644 index 7f118bbb6e3..00000000000 --- a/packaging/windows/internal/publish.bat +++ /dev/null @@ -1,89 +0,0 @@ -@echo off - -set SRC_DIR=%~dp0 -pushd %SRC_DIR% - -if NOT "%CUDA_VERSION%" == "cpu" ( - set PACKAGE_SUFFIX=_cuda%CUDA_VERSION% -) else ( - set PACKAGE_SUFFIX= -) - -if "%PACKAGEFULLNAME%" == "Conda" ( - set PACKAGE=conda -) else ( - set PACKAGE=wheels -) - -if not defined PACKAGE_SUFFIX ( - set PUBLISH_BRANCH=vision_%PACKAGE%_%DESIRED_PYTHON% -) else ( - set PUBLISH_BRANCH=vision_%PACKAGE%_%DESIRED_PYTHON%%PACKAGE_SUFFIX% -) - -git clone %ARTIFACT_REPO_URL% -b %PUBLISH_BRANCH% --single-branch >nul 2>&1 - -IF ERRORLEVEL 1 ( - echo Branch %PUBLISH_BRANCH% not exist, falling back to master - set NO_BRANCH=1 - git clone %ARTIFACT_REPO_URL% -b master --single-branch >nul 2>&1 -) - -IF ERRORLEVEL 1 ( - echo Clone failed - goto err -) - -cd pytorch_builder -attrib -s -h -r . /s /d - -:: Empty repo -rd /s /q . || ver >nul - -IF NOT EXIST %PACKAGE% mkdir %PACKAGE% - -xcopy /S /E /Y ..\..\output\*.* %PACKAGE%\ - -git config --global user.name "Azure DevOps" -git config --global user.email peterghost86@gmail.com -git init -git checkout --orphan %PUBLISH_BRANCH% -git remote add origin %ARTIFACT_REPO_URL% -git add . -git commit -m "Update artifacts" - -:push - -if "%RETRY_TIMES%" == "" ( - set /a RETRY_TIMES=10 - set /a SLEEP_TIME=2 -) else ( - set /a RETRY_TIMES=%RETRY_TIMES%-1 - set /a SLEEP_TIME=%SLEEP_TIME%*2 -) - -git push origin %PUBLISH_BRANCH% -f > nul 2>&1 - -IF ERRORLEVEL 1 ( - echo Git push retry times remaining: %RETRY_TIMES% - echo Sleep time: %SLEEP_TIME% seconds - IF %RETRY_TIMES% EQU 0 ( - echo Push failed - goto err - ) - waitfor SomethingThatIsNeverHappening /t %SLEEP_TIME% 2>nul || ver >nul - goto push -) ELSE ( - set RETRY_TIMES= - set SLEEP_TIME= -) - -popd - -exit /b 0 - -:err - -popd - -exit /b 1 diff --git a/packaging/windows/internal/setup.bat b/packaging/windows/internal/setup.bat deleted file mode 100644 index 96cb7fb23a7..00000000000 --- a/packaging/windows/internal/setup.bat +++ /dev/null @@ -1,44 +0,0 @@ -@echo off - -echo The flags after configuring: -echo NO_CUDA=%NO_CUDA% -echo CMAKE_GENERATOR=%CMAKE_GENERATOR% -if "%NO_CUDA%"=="" echo CUDA_PATH=%CUDA_PATH% -if NOT "%CC%"=="" echo CC=%CC% -if NOT "%CXX%"=="" echo CXX=%CXX% -if NOT "%DISTUTILS_USE_SDK%"=="" echo DISTUTILS_USE_SDK=%DISTUTILS_USE_SDK% - -set SRC_DIR=%~dp0\.. - -IF "%VSDEVCMD_ARGS%" == "" ( - call "%VS15VCVARSALL%" x64 -) ELSE ( - call "%VS15VCVARSALL%" x64 %VSDEVCMD_ARGS% -) - -pushd %SRC_DIR% - -IF NOT exist "setup.py" ( - cd %MODULE_NAME% -) - -if "%CXX%"=="sccache cl" ( - sccache --stop-server - sccache --start-server - sccache --zero-stats -) - -:pytorch -:: This stores in e.g. D:/_work/1/s/windows/output/cpu -pip wheel -e . --no-deps --wheel-dir ../output - -:build_end -IF ERRORLEVEL 1 exit /b 1 -IF NOT ERRORLEVEL 0 exit /b 1 - -if "%CXX%"=="sccache cl" ( - taskkill /im sccache.exe /f /t || ver > nul - taskkill /im nvcc.exe /f /t || ver > nul -) - -cd .. diff --git a/packaging/windows/internal/test.bat b/packaging/windows/internal/test.bat deleted file mode 100644 index 472f2ca05da..00000000000 --- a/packaging/windows/internal/test.bat +++ /dev/null @@ -1,79 +0,0 @@ -@echo off - -set SRC_DIR=%~dp0\.. -pushd %SRC_DIR% - -set PYTHON_VERSION=%PYTHON_PREFIX:py=cp% - -if "%BUILD_VISION%" == "" ( - pip install future pytest coverage hypothesis protobuf -) ELSE ( - pip install future pytest "pillow>=4.1.1" -) - -for /F "delims=" %%i in ('where /R %SRC_DIR%\output *%MODULE_NAME%*%PYTHON_VERSION%*.whl') do pip install "%%i" - -if ERRORLEVEL 1 exit /b 1 - -if NOT "%BUILD_VISION%" == "" ( - echo Smoke testing imports - python -c "import torchvision" - if ERRORLEVEL 1 exit /b 1 - goto smoke_test_end -) - -echo Smoke testing imports -python -c "import torch" -if ERRORLEVEL 1 exit /b 1 - -python -c "from caffe2.python import core" -if ERRORLEVEL 1 exit /b 1 - -echo Checking that MKL is available -python -c "import torch; exit(0 if torch.backends.mkl.is_available() else 1)" -if ERRORLEVEL 1 exit /b 1 - -setlocal EnableDelayedExpansion -set NVIDIA_GPU_EXISTS=0 -for /F "delims=" %%i in ('wmic path win32_VideoController get name') do ( - set GPUS=%%i - if not "x!GPUS:NVIDIA=!" == "x!GPUS!" ( - SET NVIDIA_GPU_EXISTS=1 - goto gpu_check_end - ) -) -:gpu_check_end -endlocal & set NVIDIA_GPU_EXISTS=%NVIDIA_GPU_EXISTS% - -if NOT "%CUDA_PREFIX%" == "cpu" if "%NVIDIA_GPU_EXISTS%" == "1" ( - echo Checking that CUDA archs are setup correctly - python -c "import torch; torch.randn([3,5]).cuda()" - if ERRORLEVEL 1 exit /b 1 - - echo Checking that magma is available - python -c "import torch; torch.rand(1).cuda(); exit(0 if torch.cuda.has_magma else 1)" - if ERRORLEVEL 1 exit /b 1 - - echo Checking that CuDNN is available - python -c "import torch; exit(0 if torch.backends.cudnn.is_available() else 1)" - if ERRORLEVEL 1 exit /b 1 -) -:smoke_test_end - -echo Not running unit tests. Hopefully these problems are caught by CI -goto test_end - -if "%BUILD_VISION%" == "" ( - cd pytorch\test - python run_test.py -v -) else ( - cd vision - pytest . -) - -if ERRORLEVEL 1 exit /b 1 - -:test_end - -popd -exit /b 0 diff --git a/packaging/windows/internal/upload.bat b/packaging/windows/internal/upload.bat deleted file mode 100644 index a23391a2935..00000000000 --- a/packaging/windows/internal/upload.bat +++ /dev/null @@ -1,96 +0,0 @@ -@echo off - -IF "%CONDA_UPLOADER_INSTALLATION%" == "" goto precheck_fail -IF "%PYTORCH_FINAL_PACKAGE_DIR%" == "" goto precheck_fail -IF "%today%" == "" goto precheck_fail -IF "%PYTORCH_ANACONDA_USERNAME%" == "" goto precheck_fail -IF "%PYTORCH_ANACONDA_PASSWORD%" == "" goto precheck_fail - -goto precheck_pass - -:precheck_fail - -echo Please run nightly_defaults.bat first. -echo And remember to set `PYTORCH_FINAL_PACKAGE_DIR` -echo Finally, don't forget to set anaconda tokens -exit /b 1 - -:precheck_pass - -pushd %today% - -:: Install anaconda client -set "CONDA_HOME=%CONDA_UPLOADER_INSTALLATION%" -set "tmp_conda=%CONDA_HOME%" -set "miniconda_exe=%CD%\miniconda.exe" -rmdir /s /q "%CONDA_HOME%" -del miniconda.exe -curl -k https://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe -o "%miniconda_exe%" -popd - -IF ERRORLEVEL 1 ( - echo Conda download failed - exit /b 1 -) - -call %~dp0\..\..\conda\install_conda.bat - -IF ERRORLEVEL 1 ( - echo Conda installation failed - exit /b 1 -) - -set "ORIG_PATH=%PATH%" -set "PATH=%CONDA_HOME%;%CONDA_HOME%\scripts;%CONDA_HOME%\Library\bin;%PATH%" - -REM conda install -y anaconda-client -pip install git+https://github.com/peterjc123/anaconda-client.git@log_more_meaningfull_errors -IF ERRORLEVEL 1 ( - echo Anaconda client installation failed - exit /b 1 -) - -set PYTORCH_FINAL_PACKAGE= -:: Upload all the packages under `PYTORCH_FINAL_PACKAGE_DIR` -FOR /F "delims=" %%i IN ('where /R %PYTORCH_FINAL_PACKAGE_DIR% *vision*.tar.bz2') DO ( - set "PYTORCH_FINAL_PACKAGE=%%i" -) - -IF "%PYTORCH_FINAL_PACKAGE%" == "" ( - echo No package to upload - exit /b 0 -) - -:upload - -if "%RETRY_TIMES%" == "" ( - set /a RETRY_TIMES=10 - set /a SLEEP_TIME=2 -) else ( - set /a RETRY_TIMES=%RETRY_TIMES%-1 - set /a SLEEP_TIME=%SLEEP_TIME%*2 -) - -REM bash -c "yes | anaconda login --username "%PYTORCH_ANACONDA_USERNAME%" --password "%PYTORCH_ANACONDA_PASSWORD%"" -anaconda login --username "%PYTORCH_ANACONDA_USERNAME%" --password "%PYTORCH_ANACONDA_PASSWORD%" -IF ERRORLEVEL 1 ( - echo Anaconda client login failed - exit /b 1 -) - -echo Uploading %PYTORCH_FINAL_PACKAGE% to Anaconda Cloud -anaconda upload "%PYTORCH_FINAL_PACKAGE%" -u pytorch-nightly --label main --force --no-progress - -IF ERRORLEVEL 1 ( - echo Anaconda upload retry times remaining: %RETRY_TIMES% - echo Sleep time: %SLEEP_TIME% seconds - IF %RETRY_TIMES% EQU 0 ( - echo Upload failed - exit /b 1 - ) - waitfor SomethingThatIsNeverHappening /t %SLEEP_TIME% 2>nul || ver >nul - goto upload -) ELSE ( - set RETRY_TIMES= - set SLEEP_TIME= -) diff --git a/packaging/windows/internal/vs_install.bat b/packaging/windows/internal/vs_install.bat deleted file mode 100644 index 348a5e33166..00000000000 --- a/packaging/windows/internal/vs_install.bat +++ /dev/null @@ -1,14 +0,0 @@ -@echo off - -set VS_DOWNLOAD_LINK=https://aka.ms/vs/15/release/vs_enterprise.exe -set VS_INSTALL_PATH=C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise -set VS_INSTALL_ARGS=--nocache --quiet --wait --add Microsoft.VisualStudio.Component.VC.Tools.14.11 -set VSDEVCMD_ARGS=-vcvars_ver=14.11 - -curl -k -L %VS_DOWNLOAD_LINK% --output vs_installer.exe -if errorlevel 1 exit /b 1 - -start /wait vs_installer.exe modify --installPath "%VS_INSTALL_PATH%" %VS_INSTALL_ARGS% -if not errorlevel 0 exit /b 1 -if errorlevel 1 if not errorlevel 3010 exit /b 1 -if errorlevel 3011 exit /b 1 diff --git a/packaging/windows/old/cuda100.bat b/packaging/windows/old/cuda100.bat deleted file mode 100644 index ac9be3c6907..00000000000 --- a/packaging/windows/old/cuda100.bat +++ /dev/null @@ -1,59 +0,0 @@ -@echo off - -IF NOT "%BUILD_VISION%" == "" ( - set MODULE_NAME=vision -) ELSE ( - set MODULE_NAME=pytorch -) - -IF NOT EXIST "setup.py" IF NOT EXIST "%MODULE_NAME%" ( - call internal\clone.bat - cd .. - IF ERRORLEVEL 1 goto eof -) ELSE ( - call internal\clean.bat -) - -call internal\check_deps.bat -IF ERRORLEVEL 1 goto eof - -REM Check for optional components - -set NO_CUDA= -set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 - -IF "%NVTOOLSEXT_PATH%"=="" ( - echo NVTX ^(Visual Studio Extension ^for CUDA^) ^not installed, failing - exit /b 1 - goto optcheck -) - -IF "%CUDA_PATH_V10_0%"=="" ( - echo CUDA 10.0 not found, failing - exit /b 1 -) ELSE ( - IF "%BUILD_VISION%" == "" ( - set TORCH_CUDA_ARCH_LIST=3.5;5.0+PTX;6.0;6.1;7.0;7.5 - set TORCH_NVCC_FLAGS=-Xfatbin -compress-all - ) ELSE ( - set NVCC_FLAGS=-D__CUDA_NO_HALF_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_75,code=sm_75 -gencode=arch=compute_50,code=compute_50 - ) - - set "CUDA_PATH=%CUDA_PATH_V10_0%" - set "PATH=%CUDA_PATH_V10_0%\bin;%PATH%" -) - -:optcheck - -IF "%BUILD_VISION%" == "" ( - call internal\check_opts.bat - IF ERRORLEVEL 1 goto eof - - call internal\copy.bat - IF ERRORLEVEL 1 goto eof -) - -call internal\setup.bat -IF ERRORLEVEL 1 goto eof - -:eof diff --git a/packaging/windows/old/cuda90.bat b/packaging/windows/old/cuda90.bat deleted file mode 100644 index fe0294812e2..00000000000 --- a/packaging/windows/old/cuda90.bat +++ /dev/null @@ -1,59 +0,0 @@ -@echo off - -IF NOT "%BUILD_VISION%" == "" ( - set MODULE_NAME=vision -) ELSE ( - set MODULE_NAME=pytorch -) - -IF NOT EXIST "setup.py" IF NOT EXIST "%MODULE_NAME%" ( - call internal\clone.bat - cd .. - IF ERRORLEVEL 1 goto eof -) ELSE ( - call internal\clean.bat -) - -call internal\check_deps.bat -IF ERRORLEVEL 1 goto eof - -REM Check for optional components - -set NO_CUDA= -set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 - -IF "%NVTOOLSEXT_PATH%"=="" ( - echo NVTX ^(Visual Studio Extension ^for CUDA^) ^not installed, failing - exit /b 1 - goto optcheck -) - -IF "%CUDA_PATH_V9_0%"=="" ( - echo CUDA 9 not found, failing - exit /b 1 -) ELSE ( - IF "%BUILD_VISION%" == "" ( - set TORCH_CUDA_ARCH_LIST=3.5;5.0+PTX;6.0;7.0 - set TORCH_NVCC_FLAGS=-Xfatbin -compress-all - ) ELSE ( - set NVCC_FLAGS=-D__CUDA_NO_HALF_OPERATORS__ --expt-relaxed-constexpr -gencode=arch=compute_35,code=sm_35 -gencode=arch=compute_50,code=sm_50 -gencode=arch=compute_60,code=sm_60 -gencode=arch=compute_70,code=sm_70 -gencode=arch=compute_50,code=compute_50 - ) - - set "CUDA_PATH=%CUDA_PATH_V9_0%" - set "PATH=%CUDA_PATH_V9_0%\bin;%PATH%" -) - -:optcheck - -IF "%BUILD_VISION%" == "" ( - call internal\check_opts.bat - IF ERRORLEVEL 1 goto eof - - call internal\copy.bat - IF ERRORLEVEL 1 goto eof -) - -call internal\setup.bat -IF ERRORLEVEL 1 goto eof - -:eof diff --git a/packaging/windows/templates/auth_task.yml b/packaging/windows/templates/auth_task.yml deleted file mode 100644 index 7554ffaac1d..00000000000 --- a/packaging/windows/templates/auth_task.yml +++ /dev/null @@ -1,17 +0,0 @@ -jobs: -- job: 'VSTS_Auth_Task' - timeoutInMinutes: 5 - cancelTimeoutInMinutes: 5 - variables: - - group: 'peterjc-vsts-token' - - pool: - vmImage: 'vs2017-win2016' - - steps: - - checkout: self - clean: true - - - template: vsts_auth.yml - parameters: - auth: $(vsts_auth) diff --git a/packaging/windows/templates/build_conda.yml b/packaging/windows/templates/build_conda.yml deleted file mode 100644 index 2d88271ad33..00000000000 --- a/packaging/windows/templates/build_conda.yml +++ /dev/null @@ -1,15 +0,0 @@ -parameters: - msagent: false - -steps: -- bash: 'find . -name "*.sh" -exec dos2unix {} +' - displayName: Replace file endings - -- script: 'if not exist %PYTORCH_FINAL_PACKAGE_DIR% mkdir %PYTORCH_FINAL_PACKAGE_DIR%' - displayName: 'Create final package directory' - -- bash: './packaging/conda/build_vision.sh $CUDA_VERSION $TORCHVISION_BUILD_VERSION $TORCHVISION_BUILD_NUMBER' - displayName: Build - env: - ${{ if eq(parameters.msagent, 'true') }}: - MAX_JOBS: 2 diff --git a/packaging/windows/templates/build_task.yml b/packaging/windows/templates/build_task.yml deleted file mode 100644 index 17452477b82..00000000000 --- a/packaging/windows/templates/build_task.yml +++ /dev/null @@ -1,161 +0,0 @@ -parameters: - package: '' - spec: '' - jobDesc: '' - packageDesc: '' - msagent: true - cpuEnabled: true - cudaEnabled: true - condaEnabled: true - wheelsEnabled: true - override: false - -jobs: -- job: 'Windows_${{ parameters.spec }}_${{ parameters.package }}_Build' - timeoutInMinutes: 60 - cancelTimeoutInMinutes: 5 - condition: > - or(and(eq('${{ parameters.package }}', 'Conda'), eq('${{ parameters.spec }}', 'CPU'), - eq('${{ parameters.condaEnabled }}', 'true'), eq('${{ parameters.cpuEnabled }}', 'true')), - and(eq('${{ parameters.package }}', 'Wheels'), eq('${{ parameters.spec }}', 'CPU'), - eq('${{ parameters.wheelsEnabled }}', 'true'), eq('${{ parameters.cpuEnabled }}', 'true')), - and(eq('${{ parameters.package }}', 'Conda'), eq('${{ parameters.spec }}', 'CUDA'), - eq('${{ parameters.condaEnabled }}', 'true'), eq('${{ parameters.cudaEnabled }}', 'true')), - and(eq('${{ parameters.package }}', 'Wheels'), eq('${{ parameters.spec }}', 'CUDA'), - eq('${{ parameters.wheelsEnabled }}', 'true'), eq('${{ parameters.cudaEnabled }}', 'true'))) - variables: - - ${{ if eq(parameters.override, 'true') }}: - - name: TORCHVISION_BUILD_NUMBER - value: 1 - - name: PYTORCH_REPO - value: 'pytorch' - - name: PYTORCH_BRANCH - value: 'v0.4.0' - - ${{ if eq(parameters.msagent, 'true') }}: - - name: USE_SCCACHE - value: 0 - - ${{ if eq(parameters.msagent, 'false') }}: - - name: USE_SCCACHE - value: 1 - - ${{ if eq(parameters.package, 'Conda') }}: - - group: peterjc_anaconda_token - - name: PYTORCH_FINAL_PACKAGE_DIR - value: '$(Build.Repository.LocalPath)\packaging\windows\output' - - strategy: - maxParallel: 10 - matrix: - ${{ if eq(parameters.spec, 'CPU') }}: - PY3.5: - DESIRED_PYTHON: 3.5 - CUDA_VERSION: cpu - PY3.6: - DESIRED_PYTHON: 3.6 - CUDA_VERSION: cpu - PY3.7: - DESIRED_PYTHON: 3.7 - CUDA_VERSION: cpu - PY3.8: - DESIRED_PYTHON: 3.8 - CUDA_VERSION: cpu - ${{ if ne(parameters.spec, 'CPU') }}: - PY3.5_92: - DESIRED_PYTHON: 3.5 - CUDA_VERSION: 92 - PY3.6_92: - DESIRED_PYTHON: 3.6 - CUDA_VERSION: 92 - PY3.7_92: - DESIRED_PYTHON: 3.7 - CUDA_VERSION: 92 - PY3.8_92: - DESIRED_PYTHON: 3.8 - CUDA_VERSION: 92 - PY3.5_101: - DESIRED_PYTHON: 3.5 - CUDA_VERSION: 101 - PY3.6_101: - DESIRED_PYTHON: 3.6 - CUDA_VERSION: 101 - PY3.7_101: - DESIRED_PYTHON: 3.7 - CUDA_VERSION: 101 - PY3.8_101: - DESIRED_PYTHON: 3.8 - CUDA_VERSION: 101 - PY3.5_102: - DESIRED_PYTHON: 3.5 - CUDA_VERSION: 102 - PY3.6_102: - DESIRED_PYTHON: 3.6 - CUDA_VERSION: 102 - PY3.7_102: - DESIRED_PYTHON: 3.7 - CUDA_VERSION: 102 - PY3.8_102: - DESIRED_PYTHON: 3.8 - CUDA_VERSION: 102 - - pool: - ${{ if eq(parameters.msagent, 'true') }}: - vmImage: 'vs2017-win2016' - ${{ if eq(parameters.msagent, 'false') }}: - name: 'release' - - steps: - - checkout: self - clean: true - - - template: setup_env_for_msagent.yml - parameters: - msagent: ${{ parameters.msagent }} - - # - ${{ if and(eq(parameters.override, 'true'), eq(parameters.package, 'Wheels')) }}: - # - template: override_pytorch_version.yml - - - template: setup_nightly_variables.yml - parameters: - package: ${{ parameters.package }} - - - ${{ if eq(parameters.package, 'Wheels') }}: - - template: build_wheels.yml - parameters: - msagent: ${{ parameters.msagent }} - - - ${{ if eq(parameters.package, 'Conda') }}: - - template: build_conda.yml - parameters: - msagent: ${{ parameters.msagent }} - - - ${{ if or(eq(parameters.package, 'Wheels'), eq(parameters.package, 'Conda')) }}: - - template: publish_test_results.yml - parameters: - msagent: ${{ parameters.msagent }} - - # If you want to upload binaries to S3 & Anaconda Cloud, please uncomment this section. - - ${{ if and(eq(parameters.package, 'Wheels'), eq(parameters.spec, 'CPU')) }}: - - template: upload_to_s3.yml - parameters: - cuVer: '$(CUDA_VERSION)' - cudaVer: '$(CUDA_VERSION)' - - - ${{ if and(eq(parameters.package, 'Wheels'), ne(parameters.spec, 'CPU')) }}: - - template: upload_to_s3.yml - parameters: - cuVer: 'cu$(CUDA_VERSION)' - cudaVer: 'cuda$(CUDA_VERSION)' - - - ${{ if eq(parameters.package, 'Conda') }}: - - template: upload_to_conda.yml - parameters: - user: $(peterjc_conda_username) - pass: $(peterjc_conda_password) - - # If you want to upload binaries to Azure Git, please uncomment this section. - # - ${{ if or(eq(parameters.package, 'Wheels'), eq(parameters.package, 'Conda')) }}: - # - template: publish_test_results.yml - # parameters: - # msagent: ${{ parameters.msagent }} - # - template: publish_packages.yml - # parameters: - # package: ${{ parameters.package }} diff --git a/packaging/windows/templates/build_wheels.yml b/packaging/windows/templates/build_wheels.yml deleted file mode 100644 index 05c5712e334..00000000000 --- a/packaging/windows/templates/build_wheels.yml +++ /dev/null @@ -1,9 +0,0 @@ -parameters: - msagent: false - -steps: -- script: 'call packaging/windows/build_vision.bat %CUDA_VERSION% %TORCHVISION_BUILD_VERSION% %TORCHVISION_BUILD_NUMBER%' - displayName: Build - env: - ${{ if eq(parameters.msagent, 'true') }}: - MAX_JOBS: 2 diff --git a/packaging/windows/templates/linux_build_task.yml b/packaging/windows/templates/linux_build_task.yml deleted file mode 100644 index 0b32892791a..00000000000 --- a/packaging/windows/templates/linux_build_task.yml +++ /dev/null @@ -1,38 +0,0 @@ -parameters: - msagent: true - enabled: false - -jobs: -- job: 'Linux_CPU_Conda_Build' - timeoutInMinutes: 0 - cancelTimeoutInMinutes: 5 - condition: ${{ eq(parameters.enabled, 'true') }} - variables: - CUDA_VERSION: cpu - TORCH_CONDA_BUILD_FOLDER: pytorch-nightly - PYTORCH_FINAL_PACKAGE_DIR: '$(Build.Repository.LocalPath)/output' - - strategy: - maxParallel: 10 - matrix: - PY3.5: - DESIRED_PYTHON: 3.5 - - pool: - vmImage: 'ubuntu-16.04' - - steps: - - checkout: self - clean: true - - - script: 'sudo apt-get install p7zip-full' - displayName: 'Install 7Zip' - - - task: CondaEnvironment@1 - displayName: 'Install conda-build' - inputs: - packageSpecs: 'conda-build' - - - template: build_conda.yml - parameters: - msagent: ${{ parameters.msagent }} diff --git a/packaging/windows/templates/override_pytorch_version.yml b/packaging/windows/templates/override_pytorch_version.yml deleted file mode 100644 index 8af93ae43a4..00000000000 --- a/packaging/windows/templates/override_pytorch_version.yml +++ /dev/null @@ -1,6 +0,0 @@ -steps: -- script: 'windows/internal/override_pytorch_version.bat' - displayName: 'Override PyTorch Build Version for Wheels' - -- script: 'echo $(PYTORCH_BUILD_VERSION)' - displayName: 'Show PyTorch Build Version' diff --git a/packaging/windows/templates/publish_packages.yml b/packaging/windows/templates/publish_packages.yml deleted file mode 100644 index 51ce8247bf7..00000000000 --- a/packaging/windows/templates/publish_packages.yml +++ /dev/null @@ -1,8 +0,0 @@ -parameters: - package: '' - -steps: -- script: 'packaging/windows/internal/publish.bat' - displayName: 'Upload packages to Azure DevOps Repo' - env: - PACKAGEFULLNAME: ${{ parameters.package }} diff --git a/packaging/windows/templates/publish_test_results.yml b/packaging/windows/templates/publish_test_results.yml deleted file mode 100644 index 1e0dc0215d3..00000000000 --- a/packaging/windows/templates/publish_test_results.yml +++ /dev/null @@ -1,6 +0,0 @@ -steps: -- task: PublishTestResults@2 # No test results to publish - inputs: - testResultsFiles: 'windows/pytorch/test/**/*.xml' - testRunTitle: 'Publish test results' - enabled: false diff --git a/packaging/windows/templates/setup_env_for_msagent.yml b/packaging/windows/templates/setup_env_for_msagent.yml deleted file mode 100644 index 377734fa3db..00000000000 --- a/packaging/windows/templates/setup_env_for_msagent.yml +++ /dev/null @@ -1,25 +0,0 @@ -parameters: - msagent: false - -steps: -- ${{ if eq(parameters.msagent, 'true') }}: - - task: BatchScript@1 - displayName: 'Install 7Zip & cURL' - inputs: - filename: 'packaging/windows/internal/dep_install.bat' - - modifyEnvironment: true - - - task: BatchScript@1 - displayName: 'Install Visual Studio 2017' - inputs: - filename: 'packaging/windows/internal/vs_install.bat' - - modifyEnvironment: true - - - task: BatchScript@1 - displayName: 'Install CUDA' - inputs: - filename: 'packaging/windows/internal/cuda_install.bat' - - modifyEnvironment: true diff --git a/packaging/windows/templates/setup_nightly_variables.yml b/packaging/windows/templates/setup_nightly_variables.yml deleted file mode 100644 index 94b2fe934ce..00000000000 --- a/packaging/windows/templates/setup_nightly_variables.yml +++ /dev/null @@ -1,11 +0,0 @@ -parameters: - package: '' - -steps: -- task: BatchScript@1 - displayName: 'Setup nightly variables' - inputs: - filename: 'packaging/windows/internal/nightly_defaults.bat' - arguments: ${{ parameters.package }} - - modifyEnvironment: true diff --git a/packaging/windows/templates/upload_to_conda.yml b/packaging/windows/templates/upload_to_conda.yml deleted file mode 100644 index dc172bcf878..00000000000 --- a/packaging/windows/templates/upload_to_conda.yml +++ /dev/null @@ -1,10 +0,0 @@ -parameters: - user: '' - pass: '' - -steps: -- script: 'call packaging/windows/internal/upload.bat' - displayName: 'Upload packages to Anaconda Cloud' - env: - PYTORCH_ANACONDA_USERNAME: ${{ parameters.user }} - PYTORCH_ANACONDA_PASSWORD: ${{ parameters.pass }} diff --git a/packaging/windows/templates/upload_to_s3.yml b/packaging/windows/templates/upload_to_s3.yml deleted file mode 100644 index 1de91b5786d..00000000000 --- a/packaging/windows/templates/upload_to_s3.yml +++ /dev/null @@ -1,15 +0,0 @@ -parameters: - cuVer: '' - cudaVer: '' - -steps: -- task: AmazonWebServices.aws-vsts-tools.S3Upload.S3Upload@1 - displayName: 'Upload ${{ parameters.cuVer }} wheel to S3' - inputs: - awsCredentials: 'Pytorch S3 bucket' - bucketName: 'pytorch' - sourceFolder: 'packaging/windows/output' - globExpressions: '*.whl' - targetFolder: 'whl/nightly/${{ parameters.cuVer }}/' - filesAcl: 'public-read' - flattenFolders: 'true' diff --git a/packaging/windows/templates/vsts_auth.yml b/packaging/windows/templates/vsts_auth.yml deleted file mode 100644 index fde767d7f12..00000000000 --- a/packaging/windows/templates/vsts_auth.yml +++ /dev/null @@ -1,8 +0,0 @@ -parameters: - auth: '' - -steps: -- script: 'call packaging/windows/internal/auth.bat' - displayName: 'Sign in to Azure Pipelines' - env: - VSTS_AUTH: ${{ parameters.auth }} From 076b2bf48f7838459641ec0a6c2c9b1d752ff58c Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 333/357] [fbsync] Update weights of classification models to allow proper unpickling (#3620) Summary: * Update URLS of detection models * Empty commit after setting read permission on S3 Reviewed By: NicolasHug Differential Revision: D27706954 fbshipit-source-id: 3c560abe41688f7d3b2fa8792e8f157c89a4fb81 Co-authored-by: Francisco Massa --- torchvision/models/alexnet.py | 2 +- torchvision/models/resnet.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/torchvision/models/alexnet.py b/torchvision/models/alexnet.py index e679c679aa0..b9e8206d552 100644 --- a/torchvision/models/alexnet.py +++ b/torchvision/models/alexnet.py @@ -8,7 +8,7 @@ model_urls = { - 'alexnet': 'https://download.pytorch.org/models/alexnet-owt-4df8aa71.pth', + 'alexnet': 'https://download.pytorch.org/models/alexnet-owt-7be5be79.pth', } diff --git a/torchvision/models/resnet.py b/torchvision/models/resnet.py index 739394a366d..e772650aaaf 100644 --- a/torchvision/models/resnet.py +++ b/torchvision/models/resnet.py @@ -11,11 +11,11 @@ model_urls = { - 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', - 'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth', - 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth', - 'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth', - 'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth', + 'resnet18': 'https://download.pytorch.org/models/resnet18-f37072fd.pth', + 'resnet34': 'https://download.pytorch.org/models/resnet34-b627a593.pth', + 'resnet50': 'https://download.pytorch.org/models/resnet50-0676ba61.pth', + 'resnet101': 'https://download.pytorch.org/models/resnet101-63fe2227.pth', + 'resnet152': 'https://download.pytorch.org/models/resnet152-394f9c45.pth', 'resnext50_32x4d': 'https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth', 'resnext101_32x8d': 'https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth', 'wide_resnet50_2': 'https://download.pytorch.org/models/wide_resnet50_2-95faca4d.pth', From 7a3176a3bf4dcc8d1ecfc6b6620a4bba245a8219 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 334/357] [fbsync] Add warning in docs of Resize about different results for PIL and tensors (#3615) Summary: * docs for resize * address comment: describe antialiasing Reviewed By: NicolasHug Differential Revision: D27706945 fbshipit-source-id: e48c865c09f204b75d5e209a7ba45166fc913e18 --- torchvision/transforms/functional.py | 6 ++++++ torchvision/transforms/transforms.py | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 7bd15dde4c2..d36e68c2b6f 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -346,6 +346,12 @@ def resize(img: Tensor, size: List[int], interpolation: InterpolationMode = Inte If the image is torch Tensor, it is expected to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions + .. warning:: + The output image might be different depending on its type: when downsampling, the interpolation of PIL images + and tensors is slightly different, because PIL applies antialiasing. This may lead to significant differences + in the performance of a network. Therefore, it is preferable to train and serve a model with the same input + types. + Args: img (PIL Image or Tensor): Image to be resized. size (sequence or int): Desired output size. If size is a sequence like diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 2c4a10598b4..7c25b000ce8 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -229,6 +229,12 @@ class Resize(torch.nn.Module): If the image is torch Tensor, it is expected to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions + .. warning:: + The output image might be different depending on its type: when downsampling, the interpolation of PIL images + and tensors is slightly different, because PIL applies antialiasing. This may lead to significant differences + in the performance of a network. Therefore, it is preferable to train and serve a model with the same input + types. + Args: size (sequence or int): Desired output size. If size is a sequence like (h, w), output size will be matched to this. If size is an int, From 250d4abda8c638f68e7c071b4ad1fd89b5ea2573 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 335/357] [fbsync] Minor cleanup of roi_align_forward_kernel_impl (#3619) Summary: * minor clean up * do same for ps_roialign Reviewed By: NicolasHug Differential Revision: D27706957 fbshipit-source-id: 3320466f6a8b12445f4c901460d3b6f39e6760ea Co-authored-by: Francisco Massa --- torchvision/csrc/ops/cpu/ps_roi_align_kernel.cpp | 8 +++----- torchvision/csrc/ops/cpu/roi_align_kernel.cpp | 7 ++----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/torchvision/csrc/ops/cpu/ps_roi_align_kernel.cpp b/torchvision/csrc/ops/cpu/ps_roi_align_kernel.cpp index 5e33fc0bc62..4f78d59ae6b 100644 --- a/torchvision/csrc/ops/cpu/ps_roi_align_kernel.cpp +++ b/torchvision/csrc/ops/cpu/ps_roi_align_kernel.cpp @@ -62,7 +62,7 @@ T bilinear_interpolate( template void ps_roi_align_forward_kernel_impl( - int nthreads, + int num_rois, const T* input, const T spatial_scale, int channels, @@ -75,7 +75,6 @@ void ps_roi_align_forward_kernel_impl( int channels_out, T* output, int* channel_mapping) { - int num_rois = nthreads / channels_out / pooled_width / pooled_height; for (int n = 0; n < num_rois; n++) { // [start, end) interval for spatial sampling const T* offset_rois = rois + n * 5; @@ -335,8 +334,7 @@ std::tuple ps_roi_align_forward_kernel( auto channel_mapping = at::zeros(output.sizes(), input.options().dtype(at::kInt)); - auto output_size = output.numel(); - if (output_size == 0) { + if (output.numel() == 0) { return std::make_tuple(output, channel_mapping); } @@ -344,7 +342,7 @@ std::tuple ps_roi_align_forward_kernel( AT_DISPATCH_FLOATING_TYPES_AND_HALF( input.scalar_type(), "ps_roi_align_forward_kernel", [&] { ps_roi_align_forward_kernel_impl( - output_size, + num_rois, input_.data_ptr(), spatial_scale, channels, diff --git a/torchvision/csrc/ops/cpu/roi_align_kernel.cpp b/torchvision/csrc/ops/cpu/roi_align_kernel.cpp index 8e86104513b..dc0c38cd314 100644 --- a/torchvision/csrc/ops/cpu/roi_align_kernel.cpp +++ b/torchvision/csrc/ops/cpu/roi_align_kernel.cpp @@ -117,7 +117,7 @@ void pre_calc_for_bilinear_interpolate( template void roi_align_forward_kernel_impl( - int nthreads, + int n_rois, const T* input, const T& spatial_scale, int channels, @@ -129,7 +129,6 @@ void roi_align_forward_kernel_impl( bool aligned, const T* rois, T* output) { - int n_rois = nthreads / channels / pooled_width / pooled_height; // (n, c, ph, pw) is an element in the pooled output // can be parallelized using omp // #pragma omp parallel for num_threads(32) @@ -414,8 +413,6 @@ at::Tensor roi_align_forward_kernel( at::Tensor output = at::zeros( {num_rois, channels, pooled_height, pooled_width}, input.options()); - auto output_size = num_rois * pooled_height * pooled_width * channels; - if (output.numel() == 0) return output; @@ -423,7 +420,7 @@ at::Tensor roi_align_forward_kernel( AT_DISPATCH_FLOATING_TYPES_AND_HALF( input.scalar_type(), "roi_align_forward_kernel", [&] { roi_align_forward_kernel_impl( - output_size, + num_rois, input_.data_ptr(), spatial_scale, channels, From eb240ca5f5211e0b563805c5cc69847bc7a23c99 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 336/357] [fbsync] Fix test_draw_boxes (#3631) Summary: * new image * avoid check if pil version is < 8.2 as the reference image would be different Reviewed By: NicolasHug Differential Revision: D27706947 fbshipit-source-id: 4c43289e4ebf742b643112e24a8119fc1f70ac55 --- test/assets/fakedata/draw_boxes_util.png | Bin 547 -> 547 bytes test/test_utils.py | 12 +++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/test/assets/fakedata/draw_boxes_util.png b/test/assets/fakedata/draw_boxes_util.png index d64fa2f1f360fc386494b915cef0675fdee705a0..2c361c5fafd52abb6a6b645e92fb4fe972a716ac 100644 GIT binary patch delta 408 zcmV;J0cZZB1fv9yH-9h$%+VD%;W^44aLNkI(L-10BI$vY9@^S@R@8!d->DLUMo+fm zSco*nm<}mgjW1*Kd+*LFB970;wm0Wjx1Dih0d5@tV*!iCx-MItu3yV7@Vzfs;WR{(p#fEs z*ov49WVwoR~@H$lY!0000JpD ze65b&+W$`ZP+aNqi0@{h+bxe~?Nhinb-ksw(j_y?BU<~`ZZ3QHqkdK4O9lyU1F;01 z0}%&S{VR(L4;Omv5qSHa=EbXQ=UmowRMge~d%N~y?wU1e#b36id^Ta}VfC5c_V{r{ zO`xUx`y*PfqWNBTbXd6LB-O|~{@~tTIyXpjEBCdJN!QEH&rmKeGo53d{`AD(*t;tt zH}=iEGkM0m2e~EBE-`}bjErd5$dJrxn^`|K~py{T-P0=w87$Iq$C6 z`0W#Z9uhnKrMKiXe~H+;%ZrM`miL~UCLKBbSZ=yZWP>+5(CLddp1T~j{PXo9;hOit zVHHwJlOHmQPJYTLh=%!f)#kYx|IV(ek>ITr^Zoq2?BrzukW(Ho8$Au!@O7ueL= (8, 2): + # The reference image is only valid for new PIL versions + expected = torch.as_tensor(np.array(Image.open(path))).permute(2, 0, 1) + self.assertTrue(torch.equal(result, expected)) + # Check if modification is not in place self.assertTrue(torch.all(torch.eq(boxes, boxes_cp)).item()) self.assertTrue(torch.all(torch.eq(img, img_cp)).item()) From ef436368acbd0b613ac1a96cb400cfa06ce620d2 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 337/357] [fbsync] Fixed jinja2 environment autoescape to enable select extensions (#3635) Summary: Co-authored-by: Nicolas Hug Reviewed By: NicolasHug Differential Revision: D27706943 fbshipit-source-id: ab78c486368d3287799d5a2acd45ce6f2c2ccfee --- .circleci/regenerate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/regenerate.py b/.circleci/regenerate.py index d70860de86f..c853ec273e4 100755 --- a/.circleci/regenerate.py +++ b/.circleci/regenerate.py @@ -15,6 +15,7 @@ """ import jinja2 +from jinja2 import select_autoescape import yaml import os.path @@ -295,7 +296,7 @@ def ios_workflows(indentation=6, nightly=False): env = jinja2.Environment( loader=jinja2.FileSystemLoader(d), lstrip_blocks=True, - autoescape=False, + autoescape=select_autoescape(enabled_extensions=('html', 'xml')), keep_trailing_newline=True, ) From 4f0d29829987609c6f24da3f93ae4b34da6deb80 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 338/357] [fbsync] Remove unused imports (#3639) Reviewed By: NicolasHug Differential Revision: D27706949 fbshipit-source-id: 35f027db0af62316a28860551ce8c07065eae022 --- torchvision/models/_utils.py | 1 - torchvision/ops/boxes.py | 2 +- torchvision/transforms/functional_pil.py | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/torchvision/models/_utils.py b/torchvision/models/_utils.py index c8faf12786c..df5ab9a044c 100644 --- a/torchvision/models/_utils.py +++ b/torchvision/models/_utils.py @@ -1,6 +1,5 @@ from collections import OrderedDict -import torch from torch import nn from typing import Dict diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index 47142d51527..5201ed5bd38 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -1,6 +1,6 @@ import torch from torch import Tensor -from typing import List, Tuple +from typing import Tuple from ._box_convert import _box_cxcywh_to_xyxy, _box_xyxy_to_cxcywh, _box_xywh_to_xyxy, _box_xyxy_to_xywh import torchvision from torchvision.extension import _assert_has_ops diff --git a/torchvision/transforms/functional_pil.py b/torchvision/transforms/functional_pil.py index 42d7db9f260..9059db03683 100644 --- a/torchvision/transforms/functional_pil.py +++ b/torchvision/transforms/functional_pil.py @@ -3,7 +3,7 @@ import numpy as np import torch -from PIL import Image, ImageOps, ImageEnhance, ImageFilter, __version__ as PILLOW_VERSION +from PIL import Image, ImageOps, ImageEnhance, __version__ as PILLOW_VERSION try: import accimage From c1ec02e0e02a08e553d86fab72fa3468a6eba282 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 339/357] [fbsync] Make DatasetFolder.find_classes public (#3628) Summary: Co-authored-by: Nicolas Hug Reviewed By: NicolasHug Differential Revision: D27706955 fbshipit-source-id: da038e3b92aa47a720b45f3b6ea4a48976e15ed2 --- torchvision/datasets/folder.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/torchvision/datasets/folder.py b/torchvision/datasets/folder.py index d121bad7a19..9eb849bbe34 100644 --- a/torchvision/datasets/folder.py +++ b/torchvision/datasets/folder.py @@ -182,7 +182,7 @@ def __init__( ) -> None: super(DatasetFolder, self).__init__(root, transform=transform, target_transform=target_transform) - classes, class_to_idx = self._find_classes(self.root) + classes, class_to_idx = self.find_classes(self.root) samples = self.make_dataset(self.root, class_to_idx, extensions, is_valid_file) self.loader = loader @@ -202,8 +202,12 @@ def make_dataset( ) -> List[Tuple[str, int]]: return make_dataset(directory, class_to_idx, extensions=extensions, is_valid_file=is_valid_file) - @staticmethod - def _find_classes(dir: str) -> Tuple[List[str], Dict[str, int]]: + def find_classes(self, dir: str) -> Tuple[List[str], Dict[str, int]]: + """Same as :func:`find_classes`. + + This method can be overridden to only consider + a subset of classes, or to adapt to a different dataset directory structure. + """ return find_classes(dir) def __getitem__(self, index: int) -> Tuple[Any, Any]: From 7fdcae5d1e85ddb762c65405b59b7e7c374e4915 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 340/357] [fbsync] Bump PIL dependency to >=5.3.0 and run 5.3.0 on some CI runs (#3641) Summary: * bump to 5.3.0 * Also make 3.6 CI runs rely on 5.3.0 Reviewed By: NicolasHug Differential Revision: D27706951 fbshipit-source-id: 93f598655a26ad9935f4ba910ab35b758970e2c4 --- .circleci/unittest/linux/scripts/install.sh | 6 +++++ .circleci/unittest/windows/scripts/install.sh | 6 +++++ setup.py | 2 +- torchvision/transforms/functional.py | 1 - torchvision/transforms/functional_pil.py | 22 +++++-------------- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/.circleci/unittest/linux/scripts/install.sh b/.circleci/unittest/linux/scripts/install.sh index 1a3e5c6f4d2..bec090a491e 100755 --- a/.circleci/unittest/linux/scripts/install.sh +++ b/.circleci/unittest/linux/scripts/install.sh @@ -26,5 +26,11 @@ fi printf "Installing PyTorch with %s\n" "${cudatoolkit}" conda install -y -c "pytorch-${UPLOAD_CHANNEL}" -c conda-forge "pytorch-${UPLOAD_CHANNEL}"::pytorch "${cudatoolkit}" +if [ $PYTHON_VERSION == "3.6" ]; then + printf "Installing minimal PILLOW version\n" + # Install the minimal PILLOW version. Otherwise, let setup.py install the latest + pip install pillow==5.3.0 +fi + printf "* Installing torchvision\n" python setup.py develop diff --git a/.circleci/unittest/windows/scripts/install.sh b/.circleci/unittest/windows/scripts/install.sh index 9304b4b9b65..ac5222a7b90 100644 --- a/.circleci/unittest/windows/scripts/install.sh +++ b/.circleci/unittest/windows/scripts/install.sh @@ -28,5 +28,11 @@ fi printf "Installing PyTorch with %s\n" "${cudatoolkit}" conda install -y -c "pytorch-${UPLOAD_CHANNEL}" -c conda-forge "pytorch-${UPLOAD_CHANNEL}"::pytorch "${cudatoolkit}" +if [ $PYTHON_VERSION == "3.6" ]; then + printf "Installing minimal PILLOW version\n" + # Install the minimal PILLOW version. Otherwise, let setup.py install the latest + pip install pillow==5.3.0 +fi + printf "* Installing torchvision\n" "$this_dir/vc_env_helper.bat" python setup.py develop diff --git a/setup.py b/setup.py index 23bbdaab378..ff4c48d4cbb 100644 --- a/setup.py +++ b/setup.py @@ -67,7 +67,7 @@ def write_version_file(): pytorch_dep, ] -pillow_ver = ' >= 4.1.1' +pillow_ver = ' >= 5.3.0' pillow_req = 'pillow-simd' if get_dist('pillow-simd') is not None else 'pillow' requirements.append(pillow_req + pillow_ver) diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index d36e68c2b6f..64ed0b8edd5 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -55,7 +55,6 @@ def _interpolation_modes_from_int(i: int) -> InterpolationMode: } _is_pil_image = F_pil._is_pil_image -_parse_fill = F_pil._parse_fill def _get_image_size(img: Tensor) -> List[int]: diff --git a/torchvision/transforms/functional_pil.py b/torchvision/transforms/functional_pil.py index 9059db03683..3829637fdb7 100644 --- a/torchvision/transforms/functional_pil.py +++ b/torchvision/transforms/functional_pil.py @@ -3,7 +3,7 @@ import numpy as np import torch -from PIL import Image, ImageOps, ImageEnhance, __version__ as PILLOW_VERSION +from PIL import Image, ImageOps, ImageEnhance try: import accimage @@ -147,7 +147,7 @@ def pad(img, padding, fill=0, padding_mode="constant"): raise ValueError("Padding mode should be either constant, edge, reflect or symmetric") if padding_mode == "constant": - opts = _parse_fill(fill, img, "2.3.0", name="fill") + opts = _parse_fill(fill, img, name="fill") if img.mode == "P": palette = img.getpalette() image = ImageOps.expand(img, border=padding, **opts) @@ -242,18 +242,8 @@ def resize(img, size, interpolation=Image.BILINEAR, max_size=None): @torch.jit.unused -def _parse_fill(fill, img, min_pil_version, name="fillcolor"): +def _parse_fill(fill, img, name="fillcolor"): # Process fill color for affine transforms - major_found, minor_found = (int(v) for v in PILLOW_VERSION.split('.')[:2]) - major_required, minor_required = (int(v) for v in min_pil_version.split('.')[:2]) - if major_found < major_required or (major_found == major_required and minor_found < minor_required): - if fill is None: - return {} - else: - msg = ("The option to fill background area of the transformed image, " - "requires pillow>={}") - raise RuntimeError(msg.format(min_pil_version)) - num_bands = len(img.getbands()) if fill is None: fill = 0 @@ -276,7 +266,7 @@ def affine(img, matrix, interpolation=0, fill=None): raise TypeError('img should be PIL Image. Got {}'.format(type(img))) output_size = img.size - opts = _parse_fill(fill, img, '5.0.0') + opts = _parse_fill(fill, img) return img.transform(output_size, Image.AFFINE, matrix, interpolation, **opts) @@ -285,7 +275,7 @@ def rotate(img, angle, interpolation=0, expand=False, center=None, fill=None): if not _is_pil_image(img): raise TypeError("img should be PIL Image. Got {}".format(type(img))) - opts = _parse_fill(fill, img, '5.2.0') + opts = _parse_fill(fill, img) return img.rotate(angle, interpolation, expand, center, **opts) @@ -294,7 +284,7 @@ def perspective(img, perspective_coeffs, interpolation=Image.BICUBIC, fill=None) if not _is_pil_image(img): raise TypeError('img should be PIL Image. Got {}'.format(type(img))) - opts = _parse_fill(fill, img, '5.0.0') + opts = _parse_fill(fill, img) return img.transform(img.size, Image.PERSPECTIVE, perspective_coeffs, interpolation, **opts) From 37620db43bc94408bd3f665fe01c6ad912321c6e Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 341/357] [fbsync] Documentation improvements for ops (#3634) Summary: * some doc improvements * flake8 Reviewed By: NicolasHug Differential Revision: D27706958 fbshipit-source-id: 2dff929d1d692fad720db12ea491bec5b86f8bc3 Co-authored-by: Francisco Massa --- torchvision/ops/boxes.py | 39 ++++++++++++++++----------------- torchvision/ops/deform_conv.py | 4 ++-- torchvision/ops/ps_roi_align.py | 4 ++-- torchvision/ops/ps_roi_pool.py | 4 ++-- torchvision/ops/roi_align.py | 4 ++-- torchvision/ops/roi_pool.py | 4 ++-- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/torchvision/ops/boxes.py b/torchvision/ops/boxes.py index 5201ed5bd38..c1f176f4da9 100644 --- a/torchvision/ops/boxes.py +++ b/torchvision/ops/boxes.py @@ -28,9 +28,8 @@ def nms(boxes: Tensor, scores: Tensor, iou_threshold: float) -> Tensor: iou_threshold (float): discards all overlapping boxes with IoU > iou_threshold Returns: - keep (Tensor): int64 tensor with the indices - of the elements that have been kept - by NMS, sorted in decreasing order of scores + Tensor: int64 tensor with the indices of the elements that have been kept + by NMS, sorted in decreasing order of scores """ _assert_has_ops() return torch.ops.torchvision.nms(boxes, scores, iou_threshold) @@ -57,9 +56,8 @@ def batched_nms( iou_threshold (float): discards all overlapping boxes with IoU > iou_threshold Returns: - keep (Tensor): int64 tensor with the indices of - the elements that have been kept by NMS, sorted - in decreasing order of scores + Tensor: int64 tensor with the indices of the elements that have been kept by NMS, sorted + in decreasing order of scores """ # Benchmarks that drove the following thresholds are at # https://github.com/pytorch/vision/issues/1311#issuecomment-781329339 @@ -117,8 +115,8 @@ def remove_small_boxes(boxes: Tensor, min_size: float) -> Tensor: min_size (float): minimum size Returns: - keep (Tensor[K]): indices of the boxes that have both sides - larger than min_size + Tensor[K]: indices of the boxes that have both sides + larger than min_size """ ws, hs = boxes[:, 2] - boxes[:, 0], boxes[:, 3] - boxes[:, 1] keep = (ws >= min_size) & (hs >= min_size) @@ -136,7 +134,7 @@ def clip_boxes_to_image(boxes: Tensor, size: Tuple[int, int]) -> Tensor: size (Tuple[height, width]): size of the image Returns: - clipped_boxes (Tensor[N, 4]) + Tensor[N, 4]: clipped boxes """ dim = boxes.dim() boxes_x = boxes[..., 0::2] @@ -162,6 +160,7 @@ def box_convert(boxes: Tensor, in_fmt: str, out_fmt: str) -> Tensor: Supported in_fmt and out_fmt are: 'xyxy': boxes are represented via corners, x1, y1 being top left and x2, y2 being bottom right. + This is the format that torchvision utilities expect. 'xywh' : boxes are represented via corner, width and height, x1, y2 being top left, w, h being width and height. @@ -174,7 +173,7 @@ def box_convert(boxes: Tensor, in_fmt: str, out_fmt: str) -> Tensor: out_fmt (str): Output format of given boxes. Supported formats are ['xyxy', 'xywh', 'cxcywh'] Returns: - boxes (Tensor[N, 4]): Boxes into converted format. + Tensor[N, 4]: Boxes into converted format. """ allowed_fmts = ("xyxy", "xywh", "cxcywh") @@ -215,7 +214,7 @@ def _upcast(t: Tensor) -> Tensor: def box_area(boxes: Tensor) -> Tensor: """ - Computes the area of a set of bounding boxes, which are specified by its + Computes the area of a set of bounding boxes, which are specified by their (x1, y1, x2, y2) coordinates. Args: @@ -224,7 +223,7 @@ def box_area(boxes: Tensor) -> Tensor: ``0 <= x1 < x2`` and ``0 <= y1 < y2``. Returns: - area (Tensor[N]): area for each box + Tensor[N]: the area for each box """ boxes = _upcast(boxes) return (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) @@ -249,17 +248,17 @@ def _box_inter_union(boxes1: Tensor, boxes2: Tensor) -> Tuple[Tensor, Tensor]: def box_iou(boxes1: Tensor, boxes2: Tensor) -> Tensor: """ - Return intersection-over-union (Jaccard index) of boxes. + Return intersection-over-union (Jaccard index) between two sets of boxes. Both sets of boxes are expected to be in ``(x1, y1, x2, y2)`` format with ``0 <= x1 < x2`` and ``0 <= y1 < y2``. Args: - boxes1 (Tensor[N, 4]) - boxes2 (Tensor[M, 4]) + boxes1 (Tensor[N, 4]): first set of boxes + boxes2 (Tensor[M, 4]): second set of boxes Returns: - iou (Tensor[N, M]): the NxM matrix containing the pairwise IoU values for every element in boxes1 and boxes2 + Tensor[N, M]: the NxM matrix containing the pairwise IoU values for every element in boxes1 and boxes2 """ inter, union = _box_inter_union(boxes1, boxes2) iou = inter / union @@ -269,17 +268,17 @@ def box_iou(boxes1: Tensor, boxes2: Tensor) -> Tensor: # Implementation adapted from https://github.com/facebookresearch/detr/blob/master/util/box_ops.py def generalized_box_iou(boxes1: Tensor, boxes2: Tensor) -> Tensor: """ - Return generalized intersection-over-union (Jaccard index) of boxes. + Return generalized intersection-over-union (Jaccard index) between two sets of boxes. Both sets of boxes are expected to be in ``(x1, y1, x2, y2)`` format with ``0 <= x1 < x2`` and ``0 <= y1 < y2``. Args: - boxes1 (Tensor[N, 4]) - boxes2 (Tensor[M, 4]) + boxes1 (Tensor[N, 4]): first set of boxes + boxes2 (Tensor[M, 4]): second set of boxes Returns: - generalized_iou (Tensor[N, M]): the NxM matrix containing the pairwise generalized_IoU values + Tensor[N, M]: the NxM matrix containing the pairwise generalized IoU values for every element in boxes1 and boxes2 """ diff --git a/torchvision/ops/deform_conv.py b/torchvision/ops/deform_conv.py index 4fb2684e5f6..7f8760fa35f 100644 --- a/torchvision/ops/deform_conv.py +++ b/torchvision/ops/deform_conv.py @@ -44,7 +44,7 @@ def deform_conv2d( convolution kernel. Default: None Returns: - output (Tensor[batch_sz, out_channels, out_h, out_w]): result of convolution + Tensor[batch_sz, out_channels, out_h, out_w]: result of convolution Examples:: @@ -105,7 +105,7 @@ def deform_conv2d( class DeformConv2d(nn.Module): """ - See deform_conv2d + See :func:`deform_conv2d`. """ def __init__( diff --git a/torchvision/ops/ps_roi_align.py b/torchvision/ops/ps_roi_align.py index d14f429785a..09c4ca88bea 100644 --- a/torchvision/ops/ps_roi_align.py +++ b/torchvision/ops/ps_roi_align.py @@ -38,7 +38,7 @@ def ps_roi_align( ceil(roi_width / pooled_w), and likewise for height). Default: -1 Returns: - output (Tensor[K, C, output_size[0], output_size[1]]) + Tensor[K, C, output_size[0], output_size[1]]: The pooled RoIs """ _assert_has_ops() check_roi_boxes_shape(boxes) @@ -55,7 +55,7 @@ def ps_roi_align( class PSRoIAlign(nn.Module): """ - See ps_roi_align + See :func:`ps_roi_align`. """ def __init__( self, diff --git a/torchvision/ops/ps_roi_pool.py b/torchvision/ops/ps_roi_pool.py index 8c07eb864a8..0538f454762 100644 --- a/torchvision/ops/ps_roi_pool.py +++ b/torchvision/ops/ps_roi_pool.py @@ -32,7 +32,7 @@ def ps_roi_pool( the box coordinates. Default: 1.0 Returns: - output (Tensor[K, C, output_size[0], output_size[1]]) + Tensor[K, C, output_size[0], output_size[1]]: The pooled RoIs. """ _assert_has_ops() check_roi_boxes_shape(boxes) @@ -48,7 +48,7 @@ def ps_roi_pool( class PSRoIPool(nn.Module): """ - See ps_roi_pool + See :func:`ps_roi_pool`. """ def __init__(self, output_size: int, spatial_scale: float): super(PSRoIPool, self).__init__() diff --git a/torchvision/ops/roi_align.py b/torchvision/ops/roi_align.py index 0f6c0be1729..ffcafc9f50d 100644 --- a/torchvision/ops/roi_align.py +++ b/torchvision/ops/roi_align.py @@ -42,7 +42,7 @@ def roi_align( This version in Detectron2 Returns: - output (Tensor[K, C, output_size[0], output_size[1]]) + Tensor[K, C, output_size[0], output_size[1]]: The pooled RoIs. """ _assert_has_ops() check_roi_boxes_shape(boxes) @@ -57,7 +57,7 @@ def roi_align( class RoIAlign(nn.Module): """ - See roi_align + See :func:`roi_align`. """ def __init__( self, diff --git a/torchvision/ops/roi_pool.py b/torchvision/ops/roi_pool.py index fce6392fbfd..fec3fe7febe 100644 --- a/torchvision/ops/roi_pool.py +++ b/torchvision/ops/roi_pool.py @@ -32,7 +32,7 @@ def roi_pool( the box coordinates. Default: 1.0 Returns: - output (Tensor[K, C, output_size[0], output_size[1]]) + Tensor[K, C, output_size[0], output_size[1]]: The pooled RoIs. """ _assert_has_ops() check_roi_boxes_shape(boxes) @@ -47,7 +47,7 @@ def roi_pool( class RoIPool(nn.Module): """ - See roi_pool + See :func:`roi_pool`. """ def __init__(self, output_size: BroadcastingList2[int], spatial_scale: float): super(RoIPool, self).__init__() From ed386ab483cebd4a71b8582cbc459c2aff2431c3 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 342/357] [fbsync] Redirect to correct urls (#3574) Summary: * redirect the urls * adds /edit * Apply suggestions from code review * fix lint * undo urls Reviewed By: NicolasHug Differential Revision: D27706939 fbshipit-source-id: a4a35dc5d3e873c6bb7e3d713b03d6097520c0fc Co-authored-by: Philip Meier Co-authored-by: Francisco Massa --- torchvision/datasets/celeba.py | 4 ++-- torchvision/datasets/omniglot.py | 2 +- torchvision/datasets/sbd.py | 2 +- torchvision/datasets/widerface.py | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/torchvision/datasets/celeba.py b/torchvision/datasets/celeba.py index 12beded2a19..cc6f8084a80 100644 --- a/torchvision/datasets/celeba.py +++ b/torchvision/datasets/celeba.py @@ -40,9 +40,9 @@ class CelebA(VisionDataset): # dependencies). The "in-the-wild" (not aligned+cropped) images are only in 7z, so they are not available # right now. file_list = [ - # File ID MD5 Hash Filename + # File ID MD5 Hash Filename ("0B7EVK8r0v71pZjFTYXZWM3FlRnM", "00d2c5bc6d35e252742224ab0c1e8fcb", "img_align_celeba.zip"), - # ("0B7EVK8r0v71pbWNEUjJKdDQ3dGc", "b6cd7e93bc7a96c2dc33f819aa3ac651", "img_align_celeba_png.7z"), + # ("0B7EVK8r0v71pbWNEUjJKdDQ3dGc","b6cd7e93bc7a96c2dc33f819aa3ac651", "img_align_celeba_png.7z"), # ("0B7EVK8r0v71peklHb0pGdDl6R28", "b6cd7e93bc7a96c2dc33f819aa3ac651", "img_celeba.7z"), ("0B7EVK8r0v71pblRyaVFSWGxPY0U", "75e246fa4810816ffd6ee81facbd244c", "list_attr_celeba.txt"), ("1_ee_0u7vcNLOfNLegJRHmolfH5ICW-XS", "32bd1bd63d3c78cd57e08160ec5ed1e2", "identity_CelebA.txt"), diff --git a/torchvision/datasets/omniglot.py b/torchvision/datasets/omniglot.py index 2f20bff72c6..b78bf86d16f 100644 --- a/torchvision/datasets/omniglot.py +++ b/torchvision/datasets/omniglot.py @@ -22,7 +22,7 @@ class Omniglot(VisionDataset): downloaded again. """ folder = 'omniglot-py' - download_url_prefix = 'https://github.com/brendenlake/omniglot/raw/master/python' + download_url_prefix = 'https://raw.githubusercontent.com/brendenlake/omniglot/master/python' zips_md5 = { 'images_background': '68d2efa1b9178cc56df9314c21c6e718', 'images_evaluation': '6b91aef0f799c5bb55b94e3f2daec811' diff --git a/torchvision/datasets/sbd.py b/torchvision/datasets/sbd.py index f6d7031a95e..e47c9493858 100644 --- a/torchvision/datasets/sbd.py +++ b/torchvision/datasets/sbd.py @@ -41,7 +41,7 @@ class SBDataset(VisionDataset): if `mode='boundaries'` or PIL image if `mode='segmentation'`. """ - url = "http://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/semantic_contours/benchmark.tgz" + url = "https://www2.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/semantic_contours/benchmark.tgz" md5 = "82b4d87ceb2ed10f6038a1cba92111cb" filename = "benchmark.tgz" diff --git a/torchvision/datasets/widerface.py b/torchvision/datasets/widerface.py index 55ad6d1e76a..c1775309b29 100644 --- a/torchvision/datasets/widerface.py +++ b/torchvision/datasets/widerface.py @@ -37,7 +37,7 @@ class WIDERFace(VisionDataset): BASE_FOLDER = "widerface" FILE_LIST = [ - # File ID MD5 Hash Filename + # File ID MD5 Hash Filename ("0B6eKvaijfFUDQUUwd21EckhUbWs", "3fedf70df600953d25982bcd13d91ba2", "WIDER_train.zip"), ("0B6eKvaijfFUDd3dIRmpvSk8tLUk", "dfa7d7e790efa35df3788964cf0bbaea", "WIDER_val.zip"), ("0B6eKvaijfFUDbW4tdGpaYjgzZkU", "e5d8f4248ed24c334bbd12f49c29dd40", "WIDER_test.zip") From b79d7106e1113cfa798a11f03e973457620a4b82 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 343/357] [fbsync] Added CodeQL and Bandit security checks as GitHub Actions (#3625) Summary: * Added CodeQL and Bandit security checks as GitHub Actions * Nit fix on defusedxml.ElementTree * Remove defusedxml as hard requirement * Changed diffusedxml/xml importing * Fix compilation * Removed Bandit specific changes Reviewed By: NicolasHug Differential Revision: D27706940 fbshipit-source-id: c6a9d46d814aabd38e2b2d609d495427c5f2d591 Co-authored-by: Nikita Shulga Co-authored-by: Nicolas Hug Co-authored-by: Francisco Massa --- .github/workflows/bandit.yml | 23 +++++++++++++++++++ .github/workflows/codeql.yml | 43 ++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 .github/workflows/bandit.yml create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/bandit.yml b/.github/workflows/bandit.yml new file mode 100644 index 00000000000..93bae80f9bd --- /dev/null +++ b/.github/workflows/bandit.yml @@ -0,0 +1,23 @@ +# GitHub Actions Bandit Workflow + +name: Bandit + +on: + pull_request: + branches: [ master ] + + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + # Task will fail if any high-severity issues are found + # Ignoring submodules + - name: Run Bandit Security Analysis + run: | + python -m pip install bandit + python -m bandit -r . -x ./third_party -lll diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..387d82ec343 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,43 @@ +# GitHub Actions CodeQL Workflow + +name: CodeQL + +on: + pull_request: + branches: [ master ] + + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: python, cpp + + - name: Install Ninja + run: | + sudo apt-get update -y + sudo apt-get install -y ninja-build + + - name: Update submodules + run: git submodule update --init --recursive + + - name: Install Torch + run: | + python -m pip install cmake + python -m pip install torch==1.8.1+cpu -f https://download.pytorch.org/whl/torch_stable.html + sudo ln -s /usr/bin/ninja /usr/bin/ninja-build + + - name: Build TorchVision + run: python setup.py develop --user + + # If any code scanning alerts are found, they will be under Security -> CodeQL + # Link: https://github.com/pytorch/vision/security/code-scanning + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 From 9b7abc9f868c6ee659ada1697c396aeb5f105e13 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 344/357] [fbsync] Add missing doc for get_video_backend (#3643) Summary: Reviewed By: NicolasHug Differential Revision: D27706956 fbshipit-source-id: c5e3f4030b9df7081d72ea9a2e307cadb9f0a676 Co-authored-by: Nicolas Hug Co-authored-by: Nicolas Hug --- torchvision/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/torchvision/__init__.py b/torchvision/__init__.py index 1dcc07bde6c..9508605b551 100644 --- a/torchvision/__init__.py +++ b/torchvision/__init__.py @@ -85,6 +85,13 @@ def set_video_backend(backend): def get_video_backend(): + """ + Returns the currently active video backend used to decode videos. + + Returns: + str: Name of the video backend. one of {'pyav', 'video_reader'}. + """ + return _video_backend From f30512c0f0d352d55db76df3bcd148cc9e99472e Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 345/357] [fbsync] Added defusedxml to parse untrusted XML data (#3636) Summary: * Added defusedxml to parse untrusted XML data * Added typecheck disable for defusedxml Reviewed By: NicolasHug Differential Revision: D27706948 fbshipit-source-id: 4334745d939c83e763ea5508b6284275c5c7bc32 Co-authored-by: Nicolas Hug --- mypy.ini | 4 ++++ torchvision/datasets/voc.py | 10 +++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/mypy.ini b/mypy.ini index b35ee60d907..040b52dfda4 100644 --- a/mypy.ini +++ b/mypy.ini @@ -63,3 +63,7 @@ ignore_missing_imports = True [mypy-av.*] ignore_missing_imports = True + +[mypy-defusedxml.*] + +ignore_missing_imports = True diff --git a/torchvision/datasets/voc.py b/torchvision/datasets/voc.py index 9f6685e865c..c459dcb5c9e 100644 --- a/torchvision/datasets/voc.py +++ b/torchvision/datasets/voc.py @@ -2,7 +2,11 @@ import tarfile import collections from .vision import VisionDataset -import xml.etree.ElementTree as ET +from xml.etree.ElementTree import Element as ET_Element +try: + from defusedxml.ElementTree import parse as ET_parse +except ImportError: + from xml.etree.ElementTree import parse as ET_parse from PIL import Image from typing import Any, Callable, Dict, Optional, Tuple, List from .utils import download_and_extract_archive, verify_str_arg @@ -203,14 +207,14 @@ def __getitem__(self, index: int) -> Tuple[Any, Any]: tuple: (image, target) where target is a dictionary of the XML tree. """ img = Image.open(self.images[index]).convert("RGB") - target = self.parse_voc_xml(ET.parse(self.annotations[index]).getroot()) + target = self.parse_voc_xml(ET_parse(self.annotations[index]).getroot()) if self.transforms is not None: img, target = self.transforms(img, target) return img, target - def parse_voc_xml(self, node: ET.Element) -> Dict[str, Any]: + def parse_voc_xml(self, node: ET_Element) -> Dict[str, Any]: voc_dict: Dict[str, Any] = {} children = list(node) if children: From d7d4e9ef5f912d52ef117101f542b3df6ef61d39 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 346/357] [fbsync] Update to transforms docs (#3646) Summary: * Fixed return docstrings * Added some refs and corrected some parts * more refs, and a note about dtypes Reviewed By: NicolasHug Differential Revision: D27706952 fbshipit-source-id: 8d6a7cc7fa72f446a163a102db5bc53f1465dd8d Co-authored-by: Francisco Massa --- docs/source/transforms.rst | 40 +++++++++++++++++++++++----- torchvision/transforms/functional.py | 15 ++++++----- torchvision/transforms/transforms.py | 7 ++--- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/docs/source/transforms.rst b/docs/source/transforms.rst index 6efc2dba5a2..21e2c152626 100644 --- a/docs/source/transforms.rst +++ b/docs/source/transforms.rst @@ -4,15 +4,34 @@ torchvision.transforms .. currentmodule:: torchvision.transforms Transforms are common image transformations. They can be chained together using :class:`Compose`. -Additionally, there is the :mod:`torchvision.transforms.functional` module. -Functional transforms give fine-grained control over the transformations. +Most transform classes have a function equivalent: :ref:`functional +transforms ` give fine-grained control over the +transformations. This is useful if you have to build a more complex transformation pipeline (e.g. in the case of segmentation tasks). -All transformations accept PIL Image, Tensor Image or batch of Tensor Images as input. Tensor Image is a tensor with -``(C, H, W)`` shape, where ``C`` is a number of channels, ``H`` and ``W`` are image height and width. Batch of -Tensor Images is a tensor of ``(B, C, H, W)`` shape, where ``B`` is a number of images in the batch. Deterministic or -random transformations applied on the batch of Tensor Images identically transform all the images of the batch. +Most transformations accept both `PIL `_ +images and tensor images, although some transformations are :ref:`PIL-only +` and some are :ref:`tensor-only +`. The :ref:`conversion_transforms` may be used to +convert to and from PIL images. + +The transformations that accept tensor images also accept batches of tensor +images. A Tensor Image is a tensor with ``(C, H, W)`` shape, where ``C`` is a +number of channels, ``H`` and ``W`` are image height and width. A batch of +Tensor Images is a tensor of ``(B, C, H, W)`` shape, where ``B`` is a number +of images in the batch. + +The expected range of the values of a tensor image is implicitely defined by +the tensor dtype. Tensor images with a float dtype are expected to have +values in ``[0, 1)``. Tensor images with an integer dtype are expected to +have values in ``[0, MAX_DTYPE]`` where ``MAX_DTYPE`` is the largest value +that can be represented in that dtype. + +Randomized transformations will apply the same transformation to all the +images of a given batch, but they will produce different transformations +across calls. For reproducible transformations across calls, you may use +:ref:`functional transforms `. .. warning:: @@ -117,6 +136,8 @@ Transforms on PIL Image and torch.\*Tensor .. autoclass:: GaussianBlur :members: +.. _transforms_pil_only: + Transforms on PIL Image only ---------------------------- @@ -124,6 +145,7 @@ Transforms on PIL Image only .. autoclass:: RandomOrder +.. _transforms_tensor_only: Transforms on torch.\*Tensor only --------------------------------- @@ -139,6 +161,7 @@ Transforms on torch.\*Tensor only .. autoclass:: ConvertImageDtype +.. _conversion_transforms: Conversion Transforms --------------------- @@ -173,13 +196,16 @@ The new transform can be used standalone or mixed-and-matched with existing tran :members: +.. _functional_transforms: + Functional Transforms --------------------- Functional transforms give you fine-grained control of the transformation pipeline. As opposed to the transformations above, functional transforms don't contain a random number generator for their parameters. -That means you have to specify/generate all parameters, but you can reuse the functional transform. +That means you have to specify/generate all parameters, but the functional transform will give you +reproducible results across calls. Example: you can apply a functional transform with the same parameters to multiple images like this: diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index 64ed0b8edd5..b365c7df3f3 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -671,7 +671,7 @@ def five_crop(img: Tensor, size: List[int]) -> Tuple[Tensor, Tensor, Tensor, Ten Returns: tuple: tuple (tl, tr, bl, br, center) - Corresponding top left, top right, bottom left, bottom right and center crop. + Corresponding top left, top right, bottom left, bottom right and center crop. """ if isinstance(size, numbers.Number): size = (int(size), int(size)) @@ -717,8 +717,8 @@ def ten_crop(img: Tensor, size: List[int], vertical_flip: bool = False) -> List[ Returns: tuple: tuple (tl, tr, bl, br, center, tl_flip, tr_flip, bl_flip, br_flip, center_flip) - Corresponding top left, top right, bottom left, bottom right and - center crop and same for the flipped image. + Corresponding top left, top right, bottom left, bottom right and + center crop and same for the flipped image. """ if isinstance(size, numbers.Number): size = (int(size), int(size)) @@ -1103,9 +1103,9 @@ def to_grayscale(img, num_output_channels=1): Returns: PIL Image: Grayscale version of the image. - if num_output_channels = 1 : returned image is single channel - if num_output_channels = 3 : returned image is 3 channel with r = g = b + - if num_output_channels = 1 : returned image is single channel + - if num_output_channels = 3 : returned image is 3 channel with r = g = b """ if isinstance(img, Image.Image): return F_pil.to_grayscale(img, num_output_channels) @@ -1128,9 +1128,9 @@ def rgb_to_grayscale(img: Tensor, num_output_channels: int = 1) -> Tensor: Returns: PIL Image or Tensor: Grayscale version of the image. - if num_output_channels = 1 : returned image is single channel - if num_output_channels = 3 : returned image is 3 channel with r = g = b + - if num_output_channels = 1 : returned image is single channel + - if num_output_channels = 3 : returned image is 3 channel with r = g = b """ if not isinstance(img, torch.Tensor): return F_pil.to_grayscale(img, num_output_channels) @@ -1330,6 +1330,7 @@ def equalize(img: Tensor) -> Tensor: img (PIL Image or Tensor): Image on which equalize is applied. If img is torch Tensor, it is expected to be in [..., 1 or 3, H, W] format, where ... means it can have an arbitrary number of leading dimensions. + The tensor dtype must be ``torch.uint8`` and values are expected to be in ``[0, 255]``. If img is PIL Image, it is expected to be in mode "P", "L" or "RGB". Returns: diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 7c25b000ce8..f7b6bf04970 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -841,7 +841,7 @@ def get_params( Returns: tuple: params (i, j, h, w) to be passed to ``crop`` for a random - sized crop. + sized crop. """ width, height = F._get_image_size(img) area = height * width @@ -1464,8 +1464,9 @@ class Grayscale(torch.nn.Module): Returns: PIL Image: Grayscale version of the input. - - If ``num_output_channels == 1`` : returned image is single channel - - If ``num_output_channels == 3`` : returned image is 3 channel with r == g == b + + - If ``num_output_channels == 1`` : returned image is single channel + - If ``num_output_channels == 3`` : returned image is 3 channel with r == g == b """ From 5af2cf04916518a9b531883f8bb6f722e9c0327d Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 347/357] [fbsync] Add Quantized version of RoIAlign (#3624) Summary: * WIP * clang * docs * extracted out common utils * Use better quantization function and pass tensors as parameters * proper dequantization * Some tests * Dequantization optimization, seems to gain a few ms * clang-format * again * more correct test. Had to remove optimization although it almost works * Also test aligned=True * remove useless part * more docs and comments * Put back optimization with more robust test * Added check for index upper bound * avoid possible overflow * Move common function into common.h * oops * scale=1,zero_point=0 makes more sense * Force batch size of 1 to prevent any indexingbug * format * format again * updated docstring * put back description comment for pre_calc_bilinear_interpolate * revert most changes to docstring as it's taken care of in another PR Reviewed By: NicolasHug Differential Revision: D27706946 fbshipit-source-id: 2ae1614c214ea676b4f7705dc0716efd9f34330e --- test/test_ops.py | 72 ++++++ torchvision/csrc/ops/cpu/roi_align_common.h | 128 +++++++++++ torchvision/csrc/ops/cpu/roi_align_kernel.cpp | 125 +---------- .../ops/quantized/cpu/qroi_align_kernel.cpp | 208 ++++++++++++++++++ torchvision/ops/roi_align.py | 1 + 5 files changed, 417 insertions(+), 117 deletions(-) create mode 100644 torchvision/csrc/ops/cpu/roi_align_common.h create mode 100644 torchvision/csrc/ops/quantized/cpu/qroi_align_kernel.cpp diff --git a/test/test_ops.py b/test/test_ops.py index 0031da45cce..8c63c9c29c6 100644 --- a/test/test_ops.py +++ b/test/test_ops.py @@ -299,6 +299,78 @@ def _test_forward(self, device, contiguous, x_dtype=None, rois_dtype=None, **kwa for aligned in (True, False): super()._test_forward(device, contiguous, x_dtype, rois_dtype, aligned=aligned) + def test_qroialign(self): + """Make sure quantized version of RoIAlign is close to float version""" + pool_size = 5 + img_size = 10 + n_channels = 2 + num_imgs = 1 + dtype = torch.float + + def make_rois(num_rois=1000): + rois = torch.randint(0, img_size // 2, size=(num_rois, 5)).to(dtype) + rois[:, 0] = torch.randint(0, num_imgs, size=(num_rois,)) # set batch index + rois[:, 3:] += rois[:, 1:3] # make sure boxes aren't degenerate + return rois + + for aligned in (True, False): + for scale, zero_point in ((1, 0), (2, 10), (0.1, 50)): + for qdtype in (torch.qint8, torch.quint8, torch.qint32): + + x = torch.randint(50, 100, size=(num_imgs, n_channels, img_size, img_size)).to(dtype) + qx = torch.quantize_per_tensor(x, scale=scale, zero_point=zero_point, dtype=qdtype) + + rois = make_rois() + qrois = torch.quantize_per_tensor(rois, scale=scale, zero_point=zero_point, dtype=qdtype) + + x, rois = qx.dequantize(), qrois.dequantize() # we want to pass the same inputs + + y = ops.roi_align( + x, + rois, + output_size=pool_size, + spatial_scale=1, + sampling_ratio=-1, + aligned=aligned, + ) + qy = ops.roi_align( + qx, + qrois, + output_size=pool_size, + spatial_scale=1, + sampling_ratio=-1, + aligned=aligned, + ) + + # The output qy is itself a quantized tensor and there might have been a loss of info when it was + # quantized. For a fair comparison we need to quantize y as well + quantized_float_y = torch.quantize_per_tensor(y, scale=scale, zero_point=zero_point, dtype=qdtype) + + try: + # Ideally, we would assert this, which passes with (scale, zero) == (1, 0) + self.assertTrue((qy == quantized_float_y).all()) + except AssertionError: + # But because the computation aren't exactly the same between the 2 RoIAlign procedures, some + # rounding error may lead to a difference of 2 in the output. + # For example with (scale, zero) = (2, 10), 45.00000... will be quantized to 44 + # but 45.00000001 will be rounded to 46. We make sure below that: + # - such discrepancies between qy and quantized_float_y are very rare (less then 5%) + # - any difference between qy and quantized_float_y is == scale + diff_idx = torch.where(qy != quantized_float_y) + num_diff = diff_idx[0].numel() + self.assertTrue(num_diff / qy.numel() < .05) + + abs_diff = torch.abs(qy[diff_idx].dequantize() - quantized_float_y[diff_idx].dequantize()) + t_scale = torch.full_like(abs_diff, fill_value=scale) + self.assertTrue(torch.allclose(abs_diff, t_scale, atol=1e-5)) + + x = torch.randint(50, 100, size=(2, 3, 10, 10)).to(dtype) + qx = torch.quantize_per_tensor(x, scale=1, zero_point=0, dtype=torch.qint8) + rois = make_rois(10) + qrois = torch.quantize_per_tensor(rois, scale=1, zero_point=0, dtype=torch.qint8) + with self.assertRaisesRegex(RuntimeError, "Only one image per batch is allowed"): + ops.roi_align(qx, qrois, output_size=pool_size) + class PSRoIAlignTester(RoIOpTester, unittest.TestCase): def fn(self, x, rois, pool_h, pool_w, spatial_scale=1, sampling_ratio=-1, **kwargs): diff --git a/torchvision/csrc/ops/cpu/roi_align_common.h b/torchvision/csrc/ops/cpu/roi_align_common.h new file mode 100644 index 00000000000..e10c67b5b79 --- /dev/null +++ b/torchvision/csrc/ops/cpu/roi_align_common.h @@ -0,0 +1,128 @@ +#pragma once + +#include + +namespace vision { +namespace ops { +namespace detail { + +template +struct PreCalc { + int pos1; + int pos2; + int pos3; + int pos4; + T w1; + T w2; + T w3; + T w4; +}; + +// This helper computes the interpolation weights (w1, w2...) for every sampling +// point of a given box. There are pool_height * pool_width * roi_bin_grid_h * +// roi_bin_grid_w such sampling points. +// +// The weights (w1, w2...) are computed as the areas in this figure: +// https://en.wikipedia.org/wiki/Bilinear_interpolation#/media/File:Bilinear_interpolation_visualisation.svg +// and pos1, pos2 etc correspond to the indices of their respective pixels. +// +// Note: the weights and indices are shared across all channels, which is why +// they are pre-calculated prior to the main loop in the RoIAlign kernel. +// implementation taken from Caffe2 +template +void pre_calc_for_bilinear_interpolate( + int height, + int width, + int pooled_height, + int pooled_width, + T roi_start_h, + T roi_start_w, + T bin_size_h, + T bin_size_w, + int roi_bin_grid_h, + int roi_bin_grid_w, + std::vector>& pre_calc) { + int pre_calc_index = 0; + for (int ph = 0; ph < pooled_height; ph++) { + for (int pw = 0; pw < pooled_width; pw++) { + for (int iy = 0; iy < roi_bin_grid_h; iy++) { + const T yy = roi_start_h + ph * bin_size_h + + static_cast(iy + .5f) * bin_size_h / + static_cast(roi_bin_grid_h); // e.g., 0.5, 1.5 + for (int ix = 0; ix < roi_bin_grid_w; ix++) { + const T xx = roi_start_w + pw * bin_size_w + + static_cast(ix + .5f) * bin_size_w / + static_cast(roi_bin_grid_w); + + T x = xx; + T y = yy; + // deal with: inverse elements are out of feature map boundary + if (y < -1.0 || y > height || x < -1.0 || x > width) { + // empty + PreCalc pc; + pc.pos1 = 0; + pc.pos2 = 0; + pc.pos3 = 0; + pc.pos4 = 0; + pc.w1 = 0; + pc.w2 = 0; + pc.w3 = 0; + pc.w4 = 0; + pre_calc[pre_calc_index] = pc; + pre_calc_index += 1; + continue; + } + + if (y <= 0) { + y = 0; + } + if (x <= 0) { + x = 0; + } + + int y_low = (int)y; + int x_low = (int)x; + int y_high; + int x_high; + + if (y_low >= height - 1) { + y_high = y_low = height - 1; + y = (T)y_low; + } else { + y_high = y_low + 1; + } + + if (x_low >= width - 1) { + x_high = x_low = width - 1; + x = (T)x_low; + } else { + x_high = x_low + 1; + } + + T ly = y - y_low; + T lx = x - x_low; + T hy = 1. - ly, hx = 1. - lx; + T w1 = hy * hx, w2 = hy * lx, w3 = ly * hx, w4 = ly * lx; + + // save weights and indices + PreCalc pc; + pc.pos1 = y_low * width + x_low; + pc.pos2 = y_low * width + x_high; + pc.pos3 = y_high * width + x_low; + pc.pos4 = y_high * width + x_high; + pc.w1 = w1; + pc.w2 = w2; + pc.w3 = w3; + pc.w4 = w4; + pre_calc[pre_calc_index] = pc; + + pre_calc_index += 1; + } + } + } + } +} + +} // namespace detail +} // namespace ops +} // namespace vision diff --git a/torchvision/csrc/ops/cpu/roi_align_kernel.cpp b/torchvision/csrc/ops/cpu/roi_align_kernel.cpp index dc0c38cd314..e6684e953d0 100644 --- a/torchvision/csrc/ops/cpu/roi_align_kernel.cpp +++ b/torchvision/csrc/ops/cpu/roi_align_kernel.cpp @@ -1,120 +1,13 @@ #include #include +#include "./roi_align_common.h" + namespace vision { namespace ops { namespace { -// implementation taken from Caffe2 -template -struct PreCalc { - int pos1; - int pos2; - int pos3; - int pos4; - T w1; - T w2; - T w3; - T w4; -}; - -template -void pre_calc_for_bilinear_interpolate( - int height, - int width, - int pooled_height, - int pooled_width, - int iy_upper, - int ix_upper, - T roi_start_h, - T roi_start_w, - T bin_size_h, - T bin_size_w, - int roi_bin_grid_h, - int roi_bin_grid_w, - std::vector>& pre_calc) { - int pre_calc_index = 0; - for (int ph = 0; ph < pooled_height; ph++) { - for (int pw = 0; pw < pooled_width; pw++) { - for (int iy = 0; iy < iy_upper; iy++) { - const T yy = roi_start_h + ph * bin_size_h + - static_cast(iy + .5f) * bin_size_h / - static_cast(roi_bin_grid_h); // e.g., 0.5, 1.5 - for (int ix = 0; ix < ix_upper; ix++) { - const T xx = roi_start_w + pw * bin_size_w + - static_cast(ix + .5f) * bin_size_w / - static_cast(roi_bin_grid_w); - - T x = xx; - T y = yy; - // deal with: inverse elements are out of feature map boundary - if (y < -1.0 || y > height || x < -1.0 || x > width) { - // empty - PreCalc pc; - pc.pos1 = 0; - pc.pos2 = 0; - pc.pos3 = 0; - pc.pos4 = 0; - pc.w1 = 0; - pc.w2 = 0; - pc.w3 = 0; - pc.w4 = 0; - pre_calc[pre_calc_index] = pc; - pre_calc_index += 1; - continue; - } - - if (y <= 0) { - y = 0; - } - if (x <= 0) { - x = 0; - } - - int y_low = (int)y; - int x_low = (int)x; - int y_high; - int x_high; - - if (y_low >= height - 1) { - y_high = y_low = height - 1; - y = (T)y_low; - } else { - y_high = y_low + 1; - } - - if (x_low >= width - 1) { - x_high = x_low = width - 1; - x = (T)x_low; - } else { - x_high = x_low + 1; - } - - T ly = y - y_low; - T lx = x - x_low; - T hy = 1. - ly, hx = 1. - lx; - T w1 = hy * hx, w2 = hy * lx, w3 = ly * hx, w4 = ly * lx; - - // save weights and indeces - PreCalc pc; - pc.pos1 = y_low * width + x_low; - pc.pos2 = y_low * width + x_high; - pc.pos3 = y_high * width + x_low; - pc.pos4 = y_high * width + x_high; - pc.w1 = w1; - pc.w2 = w2; - pc.w3 = w3; - pc.w4 = w4; - pre_calc[pre_calc_index] = pc; - - pre_calc_index += 1; - } - } - } - } -} - template void roi_align_forward_kernel_impl( int n_rois, @@ -167,17 +60,15 @@ void roi_align_forward_kernel_impl( // When the grid is empty, output zeros. const T count = std::max(roi_bin_grid_h * roi_bin_grid_w, 1); // e.g. = 4 - // we want to precalculate indeces and weights shared by all chanels, - // this is the key point of optimiation - std::vector> pre_calc( + // we want to precalculate indices and weights shared by all chanels, + // this is the key point of optimization + std::vector> pre_calc( roi_bin_grid_h * roi_bin_grid_w * pooled_width * pooled_height); - pre_calc_for_bilinear_interpolate( + detail::pre_calc_for_bilinear_interpolate( height, width, pooled_height, pooled_width, - roi_bin_grid_h, - roi_bin_grid_w, roi_start_h, roi_start_w, bin_size_h, @@ -199,7 +90,7 @@ void roi_align_forward_kernel_impl( T output_val = 0.; for (int iy = 0; iy < roi_bin_grid_h; iy++) { for (int ix = 0; ix < roi_bin_grid_w; ix++) { - PreCalc pc = pre_calc[pre_calc_index]; + detail::PreCalc pc = pre_calc[pre_calc_index]; output_val += pc.w1 * offset_input[pc.pos1] + pc.w2 * offset_input[pc.pos2] + pc.w3 * offset_input[pc.pos3] + pc.w4 * offset_input[pc.pos4]; @@ -207,7 +98,7 @@ void roi_align_forward_kernel_impl( pre_calc_index += 1; } } - output_val /= count; + output_val /= count; // Average pooling output[index] = output_val; } // for pw diff --git a/torchvision/csrc/ops/quantized/cpu/qroi_align_kernel.cpp b/torchvision/csrc/ops/quantized/cpu/qroi_align_kernel.cpp new file mode 100644 index 00000000000..e34b277747e --- /dev/null +++ b/torchvision/csrc/ops/quantized/cpu/qroi_align_kernel.cpp @@ -0,0 +1,208 @@ +#include +#include +#include + +#include "../../cpu/roi_align_common.h" + +namespace vision { +namespace ops { + +namespace { + +template +void qroi_align_forward_kernel_impl( + int n_rois, + const at::Tensor& t_input, + const float& spatial_scale, + int channels, + int height, + int width, + int pooled_height, + int pooled_width, + int sampling_ratio, + bool aligned, + const at::Tensor& t_rois, + T* output) { + const T* input = t_input.contiguous().data_ptr(); + int64_t input_zp = t_input.q_zero_point(); + float input_scale = t_input.q_scale(); + + const T* rois = t_rois.contiguous().data_ptr(); + int64_t rois_zp = t_rois.q_zero_point(); + float rois_scale = t_rois.q_scale(); + + for (int n = 0; n < n_rois; n++) { + int index_n = n * channels * pooled_width * pooled_height; + + const T* offset_rois = rois + n * 5; + + // FIXME: change this when batches of size > 1 are allowed + const int roi_batch_ind = 0; + + // Do not using rounding; this implementation detail is critical + float offset = aligned ? 0.5 : 0.; + float roi_start_w = + at::native::dequantize_val(rois_scale, rois_zp, offset_rois[1]) * + spatial_scale - + offset; + float roi_start_h = + at::native::dequantize_val(rois_scale, rois_zp, offset_rois[2]) * + spatial_scale - + offset; + float roi_end_w = + at::native::dequantize_val(rois_scale, rois_zp, offset_rois[3]) * + spatial_scale - + offset; + float roi_end_h = + at::native::dequantize_val(rois_scale, rois_zp, offset_rois[4]) * + spatial_scale - + offset; + + float roi_width = roi_end_w - roi_start_w; + float roi_height = roi_end_h - roi_start_h; + if (!aligned) { + // Force malformed ROIs to be 1x1 + roi_width = std::max(roi_width, 1.f); + roi_height = std::max(roi_height, 1.f); + } + + float bin_size_h = roi_height / pooled_height; + float bin_size_w = roi_width / pooled_width; + + // We use roi_bin_grid to sample the grid and mimic integral + int roi_bin_grid_h = (sampling_ratio > 0) + ? sampling_ratio + : ceil(roi_height / pooled_height); // e.g., = 2 + int roi_bin_grid_w = + (sampling_ratio > 0) ? sampling_ratio : ceil(roi_width / pooled_width); + + // We do average (integral) pooling inside a bin + // When the grid is empty, output zeros. + const float count = + std::max(roi_bin_grid_h * roi_bin_grid_w, 1); // e.g. = 4 + + // we want to precalculate indices and weights shared by all chanels, + // this is the key point of optimization + std::vector> pre_calc( + roi_bin_grid_h * roi_bin_grid_w * pooled_width * pooled_height); + detail::pre_calc_for_bilinear_interpolate( + height, + width, + pooled_height, + pooled_width, + roi_start_h, + roi_start_w, + bin_size_h, + bin_size_w, + roi_bin_grid_h, + roi_bin_grid_w, + pre_calc); + + for (int c = 0; c < channels; c++) { + int index_n_c = index_n + c * pooled_width * pooled_height; + const T* offset_input = + input + (roi_batch_ind * channels + c) * height * width; + int pre_calc_index = 0; + + for (int ph = 0; ph < pooled_height; ph++) { + for (int pw = 0; pw < pooled_width; pw++) { + int index = index_n_c + ph * pooled_width + pw; + + float output_val = 0.; + float sum_w = 0.; + for (int iy = 0; iy < roi_bin_grid_h; iy++) { + for (int ix = 0; ix < roi_bin_grid_w; ix++) { + detail::PreCalc pc = pre_calc[pre_calc_index]; + + // Optimization: we use the raw values here and we'll dequantize + // later + output_val += pc.w1 * offset_input[pc.pos1].val_ + + pc.w2 * offset_input[pc.pos2].val_ + + pc.w3 * offset_input[pc.pos3].val_ + + pc.w4 * offset_input[pc.pos4].val_; + sum_w += pc.w1 + pc.w2 + pc.w3 + pc.w4; + + pre_calc_index += 1; + } + } + // Dequantize here + output_val = input_scale * (output_val - (float)input_zp * sum_w); + + output_val /= count; // Average pooling + + output[index] = + at::native::quantize_val(input_scale, input_zp, output_val); + } // for pw + } // for ph + } // for c + } // for n +} + +at::Tensor qroi_align_forward_kernel( + const at::Tensor& input, + const at::Tensor& rois, + double spatial_scale, + int64_t pooled_height, + int64_t pooled_width, + int64_t sampling_ratio, + bool aligned) { + TORCH_CHECK(input.device().is_cpu(), "input must be a CPU tensor"); + TORCH_CHECK(rois.device().is_cpu(), "rois must be a CPU tensor"); + TORCH_CHECK(rois.size(1) == 5, "rois must have shape as Tensor[K, 5]"); + // The first column of the RoI tensor is an image index, but not all indices + // are representable depending on the quantization. For example 1, 3, 5... + // indices can't be represented when qscale is 2. To prevent any bug, we force + // a batch size of 1 and we ignore the first column + TORCH_CHECK( + input.size(0) == 1, + "Only one image per batch is allowed in roi_align when quantized tensors are passed."); + + at::TensorArg input_t{input, "input", 1}, rois_t{rois, "rois", 2}; + + at::CheckedFrom c = "qroi_align_forward_kernel"; + at::checkAllSameType(c, {input_t, rois_t}); + + auto num_rois = rois.size(0); + auto channels = input.size(1); + auto height = input.size(2); + auto width = input.size(3); + + // FIXME: This is private, API might change: + // https://github.com/pytorch/pytorch/wiki/Introducing-Quantized-Tensor#quantized-tensor-apis + at::Tensor output = at::_empty_affine_quantized( + {num_rois, channels, pooled_height, pooled_width}, + input.options(), + input.q_scale(), + input.q_zero_point()); + + if (output.numel() == 0) + return output; + + AT_DISPATCH_QINT_TYPES(input.scalar_type(), "qroi_align_forward_kernel", [&] { + qroi_align_forward_kernel_impl( + num_rois, + input, + spatial_scale, + channels, + height, + width, + pooled_height, + pooled_width, + sampling_ratio, + aligned, + rois, + output.data_ptr()); + }); + return output; +} + +} // namespace + +TORCH_LIBRARY_IMPL(torchvision, QuantizedCPU, m) { + m.impl( + TORCH_SELECTIVE_NAME("torchvision::roi_align"), + TORCH_FN(qroi_align_forward_kernel)); +} + +} // namespace ops +} // namespace vision diff --git a/torchvision/ops/roi_align.py b/torchvision/ops/roi_align.py index ffcafc9f50d..c0ac14329d4 100644 --- a/torchvision/ops/roi_align.py +++ b/torchvision/ops/roi_align.py @@ -21,6 +21,7 @@ def roi_align( Args: input (Tensor[N, C, H, W]): input tensor + If the tensor is quantized, we expect a batch size of ``N == 1``. boxes (Tensor[K, 5] or List[Tensor[L, 4]]): the box coordinates in (x1, y1, x2, y2) format where the regions will be taken from. The coordinate must satisfy ``0 <= x1 < x2`` and ``0 <= y1 < y2``. From a603cdd7a80aa468473b25060a8725162a8c8771 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 348/357] [fbsync] Add missing device info. (#3651) Reviewed By: NicolasHug Differential Revision: D27706953 fbshipit-source-id: c3810183d8acb7feec6868e28705ee25806acc27 --- torchvision/models/detection/retinanet.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/torchvision/models/detection/retinanet.py b/torchvision/models/detection/retinanet.py index f34db4ce970..c6fe8856a01 100644 --- a/torchvision/models/detection/retinanet.py +++ b/torchvision/models/detection/retinanet.py @@ -386,7 +386,8 @@ def compute_loss(self, targets, head_outputs, anchors): matched_idxs = [] for anchors_per_image, targets_per_image in zip(anchors, targets): if targets_per_image['boxes'].numel() == 0: - matched_idxs.append(torch.full((anchors_per_image.size(0),), -1, dtype=torch.int64)) + matched_idxs.append(torch.full((anchors_per_image.size(0),), -1, dtype=torch.int64, + device=anchors_per_image.device)) continue match_quality_matrix = box_ops.box_iou(targets_per_image['boxes'], anchors_per_image) From 707a69c9ed7366c62f970f228b20617f2c282e18 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 349/357] [fbsync] Unify onnx and JIT resize implementations (#3654) Summary: * Make two methods as similar as possible. * Introducing conditional fake casting. * Change the casting mechanism. Reviewed By: NicolasHug Differential Revision: D27706950 fbshipit-source-id: ef7503817cd64ffc8723fec89f1cd94647490eaf --- torchvision/models/detection/transform.py | 50 +++++++++++------------ 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/torchvision/models/detection/transform.py b/torchvision/models/detection/transform.py index 5e962f4bad9..56e502f726d 100644 --- a/torchvision/models/detection/transform.py +++ b/torchvision/models/detection/transform.py @@ -10,36 +10,35 @@ @torch.jit.unused -def _resize_image_and_masks_onnx(image, self_min_size, self_max_size, target): - # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]] +def _get_shape_onnx(image): + # type: (Tensor) -> Tensor from torch.onnx import operators - im_shape = operators.shape_as_tensor(image)[-2:] - min_size = torch.min(im_shape).to(dtype=torch.float32) - max_size = torch.max(im_shape).to(dtype=torch.float32) - scale_factor = torch.min(self_min_size / min_size, self_max_size / max_size) - - image = torch.nn.functional.interpolate( - image[None], scale_factor=scale_factor, mode='bilinear', recompute_scale_factor=True, - align_corners=False)[0] + return operators.shape_as_tensor(image)[-2:] - if target is None: - return image, target - if "masks" in target: - mask = target["masks"] - mask = F.interpolate(mask[:, None].float(), scale_factor=scale_factor, recompute_scale_factor=True)[:, 0].byte() - target["masks"] = mask - return image, target +@torch.jit.unused +def _fake_cast_onnx(v): + # type: (Tensor) -> float + # ONNX requires a tensor but here we fake its type for JIT. + return v def _resize_image_and_masks(image, self_min_size, self_max_size, target): # type: (Tensor, float, float, Optional[Dict[str, Tensor]]) -> Tuple[Tensor, Optional[Dict[str, Tensor]]] - im_shape = torch.tensor(image.shape[-2:]) - min_size = float(torch.min(im_shape)) - max_size = float(torch.max(im_shape)) - scale_factor = self_min_size / min_size - if max_size * scale_factor > self_max_size: - scale_factor = self_max_size / max_size + if torchvision._is_tracing(): + im_shape = _get_shape_onnx(image) + else: + im_shape = torch.tensor(image.shape[-2:]) + + min_size = torch.min(im_shape).to(dtype=torch.float32) + max_size = torch.max(im_shape).to(dtype=torch.float32) + scale = torch.min(self_min_size / min_size, self_max_size / max_size) + + if torchvision._is_tracing(): + scale_factor = _fake_cast_onnx(scale) + else: + scale_factor = scale.item() + image = torch.nn.functional.interpolate( image[None], scale_factor=scale_factor, mode='bilinear', recompute_scale_factor=True, align_corners=False)[0] @@ -145,10 +144,7 @@ def resize(self, image, target): else: # FIXME assume for now that testing uses the largest scale size = float(self.min_size[-1]) - if torchvision._is_tracing(): - image, target = _resize_image_and_masks_onnx(image, size, float(self.max_size), target) - else: - image, target = _resize_image_and_masks(image, size, float(self.max_size), target) + image, target = _resize_image_and_masks(image, size, float(self.max_size), target) if target is None: return image, target From 8062faa87f8c3e10785bc092eee67859c0f3b6be Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 350/357] [fbsync] Added KITTI dataset (#3640) Summary: * Added KITTI dataset * Addressed review comments * Changed type of target to List[Dict] and corrected the data types of the returned values. * Updated unit test to rely on ImageDatasetTestCase * Added kitti to dataset documentation * Cleaned up test and some minor changes * Made data_url a string instead of a list * Removed unnecessary try and print Reviewed By: NicolasHug Differential Revision: D27706941 fbshipit-source-id: aa646f17e7ad5a0858320274cc2ec226fa8f4790 Co-authored-by: Francisco Massa --- docs/source/datasets.rst | 7 ++ test/test_datasets.py | 36 +++++++ torchvision/datasets/__init__.py | 4 +- torchvision/datasets/kitti.py | 161 +++++++++++++++++++++++++++++++ 4 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 torchvision/datasets/kitti.py diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index ceb517ced8f..cb02f2bcaa3 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -149,6 +149,13 @@ Kinetics-400 :members: __getitem__ :special-members: +KITTI +~~~~~~~~~ + +.. autoclass:: Kitti + :members: __getitem__ + :special-members: + KMNIST ~~~~~~~~~~~~~ diff --git a/test/test_datasets.py b/test/test_datasets.py index db80b55a90f..1c45af1163c 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -1702,5 +1702,41 @@ def test_classes(self, config): self.assertSequenceEqual(dataset.classes, info["classes"]) +class KittiTestCase(datasets_utils.ImageDatasetTestCase): + DATASET_CLASS = datasets.Kitti + FEATURE_TYPES = (PIL.Image.Image, (list, type(None))) # test split returns None as target + ADDITIONAL_CONFIGS = datasets_utils.combinations_grid(train=(True, False)) + + def inject_fake_data(self, tmpdir, config): + kitti_dir = os.path.join(tmpdir, "Kitti", "raw") + os.makedirs(kitti_dir) + + split_to_num_examples = { + True: 1, + False: 2, + } + + # We need to create all folders(training and testing). + for is_training in (True, False): + num_examples = split_to_num_examples[is_training] + + datasets_utils.create_image_folder( + root=kitti_dir, + name=os.path.join("training" if is_training else "testing", "image_2"), + file_name_fn=lambda image_idx: f"{image_idx:06d}.png", + num_examples=num_examples, + ) + if is_training: + for image_idx in range(num_examples): + target_file_dir = os.path.join(kitti_dir, "training", "label_2") + os.makedirs(target_file_dir) + target_file_name = os.path.join(target_file_dir, f"{image_idx:06d}.txt") + target_contents = "Pedestrian 0.00 0 -0.20 712.40 143.00 810.73 307.92 1.89 0.48 1.20 1.84 1.47 8.41 0.01\n" # noqa + with open(target_file_name, "w") as target_file: + target_file.write(target_contents) + + return split_to_num_examples[config["train"]] + + if __name__ == "__main__": unittest.main() diff --git a/torchvision/datasets/__init__.py b/torchvision/datasets/__init__.py index 0ce0fd6bd60..b60fc7c7964 100644 --- a/torchvision/datasets/__init__.py +++ b/torchvision/datasets/__init__.py @@ -24,6 +24,7 @@ from .hmdb51 import HMDB51 from .ucf101 import UCF101 from .places365 import Places365 +from .kitti import Kitti __all__ = ('LSUN', 'LSUNClass', 'ImageFolder', 'DatasetFolder', 'FakeData', @@ -34,4 +35,5 @@ 'VOCSegmentation', 'VOCDetection', 'Cityscapes', 'ImageNet', 'Caltech101', 'Caltech256', 'CelebA', 'WIDERFace', 'SBDataset', 'VisionDataset', 'USPS', 'Kinetics400', 'HMDB51', 'UCF101', - 'Places365') + 'Places365', 'Kitti', + ) diff --git a/torchvision/datasets/kitti.py b/torchvision/datasets/kitti.py new file mode 100644 index 00000000000..8db2e45b715 --- /dev/null +++ b/torchvision/datasets/kitti.py @@ -0,0 +1,161 @@ +import csv +import os +from typing import Any, Callable, List, Optional, Tuple + +from PIL import Image + +from .utils import download_and_extract_archive +from .vision import VisionDataset + + +class Kitti(VisionDataset): + """`KITTI `_ Dataset. + + Args: + root (string): Root directory where images are downloaded to. + Expects the following folder structure if download=False: + + .. code:: + + + └── Kitti + └─ raw + ├── training + | ├── image_2 + | └── label_2 + └── testing + └── image_2 + train (bool, optional): Use ``train`` split if true, else ``test`` split. + Defaults to ``train``. + transform (callable, optional): A function/transform that takes in a PIL image + and returns a transformed version. E.g, ``transforms.ToTensor`` + target_transform (callable, optional): A function/transform that takes in the + target and transforms it. + transforms (callable, optional): A function/transform that takes input sample + and its target as entry and returns a transformed version. + download (bool, optional): If true, downloads the dataset from the internet and + puts it in root directory. If dataset is already downloaded, it is not + downloaded again. + + """ + + data_url = "https://s3.eu-central-1.amazonaws.com/avg-kitti/" + resources = [ + "data_object_image_2.zip", + "data_object_label_2.zip", + ] + image_dir_name = "image_2" + labels_dir_name = "label_2" + + def __init__( + self, + root: str, + train: bool = True, + transform: Optional[Callable] = None, + target_transform: Optional[Callable] = None, + transforms: Optional[Callable] = None, + download: bool = False, + ): + super().__init__( + root, + transform=transform, + target_transform=target_transform, + transforms=transforms, + ) + self.images = [] + self.targets = [] + self.root = root + self.train = train + self._location = "training" if self.train else "testing" + + if download: + self.download() + if not self._check_exists(): + raise RuntimeError( + "Dataset not found. You may use download=True to download it." + ) + + image_dir = os.path.join(self._raw_folder, self._location, self.image_dir_name) + if self.train: + labels_dir = os.path.join(self._raw_folder, self._location, self.labels_dir_name) + for img_file in os.listdir(image_dir): + self.images.append(os.path.join(image_dir, img_file)) + if self.train: + self.targets.append( + os.path.join(labels_dir, f"{img_file.split('.')[0]}.txt") + ) + + def __getitem__(self, index: int) -> Tuple[Any, Any]: + """Get item at a given index. + + Args: + index (int): Index + Returns: + tuple: (image, target), where + target is a list of dictionaries with the following keys: + + - type: str + - truncated: float + - occluded: int + - alpha: float + - bbox: float[4] + - dimensions: float[3] + - locations: float[3] + - rotation_y: float + + """ + image = Image.open(self.images[index]) + target = self._parse_target(index) if self.train else None + if self.transforms: + image, target = self.transforms(image, target) + return image, target + + def _parse_target(self, index: int) -> List: + target = [] + with open(self.targets[index]) as inp: + content = csv.reader(inp, delimiter=" ") + for line in content: + target.append({ + "type": line[0], + "truncated": float(line[1]), + "occluded": int(line[2]), + "alpha": float(line[3]), + "bbox": [float(x) for x in line[4:8]], + "dimensions": [float(x) for x in line[8:11]], + "location": [float(x) for x in line[11:14]], + "rotation_y": float(line[14]), + }) + return target + + def __len__(self) -> int: + return len(self.images) + + @property + def _raw_folder(self) -> str: + return os.path.join(self.root, self.__class__.__name__, "raw") + + def _check_exists(self) -> bool: + """Check if the data directory exists.""" + folders = [self.image_dir_name] + if self.train: + folders.append(self.labels_dir_name) + return all( + os.path.isdir(os.path.join(self._raw_folder, self._location, fname)) + for fname in folders + ) + + def download(self) -> None: + """Download the KITTI data if it doesn't exist already.""" + + if self._check_exists(): + return + + os.makedirs(self._raw_folder, exist_ok=True) + + # download files + for fname in self.resources: + download_and_extract_archive( + url=f"{self.data_url}{fname}", + download_root=self._raw_folder, + filename=fname, + ) From 043343f1488b7ee9c1654f8d23734cc011e1b680 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 351/357] [fbsync] packaging: Remove pin for jpeg, numpy (#3647) Summary: * packaging: Remove pin for jpeg, numpy These may no longer be necessary due to the default anaconda channel having the necessary packages now. Signed-off-by: Eli Uriegas * Update packaging/torchvision/meta.yaml Reviewed By: NicolasHug Differential Revision: D27706942 fbshipit-source-id: 64476f429ad8fd5ea110df3bd62b816157bdae11 Co-authored-by: Nicolas Hug Co-authored-by: Francisco Massa --- packaging/torchvision/meta.yaml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packaging/torchvision/meta.yaml b/packaging/torchvision/meta.yaml index 8279c276433..8516b2f0ed4 100644 --- a/packaging/torchvision/meta.yaml +++ b/packaging/torchvision/meta.yaml @@ -9,14 +9,13 @@ requirements: build: - {{ compiler('c') }} # [win] - libpng - - jpeg <=9b + - jpeg # NOTE: The only ffmpeg version that we build is actually 4.2 - ffmpeg >=4.2 # [not win] host: - python - setuptools - - defaults::numpy >=1.11 {{ environ.get('CONDA_PYTORCH_BUILD_CONSTRAINT') }} {{ environ.get('CONDA_CUDATOOLKIT_CONSTRAINT') }} {{ environ.get('CONDA_CPUONLY_FEATURE') }} @@ -25,9 +24,8 @@ requirements: - python - libpng - ffmpeg >=4.2 # [not win] - - jpeg <=9b - - pillow >=4.1.1 - - defaults::numpy >=1.11 + - jpeg + - pillow >=5.3.0 {{ environ.get('CONDA_PYTORCH_CONSTRAINT') }} {{ environ.get('CONDA_CUDATOOLKIT_CONSTRAINT') }} @@ -53,7 +51,7 @@ test: - pytest - scipy - av >=8.0.1 - - jpeg <=9b + - jpeg - ca-certificates From b40467463fe28fa335ea650b5b9b54c4ba29f416 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 352/357] [fbsync] Corrected spelling in a Type Error (#3659) Reviewed By: NicolasHug Differential Revision: D27706944 fbshipit-source-id: 9ee5e90200b2f7f79eccdaa4681e9caa67afb503 --- torchvision/transforms/transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index f7b6bf04970..291ac8b1ac3 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -1110,7 +1110,7 @@ def _check_input(self, value, name, center=1, bound=(0, float('inf')), clip_firs if not bound[0] <= value[0] <= value[1] <= bound[1]: raise ValueError("{} values should be between {}".format(name, bound)) else: - raise TypeError("{} should be a single number or a list/tuple with lenght 2.".format(name)) + raise TypeError("{} should be a single number or a list/tuple with length 2.".format(name)) # if value is 0 or (1., 1.) for brightness/contrast/saturation # or (0., 0.) for hue, do nothing From a81e414c65fb881dcd5884bdce45eeda166b0fe0 Mon Sep 17 00:00:00 2001 From: Francisco Massa Date: Tue, 13 Apr 2021 01:56:38 -0700 Subject: [PATCH 353/357] [fbsync] Remove pandas dependency for CelebA dataset (#3656) Summary: * Remove pandas dependecy for CelebA dataset * address PR comments * Apply suggestions from code review Reviewed By: NicolasHug Differential Revision: D27706937 fbshipit-source-id: 4beb11a0706c598735b65590afa0260f29dfa3a8 Co-authored-by: Philip Meier Co-authored-by: Vasilis Vryniotis Co-authored-by: Philip Meier --- test/datasets_utils.py | 1 - test/test_datasets.py | 1 - torchvision/datasets/celeba.py | 54 ++++++++++++++++++++++++---------- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/test/datasets_utils.py b/test/datasets_utils.py index 658ef6640fe..60e3990f3a2 100644 --- a/test/datasets_utils.py +++ b/test/datasets_utils.py @@ -53,7 +53,6 @@ class LazyImporter: MODULES = ( "av", "lmdb", - "pandas", "pycocotools", "requests", "scipy.io", diff --git a/test/test_datasets.py b/test/test_datasets.py index 1c45af1163c..167177deb30 100644 --- a/test/test_datasets.py +++ b/test/test_datasets.py @@ -616,7 +616,6 @@ class CelebATestCase(datasets_utils.ImageDatasetTestCase): split=("train", "valid", "test", "all"), target_type=("attr", "identity", "bbox", "landmarks", ["attr", "identity"]), ) - REQUIRED_PACKAGES = ("pandas",) _SPLIT_TO_IDX = dict(train=0, valid=1, test=2) diff --git a/torchvision/datasets/celeba.py b/torchvision/datasets/celeba.py index cc6f8084a80..5c202da05b9 100644 --- a/torchvision/datasets/celeba.py +++ b/torchvision/datasets/celeba.py @@ -1,3 +1,5 @@ +from collections import namedtuple +import csv from functools import partial import torch import os @@ -6,6 +8,8 @@ from .vision import VisionDataset from .utils import download_file_from_google_drive, check_integrity, verify_str_arg +CSV = namedtuple("CSV", ["header", "index", "data"]) + class CelebA(VisionDataset): """`Large-scale CelebFaces Attributes (CelebA) Dataset `_ Dataset. @@ -61,7 +65,6 @@ def __init__( target_transform: Optional[Callable] = None, download: bool = False, ) -> None: - import pandas super(CelebA, self).__init__(root, transform=transform, target_transform=target_transform) self.split = split @@ -88,23 +91,42 @@ def __init__( } split_ = split_map[verify_str_arg(split.lower(), "split", ("train", "valid", "test", "all"))] + splits = self._load_csv("list_eval_partition.txt") + identity = self._load_csv("identity_CelebA.txt") + bbox = self._load_csv("list_bbox_celeba.txt", header=1) + landmarks_align = self._load_csv("list_landmarks_align_celeba.txt", header=1) + attr = self._load_csv("list_attr_celeba.txt", header=1) + + mask = slice(None) if split_ is None else (splits.data == split_).squeeze() + + self.filename = splits.index + self.identity = identity.data[mask] + self.bbox = bbox.data[mask] + self.landmarks_align = landmarks_align.data[mask] + self.attr = attr.data[mask] + self.attr = (self.attr + 1) // 2 # map from {-1, 1} to {0, 1} + self.attr_names = attr.header + + def _load_csv( + self, + filename: str, + header: Optional[int] = None, + ) -> CSV: + data, indices, headers = [], [], [] fn = partial(os.path.join, self.root, self.base_folder) - splits = pandas.read_csv(fn("list_eval_partition.txt"), delim_whitespace=True, header=None, index_col=0) - identity = pandas.read_csv(fn("identity_CelebA.txt"), delim_whitespace=True, header=None, index_col=0) - bbox = pandas.read_csv(fn("list_bbox_celeba.txt"), delim_whitespace=True, header=1, index_col=0) - landmarks_align = pandas.read_csv(fn("list_landmarks_align_celeba.txt"), delim_whitespace=True, header=1) - attr = pandas.read_csv(fn("list_attr_celeba.txt"), delim_whitespace=True, header=1) - - mask = slice(None) if split_ is None else (splits[1] == split_) - - self.filename = splits[mask].index.values - self.identity = torch.as_tensor(identity[mask].values) - self.bbox = torch.as_tensor(bbox[mask].values) - self.landmarks_align = torch.as_tensor(landmarks_align[mask].values) - self.attr = torch.as_tensor(attr[mask].values) - self.attr = (self.attr + 1) // 2 # map from {-1, 1} to {0, 1} - self.attr_names = list(attr.columns) + with open(fn(filename)) as csv_file: + data = list(csv.reader(csv_file, delimiter=' ', skipinitialspace=True)) + + if header is not None: + headers = data[header] + data = data[header + 1:] + + indices = [row[0] for row in data] + data = [row[1:] for row in data] + data_int = [list(map(int, i)) for i in data] + + return CSV(headers, indices, torch.tensor(data_int)) def _check_integrity(self) -> bool: for (_, md5, filename) in self.file_list: From 2623952b0c49a660b7f205815751f0603d45d5b6 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Thu, 15 Apr 2021 04:10:08 -0700 Subject: [PATCH 354/357] Fix pytorch/vision/test:torchvision_models test_maskrcnn_resnet50_fpn_cuda Summary: This test is consistently failing or being skipped / omitted: https://www.internalfb.com/intern/test/562949978742689?ref_report_id=0 Some models are known to be flaky with autocast so we just ignore the check, as with other models Reviewed By: fmassa Differential Revision: D27791576 fbshipit-source-id: 1d3f7254a1031edf6a9393b9afe0aba7921d8042 --- test/test_models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_models.py b/test/test_models.py index 9b26839fa0b..90855fb71df 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -65,6 +65,7 @@ def get_available_video_models(): "fcn_resnet50", "fcn_resnet101", "lraspp_mobilenet_v3_large", + "maskrcnn_resnet50_fpn", ) From e1b9ae2122b22f17e90899733fe39031ff3a64c7 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Thu, 15 Apr 2021 05:24:02 -0700 Subject: [PATCH 355/357] Fix pytorch/vision/test:torchvision_models test_maskrcnn_resnet50_fpn_cuda (#3675) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/3675 This test is consistently failing or being skipped / omitted: https://www.internalfb.com/intern/test/562949978742689?ref_report_id=0 Some models are known to be flaky with autocast so we just ignore the check, as with other models Reviewed By: fmassa Differential Revision: D27791576 fbshipit-source-id: b7c85e4d67143bcc3cf4b5da0150a6dd6fd12298 --- test/test_models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_models.py b/test/test_models.py index 9b26839fa0b..90855fb71df 100644 --- a/test/test_models.py +++ b/test/test_models.py @@ -65,6 +65,7 @@ def get_available_video_models(): "fcn_resnet50", "fcn_resnet101", "lraspp_mobilenet_v3_large", + "maskrcnn_resnet50_fpn", ) From 63cd3add764eec450073e875ba2621c0a1b3d786 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Thu, 15 Apr 2021 05:26:58 -0700 Subject: [PATCH 356/357] Fix torchvision_functional_tensor test_rgb2hsv (#3676) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/3676 The test is constantly failing: https://www.internalfb.com/intern/test/562949982577806?ref_report_id=0 The fix just adjusts `atol` from 1e-8 to 1e-7. The equality test was likely failing on exact zeros Reviewed By: fmassa Differential Revision: D27790959 fbshipit-source-id: 58d06250df5905e39e197ee946ee2d875a5bab76 --- test/test_functional_tensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_functional_tensor.py b/test/test_functional_tensor.py index 42d44dfdbd9..73fa5583592 100644 --- a/test/test_functional_tensor.py +++ b/test/test_functional_tensor.py @@ -166,7 +166,7 @@ def test_rgb2hsv(self): self.assertLess(max_diff, 1e-5) s_hsv_img = scripted_fn(rgb_img) - self.assertTrue(hsv_img.allclose(s_hsv_img)) + self.assertTrue(hsv_img.allclose(s_hsv_img, atol=1e-7)) batch_tensors = self._create_data_batch(120, 100, num_samples=4, device=self.device).float() self._test_fn_on_batch(batch_tensors, F_t._rgb2hsv) From 7022bb19982b286814bce2726c7e34d5a1d82334 Mon Sep 17 00:00:00 2001 From: Nicolas Hug Date: Thu, 15 Apr 2021 05:28:45 -0700 Subject: [PATCH 357/357] Fix torchvision_functional_tensor - test_adjust_hue (#3677) Summary: Pull Request resolved: https://github.com/pytorch/vision/pull/3677 This test is broken: https://www.internalfb.com/intern/test/281475006043433?ref_report_id=0 This diff fixes the test on CUDA devices by adjusting the tolerance, as was previously done for this same test Reviewed By: fmassa Differential Revision: D27792082 fbshipit-source-id: b336fb68fb72a5a80136efd5c2d3c9d0e1d4f604 --- test/test_functional_tensor.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_functional_tensor.py b/test/test_functional_tensor.py index 73fa5583592..b237720d7d7 100644 --- a/test/test_functional_tensor.py +++ b/test/test_functional_tensor.py @@ -24,7 +24,7 @@ class Tester(TransformsTester): def setUp(self): self.device = "cpu" - def _test_fn_on_batch(self, batch_tensors, fn, **fn_kwargs): + def _test_fn_on_batch(self, batch_tensors, fn, scripted_fn_atol=1e-8, **fn_kwargs): transformed_batch = fn(batch_tensors, **fn_kwargs) for i in range(len(batch_tensors)): img_tensor = batch_tensors[i, ...] @@ -34,7 +34,7 @@ def _test_fn_on_batch(self, batch_tensors, fn, **fn_kwargs): scripted_fn = torch.jit.script(fn) # scriptable function test s_transformed_batch = scripted_fn(batch_tensors, **fn_kwargs) - self.assertTrue(transformed_batch.allclose(s_transformed_batch)) + self.assertTrue(transformed_batch.allclose(s_transformed_batch, atol=scripted_fn_atol)) def test_assert_image_tensor(self): shape = (100,) @@ -348,7 +348,7 @@ def _test_adjust_fn(self, fn, fn_pil, fn_t, configs, tol=2.0 + 1e-10, agg_method atol = 1.0 self.assertTrue(adjusted_tensor.allclose(scripted_result, atol=atol), msg=msg) - self._test_fn_on_batch(batch_tensors, fn, **config) + self._test_fn_on_batch(batch_tensors, fn, scripted_fn_atol=atol, **config) def test_adjust_brightness(self): self._test_adjust_fn(