Search code examples
pythonopencvgisgdalgeotiff

OpenCV return None whan imread is called with GDAL support


I have a very simple program in python with OpenCV and GDAL. In this program i read GeoTiff image with the following line

image = cv2.imread(sys.argv[1], cv2.IMREAD_LOAD_GDAL | cv2.IMREAD_COLOR)

The problem is for a specific image imread return None. I am using images from: https://www.sensefly.com/drones/example-datasets.html

Image in Assessing crops with RGB imagery (eBee SQ) > Map (orthomosaic) works well. Its size is: 19428, 19784 with 4 bands.

Image in Urban mapping (eBee Plus/senseFly S.O.D.A.) > Map (orthomosaic) doesn't work. Its size is: 26747, 25388 and 4 bands.

Any help to figure out what is the problem?

Edit: I tried the solution suggested by @en_lorithai and it works, the problem is then I need to do some image processing with OpenCV and the image loaded by GDAL has several issues

  • GDAL load images as RGB instead of BGR (used by default in OpenCV)
  • The image shape expected by OpenCV is (width, height, channels) and GDAL return an image with (channels, width, height) shape
  • The image returned by GDAL is flipped in Y-axe and rotate clockwise by 90 degree.

The image loaded by OpenCV is (resized to 700x700):

image loaded by OpenCV (resized to 700x700

The image loaded by GDAL (after change shape, of course) is (resized to 700x700)

imaged loaded by GDAL (resized to 700x700)

Finally, If I try to convert this image from BGR to RGB with

image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

I get (resized to 700x700)

GDAL image converted to BGR

I can convert from GDAL format to OpenCV format with the following code

image = ds.ReadAsArray() #Load image with GDAL
tmp = image.copy()
image[0] = tmp[2,:,:] # swap read channel and blue channel
image[2] = tmp[0,:,:]
image = np.swapaxes(image,2,0) # convert from (height, width, channels) to (channels, height, width)

image = cv2.flip(image,0) # flip in Y-axis
image = cv2.transpose(image) # Rotate by 90 degress (clockwise)
image = cv2.flip(image,1)

The problem is I think that this is a very slow process and I want to know if there is a automatic convert-process.


Solution

  • You can try and open the image in gdal instead

    from osgeo import gdal
    
    g_image = gdal.Open('161104_hq_transparent_mosaic_group1.tif')
    a_image = g_image.ReadAsArray()
    

    can't test as i don't have enough available memory to open that image.

    Edit: equivalent operation on another image

    from osgeo import gdal
    import matplotlib.pyplot as plt
    
    g_image = gdal.Open('Water-scenes-014.jpg') # 3 channel rgb image
    a_image = g_image.ReadAsArray()
    s_image = np.dstack((a_image[0],a_image[1],a_image[2]))
    plt.imshow(s_image) # show image in matplotlib (no need for color swap)
    s_image = cv2.cvtColor(s_image,cv2.COLOR_RGB2BGR) # colorswap for cv
    cv2.imshow('name',s_image)
    

    Another method of getting individual bands from gdal

    g_image = gdal.Open('image_name.PNG')
    band1 = g_image.GetRasterBand(1).ReadAsArray()
    

    You can then do a numpy dstack of each of the bands.