【问题标题】:OpenCV return None whan imread is called with GDAL support当使用 GDAL 支持调用 imread 时,OpenCV 返回 None
【发布时间】:2017-11-13 13:10:15
【问题描述】:

我有一个非常简单的 Python 程序,带有 OpenCV 和 GDAL。在这个程序中,我使用以下行读取 GeoTiff 图像

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

问题在于特定图像imread 返回None。我使用的图片来自:https://www.sensefly.com/drones/example-datasets.html

Assessing crops with RGB imagery (eBee SQ) > Map (orthomosaic) 中的图像效果很好。它的大小是:19428、19784,有 4 个波段。

Urban mapping (eBee Plus/senseFly S.O.D.A.) > Map (orthomosaic) 中的图像不起作用。其大小为:26747、25388 和 4 个波段。

任何帮助找出问题所在?

编辑:我尝试了@en_lorithai 建议的解决方案并且它有效,问题是我需要使用 OpenCV 进行一些图像处理,而 GDAL 加载的图像有几个问题

  • GDAL 将图像加载为 RGB 而不是 BGR(在 OpenCV 中默认使用)
  • OpenCV 期望的图像形状是(宽度、高度、通道),而 GDAL 返回具有(通道、宽度、高度)形状的图像
  • GDAL 返回的图像在 Y 轴上翻转,顺时针旋转 90 度。

OpenCV加载的图片为(调整为700x700):

GDAL加载的图片(当然是改变形状后)是(调整为700x700)

最后,如果我尝试将此图像从 BGR 转换为 RGB

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

我得到(调整为 700x700)

我可以使用以下代码从 GDAL 格式转换为 OpenCV 格式

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)

问题是我认为这是一个非常缓慢的过程,我想知道是否有自动转换过程。

【问题讨论】:

  • 这可能是因为您尝试打开的图像的位深度。 Opencv 在这方面有点严格,更糟糕的是,当它得到它无法处理的东西时,它不会给你任何错误。如果您使用的是 gdal,则可以使用它来打开图像。

标签: python opencv gis gdal geotiff


【解决方案1】:

您可以尝试在 gdal 中打开图像

from osgeo import gdal

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

无法测试,因为我没有足够的可用内存来打开该图像。

编辑:对另一个图像的等效操作

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)

从 gdal 获取单个乐队的另一种方法

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

然后您可以对每个波段进行 numpy dstack。

【讨论】:

  • 在这个例子中它会加载图像,但是当我调用cv2.imshow 时,图像加载的形状错误(它是 (4,X,Y) 而不是 (X,Y,4),错误颜色(通道被交换)并在 Y 方向翻转并旋转 -90 度(水平方向)。无论如何要纠正它而不是手动执行(我的意思是,我可以使用 np.swapaxes 重塑,flip 取消翻转和image[0] = tmp[2,:,:] image[2] = tmp[0,:,:] 交换频道,但速度很慢)
  • @RdlP 颜色交换的原因是因为opencv。它使用 BGR 而不是 RGB(gdal 使用)。您可以使用 numpy 方法或 Opencvs 自己的函数更改颜色:cv2.cvtColor(a_image,cv2.COLOR_RGB2BGR)。形状变化将需要 numpy 方法/功能,但图像非常庞大,无论如何都会有点慢。我不能说图像翻转是 opencv 或 gdal 的结果,还是原始图像就是这样(我的笔记本电脑没有足够的内存来打开这个东西)。
  • @en_lorithaiI 在主要问题中添加额外信息
  • @RdlP 是的,我有一个类似的方法: g_image = gdal.Open('Water-scenes-014.jpg') a_image = g_image.ReadAsArray() s_image = np.dstack((a_image[ 0],a_image[1],a_image[2])) s_image = cv2.cvtColor(s_image,cv2.COLOR_RGB2BGR) cv2.imshow('name',s_image)。问题是,我的计算机在尝试完全打开您的图像时没有计算,我看到该图像有 4 个通道,而不是 3 个(但我认为等效的应该是 np.dstack((a_image[0],a_image[1] ,a_image[2],a_image[3])) 给你)。如果你想避免颜色交换,你可以使用 plt.imshow() 代替。
  • 感谢您的帮助。我已将此答案标记为正确,因为您以正确的方式指出我(使用 GDAL 打开图像)。我将研究是否有任何自动方法可以将 GDAL 图像转换为 OpenCV
猜你喜欢
  • 2021-02-27
  • 2017-12-22
  • 1970-01-01
  • 2012-07-04
  • 2022-12-09
  • 1970-01-01
  • 2015-02-14
  • 2017-03-20
  • 2018-11-29
相关资源
最近更新 更多