Repository: Lightning-AI/torchmetrics

Issue:
StructuralSimilarityIndexMeasure : Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same
## 🐛 Bug

When `gaussian_kernel` is set to `False` and images are on gpu, we can compute ssim metric because type difference.

#### Code sample

```python
img = torch.rand(10, 3, 64, 64).to(torch.device("cuda"))

ssim = SSIM(sigma=(1.5, 1.5), kernel_size=(11, 11), gaussian_kernel=False, compute_on_cpu=False, device=torch.device("cuda")).to(torch.device("cuda")) # force computation on gpu

ssim(img, img)
```

### Expected behavior

Compute StructuralSimilarityIndexMeasure between `img` and `img`

### Environment

- TorchMetrics version (and how you installed TM, e.g. `conda`, `pip`, build from source): 0.9.2
- Python & PyTorch Version (e.g., 1.0): 3.9.7
- Any other relevant information such as OS (e.g., Linux):

### Additional context

```bash
RuntimeError Traceback (most recent call last)
<ipython-input-4-4817dbad2239> in <module>
----> 1 ssim(img, img), mean_squared_error(img, img)

~/anaconda3/lib/python3.8/site-packages/torch/nn/modules/module.py in _call_impl(self, *input, **kwargs)
   1128         if not (self._backward_hooks or self._forward_hooks or self._forward_pre_hooks or _global_backward_hooks
   1129                 or _global_forward_hooks or _global_forward_pre_hooks):
-> 1130             return forward_call(*input, **kwargs)
   1131         # Do not call functions when jit is used
   1132         full_backward_hooks, non_full_backward_hooks = [], []

~/anaconda3/lib/python3.8/site-packages/torchmetrics/metric.py in forward(self, *args, **kwargs)
    235             self._forward_cache = self._forward_full_state_update(*args, **kwargs)
    236         else:
--> 237             self._forward_cache = self._forward_reduce_state_update(*args, **kwargs)
    238 
    239         return self._forward_cache

~/anaconda3/lib/python3.8/site-packages/torchmetrics/metric.py in _forward_reduce_state_update(self, *args, **kwargs)
    300         # calculate batch state and compute batch value
    301         self.update(*args, **kwargs)
--> 302         batch_val = self.compute()
    303 
    304         # reduce batch and global state
...
--> 160         outputs = F.conv2d(input_list, kernel, groups=channel)
    161 
    162     output_list = outputs.split(preds.shape[0])

RuntimeError: Input type (torch.cuda.FloatTensor) and weight type (torch.FloatTensor) should be the same
```


Discussion:
Hi! thanks for your contribution!, great first issue!

Resolving patch:
diff --git a/src/torchmetrics/functional/image/ssim.py b/src/torchmetrics/functional/image/ssim.py
--- a/src/torchmetrics/functional/image/ssim.py
+++ b/src/torchmetrics/functional/image/ssim.py
@@ -150,7 +150,9 @@ def _ssim_compute(
             kernel = _gaussian_kernel_2d(channel, gauss_kernel_size, sigma, dtype, device)
 
     if not gaussian_kernel:
-        kernel = torch.ones((1, 1, *kernel_size)) / torch.prod(Tensor(kernel_size))
+        kernel = torch.ones((channel, 1, *kernel_size), dtype=dtype, device=device) / torch.prod(
+            torch.tensor(kernel_size, dtype=dtype, device=device)
+        )
 
     input_list = torch.cat((preds, target, preds * preds, target * target, preds * target))  # (5 * B, C, H, W)
 


Test patch:
diff --git a/tests/unittests/image/test_ssim.py b/tests/unittests/image/test_ssim.py
--- a/tests/unittests/image/test_ssim.py
+++ b/tests/unittests/image/test_ssim.py
@@ -125,6 +125,23 @@ def test_ssim(self, preds, target, sigma, ddp, dist_sync_on_step):
             dist_sync_on_step=dist_sync_on_step,
         )
 
+    @pytest.mark.parametrize("ddp", [True, False])
+    @pytest.mark.parametrize("dist_sync_on_step", [True, False])
+    def test_ssim_without_gaussian_kernel(self, preds, target, sigma, ddp, dist_sync_on_step):
+        self.run_class_metric_test(
+            ddp,
+            preds,
+            target,
+            StructuralSimilarityIndexMeasure,
+            partial(_sk_ssim, data_range=1.0, sigma=sigma, kernel_size=None),
+            metric_args={
+                "gaussian_kernel": False,
+                "data_range": 1.0,
+                "sigma": sigma,
+            },
+            dist_sync_on_step=dist_sync_on_step,
+        )
+
     def test_ssim_functional(self, preds, target, sigma):
         self.run_functional_metric_test(
             preds,