SWIN2SR: Allow to choose number of in_channels and out_channels
Author: marvingabler
Pull request: no

### Feature request

I'd like to be able to specify a different number of output and input channels for the Swin2sr superresolution model. The current [SWIN2SR](https://github.com/huggingface/transformers/blob/v4.33.3/src/transformers/models/swin2sr/modeling_swin2sr.py) implementation expects input and output images to have the same amount of channels (rgb). It's currently not possible to specify num_channels_in and num_channels_out in the model config. 

I propose to make in_channels = out_channels as default as most people will require this, but to give the user the possibility to specify a different number of out channels if required. There are some changes in the model logic required.

After implementing the feature, the config constructor should change from

```python
### [...]
  def __init__(
          self,
          image_size=64,
          patch_size=1,
          num_channels=3,
          embed_dim=180,
          depths=[6, 6, 6, 6, 6, 6],
          num_heads=[6, 6, 6, 6, 6, 6],
          window_size=8,
          mlp_ratio=2.0,
          qkv_bias=True,
          hidden_dropout_prob=0.0,
          attention_probs_dropout_prob=0.0,
          drop_path_rate=0.1,
          hidden_act="gelu",
          use_absolute_embeddings=False,
          initializer_range=0.02,
          layer_norm_eps=1e-5,
          upscale=2,
          img_range=1.0,
          resi_connection="1conv",
          upsampler="pixelshuffle",
          **kwargs,
      ):
          super().__init__(**kwargs)
  
          self.image_size = image_size
          self.patch_size = patch_size
          self.num_channels = num_channels
          self.embed_dim = embed_dim
          self.depths = depths
          self.num_layers = len(depths)
          self.num_heads = num_heads
          self.window_size = window_size
          self.mlp_ratio = mlp_ratio
          self.qkv_bias = qkv_bias
          self.hidden_dropout_prob = hidden_dropout_prob
          self.attention_probs_dropout_prob = attention_probs_dropout_prob
          self.drop_path_rate = drop_path_rate
          self.hidden_act = hidden_act
          self.use_absolute_embeddings = use_absolute_embeddings
          self.layer_norm_eps = layer_norm_eps
          self.initializer_range = initializer_range
          self.upscale = upscale
          self.img_range = img_range
          self.resi_connection = resi_connection
          self.upsampler = upsampler
```

to something like

```python

```python
### [...]
  def __init__(
          self,
          image_size=64,
          patch_size=1,
          num_channels_in=3,
          num_channels_out=3,
          embed_dim=180,
          depths=[6, 6, 6, 6, 6, 6],
          num_heads=[6, 6, 6, 6, 6, 6],
          window_size=8,
          mlp_ratio=2.0,
          qkv_bias=True,
          hidden_dropout_prob=0.0,
          attention_probs_dropout_prob=0.0,
          drop_path_rate=0.1,
          hidden_act="gelu",
          use_absolute_embeddings=False,
          initializer_range=0.02,
          layer_norm_eps=1e-5,
          upscale=2,
          img_range=1.0,
          resi_connection="1conv",
          upsampler="pixelshuffle",
          **kwargs,
      ):
          super().__init__(**kwargs)
  
          self.image_size = image_size
          self.patch_size = patch_size
          self.num_channels_in = num_channels_in
          self.num_channels_out= num_channels_out
          self.embed_dim = embed_dim
          self.depths = depths
          self.num_layers = len(depths)
          self.num_heads = num_heads
          self.window_size = window_size
          self.mlp_ratio = mlp_ratio
          self.qkv_bias = qkv_bias
          self.hidden_dropout_prob = hidden_dropout_prob
          self.attention_probs_dropout_prob = attention_probs_dropout_prob
          self.drop_path_rate = drop_path_rate
          self.hidden_act = hidden_act
          self.use_absolute_embeddings = use_absolute_embeddings
          self.layer_norm_eps = layer_norm_eps
          self.initializer_range = initializer_range
          self.upscale = upscale
          self.img_range = img_range
          self.resi_connection = resi_connection
          self.upsampler = upsampler
```

### Motivation

Having in=out in channels is totally fine when working with classical images. However when dealing with super resolution tasks in the context of earth observations, you often want to have different amounts of input and output channels, e.g. when performing super resolution from low res multi band satellite images to high res rgb band visible satellite. 

Other use cases I see is e.g. to predict from low res grayscale to high res colorscale.

### Your contribution

Happy to submit a PR for this one. 

Comments: