Skip to content Skip to sidebar Skip to footer

How Can I Use Vips For Image Normalization?

I want to normalize the exposure and color palettes of a set of images. For context, this is for training a neural net in image classification on medical images. I'm also doing thi

Solution 1:

You need hist_equal for histogram equalisation.

The main docs are here:

https://libvips.github.io/libvips/API/current/libvips-histogram.html

However, that will be extremely slow for large slide images. It will need to scan the whole slide once to build the histogram, then scan again to equalise it. It would be much faster to find the histogram of a low-res layer, then use that to equalise the high-res one.

For example:

#!/usr/bin/env python3

import sys
import pyvips

# open the slide image and get the number of layers ... we are not fetching # pixels, so this is quick
x = pyvips.Image.new_from_file(sys.argv[1])
levels = int(x.get("openslide.level-count"))

# find the histogram of the highest level ... again, this should be quick
x = pyvips.Image.new_from_file(sys.argv[1], 
                               level=levels - 1)
hist = x.hist_find()

# from that, compute the transform for histogram equalisation
equalise = hist.hist_cum().hist_norm()

# and use that on the full-res image
x = pyvips.Image.new_from_file(sys.argv[1])

x = x.maplut(equalise)

x.write_to_file(sys.argv[2])

Another factor is that histogram equalisation is non-linear, so it will distort lightness relationships. It can also distort colour relationships and make noise and compression artifacts look crazy. I tried that program on an image I have here:

$ ~/try/equal.py bild.ndpi[level=7] y.jpg

enter image description here

The stripes are from the slide scanner and the ugly fringes from compression.

I think I would instead find image max and min from the low-res level, then use them to do a simple linear stretch of pixel values.

Something like:

x = pyvips.Image.new_from_file(sys.argv[1])
levels = int(x.get("openslide.level-count"))
x = pyvips.Image.new_from_file(sys.argv[1],
                               level=levels - 1)
mn = x.min()
mx = x.max()
x = pyvips.Image.new_from_file(sys.argv[1])
x = (x - mn) * (256 / (mx - mn))
x.write_to_file(sys.argv[2])

Did you find the new Region feature in pyvips? It makes generating patches for training MUCH faster, up to 100x faster in some cases:

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

Post a Comment for "How Can I Use Vips For Image Normalization?"