libvips / pyvips

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

Downsampling OME-TIFF with PyVips and Generating Patches for Deep Learning #509

Open Fighting-bruceCHN opened 2 months ago

Fighting-bruceCHN commented 2 months ago

Hi,

I am currently working with a large OME-TIFF file (2_CD8.ome.tiff) that is quite high in resolution (9.59 GiB, Shape: (110319, 53873, 3)). For my downstream deep learning tasks, I need to downsample this image to a more manageable resolution.

I am using the following PyVips code to downsample:

import pyvips

def downsample_ome_tiff(input_file, output_file, downsample_factor=2):
    image = pyvips.Image.new_from_file(input_file, access="sequential")
    downsampled_image = image.resize(1.0 / downsample_factor)
    downsampled_image.write_to_file(output_file, Q=85, tile=True, pyramid=True)

input_tiff = '/path/to/2_CD8.ome.tiff'
output_tiff = '/path/to/2_CD8_downsampled.ome.tiff'
downsample_ome_tiff(input_tiff, output_tiff)

I would like to know if there are any improvements or alternative methods to downsample the OME-TIFF file. Additionally, I need guidance on how to generate patches from the downsampled image for deep learning purposes.

Thank you for your assistance!

Warm regards, Aobo Tan

jcupitt commented 2 months ago

Hello again,

I suppose these are pyramidal TIFFs, is that right? In which case you can downsample by using a smaller pyramid layer. For example:

$ python
Python 3.12.3 (main, Sep 11 2024, 14:17:37) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyvips
>>> image = pyvips.Image.new_from_file("9235.tif")
>>> image
<pyvips.Image 107568x79650 uchar, 3 bands, srgb>
>>> n_pages = image.get("n-pages")
>>> n_pages
18
>>> [pyvips.Image.new_from_file("9235.tif", page=n) for n in range(n_pages)]
[<pyvips.Image 107568x79650 uchar, 3 bands, srgb>, 
<pyvips.Image 53784x39825 uchar, 3 bands, srgb>, 
<pyvips.Image 26892x19913 uchar, 3 bands, srgb>, 
<pyvips.Image 13446x9957 uchar, 3 bands, srgb>, 
<pyvips.Image 6723x4979 uchar, 3 bands, srgb>, 
<pyvips.Image 3362x2490 uchar, 3 bands, srgb>, 
<pyvips.Image 1681x1245 uchar, 3 bands, srgb>, 
...

So page 0 is the full-res image and subsequent pages get smaller by a factor of two. You can just pick the page which is best for your network.

The best way to make patches depends on your network. Smaller than about 32x32, it's usually fastest to use fetch. Larger than that, crop is generally quicker.

Will you be making derivatives as well? Eg. rotate and flip to make more training data?

Fighting-bruceCHN commented 2 months ago

Thank you so much for the quick reply

jcupitt commented 2 months ago

There's some sample code here for fetch and crop:

https://github.com/libvips/pyvips/issues/100#issuecomment-493960943