Torchvision Resize vs cv2 Resize

andreydung: <p>I’m converting a data processing code to use torchvision.transforms interface. However the following unit test shows the difference between them:</p>
<pre><code class="lang-auto">import numpy as np
import torch
import cv2
import scipy.misc
from PIL import Image
from torchvision import transforms
from torchvision.transforms import Normalize, Resize, ToTensor


filepath = '2359296.jpg'

target_size = 600

# ================== Using cv2 ====================
im = scipy.misc.imread(filepath).astype(np.float32, copy=False)
im1 = im.copy()

im_size_min = np.min(im.shape[0:2])
im_size_max = np.max(im.shape[0:2])
im_scale = float(target_size) / float(im_size_min)
out1 = cv2.resize(im, None, None, fx=im_scale, fy=im_scale,
                interpolation=cv2.INTER_LINEAR)
out1 /= 255. # Convert range to [0,1]


# ================== Using torchvision ====================
im2 = Image.open(filepath)
composed = transforms.Compose([ Resize(size=target_size),
                                ToTensor()])
out2 = composed(im2)
out2 = np.transpose(out2.data.numpy(), (1, 2, 0))


np.testing.assert_almost_equal(im1, im2, decimal=4)
np.testing.assert_almost_equal(out1, out2, decimal=4)
</code></pre>
<p>The results shows 95.1% mismatch with decimal of 4:</p>
<pre><code class="lang-auto">Mismatch: 95.1%
Max absolute difference: 0.0039216
Max relative difference: nan
 x: array([[[0.4118, 0.2706, 0.1686],
        [0.3912, 0.2539, 0.1569],
        [0.35  , 0.2206, 0.1333],...
 y: array([[[0.4118, 0.2706, 0.1686],
        [0.3922, 0.2549, 0.1569],
        [0.349 , 0.2196, 0.1333],...
</code></pre>
<p>I am wondering if they are expected to match with each other?</p>

Oli: <p>Hi! torchvision uses the pillow library. The libraries opencv/pillow seem to do their resizing a bit differently. Have a look at <a href="https://github.com/python-pillow/Pillow/issues/2718#issuecomment-333669547" rel="nofollow noopener">this post</a></p>

ash_gamma: <p>Hi,</p>
<p>What’s the work around for this?</p>
<p>Thanks!</p>

Oli: <p>Depends on what you want. If you want to use the torchvision transforms but avoid its resize function I guess you could do a torchvision lambda function and perform a opencv resize in there.</p>
<p>Hard to say without knowing your problem though</p>

ash_gamma: <p>while training in pytorch (in python), I resize my image to 224 x 224.</p>
<p>I’m trying to come up with a cpp executable to run inference. Here, when I resize my image using opencv, the resize function does not do the same thing as what the transforms.resize() does since PILLOW resize != opencv resize.</p>
<p>What resize function should I use in cpp to get the same result as transforms.resize()?</p>

Oli: <p>Either train with the solution I mentioned above or figure out a way to bundle the pillow resize in the cpp. I don’t have any experience in that so report back if you manage to get the pillow in the cpp. gl!</p>

dashesy: <p>You can use resize_bilinear <a href="https://github.com/microsoft/pytorch_od/blob/114c2eef51bff73dfd7dec4f2fad1c2c96e637da/mictorch/imresize.py#L19" rel="nofollow noopener">here</a>. I have a test, it is very close to <code>cv2</code> resizing, and can be exported to ONNX as well. Also you can easily try other grids or methods.</p>