Search code examples
pythonnumpymatplotlibimage-processinggdal

Reading .TIF image using GDAL Python becomes too dark


I'm reading a .TIF image using GDAL in Python, but when I re-plot the image it is significantly darker than the original image.

Additionally, it seems as though there are some intensity values in the 2D arrays that are over 255. Here's the code:

import gdal
import numpy as np
import matplotlib.pyplot as plt

tf = "pic.TIF"
img = gdal.Open(tf)
image_DN = np.zeros((img.RasterYSize, img.RasterXSize, img.RasterCount))

for band in range(img.RasterCount):
    imgband = img.GetRasterBand(band + 1)
    image_DN[:, :, band] = imgband.ReadAsArray()

# an array with the max value in each channel
maxes = np.zeros(img.RasterCount)
for i in range(img.RasterCount):
    maxes[i] = np.amax(image_DN[:, :, i])

img_RGB_DN = np.rollaxis(np.asarray([1 / maxes[0] * image_DN[:, :, 0], \
                                     1 / maxes[1] * image_DN[:, :, 1], \
                                     1 / maxes[2] * image_DN[:, :, 2]]), 0, 3)

plt.figure(1)
plt.imshow(img_RGB_DN)
plt.title('original DN')
plt.show()

I am a beginner at image processing, so any details would be greatly appreciated.


Solution

  • Check the dtype of image_DN You will likely see that this is not in uint8 format. Probably uint16 or float16/32. Hence the values can be much larger than 255. You can bruteforce convert the array to uint8 by using

    image_DN = image_DN.astype(uint8)

    If you like to rescale it to to the 0-255 integer range, you should convert the image to 8-bit. You can either do this manually using numpy using np.interp like this

    image_DN = np.interp(image_DN, (minval, maxval), (0, 255)).astype(np.uint8)

    Then it is a question of choosing a minval and maxval which makes sense.

    GDAL can also solve this for you with gdal.Translate like this

    img = gdal.Translate('',
                   'pic.TIF',
                   options='-ot Byte -scale minval maxval -of MEM')