[mlir][tosa] Lowering of tfl.resize_nearest_neighbor produces off-by-one error
Hello, @sabauma!
tfl.resize_nearest_neighbor is [deprecated](https://colab.research.google.com/gist/sushreebarsa/1f7b8b8f65b24ad4d9ffe44a7eeca372/62386.ipynb) and not recommended to be used. Could you please try to use other up sampling operations such as tfl.upsample_bilinear and tfl.upsample_nearest instead. Generally  `tf.image.resize(...method=ResizeMethod.NEAREST_NEIGHBOR...)` is referred for current use in the latest version. 


Thank you! This issue is stale because it has been open for 7 days with no activity. It will be closed if no further activity occurs. Thank you. This issue was closed because it has been inactive for 7 days since being marked as stale. Please reopen if you'd like to work on this further. Are you satisfied with the resolution of your issue?
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=Yes&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/62386">Yes</a>
<a href="https://docs.google.com/forms/d/e/1FAIpQLSfaP12TRhd9xSxjXZjcZFNXPGk4kc1-qMdv3gc6bEP90vY1ew/viewform?entry.85265664=No&entry.2137816233=https://github.com/tensorflow/tensorflow/issues/62386">No</a>

### Issue type

Bug

### Have you reproduced the bug with TensorFlow Nightly?

No

### Source

source

### TensorFlow version

2.13

### Custom code

Yes

### OS platform and distribution

Debian 11

### Mobile device

_No response_

### Python version

3.9.2

### Bazel version

6.1.0

### GCC/compiler version

10.2.1

### CUDA/cuDNN version

_No response_

### GPU model and memory

_No response_

### Current behavior?

Certain configurations of `tfl.resize_nearest_neighbor` produce an off-by-one error when upsampling the input tensor when using the TFL->TOSA backend. This causes the resulting image to be shifted by one pixel.

### Standalone code to reproduce the issue

```shell
Below is `tfl.resize_nearest_neighbor` operation, what it lowers to using the TFL->TOSA
pipeline, and a driver main function for ease of reproduction.
I've included the result of lowering `tfl.resize_nearest_neighbor` in case that is easier
to work with.


// Original tfl.resize_nearest_neighbor operator
func.func @predict(%arg0: tensor<1x4x5x3xf32>) -> (tensor<1x8x10x3xf32>) {

  %0 = "tfl.pseudo_const"() {value = dense<[8, 10]> : tensor<2xi32>} : () -> tensor<2xi32>
  %1 = "tfl.resize_nearest_neighbor"(%arg0, %0) {align_corners = false, half_pixel_centers = true} : (tensor<1x4x5x3xf32>, tensor<2xi32>) -> tensor<1x8x10x3xf32>

  return %1 : tensor<1x8x10x3xf32>
}

// After lowering to TOSA
// func.func @predict(%arg0: tensor<1x4x5x3xf32>) -> tensor<1x8x10x3xf32> {
//   %0 = "tosa.resize"(%arg0) <{border = array<i64: 3, 3>, mode = "NEAREST_NEIGHBOR", offset = array<i64: 1, 1>, scale = array<i64: 4, 2, 4, 2>}> : (tensor<1x4x5x3xf32>) -> tensor<1x8x10x3xf32>
//   return %0 : tensor<1x8x10x3xf32>
// }


// Driver main function (for convenience)
func.func @main() {
  %input = tensor.generate {
  ^bb0(%n: index, %h: index, %w: index, %c: index):
    %val = arith.index_cast %h : index to i64
    %out = arith.uitofp %val : i64 to f32
    tensor.yield %out : f32
  } : tensor<1x4x5x3xf32>

  %out = func.call @predict(%input) : (tensor<1x4x5x3xf32>) -> (tensor<1x8x10x3xf32>)

  %c0 = arith.constant 0 : index
  %c8 = arith.constant 8 : index
  %c1 = arith.constant 1 : index

  %arg6 = tensor.cast %out : tensor<1x8x10x3xf32> to tensor<*xf32>
  call @printMemrefF32(%arg6) : (tensor<*xf32>) -> ()
  return
}

func.func private @printF32(f32)
func.func private @printMemrefF32(%ptr : tensor<*xf32>)


The smallest Python reproducer I can produce. I am not certain if
`tf.compat.v1.image.resize_nearest_neighbor` is intended to be the reference
implementation of `tfl.resize_nearest_neighbor`, but it produces the output that
matches the model where we are seeing the answer divergence.

```python
import numpy as np
import tensorflow as tf

data = np.zeros([1, 4, 5, 3])
for i in range(4):
    data[:,i,:,:] = i

expected = tf.compat.v1.image.resize_nearest_neighbor(
    data, [8, 10],
    half_pixel_centers=True,
    align_corners=False)

print(expected)
```

Below is the output of the MLIR example on the left and the Python reference
implementation on the right. The upsampling on the MLIR version replicates the value
`0` only once, while the Python implementation replicates it twice.

```text
tfl.resize_nearest_neighbor         tf.compat.v1.image.resize_nearest_neighbor
[[[[0,     0,     0],               [[[[0. 0. 0.]
   [0,     0,     0],                  [0. 0. 0.]
   [0,     0,     0],                  [0. 0. 0.]
   [0,     0,     0],                  [0. 0. 0.]
   [0,     0,     0],                  [0. 0. 0.]
   [0,     0,     0],                  [0. 0. 0.]
   [0,     0,     0],                  [0. 0. 0.]
   [0,     0,     0],                  [0. 0. 0.]
   [0,     0,     0],                  [0. 0. 0.]
   [0,     0,     0]],                 [0. 0. 0.]]
  [[1,     1,     1],                 [[0. 0. 0.]
   [1,     1,     1],                  [0. 0. 0.]
   [1,     1,     1],                  [0. 0. 0.]
   [1,     1,     1],                  [0. 0. 0.]
   [1,     1,     1],                  [0. 0. 0.]
   [1,     1,     1],                  [0. 0. 0.]
   [1,     1,     1],                  [0. 0. 0.]
   [1,     1,     1],                  [0. 0. 0.]
   [1,     1,     1],                  [0. 0. 0.]
   [1,     1,     1]],                 [0. 0. 0.]]
  [[1,     1,     1],                 [[1. 1. 1.]
   [1,     1,     1],                  [1. 1. 1.]
   [1,     1,     1],                  [1. 1. 1.]
   [1,     1,     1],                  [1. 1. 1.]
   [1,     1,     1],                  [1. 1. 1.]
   [1,     1,     1],                  [1. 1. 1.]
   [1,     1,     1],                  [1. 1. 1.]
   [1,     1,     1],                  [1. 1. 1.]
   [1,     1,     1],                  [1. 1. 1.]
   [1,     1,     1]],                 [1. 1. 1.]]
  [[2,     2,     2],                 [[1. 1. 1.]
   [2,     2,     2],                  [1. 1. 1.]
   [2,     2,     2],                  [1. 1. 1.]
   [2,     2,     2],                  [1. 1. 1.]
   [2,     2,     2],                  [1. 1. 1.]
   [2,     2,     2],                  [1. 1. 1.]
   [2,     2,     2],                  [1. 1. 1.]
   [2,     2,     2],                  [1. 1. 1.]
   [2,     2,     2],                  [1. 1. 1.]
   [2,     2,     2]],                 [1. 1. 1.]]
  [[2,     2,     2],                 [[2. 2. 2.]
   [2,     2,     2],                  [2. 2. 2.]
   [2,     2,     2],                  [2. 2. 2.]
   [2,     2,     2],                  [2. 2. 2.]
   [2,     2,     2],                  [2. 2. 2.]
   [2,     2,     2],                  [2. 2. 2.]
   [2,     2,     2],                  [2. 2. 2.]
   [2,     2,     2],                  [2. 2. 2.]
   [2,     2,     2],                  [2. 2. 2.]
   [2,     2,     2]],                 [2. 2. 2.]]
  [[3,     3,     3],                 [[2. 2. 2.]
   [3,     3,     3],                  [2. 2. 2.]
   [3,     3,     3],                  [2. 2. 2.]
   [3,     3,     3],                  [2. 2. 2.]
   [3,     3,     3],                  [2. 2. 2.]
   [3,     3,     3],                  [2. 2. 2.]
   [3,     3,     3],                  [2. 2. 2.]
   [3,     3,     3],                  [2. 2. 2.]
   [3,     3,     3],                  [2. 2. 2.]
   [3,     3,     3]],                 [2. 2. 2.]]
  [[3,     3,     3],                 [[3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3]],                 [3. 3. 3.]]
  [[3,     3,     3],                 [[3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3],                  [3. 3. 3.]
   [3,     3,     3]]]]                [3. 3. 3.]]]], shape=(1, 8, 10, 3), dtype=float64)
```
```


### Relevant log output

_No response_