libvips / pyvips

python binding for libvips using cffi
MIT License
649 stars 50 forks source link

What is the difference between resizing and opening at a certain downsample? #159

Open EKami opened 4 years ago

EKami commented 4 years ago

Hello, So I'm developing a deep learning program and I use pyvips to open my WSI images. Recently I stumbled upon a weird issue where my program would predict completely different things depending on how I opened my WSI with pyvips.

If I open my WSIs with:

slide = pyvips.Image.openslideload(wsi_path, level=0)
slide = slide.resize(rescale_factor)
# Now slide is of size 39706x94762

and/or:

slide = pyvips.Image.openslideload(wsi_path, level=1)
# At level 1, slide is already at size 39706x94762

then I get completely different results with my neural network. This led me to think there is a fundamental difference between opening at full res and resizing vs opening at the right level (performances put aside).

I just can't find what is the difference of the final output between those two things. Could anyone shed some light? Thanks!

jcupitt commented 4 years ago

Hello @EKami,

The level= argument will pull out specific levels from the pyramidal WSI file. These are generated from the full-res image by some unknown algorithm inside the slide scanner software.

libvips resize will use lanczos3, a high-quality resizer that adds a little ringing to the image to make it more pleasing to look at.

I would try resize(rescale_factor, kernel=linear) to select simple linear scaling -- this will produce a very smooth downsampling which will probably work better for ML applications.

Your network has probably learned some very specific features of the openslide downsampling output. If you want to make your network less fragile to changes like this, you probably need to do some pre-filtering, such as median, gblur, LBP, canny etc.

EKami commented 4 years ago

Hi @jcupitt , Thanks a lot for this response! We did some pretty data augmentation in fact during training, but during eval we still end up with less good predictions if we open at level 0.

I'll try with the different resizing kernels, thanks for the tip! :)

EKami commented 4 years ago

Turns out the kernel="linear" was in fact the culprit. It changes everything for me now that you pointed me in the right direction. My friend and I spent countless nights trying to figure out why our neural network didn't work as expected. I guess better later than never aha.

Thanks a lot @jcupitt :)

jcupitt commented 4 years ago

I wrote an SO answer with some shots from linear vs. lanczos3:

https://stackoverflow.com/questions/54941643/image-downsampling-by-large-factor-without-artefacts/54947439#54947439

You should be able to see the bright lines that lanczos is adding around objects.