swarm-lab/Rvision

Loss of quality with resize

Closed this issue · 10 comments

My main reason to use Rvision is because it's super fast compared with other R packages that deal with images (e.g., imager).
I am reading large tiffs from confocal images of mice brains, for which Rvision performs great, but I am struggling with data loss on display.

Rvision::image(files[1]) %>% 
  Rvision::resize(fx = 0.05, fy=0.05) %>% 
  Rvision::display()

Here side by side with windows native application.

image

Here side by side against imager version (much much much slower, but quality is better).

imager::load.image(files[1]) %>% 
  imager::imresize(scale = 0.05) %>% 
  plot()

image

I get a similar result of this resizing while running it on python side, so I'm not sure this is not "expected behavior".
I get similar bad quality using plot and using different scaling (0.05, 0.1, 0.5, ...)

I was wondering whether there's an effect of shrinking + upscaling for display, but it seems to be minimal. It looks like the most damage is done on the original shrinking.

image

Different methods produce slightly better quality but nothing similar to the native windows app or imager

@matiasandina This is normal. resize changes the size of the image by changing the number of pixels. So with fx=0.05 and fy=0.05, you only keep 5% of the pixels in each dimension (e.g. if your image was 1000x1000 pixels, you would be left with an image of only 50x50 pixels).

If your goal is to resize the display while maintaining the original image quality, you need to play with the height and width parameters of the display function.

My original image is 6560x8400, this is the kind of resolution I get with display() at img$ncol()/2 and img$nrow()/2. It's great resolution but obviously I cannot fit it on the screen.
Again, I'm curious as how the resizing can be done in such a way to produce a nice looking image but smaller (as imager and the native app get)

image

@matiasandina With img$ncol()/2 and img$nrow()/2, you are still displaying 3280x4200 pixels. If your screen has a lower resolution than that, it just won't fit. You need to set height and width` so that they are not bigger than your screen's resolution. For instance, if your monitor has a resolution of 1920x1080, you could do:

max_h <- 1080
r <- img$ncol() / img$nrow() 
h <- min(max_h, img$nrow())
w <- min(max_h * r, img$ncol())
display(img, height = h, width = w)

Note that this assumes no space is taken by

I believe this issue might not be because of the particular display settings.
For example, even when using resize

scale <- 0.1
img %>% 
  Rvision::resize(fx = scale, fy=scale,
                  interpolation = "exact") %>%
  write.Image("trial.png")

Display of trial.png on windows native app is flawless, basically achieves the shrinking with the small quality loss I am aiming for.
Display of trial.png using Rvision::display() has the same issues as the resize + display method or display method you suggest.

@matiasandina What's the output of print(img)?

@matiasandina And can you share that image with me? It might help me understand what the issue is.

print(img)
Class: image. 
Dimensions: 8400x6560.
Type: GRAY, 1-channel, 8U.
GPU: FALSE.

Original image is 52 MB
I think what I am saying is reproducible with the balloon example.

balloon <- image(system.file("sample_img/balloon1.png", package = "Rvision"))
balloon %>% 
  resize(fx=0.1, fy=0.1) %>% 
  display()

imager::load.image(system.file("sample_img/balloon1.png", package = "Rvision")) %>% 
  imager::imresize(scale=0.1) %>% 
  plot()

This is the imager result. Yes, there is data loss, but it is expected because of the heavy resizing I am doing. Still, I can see the edges and shapes pretty well.

image

This is the side by side. I don't know how imager is handling the interpolation such that the shapes are much better conserved. It's possible that the scale up for display() is the problem.

image

@matiasandina I see. The default value of the interpolation parameter in resize is "linear". Try "area" instead. It tends to work better for heavy downsizing.

Yes, That was it!
Thank you so much I tried several interpolation methods but not "area". Results are just as expected now!
image

@matiasandina Great to hear! I've also just added an option in display to choose a different interpolation. Not critical but that may be useful in the future.