[GIS] Converting GeoTIFF file to numpy array to QPixmap with PyQt4

gdalgeotiff-tiffnumpypyqt4python

I'm a student in CS doing an internship and I'm not familiar at all with GIS yet.

I have to display a GeoTIFF image (with a single band) into a QPixmap with PyQt4. So, I found some code that could help me in the GDAL library, but I think my conversion from my GeoTIFF file to a numpy array isn't correct. Here's why:

  • When I display my QPixmap from a QImage (see code below), the only thing I have is a transparent band at the top and the rest of the image is just a huge black rectangle.
  • When I type gdalinfo <FILENAME> in my console, it tells me that the maximum value is 165.146. However, when I get the max value from my numpy array, I get 544.843.

Here's the code:

import numpy as np
from osgeo import gdal
ds = gdal.Open("path/to/file.tiff")
mr_array = np.array(ds.ReadAsArray())
maxes = []
for sub in mr_array:
    maxes.append(np.amax(sub))
print(max(maxes)) # => 544.843
mr_img = gray2qimage(mr_array) # comes from this script: https://github.com/sjara/brainmix/blob/master/brainmix/gui/numpy2qimage.py
self.pxm_mr = QtGui.QPixmap.fromImage(mr_img).scaled(371,301,QtCore.Qt.KeepAspectRatio)
self.lbl_pxmap_mr.setPixmap(self.pxm_mr)

The idea was to search where the problem was coming from: the GeoTIFF -> numpy array conversion, the numpy array -> QImage or the QImage -> QPixmap conversion. My guess is that it comes from the GeoTIFF -> numpy array because of the different maximums, but every code I find about that kind of conversion is basically the same as mine.

Am I right in thinking it comes from here?

If so, how could I correct this?

If not, where is my problem most likely to come from?

Best Answer

I managed to do it in the end, so I'll post the answer here in case anyone needs it later.

The problem was that my image contained float32 and sometimes even complex32 data, but QImage does not support it, so I had to convert it to uint8.

Another problem that came up was that my image was completely black, because the values were most of the time like 0.x, so it was considered as black. I tried to use ImageEnhance from the PIL library, but the result wasn't satisfying due to some unusual values that would trouble the results. So I just decided to multiply every value of the array by a factor, determined by the user. Depending on the values you have in your array, it is not unusual to set the factor really high, for example in my case I usually set it at 300.

The code looks like this:

# Import the libraries
from osgeo import gdal
from PIL import Image, ImageQt
from PyQt4 import QtGui
import numpy as np

# Read the dataset and setting up the numpy arrays
dsr = gdal.Open("path/to/file")
np_array = np.array(dsr.ReadAsArray())
np_array_uint8 = (np_array * factor).astype(np.uint8) # 'factor' is a user-determined value

# Convert to image
im8 = Image.fromarray(np_array_uint8)
imQt = QtGui.QImage(ImageQt.ImageQt(im8))
pxmap = QtGui.QPixmap.fromImage(imQt)

# Set the pixmap into a label
self.label = QtGui.QLabel(self.centralwidget)
self.label.setPixmap(QtGui.QPixmap(mr_img)) # You can scale it as well

There you go, in case you ever need it. You can also save memory by setting everything to None if you need.

Hope this helps!

Related Question