Can't save_image of int tensor

Ankit_Maurya: <p>Hi all,<br>
I have an output tensor of torch.int64 type in the range[0,255] .  I am trying to save the tensor as image using save_image()  but it’s giving me an error.<br>
<strong>My tensor</strong></p>
<pre><code class="lang-auto">img_hr,a,b = learn.predict(fn)
img_hr.dtype
torch.int64
</code></pre>
<p><strong>Error</strong></p>
<pre><code class="lang-auto">save_image(img_hr,'img.jpg')
RuntimeError                              Traceback (most recent call last)
Input In [186], in &lt;cell line: 1&gt;()
----&gt; 1 save_image(img_hr,'img.jpg')

File ~/mambaforge/lib/python3.9/site-packages/torch/autograd/grad_mode.py:27, in _DecoratorContextManager.__call__.&lt;locals&gt;.decorate_context(*args, **kwargs)
     24 @functools.wraps(func)
     25 def decorate_context(*args, **kwargs):
     26     with self.clone():
---&gt; 27         return func(*args, **kwargs)

File ~/mambaforge/lib/python3.9/site-packages/torchvision/utils.py:154, in save_image(tensor, fp, format, **kwargs)
    152 grid = make_grid(tensor, **kwargs)
    153 # Add 0.5 after unnormalizing to [0, 255] to round to nearest integer
--&gt; 154 ndarr = grid.mul(255).add_(0.5).clamp_(0, 255).permute(1, 2, 0).to("cpu", torch.uint8).numpy()
    155 im = Image.fromarray(ndarr)
    156 im.save(fp, format=format)

File ~/mambaforge/lib/python3.9/site-packages/fastai/torch_core.py:365, in TensorBase.__torch_function__(cls, func, types, args, kwargs)
    363 if cls.debug and func.__name__ not in ('__str__','__repr__'): print(func, types, args, kwargs)
    364 if _torch_handled(args, cls._opt, func): types = (torch.Tensor,)
--&gt; 365 res = super().__torch_function__(func, types, args, ifnone(kwargs, {}))
    366 dict_objs = _find_args(args) if args else _find_args(list(kwargs.values()))
    367 if issubclass(type(res),TensorBase) and dict_objs: res.set_meta(dict_objs[0],as_copy=True)

File ~/mambaforge/lib/python3.9/site-packages/torch/_tensor.py:1142, in Tensor.__torch_function__(cls, func, types, args, kwargs)
   1139     return NotImplemented
   1141 with _C.DisableTorchFunction():
-&gt; 1142     ret = func(*args, **kwargs)
   1143     if func in get_default_nowrap_functions():
   1144         return ret

RuntimeError: result type Float can't be cast to the desired output type Long
</code></pre>
<p>Any ideas on how to save it?</p>
<p>Thanks,<br>
Ankit</p>

vadimkantorov: <p><code>save_image</code> only expects [0; 1] float tensor inputs. unfortunately, this function is quite antique. please chime in <a href="https://github.com/pytorch/vision/issues/5461" class="inline-onebox" rel="noopener nofollow ugc">Move torchvision.utils.save_image -&gt; torchvision.io.save_image (or introduce this function from scratch) · Issue #5461 · pytorch/vision · GitHub</a> to vote for its modernization. In general, i/o in torch is a big design/implementation mess IMHO. For example, both torchvision and torchaudio have their own separate ffmpeg wrapper with their own quirks of building from sources / linking with your own ffmpeg libraries etc <img src="https://discuss.pytorch.org/images/emoji/apple/frowning.png?v=12" title=":frowning:" class="emoji" alt=":frowning:" loading="lazy" width="20" height="20"> My proposal would be creating a separate torchio package grouping all this code.</p>

Ankit_Maurya: <p>Thanks <a class="mention" href="/u/vadimkantorov">@vadimkantorov</a> I will definitely chime in. But any ideas to save the image now ?</p>

vadimkantorov: <p>In the meanwhile, you can pass in <code>torchvision.utils.save_image(your_int64_tensor / 255.0)</code> or maybe using a newer <code>encode_jpeg</code>: <code>open("your_file.jpg", "wb").write(bytes(torchvision.io.encode_jpeg((your_int64_tensor - 128).to(torch.int8))))</code></p>
<p>An alternative to this conversion probably could be <code>your_int64_tensor.to(torch.uint8).view(torch.int8)</code> (saves the subtraction) but you need to double-check</p>

Ankit_Maurya: <p>Thanks <a class="mention" href="/u/vadimkantorov">@vadimkantorov</a></p>
<pre><code class="lang-auto">torchvision.utils.save_image(your_int64_tensor / 255.0)
</code></pre>
<p>works pretty well.</p>