I'm trying to visualize a 11-bit TIFF image using matplotlib. To do it, I load the image using tifffile to obtain a 3D numpy array. Next, I have to down-sample the image because the array contains values beyond the range [0, 255]. Here is my code:

import tifffile as ti
from scipy.misc import bytescale

x_3band = ti.imread(three_band_file_path)
# transpose to make the shape [M, N, 3]
X = np.transpose(x_3band, (1,2,0))
X = bytescale(X)

The problem is that the visualized picture is different with the picture visualized in QGIS (see the picture, the left picture is with matplotlib).

How can I show the picture like in QGIS?enter image description here


QGIS is applying a contrast stretch.

A simple 2-98% stretch can be accomplished like this:

import numpy as np

def bytescale(data, in_min, in_max):

    data = np.clip(data, in_min, in_max)
    data = (data - float(in_min)) / float(in_max - in_min)
    return np.array(data * 255, dtype=np.uint8)

in_min, in_max = np.percentile(data , (2,98))  # Where data = a single band
data = bytescale(data, in_min, in_max)

Note this simple example doesn't handle NoData/Null/NaN values (hint: np.nanpercentile) and it is only scaling a single band/channel, you'll need to loop through each band, rescale/stretch and put the bands back together into a 3d array.

  • It creates another image, but still it is very different from the image in QGIST. Here is the link: imgur.com/a/ScyC9UE – lenhhoxung Feb 13 at 16:35
  • You can use other percentiles, or use a standard deviation stretch instead. Why not have a look at layer symbology in QGIS to see what stretch is being applied. – user2856 Feb 15 at 9:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.